From aef3be1779609db50d690c54cb1b9a77aae288d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 6 Oct 2024 22:13:37 +0200 Subject: [PATCH 01/97] Start v0.4.16 --- distribution/changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 8b2dd07cbf..0d4c58e4c3 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,3 +1,6 @@ +0.4.16 (in development) +------------------------------------------------------------------------ + 0.4.15 (2024-10-06) ------------------------------------------------------------------------ - Feature: [#775] Add 2x and 4x zoom levels to software renderer (previously limited to OpenGL). From 85863f000a460280b93532ed9340222d0d8dea9a Mon Sep 17 00:00:00 2001 From: mix <167040362+mixiate@users.noreply.github.com> Date: Mon, 7 Oct 2024 07:06:22 +0100 Subject: [PATCH 02/97] Fix Wooden RC flat to steep rails drawing order (#22921) --- distribution/changelog.txt | 1 + .../track/coaster/WoodenRollerCoaster.cpp | 71 +++---------------- 2 files changed, 11 insertions(+), 61 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 0d4c58e4c3..dbc69c99e6 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.4.16 (in development) ------------------------------------------------------------------------ +- Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp index 3144049520..73d2b43075 100644 --- a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp @@ -8216,39 +8216,14 @@ static void WoodenRCTrackFlatTo60DegUpLongBase( { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); break; case 1: - session.WoodenSupportsPrependTo = PaintAddImageAsParentRotated( - session, direction, - WoodenRCGetTrackColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 7), + session.WoodenSupportsPrependTo = WoodenRCTrackPaint( + session, direction, SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 7, SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 7, { 0, 0, height }, { { 28, 4, height - 16 }, { 2, 24, 56 } }); - session.WoodenSupportsPrependTo = PaintAddImageAsChildRotated( - session, direction, WoodenRCGetRailsColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 7), - { 0, 0, height }, { { 28, 4, height - 16 }, { 2, 24, 56 } }); - PaintAddImageAsParentRotated( - session, direction, - WoodenRCGetTrackColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT + 3), - { 0, 0, height }, { { 28, 4, height + 16 }, { 2, 22, 0 } }); - PaintAddImageAsChildRotated( - session, direction, - WoodenRCGetRailsColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT_RAILS + 3), - { 0, 0, height }, { { 28, 4, height + 16 }, { 2, 22, 0 } }); break; case 2: - session.WoodenSupportsPrependTo = PaintAddImageAsParentRotated( - session, direction, - WoodenRCGetTrackColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 11), + session.WoodenSupportsPrependTo = WoodenRCTrackPaint( + session, direction, SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 11, SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 11, { 0, 0, height }, { { 28, 4, height - 16 }, { 2, 24, 56 } }); - session.WoodenSupportsPrependTo = PaintAddImageAsChildRotated( - session, direction, - WoodenRCGetRailsColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 11), { 0, 0, height }, - { { 28, 4, height - 16 }, { 2, 24, 56 } }); - PaintAddImageAsParentRotated( - session, direction, - WoodenRCGetTrackColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT + 7), - { 0, 0, height }, { { 28, 4, height + 16 }, { 2, 22, 0 } }); - PaintAddImageAsChildRotated( - session, direction, - WoodenRCGetRailsColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT_RAILS + 7), - { 0, 0, height }, { { 28, 4, height + 16 }, { 2, 22, 0 } }); break; case 3: PaintAddImageAsParentRotated( @@ -8300,40 +8275,14 @@ static void WoodenRCTrack60DegUpToFlatLongBase( { { 0, 6, height }, { 32, 20, 3 } }); break; case 1: - session.WoodenSupportsPrependTo = PaintAddImageAsParentRotated( - session, direction, - WoodenRCGetTrackColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 20), - { 0, 0, height }, { { 28, 4, height - 16 }, { 2, 24, 56 } }); - session.WoodenSupportsPrependTo = PaintAddImageAsChildRotated( - session, direction, - WoodenRCGetRailsColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 20), { 0, 0, height }, - { { 28, 4, height - 16 }, { 2, 24, 56 } }); - PaintAddImageAsParentRotated( - session, direction, - WoodenRCGetTrackColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT + 8), - { 0, 0, height }, { { 28, 4, height + 16 }, { 2, 22, 0 } }); - PaintAddImageAsChildRotated( - session, direction, - WoodenRCGetRailsColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT_RAILS + 8), - { 0, 0, height }, { { 28, 4, height + 16 }, { 2, 22, 0 } }); + session.WoodenSupportsPrependTo = WoodenRCTrackPaint( + session, direction, SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 20, SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 20, + { 0, 0, height }, { { 28, 4, height - 16 }, { 2, 24, 76 } }); break; case 2: - session.WoodenSupportsPrependTo = PaintAddImageAsParentRotated( - session, direction, - WoodenRCGetTrackColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 24), - { 0, 0, height }, { { 28, 4, height - 16 }, { 2, 24, 56 } }); - session.WoodenSupportsPrependTo = PaintAddImageAsChildRotated( - session, direction, - WoodenRCGetRailsColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 24), { 0, 0, height }, - { { 28, 4, height - 16 }, { 2, 24, 56 } }); - PaintAddImageAsParentRotated( - session, direction, - WoodenRCGetTrackColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT + 12), - { 0, 0, height }, { { 28, 4, height + 16 }, { 2, 22, 0 } }); - PaintAddImageAsChildRotated( - session, direction, - WoodenRCGetRailsColour(session).WithIndex(SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT_RAILS + 12), - { 0, 0, height }, { { 28, 4, height + 16 }, { 2, 22, 0 } }); + session.WoodenSupportsPrependTo = WoodenRCTrackPaint( + session, direction, SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 24, SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 24, + { 0, 0, height }, { { 28, 4, height - 16 }, { 2, 24, 76 } }); break; case 3: PaintAddImageAsParentRotated( From 117201626409b5dddcfedecabc160b4d2695940f Mon Sep 17 00:00:00 2001 From: mrmbernardi Date: Tue, 8 Oct 2024 06:46:09 +1100 Subject: [PATCH 03/97] Fix zooming with keyboard moving the view off centre --- distribution/changelog.txt | 1 + src/openrct2/interface/Window.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index dbc69c99e6..7666eae8f7 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.4.16 (in development) ------------------------------------------------------------------------ +- Fix: [#22918] Zooming with keyboard moves the view off centre. - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. 0.4.15 (2024-10-06) diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index c67fcca795..03e48f1409 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -934,16 +934,16 @@ void WindowZoomSet(WindowBase& w, ZoomLevel zoomLevel, bool atCursor) while (v->zoom > zoomLevel) { v->zoom--; - w.savedViewPos.x += v->ViewWidth() / 4; - w.savedViewPos.y += v->ViewHeight() / 4; + w.savedViewPos.x += v->ViewWidth() / 2; + w.savedViewPos.y += v->ViewHeight() / 2; } // Zoom out while (v->zoom < zoomLevel) { v->zoom++; - w.savedViewPos.x -= v->ViewWidth() / 2; - w.savedViewPos.y -= v->ViewHeight() / 2; + w.savedViewPos.x -= v->ViewWidth() / 4; + w.savedViewPos.y -= v->ViewHeight() / 4; } // Zooming to cursor? Centre around the tile we were hovering over just now. From 62839933517e35f40d4d1819235d284cd6783089 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Thu, 3 Oct 2024 21:09:30 +0100 Subject: [PATCH 04/97] Move WallElement into its own header/source files --- src/openrct2-ui/input/Shortcuts.cpp | 1 + .../interface/ViewportInteraction.cpp | 2 +- src/openrct2-ui/windows/Scenery.cpp | 1 + src/openrct2-ui/windows/Sign.cpp | 2 +- src/openrct2-ui/windows/TileInspector.cpp | 1 + src/openrct2-ui/windows/TopToolbar.cpp | 1 - src/openrct2/EditorObjectSelectionSession.cpp | 1 + .../actions/FootpathAdditionPlaceAction.cpp | 1 - .../actions/FootpathAdditionRemoveAction.cpp | 1 - .../actions/FootpathLayoutPlaceAction.cpp | 1 - src/openrct2/actions/FootpathPlaceAction.cpp | 1 - src/openrct2/actions/FootpathRemoveAction.cpp | 1 - src/openrct2/actions/SignSetStyleAction.cpp | 1 + src/openrct2/actions/WallPlaceAction.cpp | 1 + src/openrct2/actions/WallRemoveAction.cpp | 2 +- src/openrct2/actions/WallSetColourAction.cpp | 1 + src/openrct2/entity/Guest.cpp | 1 + src/openrct2/interface/Viewport.cpp | 1 + src/openrct2/libopenrct2.vcxproj | 4 +- .../paint/tile_element/Paint.Wall.cpp | 2 +- src/openrct2/rct1/S4Importer.cpp | 1 + src/openrct2/rct12/RCT12.cpp | 1 + src/openrct2/rct2/S6Importer.cpp | 1 + src/openrct2/ride/TrackDesign.cpp | 1 - src/openrct2/ride/TrackDesignSave.cpp | 2 +- src/openrct2/ride/Vehicle.cpp | 2 +- .../bindings/world/ScTileElement.cpp | 1 + src/openrct2/world/Banner.cpp | 3 +- src/openrct2/world/ConstructionClearance.cpp | 1 + src/openrct2/world/Map.cpp | 1 - src/openrct2/world/MapAnimation.cpp | 2 +- src/openrct2/world/Scenery.cpp | 1 - src/openrct2/world/TileElement.cpp | 1 + src/openrct2/world/TileElement.h | 45 ------- src/openrct2/world/TileInspector.cpp | 3 +- src/openrct2/world/Wall.cpp | 123 +----------------- src/openrct2/world/Wall.h | 8 -- .../world/tile_element/TileElementBase.cpp | 1 + .../world/tile_element/WallElement.cpp | 118 +++++++++++++++++ src/openrct2/world/tile_element/WallElement.h | 71 ++++++++++ test/tests/TileElementsView.cpp | 1 + 41 files changed, 221 insertions(+), 194 deletions(-) create mode 100644 src/openrct2/world/tile_element/WallElement.cpp create mode 100644 src/openrct2/world/tile_element/WallElement.h diff --git a/src/openrct2-ui/input/Shortcuts.cpp b/src/openrct2-ui/input/Shortcuts.cpp index 10a1dad985..d91f354187 100644 --- a/src/openrct2-ui/input/Shortcuts.cpp +++ b/src/openrct2-ui/input/Shortcuts.cpp @@ -45,6 +45,7 @@ #include #include #include +#include using namespace OpenRCT2; using namespace OpenRCT2::Ui; diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 7bab99d682..34be65ac1f 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -52,8 +52,8 @@ #include #include #include -#include #include +#include using namespace OpenRCT2; using namespace OpenRCT2::Ui::Windows; diff --git a/src/openrct2-ui/windows/Scenery.cpp b/src/openrct2-ui/windows/Scenery.cpp index 7af4b72184..4b0ac2cb4a 100644 --- a/src/openrct2-ui/windows/Scenery.cpp +++ b/src/openrct2-ui/windows/Scenery.cpp @@ -50,6 +50,7 @@ #include #include #include +#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index 15358aba33..9deff0ae4d 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index dba404683d..6e0585eaf2 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -43,6 +43,7 @@ #include #include #include +#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 82b170f2e5..7990116f8b 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -49,7 +49,6 @@ #include #include #include -#include #include namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp index 814f10e95c..79b41c0ebd 100644 --- a/src/openrct2/EditorObjectSelectionSession.cpp +++ b/src/openrct2/EditorObjectSelectionSession.cpp @@ -31,6 +31,7 @@ #include "world/Footpath.h" #include "world/Scenery.h" #include "world/tile_element/EntranceElement.h" +#include "world/tile_element/WallElement.h" #include #include diff --git a/src/openrct2/actions/FootpathAdditionPlaceAction.cpp b/src/openrct2/actions/FootpathAdditionPlaceAction.cpp index c3ba64ac4c..9c75c5f2bf 100644 --- a/src/openrct2/actions/FootpathAdditionPlaceAction.cpp +++ b/src/openrct2/actions/FootpathAdditionPlaceAction.cpp @@ -23,7 +23,6 @@ #include "../world/Location.hpp" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Wall.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/FootpathAdditionRemoveAction.cpp b/src/openrct2/actions/FootpathAdditionRemoveAction.cpp index 1d6d3bba05..d592ab7ba2 100644 --- a/src/openrct2/actions/FootpathAdditionRemoveAction.cpp +++ b/src/openrct2/actions/FootpathAdditionRemoveAction.cpp @@ -20,7 +20,6 @@ #include "../world/Footpath.h" #include "../world/Location.hpp" #include "../world/Park.h" -#include "../world/Wall.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/FootpathLayoutPlaceAction.cpp b/src/openrct2/actions/FootpathLayoutPlaceAction.cpp index 982c5cc262..b99740aa17 100644 --- a/src/openrct2/actions/FootpathLayoutPlaceAction.cpp +++ b/src/openrct2/actions/FootpathLayoutPlaceAction.cpp @@ -23,7 +23,6 @@ #include "../world/Park.h" #include "../world/QuarterTile.h" #include "../world/Surface.h" -#include "../world/Wall.h" #include "../world/tile_element/EntranceElement.h" #include "../world/tile_element/Slope.h" diff --git a/src/openrct2/actions/FootpathPlaceAction.cpp b/src/openrct2/actions/FootpathPlaceAction.cpp index 14a19f47cf..70eb1d1418 100644 --- a/src/openrct2/actions/FootpathPlaceAction.cpp +++ b/src/openrct2/actions/FootpathPlaceAction.cpp @@ -29,7 +29,6 @@ #include "../world/Scenery.h" #include "../world/Surface.h" #include "../world/TileElementsView.h" -#include "../world/Wall.h" #include "../world/tile_element/EntranceElement.h" #include "../world/tile_element/Slope.h" diff --git a/src/openrct2/actions/FootpathRemoveAction.cpp b/src/openrct2/actions/FootpathRemoveAction.cpp index 44b35a5ad9..21b5b5ec9d 100644 --- a/src/openrct2/actions/FootpathRemoveAction.cpp +++ b/src/openrct2/actions/FootpathRemoveAction.cpp @@ -19,7 +19,6 @@ #include "../world/Footpath.h" #include "../world/Location.hpp" #include "../world/Park.h" -#include "../world/Wall.h" #include "BannerRemoveAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/SignSetStyleAction.cpp b/src/openrct2/actions/SignSetStyleAction.cpp index a6b4c1c829..df5cbf31d1 100644 --- a/src/openrct2/actions/SignSetStyleAction.cpp +++ b/src/openrct2/actions/SignSetStyleAction.cpp @@ -18,6 +18,7 @@ #include "../windows/Intent.h" #include "../world/Banner.h" #include "../world/Scenery.h" +#include "../world/tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/WallPlaceAction.cpp b/src/openrct2/actions/WallPlaceAction.cpp index b930aa0ac3..8f40159e08 100644 --- a/src/openrct2/actions/WallPlaceAction.cpp +++ b/src/openrct2/actions/WallPlaceAction.cpp @@ -25,6 +25,7 @@ #include "../world/Surface.h" #include "../world/Wall.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/WallElement.h" using namespace OpenRCT2; using namespace OpenRCT2::TrackMetaData; diff --git a/src/openrct2/actions/WallRemoveAction.cpp b/src/openrct2/actions/WallRemoveAction.cpp index 41a01ea093..f524c96370 100644 --- a/src/openrct2/actions/WallRemoveAction.cpp +++ b/src/openrct2/actions/WallRemoveAction.cpp @@ -18,7 +18,7 @@ #include "../management/Finance.h" #include "../world/Location.hpp" #include "../world/TileElementsView.h" -#include "../world/Wall.h" +#include "../world/tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/WallSetColourAction.cpp b/src/openrct2/actions/WallSetColourAction.cpp index 9c0a12579b..e027958d42 100644 --- a/src/openrct2/actions/WallSetColourAction.cpp +++ b/src/openrct2/actions/WallSetColourAction.cpp @@ -20,6 +20,7 @@ #include "../world/MapAnimation.h" #include "../world/Scenery.h" #include "../world/Surface.h" +#include "../world/tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/entity/Guest.cpp b/src/openrct2/entity/Guest.cpp index c09f0e2e01..35cd3e777f 100644 --- a/src/openrct2/entity/Guest.cpp +++ b/src/openrct2/entity/Guest.cpp @@ -61,6 +61,7 @@ #include "../world/Surface.h" #include "../world/TileElementsView.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/WallElement.h" #include "Peep.h" #include "Staff.h" diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 8e4d4a8a37..5baa7d259f 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -38,6 +38,7 @@ #include "../util/Math.hpp" #include "../world/Climate.h" #include "../world/Map.h" +#include "../world/tile_element/WallElement.h" #include "Colour.h" #include "Window.h" #include "Window_internal.h" diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 1765cdb9ed..2d729f224a 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -624,6 +624,7 @@ + @@ -1105,6 +1106,7 @@ + NotUsing @@ -1114,4 +1116,4 @@ - + \ No newline at end of file diff --git a/src/openrct2/paint/tile_element/Paint.Wall.cpp b/src/openrct2/paint/tile_element/Paint.Wall.cpp index 5f091e477a..d2cfbb1454 100644 --- a/src/openrct2/paint/tile_element/Paint.Wall.cpp +++ b/src/openrct2/paint/tile_element/Paint.Wall.cpp @@ -25,7 +25,7 @@ #include "../../world/Map.h" #include "../../world/Scenery.h" #include "../../world/TileInspector.h" -#include "../../world/Wall.h" +#include "../../world/tile_element/WallElement.h" #include "Paint.TileElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index e84ee3ddba..b5eaec8471 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -73,6 +73,7 @@ #include "../world/TilePointerIndex.hpp" #include "../world/Wall.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/WallElement.h" #include "RCT1.h" #include "Tables.h" diff --git a/src/openrct2/rct12/RCT12.cpp b/src/openrct2/rct12/RCT12.cpp index 7cbcffd2c1..cc6ffc2a0f 100644 --- a/src/openrct2/rct12/RCT12.cpp +++ b/src/openrct2/rct12/RCT12.cpp @@ -27,6 +27,7 @@ #include "../world/TileElement.h" #include "../world/Wall.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/WallElement.h" #include "EntryList.h" using namespace OpenRCT2; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 0a5dd0203e..06476b20db 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -78,6 +78,7 @@ #include "../world/Surface.h" #include "../world/TilePointerIndex.hpp" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/WallElement.h" #include diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 376cef2df9..6dda14b77e 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -57,7 +57,6 @@ #include "../world/Park.h" #include "../world/Scenery.h" #include "../world/Surface.h" -#include "../world/Wall.h" #include "../world/tile_element/EntranceElement.h" #include "../world/tile_element/Slope.h" #include "Ride.h" diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 5714b72797..2ba0111554 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -25,8 +25,8 @@ #include "../windows/Intent.h" #include "../world/Footpath.h" #include "../world/Scenery.h" -#include "../world/Wall.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/WallElement.h" #include "RideData.h" #include "Station.h" #include "Track.h" diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 51701479d5..7c30157c8d 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -47,7 +47,7 @@ #include "../world/Park.h" #include "../world/Scenery.h" #include "../world/Surface.h" -#include "../world/Wall.h" +#include "../world/tile_element/WallElement.h" #include "CableLift.h" #include "Ride.h" #include "RideData.h" diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.cpp b/src/openrct2/scripting/bindings/world/ScTileElement.cpp index 6f545616e0..0ee51b394a 100644 --- a/src/openrct2/scripting/bindings/world/ScTileElement.cpp +++ b/src/openrct2/scripting/bindings/world/ScTileElement.cpp @@ -23,6 +23,7 @@ # include "../../../world/Scenery.h" # include "../../../world/Surface.h" # include "../../../world/tile_element/EntranceElement.h" +# include "../../../world/tile_element/WallElement.h" # include "../../Duktape.hpp" # include "../../ScriptEngine.h" diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp index 94dd98b6c3..dc1e6dec07 100644 --- a/src/openrct2/world/Banner.cpp +++ b/src/openrct2/world/Banner.cpp @@ -27,11 +27,12 @@ #include "../ride/RideData.h" #include "../ride/Track.h" #include "../windows/Intent.h" -#include "../world/TileElementsView.h" #include "Map.h" #include "MapAnimation.h" #include "Park.h" #include "Scenery.h" +#include "TileElementsView.h" +#include "tile_element/WallElement.h" #include #include diff --git a/src/openrct2/world/ConstructionClearance.cpp b/src/openrct2/world/ConstructionClearance.cpp index 7335bda579..428deec5cf 100644 --- a/src/openrct2/world/ConstructionClearance.cpp +++ b/src/openrct2/world/ConstructionClearance.cpp @@ -24,6 +24,7 @@ #include "Surface.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" +#include "tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 960de4270c..3730807b1a 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -57,7 +57,6 @@ #include "Surface.h" #include "TileElementsView.h" #include "TileInspector.h" -#include "Wall.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index 7b755bbfa4..46ff7bdae4 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -24,12 +24,12 @@ #include "../ride/Ride.h" #include "../ride/RideData.h" #include "../ride/Track.h" -#include "../world/Wall.h" #include "Banner.h" #include "Footpath.h" #include "Map.h" #include "Scenery.h" #include "tile_element/EntranceElement.h" +#include "tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index 5d7ba79544..c2c5a424b6 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -36,7 +36,6 @@ #include "Footpath.h" #include "Map.h" #include "Park.h" -#include "Wall.h" uint8_t gSceneryQuadrant; diff --git a/src/openrct2/world/TileElement.cpp b/src/openrct2/world/TileElement.cpp index bc298b743b..c98f5b35ed 100644 --- a/src/openrct2/world/TileElement.cpp +++ b/src/openrct2/world/TileElement.cpp @@ -20,6 +20,7 @@ #include "Scenery.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" +#include "tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index da3545cb0c..e7487ef2b1 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -456,51 +456,6 @@ public: }; static_assert(sizeof(LargeSceneryElement) == 16); -struct WallElement : TileElementBase -{ - static constexpr TileElementType ElementType = TileElementType::Wall; - -private: - ObjectEntryIndex entryIndex; // 05 - colour_t colour_1; // 07 - colour_t colour_2; // 08 - colour_t colour_3; // 09 - BannerIndex banner_index; // 0A - uint8_t animation; // 0C 0b_dfff_ft00 d = direction, f = frame num, t = across track flag (not used) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-private-field" - uint8_t Pad0D[3]; -#pragma clang diagnostic pop - -public: - uint16_t GetEntryIndex() const; - void SetEntryIndex(uint16_t newIndex); - const WallSceneryEntry* GetEntry() const; - - uint8_t GetSlope() const; - void SetSlope(uint8_t newslope); - - colour_t GetPrimaryColour() const; - void SetPrimaryColour(colour_t newColour); - colour_t GetSecondaryColour() const; - void SetSecondaryColour(colour_t newColour); - colour_t GetTertiaryColour() const; - void SetTertiaryColour(colour_t newColour); - - uint8_t GetAnimationFrame() const; - void SetAnimationFrame(uint8_t frameNum); - - Banner* GetBanner() const; - BannerIndex GetBannerIndex() const; - void SetBannerIndex(BannerIndex newIndex); - - bool IsAcrossTrack() const; - void SetAcrossTrack(bool acrossTrack); - bool AnimationIsBackwards() const; - void SetAnimationIsBackwards(bool isBackwards); -}; -static_assert(sizeof(WallElement) == 16); - struct BannerElement : TileElementBase { static constexpr TileElementType ElementType = TileElementType::Banner; diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index 30223f62e1..cf7445d784 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -17,16 +17,17 @@ #include "../ride/Track.h" #include "../ride/TrackData.h" #include "../windows/TileInspectorGlobals.h" -#include "../world/MapAnimation.h" #include "Banner.h" #include "Footpath.h" #include "Location.hpp" #include "Map.h" +#include "MapAnimation.h" #include "Park.h" #include "Scenery.h" #include "Surface.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" +#include "tile_element/WallElement.h" #include diff --git a/src/openrct2/world/Wall.cpp b/src/openrct2/world/Wall.cpp index f8b9871ce0..22e34cbcfe 100644 --- a/src/openrct2/world/Wall.cpp +++ b/src/openrct2/world/Wall.cpp @@ -9,23 +9,8 @@ #include "Wall.h" -#include "../Cheats.h" -#include "../Game.h" -#include "../OpenRCT2.h" -#include "../localisation/StringIds.h" -#include "../management/Finance.h" -#include "../network/network.h" -#include "../object/ObjectEntryManager.h" -#include "../object/WallSceneryEntry.h" -#include "../ride/Track.h" -#include "../ride/TrackData.h" -#include "Banner.h" #include "Map.h" -#include "MapAnimation.h" -#include "Park.h" -#include "Scenery.h" -#include "Surface.h" -#include "Wall.h" +#include "tile_element/WallElement.h" /** * @@ -79,112 +64,6 @@ void WallRemoveIntersectingWalls(const CoordsXYRangedZ& wallPos, Direction direc } while (!(tileElement++)->IsLastForTile()); } -uint8_t WallElement::GetSlope() const -{ - return (Type & kTileElementQuadrantMask) >> 6; -} - -void WallElement::SetSlope(uint8_t newSlope) -{ - Type &= ~kTileElementQuadrantMask; - Type |= (newSlope << 6); -} - -colour_t WallElement::GetPrimaryColour() const -{ - return colour_1; -} - -colour_t WallElement::GetSecondaryColour() const -{ - return colour_2; -} - -colour_t WallElement::GetTertiaryColour() const -{ - return colour_3; -} - -void WallElement::SetPrimaryColour(colour_t newColour) -{ - colour_1 = newColour; -} - -void WallElement::SetSecondaryColour(colour_t newColour) -{ - colour_2 = newColour; -} - -void WallElement::SetTertiaryColour(colour_t newColour) -{ - colour_3 = newColour; -} - -uint8_t WallElement::GetAnimationFrame() const -{ - return (animation >> 3) & 0xF; -} - -void WallElement::SetAnimationFrame(uint8_t frameNum) -{ - animation &= WALL_ANIMATION_FLAG_ALL_FLAGS; - animation |= (frameNum & 0xF) << 3; -} - -uint16_t WallElement::GetEntryIndex() const -{ - return entryIndex; -} - -const WallSceneryEntry* WallElement::GetEntry() const -{ - return OpenRCT2::ObjectManager::GetObjectEntry(entryIndex); -} - -void WallElement::SetEntryIndex(uint16_t newIndex) -{ - entryIndex = newIndex; -} - -Banner* WallElement::GetBanner() const -{ - return ::GetBanner(GetBannerIndex()); -} - -BannerIndex WallElement::GetBannerIndex() const -{ - return banner_index; -} - -void WallElement::SetBannerIndex(BannerIndex newIndex) -{ - banner_index = newIndex; -} - -bool WallElement::IsAcrossTrack() const -{ - return (animation & WALL_ANIMATION_FLAG_ACROSS_TRACK) != 0; -} - -void WallElement::SetAcrossTrack(bool acrossTrack) -{ - animation &= ~WALL_ANIMATION_FLAG_ACROSS_TRACK; - if (acrossTrack) - animation |= WALL_ANIMATION_FLAG_ACROSS_TRACK; -} - -bool WallElement::AnimationIsBackwards() const -{ - return (animation & WALL_ANIMATION_FLAG_DIRECTION_BACKWARD) != 0; -} - -void WallElement::SetAnimationIsBackwards(bool isBackwards) -{ - animation &= ~WALL_ANIMATION_FLAG_DIRECTION_BACKWARD; - if (isBackwards) - animation |= WALL_ANIMATION_FLAG_DIRECTION_BACKWARD; -} - #pragma region Edge Slopes Table // clang-format off diff --git a/src/openrct2/world/Wall.h b/src/openrct2/world/Wall.h index 354c5bafc2..43e39b5e69 100644 --- a/src/openrct2/world/Wall.h +++ b/src/openrct2/world/Wall.h @@ -11,14 +11,6 @@ #include "TileElement.h" -enum -{ - WALL_ANIMATION_FLAG_ACROSS_TRACK = (1 << 2), - // 3 - 6 animation frame number - WALL_ANIMATION_FLAG_DIRECTION_BACKWARD = (1 << 7), - WALL_ANIMATION_FLAG_ALL_FLAGS = WALL_ANIMATION_FLAG_ACROSS_TRACK | WALL_ANIMATION_FLAG_DIRECTION_BACKWARD -}; - enum EDGE_SLOPE { EDGE_SLOPE_UPWARDS = (1 << 0), diff --git a/src/openrct2/world/tile_element/TileElementBase.cpp b/src/openrct2/world/tile_element/TileElementBase.cpp index 3541e6c02e..a8af4cacd5 100644 --- a/src/openrct2/world/tile_element/TileElementBase.cpp +++ b/src/openrct2/world/tile_element/TileElementBase.cpp @@ -10,6 +10,7 @@ #include "../Map.h" #include "../TileElement.h" #include "EntranceElement.h" +#include "WallElement.h" TileElementType TileElementBase::GetType() const { diff --git a/src/openrct2/world/tile_element/WallElement.cpp b/src/openrct2/world/tile_element/WallElement.cpp new file mode 100644 index 0000000000..0f34685ac6 --- /dev/null +++ b/src/openrct2/world/tile_element/WallElement.cpp @@ -0,0 +1,118 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ +#include "WallElement.h" + +#include "../../object/ObjectEntryManager.h" +#include "../../object/WallSceneryEntry.h" + +uint8_t WallElement::GetSlope() const +{ + return (Type & kTileElementQuadrantMask) >> 6; +} + +void WallElement::SetSlope(uint8_t newSlope) +{ + Type &= ~kTileElementQuadrantMask; + Type |= (newSlope << 6); +} + +colour_t WallElement::GetPrimaryColour() const +{ + return colour_1; +} + +colour_t WallElement::GetSecondaryColour() const +{ + return colour_2; +} + +colour_t WallElement::GetTertiaryColour() const +{ + return colour_3; +} + +void WallElement::SetPrimaryColour(colour_t newColour) +{ + colour_1 = newColour; +} + +void WallElement::SetSecondaryColour(colour_t newColour) +{ + colour_2 = newColour; +} + +void WallElement::SetTertiaryColour(colour_t newColour) +{ + colour_3 = newColour; +} + +uint8_t WallElement::GetAnimationFrame() const +{ + return (animation >> 3) & 0xF; +} + +void WallElement::SetAnimationFrame(uint8_t frameNum) +{ + animation &= WALL_ANIMATION_FLAG_ALL_FLAGS; + animation |= (frameNum & 0xF) << 3; +} + +uint16_t WallElement::GetEntryIndex() const +{ + return entryIndex; +} + +const WallSceneryEntry* WallElement::GetEntry() const +{ + return OpenRCT2::ObjectManager::GetObjectEntry(entryIndex); +} + +void WallElement::SetEntryIndex(uint16_t newIndex) +{ + entryIndex = newIndex; +} + +Banner* WallElement::GetBanner() const +{ + return ::GetBanner(GetBannerIndex()); +} + +BannerIndex WallElement::GetBannerIndex() const +{ + return banner_index; +} + +void WallElement::SetBannerIndex(BannerIndex newIndex) +{ + banner_index = newIndex; +} + +bool WallElement::IsAcrossTrack() const +{ + return (animation & WALL_ANIMATION_FLAG_ACROSS_TRACK) != 0; +} + +void WallElement::SetAcrossTrack(bool acrossTrack) +{ + animation &= ~WALL_ANIMATION_FLAG_ACROSS_TRACK; + if (acrossTrack) + animation |= WALL_ANIMATION_FLAG_ACROSS_TRACK; +} + +bool WallElement::AnimationIsBackwards() const +{ + return (animation & WALL_ANIMATION_FLAG_DIRECTION_BACKWARD) != 0; +} + +void WallElement::SetAnimationIsBackwards(bool isBackwards) +{ + animation &= ~WALL_ANIMATION_FLAG_DIRECTION_BACKWARD; + if (isBackwards) + animation |= WALL_ANIMATION_FLAG_DIRECTION_BACKWARD; +} diff --git a/src/openrct2/world/tile_element/WallElement.h b/src/openrct2/world/tile_element/WallElement.h new file mode 100644 index 0000000000..bb179b4425 --- /dev/null +++ b/src/openrct2/world/tile_element/WallElement.h @@ -0,0 +1,71 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../Identifiers.h" +#include "../TileElement.h" + +#include + +enum +{ + WALL_ANIMATION_FLAG_ACROSS_TRACK = (1 << 2), + // 3 - 6 animation frame number + WALL_ANIMATION_FLAG_DIRECTION_BACKWARD = (1 << 7), + WALL_ANIMATION_FLAG_ALL_FLAGS = WALL_ANIMATION_FLAG_ACROSS_TRACK | WALL_ANIMATION_FLAG_DIRECTION_BACKWARD +}; + +#pragma pack(push, 1) +struct WallElement : TileElementBase +{ + static constexpr TileElementType ElementType = TileElementType::Wall; + +private: + ObjectEntryIndex entryIndex; // 05 + colour_t colour_1; // 07 + colour_t colour_2; // 08 + colour_t colour_3; // 09 + BannerIndex banner_index; // 0A + uint8_t animation; // 0C 0b_dfff_ft00 d = direction, f = frame num, t = across track flag (not used) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" + uint8_t Pad0D[3]; +#pragma clang diagnostic pop + +public: + uint16_t GetEntryIndex() const; + void SetEntryIndex(uint16_t newIndex); + const WallSceneryEntry* GetEntry() const; + + uint8_t GetSlope() const; + void SetSlope(uint8_t newslope); + + colour_t GetPrimaryColour() const; + void SetPrimaryColour(colour_t newColour); + colour_t GetSecondaryColour() const; + void SetSecondaryColour(colour_t newColour); + colour_t GetTertiaryColour() const; + void SetTertiaryColour(colour_t newColour); + + uint8_t GetAnimationFrame() const; + void SetAnimationFrame(uint8_t frameNum); + + Banner* GetBanner() const; + BannerIndex GetBannerIndex() const; + void SetBannerIndex(BannerIndex newIndex); + + bool IsAcrossTrack() const; + void SetAcrossTrack(bool acrossTrack); + bool AnimationIsBackwards() const; + void SetAnimationIsBackwards(bool isBackwards); +}; +static_assert(sizeof(WallElement) == kTileElementSize); + +#pragma pack(pop) diff --git a/test/tests/TileElementsView.cpp b/test/tests/TileElementsView.cpp index 0229ffb4b2..edc026eeb6 100644 --- a/test/tests/TileElementsView.cpp +++ b/test/tests/TileElementsView.cpp @@ -19,6 +19,7 @@ #include #include #include +#include using namespace OpenRCT2; From 1cdcbba65504e0b98f9c9e037c15aef599b4eafb Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Thu, 3 Oct 2024 21:15:12 +0100 Subject: [PATCH 05/97] Move wall declarations into wall.h --- src/openrct2/actions/FootpathPlaceAction.cpp | 1 + src/openrct2/actions/LandSetHeightAction.cpp | 1 + src/openrct2/actions/LargeSceneryPlaceAction.cpp | 1 + src/openrct2/actions/MazePlaceTrackAction.cpp | 1 + src/openrct2/actions/MazeSetTrackAction.cpp | 1 + src/openrct2/actions/RideEntranceExitPlaceAction.cpp | 1 + src/openrct2/actions/SmallSceneryPlaceAction.cpp | 1 + src/openrct2/actions/TrackPlaceAction.cpp | 1 + src/openrct2/actions/WaterSetHeightAction.cpp | 1 + src/openrct2/world/Map.h | 3 --- src/openrct2/world/Wall.h | 6 +++++- 11 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/openrct2/actions/FootpathPlaceAction.cpp b/src/openrct2/actions/FootpathPlaceAction.cpp index 70eb1d1418..14a19f47cf 100644 --- a/src/openrct2/actions/FootpathPlaceAction.cpp +++ b/src/openrct2/actions/FootpathPlaceAction.cpp @@ -29,6 +29,7 @@ #include "../world/Scenery.h" #include "../world/Surface.h" #include "../world/TileElementsView.h" +#include "../world/Wall.h" #include "../world/tile_element/EntranceElement.h" #include "../world/tile_element/Slope.h" diff --git a/src/openrct2/actions/LandSetHeightAction.cpp b/src/openrct2/actions/LandSetHeightAction.cpp index a2f6fd8b23..eb7bf19262 100644 --- a/src/openrct2/actions/LandSetHeightAction.cpp +++ b/src/openrct2/actions/LandSetHeightAction.cpp @@ -23,6 +23,7 @@ #include "../world/Scenery.h" #include "../world/Surface.h" #include "../world/TileElementsView.h" +#include "../world/Wall.h" #include "../world/tile_element/Slope.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LargeSceneryPlaceAction.cpp b/src/openrct2/actions/LargeSceneryPlaceAction.cpp index 86967f1b03..b4229620a9 100644 --- a/src/openrct2/actions/LargeSceneryPlaceAction.cpp +++ b/src/openrct2/actions/LargeSceneryPlaceAction.cpp @@ -23,6 +23,7 @@ #include "../world/MapAnimation.h" #include "../world/QuarterTile.h" #include "../world/Surface.h" +#include "../world/Wall.h" #include "../world/tile_element/Slope.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/MazePlaceTrackAction.cpp b/src/openrct2/actions/MazePlaceTrackAction.cpp index d76a737535..5ae8c13497 100644 --- a/src/openrct2/actions/MazePlaceTrackAction.cpp +++ b/src/openrct2/actions/MazePlaceTrackAction.cpp @@ -15,6 +15,7 @@ #include "../ride/RideData.h" #include "../ride/TrackData.h" #include "../world/ConstructionClearance.h" +#include "../world/Wall.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/MazeSetTrackAction.cpp b/src/openrct2/actions/MazeSetTrackAction.cpp index b2a2c7043f..ffae52ea7e 100644 --- a/src/openrct2/actions/MazeSetTrackAction.cpp +++ b/src/openrct2/actions/MazeSetTrackAction.cpp @@ -23,6 +23,7 @@ #include "../world/ConstructionClearance.h" #include "../world/Footpath.h" #include "../world/Park.h" +#include "../world/Wall.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/RideEntranceExitPlaceAction.cpp b/src/openrct2/actions/RideEntranceExitPlaceAction.cpp index 0c36593739..b10188e9be 100644 --- a/src/openrct2/actions/RideEntranceExitPlaceAction.cpp +++ b/src/openrct2/actions/RideEntranceExitPlaceAction.cpp @@ -17,6 +17,7 @@ #include "../ride/Station.h" #include "../world/ConstructionClearance.h" #include "../world/MapAnimation.h" +#include "../world/Wall.h" #include "../world/tile_element/EntranceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/SmallSceneryPlaceAction.cpp b/src/openrct2/actions/SmallSceneryPlaceAction.cpp index 876f04bb09..3f6ee3302c 100644 --- a/src/openrct2/actions/SmallSceneryPlaceAction.cpp +++ b/src/openrct2/actions/SmallSceneryPlaceAction.cpp @@ -28,6 +28,7 @@ #include "../world/Scenery.h" #include "../world/Surface.h" #include "../world/TileElement.h" +#include "../world/Wall.h" #include "../world/tile_element/Slope.h" #include "GameAction.h" #include "SmallSceneryRemoveAction.h" diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index 277670afe4..7992d643f8 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -22,6 +22,7 @@ #include "../world/MapAnimation.h" #include "../world/QuarterTile.h" #include "../world/Surface.h" +#include "../world/Wall.h" #include "../world/tile_element/Slope.h" #include "RideSetSettingAction.h" diff --git a/src/openrct2/actions/WaterSetHeightAction.cpp b/src/openrct2/actions/WaterSetHeightAction.cpp index b5922c6912..283c96892a 100644 --- a/src/openrct2/actions/WaterSetHeightAction.cpp +++ b/src/openrct2/actions/WaterSetHeightAction.cpp @@ -16,6 +16,7 @@ #include "../world/ConstructionClearance.h" #include "../world/Park.h" #include "../world/Surface.h" +#include "../world/Wall.h" using namespace OpenRCT2; diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index d05ac925d9..d877aa6aae 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -200,9 +200,6 @@ void MapExtendBoundarySurfaceX(); void MapExtendBoundarySurfaceY(); bool MapLargeScenerySignSetColour(const CoordsXYZD& signPos, int32_t sequence, uint8_t mainColour, uint8_t textColour); -void WallRemoveAt(const CoordsXYRangedZ& wallPos); -void WallRemoveAtZ(const CoordsXYZ& wallPos); -void WallRemoveIntersectingWalls(const CoordsXYRangedZ& wallPos, Direction direction); void MapInvalidateTile(const CoordsXYRangedZ& tilePos); void MapInvalidateTileZoom1(const CoordsXYRangedZ& tilePos); diff --git a/src/openrct2/world/Wall.h b/src/openrct2/world/Wall.h index 43e39b5e69..1c4db9ca84 100644 --- a/src/openrct2/world/Wall.h +++ b/src/openrct2/world/Wall.h @@ -9,7 +9,7 @@ #pragma once -#include "TileElement.h" +#include "Location.hpp" enum EDGE_SLOPE { @@ -21,4 +21,8 @@ enum EDGE_SLOPE EDGE_SLOPE_DOWNWARDS_ELEVATED = EDGE_SLOPE_DOWNWARDS | EDGE_SLOPE_ELEVATED, }; +void WallRemoveAt(const CoordsXYRangedZ& wallPos); +void WallRemoveAtZ(const CoordsXYZ& wallPos); +void WallRemoveIntersectingWalls(const CoordsXYRangedZ& wallPos, Direction direction); + uint8_t GetWallSlopeFromEdgeSlope(uint8_t Slope, uint8_t Edge); From 98992ea6166b6b8df923d6756d3376acd8bf5194 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sat, 7 Sep 2024 00:37:17 +0200 Subject: [PATCH 06/97] Extract UpdateTrackMotionMiniGolfFlagsStatus() --- src/openrct2/ride/Vehicle.cpp | 353 ++++++++++++++++++---------------- src/openrct2/ride/Vehicle.h | 8 + 2 files changed, 192 insertions(+), 169 deletions(-) diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 7c30157c8d..1bfeb193f6 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -7604,6 +7604,183 @@ bool Vehicle::UpdateTrackMotionBackwards(const CarEntry* carEntry, const Ride& c } } +Vehicle::UpdateMiniGolfFlagsStatus Vehicle::UpdateTrackMotionMiniGolfFlagsStatus(const Ride& curRide) +{ + if (var_D3 != 0) + { + var_D3--; + remaining_distance -= 0x368A; + if (remaining_distance < 0) + { + remaining_distance = 0; + } + + if (remaining_distance < 0x368A) + { + Loc6DCDE4(curRide); + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + acceleration = AccelerationFromPitch[Pitch]; + _vehicleUnkF64E10++; + return Vehicle::UpdateMiniGolfFlagsStatus::restart; + } + + if (mini_golf_flags & MiniGolfFlag::Flag2) + { + uint8_t nextFrame = animation_frame + 1; + if (nextFrame < MiniGolfPeepAnimationLengths[EnumValue(mini_golf_current_animation)]) + { + animation_frame = nextFrame; + remaining_distance -= 0x368A; + if (remaining_distance < 0) + { + remaining_distance = 0; + } + + if (remaining_distance < 0x368A) + { + Loc6DCDE4(curRide); + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + acceleration = AccelerationFromPitch[Pitch]; + _vehicleUnkF64E10++; + return Vehicle::UpdateMiniGolfFlagsStatus::restart; + } + mini_golf_flags &= ~MiniGolfFlag::Flag2; + } + + if (mini_golf_flags & MiniGolfFlag::Flag0) + { + auto vehicleIdx = IsHead() ? next_vehicle_on_ride : prev_vehicle_on_ride; + Vehicle* vEDI = GetEntity(vehicleIdx); + if (vEDI == nullptr) + { + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + if (!(vEDI->mini_golf_flags & MiniGolfFlag::Flag0) || (vEDI->mini_golf_flags & MiniGolfFlag::Flag2)) + { + remaining_distance -= 0x368A; + if (remaining_distance < 0) + { + remaining_distance = 0; + } + + if (remaining_distance < 0x368A) + { + Loc6DCDE4(curRide); + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + acceleration = AccelerationFromPitch[Pitch]; + _vehicleUnkF64E10++; + return Vehicle::UpdateMiniGolfFlagsStatus::restart; + } + if (vEDI->var_D3 != 0) + { + remaining_distance -= 0x368A; + if (remaining_distance < 0) + { + remaining_distance = 0; + } + + if (remaining_distance < 0x368A) + { + Loc6DCDE4(curRide); + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + acceleration = AccelerationFromPitch[Pitch]; + _vehicleUnkF64E10++; + return Vehicle::UpdateMiniGolfFlagsStatus::restart; + } + vEDI->mini_golf_flags &= ~MiniGolfFlag::Flag0; + mini_golf_flags &= ~MiniGolfFlag::Flag0; + } + + if (mini_golf_flags & MiniGolfFlag::Flag1) + { + auto vehicleIdx = IsHead() ? next_vehicle_on_ride : prev_vehicle_on_ride; + Vehicle* vEDI = GetEntity(vehicleIdx); + if (vEDI == nullptr) + { + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + if (!(vEDI->mini_golf_flags & MiniGolfFlag::Flag1) || (vEDI->mini_golf_flags & MiniGolfFlag::Flag2)) + { + remaining_distance -= 0x368A; + if (remaining_distance < 0) + { + remaining_distance = 0; + } + + if (remaining_distance < 0x368A) + { + Loc6DCDE4(curRide); + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + acceleration = AccelerationFromPitch[Pitch]; + _vehicleUnkF64E10++; + return Vehicle::UpdateMiniGolfFlagsStatus::restart; + } + if (vEDI->var_D3 != 0) + { + remaining_distance -= 0x368A; + if (remaining_distance < 0) + { + remaining_distance = 0; + } + + if (remaining_distance < 0x368A) + { + Loc6DCDE4(curRide); + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + acceleration = AccelerationFromPitch[Pitch]; + _vehicleUnkF64E10++; + return Vehicle::UpdateMiniGolfFlagsStatus::restart; + } + vEDI->mini_golf_flags &= ~MiniGolfFlag::Flag1; + mini_golf_flags &= ~MiniGolfFlag::Flag1; + } + + if (mini_golf_flags & MiniGolfFlag::Flag3) + { + Vehicle* vEDI = this; + + for (;;) + { + vEDI = GetEntity(vEDI->prev_vehicle_on_ride); + if (vEDI == this || vEDI == nullptr) + { + break; + } + if (vEDI->IsHead()) + continue; + if (!(vEDI->mini_golf_flags & MiniGolfFlag::Flag4)) + continue; + if (vEDI->TrackLocation != TrackLocation) + continue; + remaining_distance -= 0x368A; + if (remaining_distance < 0) + { + remaining_distance = 0; + } + + if (remaining_distance < 0x368A) + { + Loc6DCDE4(curRide); + return Vehicle::UpdateMiniGolfFlagsStatus::stop; + } + acceleration = AccelerationFromPitch[Pitch]; + _vehicleUnkF64E10++; + return Vehicle::UpdateMiniGolfFlagsStatus::restart; + } + + mini_golf_flags |= MiniGolfFlag::Flag4; + mini_golf_flags &= ~MiniGolfFlag::Flag3; + } + + return Vehicle::UpdateMiniGolfFlagsStatus::carryOn; +} + /** * rct2: 0x006DC3A7 * @@ -7637,177 +7814,15 @@ void Vehicle::UpdateTrackMotionMiniGolfVehicle(const Ride& curRide, const RideOb goto Loc6DCA9A; Loc6DC462: - if (var_D3 != 0) +{ + Vehicle::UpdateMiniGolfFlagsStatus flagsStatus = Vehicle::UpdateMiniGolfFlagsStatus::restart; + while (flagsStatus == Vehicle::UpdateMiniGolfFlagsStatus::restart) { - var_D3--; - remaining_distance -= 0x368A; - if (remaining_distance < 0) - { - remaining_distance = 0; - } - - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } - acceleration = AccelerationFromPitch[Pitch]; - _vehicleUnkF64E10++; - goto Loc6DC462; - } - - if (mini_golf_flags & MiniGolfFlag::Flag2) - { - uint8_t nextFrame = animation_frame + 1; - if (nextFrame < MiniGolfPeepAnimationLengths[EnumValue(mini_golf_current_animation)]) - { - animation_frame = nextFrame; - remaining_distance -= 0x368A; - if (remaining_distance < 0) - { - remaining_distance = 0; - } - - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } - acceleration = AccelerationFromPitch[Pitch]; - _vehicleUnkF64E10++; - goto Loc6DC462; - } - mini_golf_flags &= ~MiniGolfFlag::Flag2; - } - - if (mini_golf_flags & MiniGolfFlag::Flag0) - { - auto vehicleIdx = IsHead() ? next_vehicle_on_ride : prev_vehicle_on_ride; - Vehicle* vEDI = GetEntity(vehicleIdx); - if (vEDI == nullptr) - { - return; - } - if (!(vEDI->mini_golf_flags & MiniGolfFlag::Flag0) || (vEDI->mini_golf_flags & MiniGolfFlag::Flag2)) - { - remaining_distance -= 0x368A; - if (remaining_distance < 0) - { - remaining_distance = 0; - } - - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } - acceleration = AccelerationFromPitch[Pitch]; - _vehicleUnkF64E10++; - goto Loc6DC462; - } - if (vEDI->var_D3 != 0) - { - remaining_distance -= 0x368A; - if (remaining_distance < 0) - { - remaining_distance = 0; - } - - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } - acceleration = AccelerationFromPitch[Pitch]; - _vehicleUnkF64E10++; - goto Loc6DC462; - } - vEDI->mini_golf_flags &= ~MiniGolfFlag::Flag0; - mini_golf_flags &= ~MiniGolfFlag::Flag0; - } - - if (mini_golf_flags & MiniGolfFlag::Flag1) - { - auto vehicleIdx = IsHead() ? next_vehicle_on_ride : prev_vehicle_on_ride; - Vehicle* vEDI = GetEntity(vehicleIdx); - if (vEDI == nullptr) - { - return; - } - if (!(vEDI->mini_golf_flags & MiniGolfFlag::Flag1) || (vEDI->mini_golf_flags & MiniGolfFlag::Flag2)) - { - remaining_distance -= 0x368A; - if (remaining_distance < 0) - { - remaining_distance = 0; - } - - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } - acceleration = AccelerationFromPitch[Pitch]; - _vehicleUnkF64E10++; - goto Loc6DC462; - } - if (vEDI->var_D3 != 0) - { - remaining_distance -= 0x368A; - if (remaining_distance < 0) - { - remaining_distance = 0; - } - - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } - acceleration = AccelerationFromPitch[Pitch]; - _vehicleUnkF64E10++; - goto Loc6DC462; - } - vEDI->mini_golf_flags &= ~MiniGolfFlag::Flag1; - mini_golf_flags &= ~MiniGolfFlag::Flag1; - } - - if (mini_golf_flags & MiniGolfFlag::Flag3) - { - Vehicle* vEDI = this; - - for (;;) - { - vEDI = GetEntity(vEDI->prev_vehicle_on_ride); - if (vEDI == this || vEDI == nullptr) - { - break; - } - if (vEDI->IsHead()) - continue; - if (!(vEDI->mini_golf_flags & MiniGolfFlag::Flag4)) - continue; - if (vEDI->TrackLocation != TrackLocation) - continue; - remaining_distance -= 0x368A; - if (remaining_distance < 0) - { - remaining_distance = 0; - } - - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } - acceleration = AccelerationFromPitch[Pitch]; - _vehicleUnkF64E10++; - goto Loc6DC462; - } - - mini_golf_flags |= MiniGolfFlag::Flag4; - mini_golf_flags &= ~MiniGolfFlag::Flag3; + flagsStatus = UpdateTrackMotionMiniGolfFlagsStatus(curRide); } + if (flagsStatus == UpdateMiniGolfFlagsStatus::stop) + return; +}; { uint16_t trackTotalProgress = GetTrackProgress(); diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index b2299c063c..7f2ec05343 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -379,6 +379,14 @@ private: void Loc6DCE02(const Ride& curRide); void Loc6DCDE4(const Ride& curRide); + + enum class UpdateMiniGolfFlagsStatus + { + carryOn, + restart, + stop, + }; + UpdateMiniGolfFlagsStatus UpdateTrackMotionMiniGolfFlagsStatus(const Ride& curRide); }; static_assert(sizeof(Vehicle) <= 512); From 717622ed01cc262811618b8339c88b2ba9e7a77c Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 7 Oct 2024 22:32:54 +0200 Subject: [PATCH 07/97] Cut out Mini Golf inverted code --- src/openrct2/ride/Vehicle.cpp | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 1bfeb193f6..3baf4634d3 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -7852,7 +7852,7 @@ Loc6DC462: direction = outDirection; } - if (PitchAndRollStart(HasFlag(VehicleFlags::CarIsInverted), tileElement) != TrackPitchAndRollEnd(GetTrackType())) + if (PitchAndRollStart(false, tileElement) != TrackPitchAndRollEnd(GetTrackType())) { _vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_5; _vehicleVelocityF64E0C -= remaining_distance + 1; @@ -7866,18 +7866,6 @@ Loc6DC462: goto Loc6DCA9A; } - { - int32_t rideType = ::GetRide(tileElement->AsTrack()->GetRideIndex())->type; - ClearFlag(VehicleFlags::CarIsInverted); - if (GetRideTypeDescriptor(rideType).HasFlag(RtdFlag::hasInvertedVariant)) - { - if (tileElement->AsTrack()->IsInverted()) - { - SetFlag(VehicleFlags::CarIsInverted); - } - } - } - TrackLocation = trackPos; if (!IsHead()) @@ -8070,7 +8058,7 @@ Loc6DCA9A: tileElement = trackBeginEnd.begin_element; } - if (PitchAndRollStart(HasFlag(VehicleFlags::CarIsInverted), tileElement) != TrackPitchAndRollEnd(GetTrackType())) + if (PitchAndRollStart(false, tileElement) != TrackPitchAndRollEnd(GetTrackType())) { _vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_5; _vehicleVelocityF64E0C -= remaining_distance - 0x368A; @@ -8085,18 +8073,6 @@ Loc6DCA9A: goto Loc6DC462; } - { - int32_t rideType = ::GetRide(tileElement->AsTrack()->GetRideIndex())->type; - ClearFlag(VehicleFlags::CarIsInverted); - if (GetRideTypeDescriptor(rideType).HasFlag(RtdFlag::hasInvertedVariant)) - { - if (tileElement->AsTrack()->IsInverted()) - { - SetFlag(VehicleFlags::CarIsInverted); - } - } - } - TrackLocation = trackPos; if (HasFlag(VehicleFlags::OnLiftHill)) From 7694195db7bfd77cd740d620cbc86e5919494d29 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 7 Oct 2024 22:35:53 +0200 Subject: [PATCH 08/97] Mini golf vehicle code: remove ifs that are always true --- src/openrct2/ride/Vehicle.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 3baf4634d3..f53f634da2 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -7839,10 +7839,6 @@ Loc6DC462: _vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_5; _vehicleVelocityF64E0C -= remaining_distance + 1; remaining_distance = -1; - if (remaining_distance >= 0) - { - Loc6DCDE4(curRide); - } acceleration += AccelerationFromPitch[Pitch]; _vehicleUnkF64E10++; goto Loc6DCA9A; @@ -8045,10 +8041,6 @@ Loc6DCA9A: _vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_5; _vehicleVelocityF64E0C -= remaining_distance + 1; remaining_distance = -1; - if (remaining_distance >= 0) - { - Loc6DCDE4(curRide); - } acceleration += AccelerationFromPitch[Pitch]; _vehicleUnkF64E10++; goto Loc6DCA9A; @@ -8063,11 +8055,6 @@ Loc6DCA9A: _vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_5; _vehicleVelocityF64E0C -= remaining_distance - 0x368A; remaining_distance = 0x368A; - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } acceleration = AccelerationFromPitch[Pitch]; _vehicleUnkF64E10++; goto Loc6DC462; @@ -8151,11 +8138,6 @@ Loc6DCA9A: vEBP->velocity = vEDI->velocity >> 1; } _vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_2; - if (remaining_distance < 0x368A) - { - Loc6DCDE4(curRide); - return; - } acceleration = AccelerationFromPitch[Pitch]; _vehicleUnkF64E10++; goto Loc6DC462; From 9bdbeaf563b3fce6e38821df38880865ea99d1dc Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 7 Oct 2024 22:44:37 +0200 Subject: [PATCH 09/97] Mini golf vehicle code: remove more flag checks that are never set --- src/openrct2/ride/Vehicle.cpp | 63 +---------------------------------- 1 file changed, 1 insertion(+), 62 deletions(-) diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index f53f634da2..24ccefca8b 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -8003,16 +8003,6 @@ Loc6DC462: bank_rotation = moveInfo->bank_rotation; Pitch = moveInfo->Pitch; - if (rideEntry.Cars[0].flags & CAR_ENTRY_FLAG_WOODEN_WILD_MOUSE_SWING) - { - if (Pitch != 0) - { - SwingSprite = 0; - SwingPosition = 0; - SwingSpeed = 0; - } - } - if (this == _vehicleFrontVehicle) { if (_vehicleVelocityF64E08 >= 0) @@ -8101,16 +8091,6 @@ Loc6DCA9A: bank_rotation = moveInfo->bank_rotation; Pitch = moveInfo->Pitch; - if (rideEntry.Cars[0].flags & CAR_ENTRY_FLAG_WOODEN_WILD_MOUSE_SWING) - { - if (Pitch != 0) - { - SwingSprite = 0; - SwingPosition = 0; - SwingSpeed = 0; - } - } - if (this == _vehicleFrontVehicle) { if (_vehicleVelocityF64E08 >= 0) @@ -8129,10 +8109,7 @@ Loc6DCA9A: Vehicle* vEDI = gCurrentVehicle; if (abs(vEDI->velocity - vEBP->velocity) > 14.0_mph) { - if (!(carEntry->flags & CAR_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION)) - { - _vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_COLLISION; - } + _vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_COLLISION; } vEDI->velocity = vEBP->velocity >> 1; vEBP->velocity = vEDI->velocity >> 1; @@ -8248,17 +8225,6 @@ int32_t Vehicle::UpdateTrackMotionMiniGolfCalculateAcceleration(const CarEntry& newAcceleration -= velocity >> 12; newAcceleration -= GetAccelerationDecrease2(velocity, totalMass); - if (!(carEntry.flags & CAR_ENTRY_FLAG_POWERED)) - { - return newAcceleration; - } - if (carEntry.flags & CAR_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY) - { - if (speed * 0x4000 < velocity) - { - return newAcceleration; - } - } { int32_t poweredAcceleration = speed << 14; int32_t quarterForce = (speed * totalMass) >> 2; @@ -8271,33 +8237,6 @@ int32_t Vehicle::UpdateTrackMotionMiniGolfCalculateAcceleration(const CarEntry& if (quarterForce != 0) poweredAcceleration /= quarterForce; - if (carEntry.flags & CAR_ENTRY_FLAG_WATER_RIDE) - { - if (poweredAcceleration < 0) - { - poweredAcceleration >>= 4; - } - - if (carEntry.flags & CAR_ENTRY_FLAG_SPINNING) - { - spin_speed = std::clamp(spin_speed, VEHICLE_MIN_SPIN_SPEED_WATER_RIDE, VEHICLE_MAX_SPIN_SPEED_WATER_RIDE); - } - - if (Pitch != 0) - { - poweredAcceleration = std::max(0, poweredAcceleration); - if (carEntry.flags & CAR_ENTRY_FLAG_SPINNING) - { - if (Pitch == 2) - { - spin_speed = 0; - } - } - newAcceleration += poweredAcceleration; - return newAcceleration; - } - } - if (abs(velocity) > 1.0_mph) { newAcceleration = 0; From 484732d73529c6e9e7ad52ae88bfdde29d3db3c4 Mon Sep 17 00:00:00 2001 From: OpenRCT2 git bot Date: Tue, 8 Oct 2024 04:02:09 +0000 Subject: [PATCH 10/97] Merge Localisation/master into OpenRCT2/develop --- data/language/eo-ZZ.txt | 2 +- data/language/nl-NL.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/language/eo-ZZ.txt b/data/language/eo-ZZ.txt index 61a8dfab40..73694e8de9 100644 --- a/data/language/eo-ZZ.txt +++ b/data/language/eo-ZZ.txt @@ -3765,7 +3765,7 @@ STR_6693 :Entajpu maksimuman altecon de tero inter {COMMA16} kaj {COMMA16} STR_6694 :Minimuma alteco de arboj STR_6695 :Entajpu minimuman altecon de arboj inter {COMMA16} kaj {COMMA16} STR_6696 :Maksimuma alteco de arboj -STR_6697 :Entajpu maksimuman altecon de arboj inter {COMMA16} akj {COMMA16} +STR_6697 :Entajpu maksimuman altecon de arboj inter {COMMA16} kaj {COMMA16} STR_6698 :Proporcio de arbo al tero STR_6699 :Entajpu proporcion de arbo al tero inter {COMMA16} kaj {COMMA16} STR_6700 :Baza frekvenco de simplaĵo diff --git a/data/language/nl-NL.txt b/data/language/nl-NL.txt index 44750bf96a..d20a774264 100644 --- a/data/language/nl-NL.txt +++ b/data/language/nl-NL.txt @@ -3164,7 +3164,7 @@ STR_6041 :{BLACK}Er zijn geen monteurs ingehuurd! STR_6042 :Hoogtekaart laden STR_6043 :Hoogtekaart selecteren STR_6044 :Hoogtekaart verzachten -STR_6045 :SterkteL +STR_6045 :Sterkte: STR_6046 :Hoogtekaart normaliseren STR_6047 :Landschap verzachten STR_6048 :Fout bij het verwerken van hoogtekaart From 52b70703af3ff48355d55bae69f5a83d7064d966 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:30:27 +0200 Subject: [PATCH 11/97] Turn TrackElemType into a strong enum --- CMakeLists.txt | 4 +- openrct2.proj | 4 +- src/openrct2-ui/ride/Construction.cpp | 2 +- src/openrct2-ui/ride/Construction.h | 4 +- src/openrct2-ui/windows/NewRide.cpp | 2 +- src/openrct2-ui/windows/RideConstruction.cpp | 84 +- src/openrct2-ui/windows/TileInspector.cpp | 4 +- .../actions/RideSetColourSchemeAction.cpp | 2 +- .../actions/RideSetColourSchemeAction.h | 4 +- src/openrct2/actions/TrackPlaceAction.cpp | 10 +- src/openrct2/actions/TrackPlaceAction.h | 6 +- src/openrct2/actions/TrackRemoveAction.cpp | 12 +- src/openrct2/actions/TrackRemoveAction.h | 4 +- .../actions/TrackSetBrakeSpeedAction.cpp | 2 +- .../actions/TrackSetBrakeSpeedAction.h | 4 +- src/openrct2/actions/WallPlaceAction.cpp | 4 +- src/openrct2/actions/WallPlaceAction.h | 3 +- src/openrct2/core/DataSerialiserTraits.h | 2 +- src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/paint/support/MetalSupports.h | 2 - src/openrct2/paint/support/WoodenSupports.cpp | 8 +- src/openrct2/paint/support/WoodenSupports.h | 13 +- src/openrct2/paint/support/WoodenSupports.hpp | 4 +- .../coaster/AirPoweredVerticalCoaster.cpp | 5 +- .../paint/track/coaster/AlpineCoaster.cpp | 5 +- .../paint/track/coaster/BobsleighCoaster.cpp | 6 +- .../coaster/ClassicStandUpRollerCoaster.cpp | 6 +- .../coaster/ClassicWoodenRollerCoaster.cpp | 6 +- .../track/coaster/CompactInvertedCoaster.cpp | 5 +- .../track/coaster/CorkscrewRollerCoaster.cpp | 7 +- .../track/coaster/FlyingRollerCoaster.cpp | 5 +- .../coaster/FlyingRollerCoasterInverted.cpp | 7 +- .../track/coaster/HeartlineTwisterCoaster.cpp | 5 +- .../paint/track/coaster/HybridCoaster.cpp | 7 +- .../track/coaster/InvertedHairpinCoaster.cpp | 5 +- .../track/coaster/InvertedImpulseCoaster.cpp | 5 +- .../track/coaster/InvertedRollerCoaster.cpp | 5 +- .../track/coaster/JuniorRollerCoaster.cpp | 9 +- .../track/coaster/LatticeTriangleTrack.cpp | 5 +- .../coaster/LayDownRollerCoasterInverted.cpp | 5 +- .../coaster/LimLaunchedRollerCoaster.cpp | 5 +- .../track/coaster/LoopingRollerCoaster.cpp | 6 +- src/openrct2/paint/track/coaster/MineRide.cpp | 5 +- .../paint/track/coaster/MineTrainCoaster.cpp | 5 +- .../paint/track/coaster/MiniRollerCoaster.cpp | 5 +- .../track/coaster/MiniSuspendedCoaster.cpp | 5 +- .../coaster/MultiDimensionRollerCoaster.cpp | 5 +- .../track/coaster/ReverseFreefallCoaster.cpp | 5 +- .../track/coaster/ReverserRollerCoaster.cpp | 5 +- .../coaster/SideFrictionRollerCoaster.cpp | 5 +- .../track/coaster/SingleRailRollerCoaster.cpp | 5 +- .../track/coaster/StandUpRollerCoaster.cpp | 5 +- .../paint/track/coaster/Steeplechase.cpp | 5 +- .../coaster/SuspendedSwingingCoaster.cpp | 5 +- .../track/coaster/TwisterRollerCoaster.cpp | 5 +- .../paint/track/coaster/VirginiaReel.cpp | 7 +- .../paint/track/coaster/WildMouse.cpp | 7 +- .../track/coaster/WoodenRollerCoaster.cpp | 11 +- .../paint/track/coaster/WoodenRollerCoaster.h | 2 +- .../paint/track/coaster/WoodenWildMouse.cpp | 5 +- src/openrct2/paint/track/gentle/CarRide.cpp | 7 +- src/openrct2/paint/track/gentle/Circus.cpp | 2 +- .../paint/track/gentle/CrookedHouse.cpp | 2 +- src/openrct2/paint/track/gentle/Dodgems.cpp | 2 +- .../paint/track/gentle/FerrisWheel.cpp | 2 +- .../paint/track/gentle/FlyingSaucers.cpp | 2 +- .../paint/track/gentle/GhostTrain.cpp | 6 +- .../paint/track/gentle/HauntedHouse.cpp | 2 +- src/openrct2/paint/track/gentle/Maze.cpp | 2 +- .../paint/track/gentle/MerryGoRound.cpp | 2 +- src/openrct2/paint/track/gentle/MiniGolf.cpp | 6 +- .../paint/track/gentle/MiniHelicopters.cpp | 6 +- .../paint/track/gentle/MonorailCycles.cpp | 6 +- .../paint/track/gentle/ObservationTower.cpp | 6 +- .../paint/track/gentle/SpaceRings.cpp | 2 +- .../paint/track/gentle/SpiralSlide.cpp | 2 +- src/openrct2/paint/track/shops/Facility.cpp | 5 +- src/openrct2/paint/track/shops/Shop.cpp | 5 +- src/openrct2/paint/track/thrill/3dCinema.cpp | 2 +- .../paint/track/thrill/Enterprise.cpp | 2 +- src/openrct2/paint/track/thrill/GoKarts.cpp | 6 +- .../paint/track/thrill/LaunchedFreefall.cpp | 6 +- .../paint/track/thrill/MagicCarpet.cpp | 5 +- .../paint/track/thrill/MotionSimulator.cpp | 5 +- src/openrct2/paint/track/thrill/RotoDrop.cpp | 6 +- .../track/thrill/SwingingInverterShip.cpp | 2 +- .../paint/track/thrill/SwingingShip.cpp | 2 +- src/openrct2/paint/track/thrill/TopSpin.cpp | 2 +- src/openrct2/paint/track/thrill/Twist.cpp | 2 +- .../paint/track/transport/Chairlift.cpp | 10 +- src/openrct2/paint/track/transport/Lift.cpp | 6 +- .../track/transport/MiniatureRailway.cpp | 6 +- .../paint/track/transport/Monorail.cpp | 6 +- .../track/transport/SuspendedMonorail.cpp | 5 +- src/openrct2/paint/track/water/BoatHire.cpp | 6 +- .../paint/track/water/DinghySlide.cpp | 6 +- .../paint/track/water/DinghySlideCovered.cpp | 6 +- src/openrct2/paint/track/water/LogFlume.cpp | 6 +- .../paint/track/water/RiverRapids.cpp | 6 +- .../paint/track/water/SplashBoats.cpp | 6 +- .../paint/track/water/SubmarineRide.cpp | 6 +- src/openrct2/park/Legacy.cpp | 6 +- src/openrct2/park/Legacy.h | 14 +- src/openrct2/rct1/RCT1.h | 6 +- src/openrct2/rct1/S4Importer.cpp | 2 +- src/openrct2/rct1/Tables.cpp | 4 +- src/openrct2/rct12/RCT12.cpp | 78 +- src/openrct2/rct12/RCT12.h | 296 ++++++- src/openrct2/rct12/ScenarioPatcher.cpp | 2 +- src/openrct2/rct2/RCT2.cpp | 51 +- src/openrct2/rct2/RCT2.h | 28 +- src/openrct2/rct2/S6Importer.cpp | 29 +- src/openrct2/rct2/T6Exporter.cpp | 4 +- src/openrct2/rct2/T6Importer.cpp | 10 +- src/openrct2/ride/Ride.cpp | 10 +- src/openrct2/ride/RideConstruction.cpp | 16 +- src/openrct2/ride/RideConstruction.h | 8 +- src/openrct2/ride/RideData.h | 4 +- src/openrct2/ride/RideRatings.cpp | 6 +- src/openrct2/ride/RideRatings.h | 7 +- src/openrct2/ride/Track.cpp | 30 +- src/openrct2/ride/Track.h | 751 +++++++++--------- src/openrct2/ride/TrackData.cpp | 44 +- src/openrct2/ride/TrackData.h | 10 +- src/openrct2/ride/TrackDesign.h | 3 +- src/openrct2/ride/TrackPaint.h | 158 ++-- src/openrct2/ride/Vehicle.cpp | 44 +- src/openrct2/ride/Vehicle.h | 23 +- src/openrct2/ride/VehicleSubpositionData.h | 3 +- .../scripting/bindings/entity/ScVehicle.cpp | 4 +- .../scripting/bindings/game/ScContext.hpp | 10 +- .../bindings/ride/ScTrackIterator.cpp | 2 +- .../scripting/bindings/ride/ScTrackIterator.h | 4 +- .../bindings/ride/ScTrackSegment.cpp | 14 +- .../scripting/bindings/ride/ScTrackSegment.h | 4 +- .../bindings/world/ScTileElement.cpp | 4 +- src/openrct2/world/Map.cpp | 10 +- src/openrct2/world/Map.h | 10 +- src/openrct2/world/MapAnimation.cpp | 2 + src/openrct2/world/TileElement.h | 11 +- 140 files changed, 1353 insertions(+), 943 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9b98ca2e6..729764dfc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,9 +80,9 @@ set(OPENMSX_VERSION "1.6") set(OPENMSX_URL "https://github.com/OpenRCT2/OpenMusic/releases/download/v${OPENMSX_VERSION}/openmusic.zip") set(OPENMSX_SHA1 "ba170fa6d777b309c15420f4b6eb3fa25082a9d1") -set(REPLAYS_VERSION "0.0.80") +set(REPLAYS_VERSION "0.0.81") set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip") -set(REPLAYS_SHA1 "76C977E1B5CA5A87798E98D489247C766F129D89") +set(REPLAYS_SHA1 "F698526D1D2DABEF80F350A6363223D67DBC96B1") 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 243ad134a9..46c0fbb70d 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -51,8 +51,8 @@ b1b1f1b241d2cbff63a1889c4dc5a09bdf769bfb https://github.com/OpenRCT2/OpenMusic/releases/download/v1.6/openmusic.zip ba170fa6d777b309c15420f4b6eb3fa25082a9d1 - https://github.com/OpenRCT2/replays/releases/download/v0.0.80/replays.zip - 76C977E1B5CA5A87798E98D489247C766F129D89 + https://github.com/OpenRCT2/replays/releases/download/v0.0.81/replays.zip + F698526D1D2DABEF80F350A6363223D67DBC96B1 diff --git a/src/openrct2-ui/ride/Construction.cpp b/src/openrct2-ui/ride/Construction.cpp index 9362432430..3ce3ff129f 100644 --- a/src/openrct2-ui/ride/Construction.cpp +++ b/src/openrct2-ui/ride/Construction.cpp @@ -59,7 +59,7 @@ namespace OpenRCT2 && state != RideConstructionState::Back) return list; - for (track_type_t trackType : DropdownOrder) + for (OpenRCT2::TrackElemType trackType : DropdownOrder) { const auto& ted = GetTrackElementDescriptor(trackType); if (!IsTrackEnabled(ted.definition.group)) diff --git a/src/openrct2-ui/ride/Construction.h b/src/openrct2-ui/ride/Construction.h index 5c8b177cef..9ffdd9cdc7 100644 --- a/src/openrct2-ui/ride/Construction.h +++ b/src/openrct2-ui/ride/Construction.h @@ -142,7 +142,7 @@ namespace OpenRCT2 constexpr size_t DropdownLength = DropdownOrder.size(); // Update the magic number with the current number of track elements to silence - static_assert(TrackElemType::Count == 340, "Reminder to add new track element to special dropdown list"); + static_assert(EnumValue(TrackElemType::Count) == 340, "Reminder to add new track element to special dropdown list"); constexpr bool TrackPieceDirectionIsDiagonal(const uint8_t direction) { @@ -151,7 +151,7 @@ namespace OpenRCT2 struct SpecialElement { - track_type_t TrackType; + OpenRCT2::TrackElemType TrackType; bool Disabled; }; diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index ce7df6f400..5ef6e9acff 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -957,7 +957,7 @@ namespace OpenRCT2::Ui::Windows if (!(GetGameState().Park.Flags & PARK_FLAGS_NO_MONEY)) { // Get price of ride - int32_t startPieceId = GetRideTypeDescriptor(item.Type).StartTrackPiece; + auto startPieceId = GetRideTypeDescriptor(item.Type).StartTrackPiece; money64 price = GetRideTypeDescriptor(item.Type).BuildCosts.TrackPrice; const auto& ted = GetTrackElementDescriptor(startPieceId); price *= ted.priceModifier; diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index b7f53646b6..52a2159c26 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -63,12 +63,12 @@ namespace OpenRCT2::Ui::Windows static RideConstructionState _rideConstructionState2; static bool WindowRideConstructionUpdateState( - int32_t* trackType, int32_t* trackDirection, RideId* rideIndex, SelectedLiftAndInverted* _liftHillAndAlternativeState, - CoordsXYZ* trackPos, int32_t* properties); + OpenRCT2::TrackElemType* trackType, int32_t* trackDirection, RideId* rideIndex, + SelectedLiftAndInverted* _liftHillAndAlternativeState, CoordsXYZ* trackPos, int32_t* properties); money64 PlaceProvisionalTrackPiece( - RideId rideIndex, int32_t trackType, int32_t trackDirection, SelectedLiftAndInverted liftHillAndAlternativeState, - const CoordsXYZ& trackPos); - static std::pair WindowRideConstructionUpdateStateGetTrackElement(); + RideId rideIndex, OpenRCT2::TrackElemType trackType, int32_t trackDirection, + SelectedLiftAndInverted liftHillAndAlternativeState, const CoordsXYZ& trackPos); + static std::pair WindowRideConstructionUpdateStateGetTrackElement(); static constexpr StringId WINDOW_TITLE = STR_RIDE_CONSTRUCTION_WINDOW_TITLE; static constexpr int32_t WH = 394; @@ -199,7 +199,7 @@ namespace OpenRCT2::Ui::Windows STR_RIDE_CONSTRUCTION_SEAT_ROTATION_ANGLE_450, STR_RIDE_CONSTRUCTION_SEAT_ROTATION_ANGLE_495, }; - static void WindowRideConstructionMouseUpDemolishNextPiece(const CoordsXYZD& piecePos, int32_t type); + static void WindowRideConstructionMouseUpDemolishNextPiece(const CoordsXYZD& piecePos, OpenRCT2::TrackElemType type); static void WindowRideConstructionUpdateActiveElements(); /* move to ride.c */ @@ -947,6 +947,8 @@ namespace OpenRCT2::Ui::Windows case TrackElemType::Waterfall: WidgetInvalidate(*this, WIDX_CONSTRUCT); break; + default: + break; } } @@ -1453,7 +1455,7 @@ namespace OpenRCT2::Ui::Windows RideConstructionInvalidateCurrentTrack(); _currentTrackPrice = kMoney64Undefined; - track_type_t trackPiece = _specialElementDropdownState.Elements[selectedIndex].TrackType; + OpenRCT2::TrackElemType trackPiece = _specialElementDropdownState.Elements[selectedIndex].TrackType; switch (trackPiece) { case TrackElemType::EndStation: @@ -1469,6 +1471,8 @@ namespace OpenRCT2::Ui::Windows case TrackElemType::BlockBrakes: case TrackElemType::DiagBlockBrakes: _currentBrakeSpeed = kRCT2DefaultBlockBrakeSpeed; + default: + break; } _currentlySelectedTrack = trackPiece; WindowRideConstructionUpdateActiveElements(); @@ -1603,7 +1607,8 @@ namespace OpenRCT2::Ui::Windows return; RideId rideIndex; - int32_t trackType, trackDirection; + OpenRCT2::TrackElemType trackType; + int32_t trackDirection; SelectedLiftAndInverted liftHillAndInvertedState{}; if (WindowRideConstructionUpdateState( &trackType, &trackDirection, &rideIndex, &liftHillAndInvertedState, nullptr, nullptr)) @@ -2159,7 +2164,8 @@ namespace OpenRCT2::Ui::Windows void UpdateMapSelection() { - int32_t trackType, trackDirection; + OpenRCT2::TrackElemType trackType; + int32_t trackDirection; CoordsXYZ trackPos{}; MapInvalidateMapSelectionTiles(); @@ -2170,7 +2176,7 @@ namespace OpenRCT2::Ui::Windows { case RideConstructionState::State0: trackDirection = _currentTrackPieceDirection; - trackType = 0; + trackType = TrackElemType::Flat; trackPos = _currentTrackBegin; break; case RideConstructionState::Selected: @@ -2185,7 +2191,7 @@ namespace OpenRCT2::Ui::Windows if (WindowRideConstructionUpdateState(&trackType, &trackDirection, nullptr, nullptr, &trackPos, nullptr)) { trackDirection = _currentTrackPieceDirection; - trackType = 0; + trackType = OpenRCT2::TrackElemType::Flat; trackPos = _currentTrackBegin; } break; @@ -2198,7 +2204,7 @@ namespace OpenRCT2::Ui::Windows } } - void SelectMapTiles(int32_t trackType, int32_t trackDirection, const CoordsXY& tileCoords) + void SelectMapTiles(OpenRCT2::TrackElemType trackType, int32_t trackDirection, const CoordsXY& tileCoords) { // If the scenery tool is active, we do not display our tiles as it // will conflict with larger scenery objects selecting tiles @@ -2223,7 +2229,8 @@ namespace OpenRCT2::Ui::Windows void Construct() { RideId rideIndex; - int32_t trackType, trackDirection, properties; + OpenRCT2::TrackElemType trackType; + int32_t trackDirection, properties; SelectedLiftAndInverted liftHillAndAlternativeState{}; CoordsXYZ trackPos{}; @@ -2328,7 +2335,7 @@ namespace OpenRCT2::Ui::Windows direction = _currentTrackPieceDirection; // The direction is reset by ride_initialise_construction_window(), but we need it to remove flat rides properly. Direction currentDirection = _currentTrackPieceDirection; - track_type_t type = _currentTrackPieceType; + OpenRCT2::TrackElemType type = _currentTrackPieceType; auto newCoords = GetTrackElementOriginAndApplyChanges( { _currentTrackBegin, static_cast(direction & 3) }, type, 0, &tileElement, 0); if (!newCoords.has_value()) @@ -2509,7 +2516,7 @@ namespace OpenRCT2::Ui::Windows int32_t defaultIndex = -1; for (size_t i = 0; i < _specialElementDropdownState.Elements.size(); i++) { - track_type_t trackPiece = _specialElementDropdownState.Elements[i].TrackType; + OpenRCT2::TrackElemType trackPiece = _specialElementDropdownState.Elements[i].TrackType; const auto& ted = GetTrackElementDescriptor(trackPiece); StringId trackPieceStringId = ted.description; @@ -2596,7 +2603,7 @@ namespace OpenRCT2::Ui::Windows } void DrawTrackPiece( - DrawPixelInfo& dpi, RideId rideIndex, int32_t trackType, int32_t trackDirection, + DrawPixelInfo& dpi, RideId rideIndex, OpenRCT2::TrackElemType trackType, int32_t trackDirection, SelectedLiftAndInverted liftHillAndInvertedState, int32_t widgetWidth, int32_t widgetHeight) { auto currentRide = GetRide(rideIndex); @@ -2632,7 +2639,7 @@ namespace OpenRCT2::Ui::Windows } void DrawTrackPieceHelper( - DrawPixelInfo& dpi, RideId rideIndex, int32_t trackType, int32_t trackDirection, + DrawPixelInfo& dpi, RideId rideIndex, OpenRCT2::TrackElemType trackType, int32_t trackDirection, SelectedLiftAndInverted liftHillAndInvertedState, const CoordsXY& originCoords, int32_t originZ) { TileElement tempSideTrackTileElement{ 0x80, 0x8F, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -3105,7 +3112,8 @@ namespace OpenRCT2::Ui::Windows void UpdateGhostTrackAndArrow() { RideId rideIndex; - int32_t direction, type; + int32_t direction; + OpenRCT2::TrackElemType type; SelectedLiftAndInverted liftHillAndAlternativeState{}; CoordsXYZ trackPos{}; @@ -3262,7 +3270,8 @@ namespace OpenRCT2::Ui::Windows gMapSelectionTiles.push_back(*mapCoords); RideId rideIndex; - int32_t trackType, trackDirection; + OpenRCT2::TrackElemType trackType; + int32_t trackDirection; SelectedLiftAndInverted liftHillAndAlternativeState{}; if (WindowRideConstructionUpdateState( &trackType, &trackDirection, &rideIndex, &liftHillAndAlternativeState, nullptr, nullptr)) @@ -3503,7 +3512,8 @@ namespace OpenRCT2::Ui::Windows RideConstructionInvalidateCurrentTrack(); CoordsXYZ mapCoords{}; - int32_t trackType, z, highestZ; + OpenRCT2::TrackElemType trackType; + int32_t z, highestZ; if (WindowRideConstructionUpdateState(&trackType, nullptr, nullptr, nullptr, nullptr, nullptr)) return; @@ -4581,7 +4591,7 @@ namespace OpenRCT2::Ui::Windows w->OnMouseDown(WIDX_DEMOLISH); } - static void WindowRideConstructionMouseUpDemolishNextPiece(const CoordsXYZD& piecePos, int32_t type) + static void WindowRideConstructionMouseUpDemolishNextPiece(const CoordsXYZD& piecePos, OpenRCT2::TrackElemType type) { if (_gotoStartPlacementMode) { @@ -4665,8 +4675,8 @@ namespace OpenRCT2::Ui::Windows * rct2: 0x006CA162 */ money64 PlaceProvisionalTrackPiece( - RideId rideIndex, int32_t trackType, int32_t trackDirection, SelectedLiftAndInverted liftHillAndAlternativeState, - const CoordsXYZ& trackPos) + RideId rideIndex, OpenRCT2::TrackElemType trackType, int32_t trackDirection, + SelectedLiftAndInverted liftHillAndAlternativeState, const CoordsXYZ& trackPos) { auto ride = GetRide(rideIndex); if (ride == nullptr) @@ -4737,7 +4747,7 @@ namespace OpenRCT2::Ui::Windows return res.Cost; } - static std::pair WindowRideConstructionUpdateStateGetTrackElement() + static std::pair WindowRideConstructionUpdateStateGetTrackElement() { auto startSlope = _previousTrackPitchEnd; auto endSlope = _currentTrackPitchEnd; @@ -4755,7 +4765,7 @@ namespace OpenRCT2::Ui::Windows auto selectedTrack = _currentlySelectedTrack; if (selectedTrack == TrackElemType::None) { - return std::make_pair(false, 0); + return std::make_pair(false, OpenRCT2::TrackElemType::Flat); } bool startsDiagonal = (_currentTrackPieceDirection & (1 << 2)) != 0; @@ -4774,7 +4784,7 @@ namespace OpenRCT2::Ui::Windows if (trackPiece != TrackElemType::None) return std::make_pair(true, trackPiece); else - return std::make_pair(false, 0); + return std::make_pair(false, OpenRCT2::TrackElemType::Flat); } auto asTrackType = selectedTrack.trackType; @@ -4785,12 +4795,12 @@ namespace OpenRCT2::Ui::Windows case TrackElemType::SBendRight: if (startSlope != TrackPitch::None || endSlope != TrackPitch::None) { - return std::make_pair(false, 0); + return std::make_pair(false, OpenRCT2::TrackElemType::Flat); } if (startBank != TrackRoll::None || endBank != TrackRoll::None) { - return std::make_pair(false, 0); + return std::make_pair(false, OpenRCT2::TrackElemType::Flat); } return std::make_pair(true, asTrackType); @@ -4799,21 +4809,21 @@ namespace OpenRCT2::Ui::Windows case TrackElemType::RightVerticalLoop: if (startBank != TrackRoll::None || endBank != TrackRoll::None) { - return std::make_pair(false, 0); + return std::make_pair(false, OpenRCT2::TrackElemType::Flat); } if (_rideConstructionState == RideConstructionState::Back) { if (endSlope != TrackPitch::Down25) { - return std::make_pair(false, 0); + return std::make_pair(false, OpenRCT2::TrackElemType::Flat); } } else { if (startSlope != TrackPitch::Up25) { - return std::make_pair(false, 0); + return std::make_pair(false, OpenRCT2::TrackElemType::Flat); } } @@ -4838,8 +4848,8 @@ namespace OpenRCT2::Ui::Windows * @return (CF) */ static bool WindowRideConstructionUpdateState( - int32_t* _trackType, int32_t* _trackDirection, RideId* _rideIndex, SelectedLiftAndInverted* _liftHillAndInvertedState, - CoordsXYZ* _trackPos, int32_t* _properties) + OpenRCT2::TrackElemType* _trackType, int32_t* _trackDirection, RideId* _rideIndex, + SelectedLiftAndInverted* _liftHillAndInvertedState, CoordsXYZ* _trackPos, int32_t* _properties) { RideId rideIndex; uint8_t trackDirection; @@ -4854,7 +4864,7 @@ namespace OpenRCT2::Ui::Windows return true; } - track_type_t trackType = std::get<1>(updated_element); + OpenRCT2::TrackElemType trackType = std::get<1>(updated_element); rideIndex = _currentRideIndex; if (_currentTrackHasLiftHill) { @@ -4895,6 +4905,9 @@ namespace OpenRCT2::Ui::Windows case TrackElemType::DiagFlatToDown60: case TrackElemType::DiagDown60ToFlat: return true; + + default: + break; } } @@ -5001,7 +5014,8 @@ namespace OpenRCT2::Ui::Windows if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_TRACK) { RideId rideIndex; - int32_t direction, type; + int32_t direction; + OpenRCT2::TrackElemType type; SelectedLiftAndInverted liftHillAndAlternativeState{}; CoordsXYZ trackPos; if (WindowRideConstructionUpdateState( diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index 6e0585eaf2..3c09fe15c9 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -1248,12 +1248,12 @@ static uint64_t PageDisabledWidgets[] = { // Track ft = Formatter(); - ft.Add(trackElement->GetTrackType()); + ft.Add(trackElement->GetTrackType()); DrawTextBasic( dpi, screenCoords + ScreenCoordsXY{ 0, 33 }, STR_TILE_INSPECTOR_TRACK_PIECE_ID, ft, { colours[1] }); ft = Formatter(); - ft.Add(trackElement->GetSequenceIndex()); + ft.Add(trackElement->GetSequenceIndex()); DrawTextBasic( dpi, screenCoords + ScreenCoordsXY{ 0, 44 }, STR_TILE_INSPECTOR_TRACK_SEQUENCE, ft, { colours[1] }); if (trackElement->IsStation()) diff --git a/src/openrct2/actions/RideSetColourSchemeAction.cpp b/src/openrct2/actions/RideSetColourSchemeAction.cpp index 7ed4050284..561b3ff833 100644 --- a/src/openrct2/actions/RideSetColourSchemeAction.cpp +++ b/src/openrct2/actions/RideSetColourSchemeAction.cpp @@ -21,7 +21,7 @@ using namespace OpenRCT2; RideSetColourSchemeAction::RideSetColourSchemeAction( - const CoordsXYZD& location, track_type_t trackType, uint16_t newColourScheme) + const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, uint16_t newColourScheme) : _loc(location) , _trackType(trackType) , _newColourScheme(newColourScheme) diff --git a/src/openrct2/actions/RideSetColourSchemeAction.h b/src/openrct2/actions/RideSetColourSchemeAction.h index 6fab260008..5d75dd964c 100644 --- a/src/openrct2/actions/RideSetColourSchemeAction.h +++ b/src/openrct2/actions/RideSetColourSchemeAction.h @@ -15,12 +15,12 @@ class RideSetColourSchemeAction final : public GameActionBaseSetBrakeClosed(true); break; + default: + break; } if (TrackTypeHasSpeedSetting(_trackType)) { @@ -716,6 +718,8 @@ GameActions::Result TrackPlaceAction::Execute() const GameActions::ExecuteNested(&rideSetSetting); break; } + default: + break; } switch (_trackType) @@ -730,6 +734,8 @@ GameActions::Result TrackPlaceAction::Execute() const case TrackElemType::CableLiftHill: ride->num_block_brakes++; break; + default: + break; } } diff --git a/src/openrct2/actions/TrackPlaceAction.h b/src/openrct2/actions/TrackPlaceAction.h index c38d7589ed..e7ca90b3c7 100644 --- a/src/openrct2/actions/TrackPlaceAction.h +++ b/src/openrct2/actions/TrackPlaceAction.h @@ -23,7 +23,7 @@ class TrackPlaceAction final : public GameActionBase { private: RideId _rideIndex{ RideId::GetNull() }; - int32_t _trackType{}; + OpenRCT2::TrackElemType _trackType{}; ride_type_t _rideType{}; CoordsXYZD _origin; int32_t _brakeSpeed{}; @@ -35,8 +35,8 @@ private: public: TrackPlaceAction() = default; TrackPlaceAction( - RideId rideIndex, int32_t trackType, ride_type_t rideType, const CoordsXYZD& origin, int32_t brakeSpeed, int32_t colour, - int32_t seatRotation, SelectedLiftAndInverted liftHillAndAlternativeState, bool fromTrackDesign); + RideId rideIndex, OpenRCT2::TrackElemType trackType, ride_type_t rideType, const CoordsXYZD& origin, int32_t brakeSpeed, + int32_t colour, int32_t seatRotation, SelectedLiftAndInverted liftHillAndAlternativeState, bool fromTrackDesign); void AcceptParameters(GameActionParameterVisitor& visitor) override; diff --git a/src/openrct2/actions/TrackRemoveAction.cpp b/src/openrct2/actions/TrackRemoveAction.cpp index 59eb0020d6..65ee27bf43 100644 --- a/src/openrct2/actions/TrackRemoveAction.cpp +++ b/src/openrct2/actions/TrackRemoveAction.cpp @@ -24,7 +24,7 @@ using namespace OpenRCT2; using namespace OpenRCT2::TrackMetaData; -TrackRemoveAction::TrackRemoveAction(track_type_t trackType, int32_t sequence, const CoordsXYZD& origin) +TrackRemoveAction::TrackRemoveAction(OpenRCT2::TrackElemType trackType, int32_t sequence, const CoordsXYZD& origin) : _trackType(trackType) , _sequence(sequence) , _origin(origin) @@ -44,16 +44,16 @@ uint16_t TrackRemoveAction::GetActionFlags() const return GameAction::GetActionFlags(); } -static int32_t normaliseTrackType(int32_t trackType) +static OpenRCT2::TrackElemType normaliseTrackType(OpenRCT2::TrackElemType trackType) { switch (trackType) { case TrackElemType::BeginStation: case TrackElemType::MiddleStation: return TrackElemType::EndStation; + default: + return trackType; } - - return trackType; } void TrackRemoveAction::Serialise(DataSerialiser& stream) @@ -477,6 +477,8 @@ GameActions::Result TrackRemoveAction::Execute() const GameActions::ExecuteNested(&rideSetSetting); } + break; + default: break; } @@ -492,6 +494,8 @@ GameActions::Result TrackRemoveAction::Execute() const case TrackElemType::CableLiftHill: ride->num_block_brakes--; break; + default: + break; } } diff --git a/src/openrct2/actions/TrackRemoveAction.h b/src/openrct2/actions/TrackRemoveAction.h index 8caafaa85a..ed02a76fa6 100644 --- a/src/openrct2/actions/TrackRemoveAction.h +++ b/src/openrct2/actions/TrackRemoveAction.h @@ -14,13 +14,13 @@ class TrackRemoveAction final : public GameActionBase { private: - track_type_t _trackType{}; + OpenRCT2::TrackElemType _trackType{}; int32_t _sequence{}; CoordsXYZD _origin; public: TrackRemoveAction() = default; - TrackRemoveAction(track_type_t trackType, int32_t sequence, const CoordsXYZD& origin); + TrackRemoveAction(OpenRCT2::TrackElemType trackType, int32_t sequence, const CoordsXYZD& origin); void AcceptParameters(GameActionParameterVisitor& visitor) override; diff --git a/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp b/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp index 4e4711343b..46eca92412 100644 --- a/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp +++ b/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp @@ -14,7 +14,7 @@ using namespace OpenRCT2; -TrackSetBrakeSpeedAction::TrackSetBrakeSpeedAction(const CoordsXYZ& loc, track_type_t trackType, uint8_t brakeSpeed) +TrackSetBrakeSpeedAction::TrackSetBrakeSpeedAction(const CoordsXYZ& loc, OpenRCT2::TrackElemType trackType, uint8_t brakeSpeed) : _loc(loc) , _trackType(trackType) , _brakeSpeed(brakeSpeed) diff --git a/src/openrct2/actions/TrackSetBrakeSpeedAction.h b/src/openrct2/actions/TrackSetBrakeSpeedAction.h index ead200491e..b1eea86c86 100644 --- a/src/openrct2/actions/TrackSetBrakeSpeedAction.h +++ b/src/openrct2/actions/TrackSetBrakeSpeedAction.h @@ -15,12 +15,12 @@ class TrackSetBrakeSpeedAction final : public GameActionBaseGetTrackType(); + OpenRCT2::TrackElemType trackType = trackElement->GetTrackType(); using namespace OpenRCT2::TrackMetaData; const auto& ted = GetTrackElementDescriptor(trackType); @@ -599,7 +599,7 @@ GameActions::Result WallPlaceAction::WallCheckObstruction( } bool WallPlaceAction::TrackIsAllowedWallEdges( - ride_type_t rideType, track_type_t trackType, uint8_t trackSequence, uint8_t direction) + ride_type_t rideType, OpenRCT2::TrackElemType trackType, uint8_t trackSequence, uint8_t direction) { if (!GetRideTypeDescriptor(rideType).HasFlag(RtdFlag::noWallsAroundTrack)) { diff --git a/src/openrct2/actions/WallPlaceAction.h b/src/openrct2/actions/WallPlaceAction.h index d2ee3d3732..c511e9b307 100644 --- a/src/openrct2/actions/WallPlaceAction.h +++ b/src/openrct2/actions/WallPlaceAction.h @@ -63,5 +63,6 @@ private: * Gets whether the given track type can have a wall placed on the edge of the given direction. * Some thin tracks for example are allowed to have walls either side of the track, but wider tracks can not. */ - static bool TrackIsAllowedWallEdges(ride_type_t rideType, track_type_t trackType, uint8_t trackSequence, uint8_t direction); + static bool TrackIsAllowedWallEdges( + ride_type_t rideType, OpenRCT2::TrackElemType trackType, uint8_t trackSequence, uint8_t direction); }; diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index 5ce8ff20ec..05531e8ce8 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -692,7 +692,7 @@ template<> struct DataSerializerTraitsT static void log(OpenRCT2::IStream* stream, const TrackDesignTrackElement& val) { char msg[128] = {}; - snprintf(msg, sizeof(msg), "TrackDesignTrackElement(type = %d, flags = %d)", val.type, val.flags); + snprintf(msg, sizeof(msg), "TrackDesignTrackElement(type = %d, flags = %d)", EnumValue(val.type), val.flags); stream->Write(msg, strlen(msg)); } }; diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index df0322abc1..8cc33fafcb 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -49,7 +49,7 @@ using namespace OpenRCT2; // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -constexpr uint8_t kNetworkStreamVersion = 5; +constexpr uint8_t kNetworkStreamVersion = 6; const std::string kNetworkStreamID = std::string(OPENRCT2_VERSION) + "-" + std::to_string(kNetworkStreamVersion); diff --git a/src/openrct2/paint/support/MetalSupports.h b/src/openrct2/paint/support/MetalSupports.h index 19e79a627b..00b0268268 100644 --- a/src/openrct2/paint/support/MetalSupports.h +++ b/src/openrct2/paint/support/MetalSupports.h @@ -14,8 +14,6 @@ #include -using track_type_t = uint16_t; - enum class MetalSupportType { /** diff --git a/src/openrct2/paint/support/WoodenSupports.cpp b/src/openrct2/paint/support/WoodenSupports.cpp index 28260daa82..eaec306c5b 100644 --- a/src/openrct2/paint/support/WoodenSupports.cpp +++ b/src/openrct2/paint/support/WoodenSupports.cpp @@ -641,8 +641,8 @@ bool PathBoxSupportsPaintSetup( } bool DrawSupportForSequenceA( - PaintSession& session, WoodenSupportType supportType, track_type_t trackType, uint8_t sequence, Direction direction, - int32_t height, ImageId imageTemplate) + PaintSession& session, WoodenSupportType supportType, OpenRCT2::TrackElemType trackType, uint8_t sequence, + Direction direction, int32_t height, ImageId imageTemplate) { const auto& ted = OpenRCT2::TrackMetaData::GetTrackElementDescriptor(trackType); const auto& desc = ted.sequences[sequence].woodenSupports; @@ -655,8 +655,8 @@ bool DrawSupportForSequenceA( } bool DrawSupportForSequenceB( - PaintSession& session, WoodenSupportType supportType, track_type_t trackType, uint8_t sequence, Direction direction, - int32_t height, ImageId imageTemplate) + PaintSession& session, WoodenSupportType supportType, OpenRCT2::TrackElemType trackType, uint8_t sequence, + Direction direction, int32_t height, ImageId imageTemplate) { const auto& ted = OpenRCT2::TrackMetaData::GetTrackElementDescriptor(trackType); const auto& desc = ted.sequences[sequence].woodenSupports; diff --git a/src/openrct2/paint/support/WoodenSupports.h b/src/openrct2/paint/support/WoodenSupports.h index 3be24ba434..953672bc21 100644 --- a/src/openrct2/paint/support/WoodenSupports.h +++ b/src/openrct2/paint/support/WoodenSupports.h @@ -14,7 +14,10 @@ #include -using track_type_t = uint16_t; +namespace OpenRCT2 +{ + enum class TrackElemType : uint16_t; +} enum class WoodenSupportType : uint8_t { @@ -100,8 +103,8 @@ bool PathBoxSupportsPaintSetup( PaintSession& session, WoodenSupportSubType supportType, bool isSloped, Direction slopeRotation, int32_t height, ImageId imageTemplate, const FootpathPaintInfo& pathPaintInfo); bool DrawSupportForSequenceA( - PaintSession& session, WoodenSupportType supportType, track_type_t trackType, uint8_t sequence, Direction direction, - int32_t height, ImageId imageTemplate); + PaintSession& session, WoodenSupportType supportType, OpenRCT2::TrackElemType trackType, uint8_t sequence, + Direction direction, int32_t height, ImageId imageTemplate); bool DrawSupportForSequenceB( - PaintSession& session, WoodenSupportType supportType, track_type_t trackType, uint8_t sequence, Direction direction, - int32_t height, ImageId imageTemplate); + PaintSession& session, WoodenSupportType supportType, OpenRCT2::TrackElemType trackType, uint8_t sequence, + Direction direction, int32_t height, ImageId imageTemplate); diff --git a/src/openrct2/paint/support/WoodenSupports.hpp b/src/openrct2/paint/support/WoodenSupports.hpp index 806cdfeed5..58823aef69 100644 --- a/src/openrct2/paint/support/WoodenSupports.hpp +++ b/src/openrct2/paint/support/WoodenSupports.hpp @@ -11,7 +11,7 @@ #include "../../ride/TrackData.h" -template +template bool DrawSupportForSequenceA( PaintSession& session, WoodenSupportType supportType, uint8_t sequence, Direction direction, int32_t height, ImageId imageTemplate) @@ -26,7 +26,7 @@ bool DrawSupportForSequenceA( session, supportType, desc.subType, direction, height, imageTemplate, desc.transitionType); } -template +template bool DrawSupportForSequenceB( PaintSession& session, WoodenSupportType supportType, uint8_t sequence, Direction direction, int32_t height, ImageId imageTemplate) diff --git a/src/openrct2/paint/track/coaster/AirPoweredVerticalCoaster.cpp b/src/openrct2/paint/track/coaster/AirPoweredVerticalCoaster.cpp index 125845219e..b218474a0c 100644 --- a/src/openrct2/paint/track/coaster/AirPoweredVerticalCoaster.cpp +++ b/src/openrct2/paint/track/coaster/AirPoweredVerticalCoaster.cpp @@ -1015,7 +1015,7 @@ static void AirPoweredVerticalRCTrackOnridePhoto( TrackPaintUtilOnridePhotoPaint2(session, direction, trackElement, height); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionAirPoweredVerticalRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionAirPoweredVerticalRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1061,6 +1061,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionAirPoweredVerticalRC(int32_t trackType return AirPoweredVerticalRCTrackBooster; case TrackElemType::OnRidePhoto: return AirPoweredVerticalRCTrackOnridePhoto; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/AlpineCoaster.cpp b/src/openrct2/paint/track/coaster/AlpineCoaster.cpp index 050a1fdff8..e2e21cae21 100644 --- a/src/openrct2/paint/track/coaster/AlpineCoaster.cpp +++ b/src/openrct2/paint/track/coaster/AlpineCoaster.cpp @@ -7176,7 +7176,7 @@ namespace OpenRCT2::AlpineRC } } - TRACK_PAINT_FUNCTION GetTrackPaintFunction(int32_t trackType) + TRACK_PAINT_FUNCTION GetTrackPaintFunction(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -7346,8 +7346,9 @@ namespace OpenRCT2::AlpineRC return TrackLeftQuarterTurn3Tile25DegDownToLeftBank; case TrackElemType::RightQuarterTurn3TilesDown25ToRightBank: return TrackRightQuarterTurn3Tile25DegDownToRightBank; + default: + return nullptr; } - return nullptr; } } // namespace OpenRCT2::AlpineRC diff --git a/src/openrct2/paint/track/coaster/BobsleighCoaster.cpp b/src/openrct2/paint/track/coaster/BobsleighCoaster.cpp index 4d3340eb95..dae12fe76d 100644 --- a/src/openrct2/paint/track/coaster/BobsleighCoaster.cpp +++ b/src/openrct2/paint/track/coaster/BobsleighCoaster.cpp @@ -4120,7 +4120,7 @@ static void BobsleighRCTrackOnRidePhoto( TrackPaintUtilOnridePhotoPaint2(session, direction, trackElement, height); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionBobsleighRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionBobsleighRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -4213,6 +4213,8 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionBobsleighRC(int32_t trackType) case TrackElemType::OnRidePhoto: return BobsleighRCTrackOnRidePhoto; + + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp b/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp index 33b36ee5f6..61c6c39f26 100644 --- a/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp @@ -1386,7 +1386,7 @@ static void classicStandUpRCTrackDiagRightBankTo25DegDown( classicStandUpRCTrackDiag25DegUpToLeftBank(session, ride, trackSequence, direction, height, trackElement, supportType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicStandUpRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicStandUpRC(OpenRCT2::TrackElemType trackType) { if (!IsCsgLoaded()) { @@ -1469,7 +1469,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicStandUpRC(int32_t trackType) return classicStandUpRCTrackDiagLeftBank; case TrackElemType::DiagRightBank: return classicStandUpRCTrackDiagRightBank; + default: + return GetTrackPaintFunctionStandUpRC(trackType); } - - return GetTrackPaintFunctionStandUpRC(trackType); } diff --git a/src/openrct2/paint/track/coaster/ClassicWoodenRollerCoaster.cpp b/src/openrct2/paint/track/coaster/ClassicWoodenRollerCoaster.cpp index 345d70f3d1..87e1c72ce4 100644 --- a/src/openrct2/paint/track/coaster/ClassicWoodenRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ClassicWoodenRollerCoaster.cpp @@ -2142,7 +2142,7 @@ static void ClassicWoodenRCTrackDiag25DegDownToRightBank( // Stylistically, this coaster is _very_ similar to the regular Wooden Roller Coaster. // The only difference is to which parts the colours are applied, and the degree of the banking. // As such, all non-banked pieces are simply drawn as regular wooden roller coaster pieces with a different paint scheme. -TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRC(OpenRCT2::TrackElemType trackType) { if (!IsCsgLoaded()) { @@ -2223,7 +2223,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRC(int32_t trackType) return ClassicWoodenRCTrackDiagLeftBank; case TrackElemType::DiagRightBank: return ClassicWoodenRCTrackDiagRightBank; + default: + return GetTrackPaintFunctionClassicWoodenRCFallback(trackType); } - - return GetTrackPaintFunctionClassicWoodenRCFallback(trackType); } diff --git a/src/openrct2/paint/track/coaster/CompactInvertedCoaster.cpp b/src/openrct2/paint/track/coaster/CompactInvertedCoaster.cpp index 76a3d3cd8a..4d128d5843 100644 --- a/src/openrct2/paint/track/coaster/CompactInvertedCoaster.cpp +++ b/src/openrct2/paint/track/coaster/CompactInvertedCoaster.cpp @@ -9799,7 +9799,7 @@ static void CompactInvertedRCTrackBlockBrakes( PaintUtilSetGeneralSupportHeight(session, height + 48); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCompactInvertedRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCompactInvertedRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -10029,6 +10029,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionCompactInvertedRC(int32_t trackType) return CompactInvertedRCTrackDiagBrakes; case TrackElemType::DiagBlockBrakes: return CompactInvertedRCTrackDiagBlockBrakes; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp b/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp index 00a9383054..d358931e57 100644 --- a/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp @@ -11045,7 +11045,7 @@ static void LayDownRCTrackHalfLoopUninvertedDown( return; } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -11283,7 +11283,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(int32_t trackType) case TrackElemType::RightTwistUpToDown: return CorkscrewRCTrackRightTwistUpToDown; - // From Lay-down + // From Lay-down case TrackElemType::LeftFlyerTwistUp: return LayDownRCTrackLeftFlyerTwistUp; case TrackElemType::RightFlyerTwistUp: @@ -11296,6 +11296,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(int32_t trackType) return LayDownRCTrackRightFlyerCorkscrewUp; case TrackElemType::FlyerHalfLoopUninvertedDown: return LayDownRCTrackHalfLoopUninvertedDown; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/FlyingRollerCoaster.cpp b/src/openrct2/paint/track/coaster/FlyingRollerCoaster.cpp index 1cd57c1ca7..5298d82e31 100644 --- a/src/openrct2/paint/track/coaster/FlyingRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/FlyingRollerCoaster.cpp @@ -855,7 +855,7 @@ static void FlyingRCTrackRightFlyingLargeHalfLoopUninvertedDown( session, ride, 6 - trackSequence, direction, height, trackElement, supportType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -889,6 +889,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRC(int32_t trackType) return FlyingRCTrackLeftFlyingLargeHalfLoopUninvertedDown; case TrackElemType::RightFlyerLargeHalfLoopUninvertedDown: return FlyingRCTrackRightFlyingLargeHalfLoopUninvertedDown; + default: + return GetTrackPaintFunctionTwisterRC(trackType); } - return GetTrackPaintFunctionTwisterRC(trackType); } diff --git a/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp b/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp index 1d5a48de74..2bc4fb98f5 100644 --- a/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp +++ b/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp @@ -9097,7 +9097,7 @@ static void FlyingRCTrackFlyerHalfLoopDown( } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRCInverted(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRCInverted(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -9377,7 +9377,8 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRCInverted(int32_t trackType) return InvertedFlyingRCTrackDiagBrakes; case TrackElemType::DiagBlockBrakes: return InvertedFlyingRCTrackDiagBlockBrakes; - } - return GetTrackPaintFunctionFlyingRC(trackType); + default: + return GetTrackPaintFunctionFlyingRC(trackType); + } } diff --git a/src/openrct2/paint/track/coaster/HeartlineTwisterCoaster.cpp b/src/openrct2/paint/track/coaster/HeartlineTwisterCoaster.cpp index 1d701eb290..99f104b6c1 100644 --- a/src/openrct2/paint/track/coaster/HeartlineTwisterCoaster.cpp +++ b/src/openrct2/paint/track/coaster/HeartlineTwisterCoaster.cpp @@ -1672,7 +1672,7 @@ static void HeartlineTwisterRCTrackRightHeartlineRoll( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionHeartlineTwisterRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionHeartlineTwisterRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1714,6 +1714,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionHeartlineTwisterRC(int32_t trackType) return HeartlineTwisterRCTrackLeftHeartlineRoll; case TrackElemType::RightHeartLineRoll: return HeartlineTwisterRCTrackRightHeartlineRoll; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/HybridCoaster.cpp b/src/openrct2/paint/track/coaster/HybridCoaster.cpp index f5f734ebdf..66d3249e5e 100644 --- a/src/openrct2/paint/track/coaster/HybridCoaster.cpp +++ b/src/openrct2/paint/track/coaster/HybridCoaster.cpp @@ -14364,7 +14364,7 @@ namespace OpenRCT2::HybridRC PaintUtilSetGeneralSupportHeight(session, height + 56); } - TRACK_PAINT_FUNCTION GetTrackPaintFunction(int32_t trackType) + TRACK_PAINT_FUNCTION GetTrackPaintFunction(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -14796,10 +14796,11 @@ namespace OpenRCT2::HybridRC return TrackpoweredLift; case TrackElemType::Booster: return Trackbooster; - case TrackElemType::Down25Brakes: return Track25DegDownBrakes; + + default: + return nullptr; } - return nullptr; } } // namespace OpenRCT2::HybridRC diff --git a/src/openrct2/paint/track/coaster/InvertedHairpinCoaster.cpp b/src/openrct2/paint/track/coaster/InvertedHairpinCoaster.cpp index c534502f31..9598850d12 100644 --- a/src/openrct2/paint/track/coaster/InvertedHairpinCoaster.cpp +++ b/src/openrct2/paint/track/coaster/InvertedHairpinCoaster.cpp @@ -1386,7 +1386,7 @@ static void InvertedHairpinRCTrackBlockBrakes( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedHairpinRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedHairpinRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1448,6 +1448,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedHairpinRC(int32_t trackType) return InvertedHairpinRCTrackBrakes; case TrackElemType::BlockBrakes: return InvertedHairpinRCTrackBlockBrakes; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/InvertedImpulseCoaster.cpp b/src/openrct2/paint/track/coaster/InvertedImpulseCoaster.cpp index 2d77c9682d..3a1647fa0f 100644 --- a/src/openrct2/paint/track/coaster/InvertedImpulseCoaster.cpp +++ b/src/openrct2/paint/track/coaster/InvertedImpulseCoaster.cpp @@ -758,7 +758,7 @@ static void InvertedImpulseRCTrackRightQuarterTurn190DegDown( session, ride, trackSequence, (direction - 1) & 3, height, trackElement, supportType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedImpulseRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedImpulseRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -812,6 +812,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedImpulseRC(int32_t trackType) return InvertedImpulseRCTrackLeftQuarterTurn190DegDown; case TrackElemType::RightQuarterTurn1TileDown90: return InvertedImpulseRCTrackRightQuarterTurn190DegDown; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/InvertedRollerCoaster.cpp b/src/openrct2/paint/track/coaster/InvertedRollerCoaster.cpp index ee71fe619c..b9fdbc695b 100644 --- a/src/openrct2/paint/track/coaster/InvertedRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/InvertedRollerCoaster.cpp @@ -11524,7 +11524,7 @@ static void InvertedRCTrackBooster( PaintUtilSetGeneralSupportHeight(session, height + 48); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -11825,6 +11825,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedRC(int32_t trackType) case TrackElemType::Booster: return InvertedRCTrackBooster; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp b/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp index d9dc4a1865..6b0003f652 100644 --- a/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp @@ -5798,7 +5798,7 @@ static void JuniorRCTrackOnRidePhoto( } /* 0x008AAA0C */ -template TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRCTemplate(int32_t trackType) +template TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRCTemplate(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -6022,16 +6022,17 @@ template TRACK_PAINT_FUNCTION GetTrackPaintFunctionJun case TrackElemType::OnRidePhoto: return JuniorRCTrackOnRidePhoto; + default: + return nullptr; } - return nullptr; } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRC(OpenRCT2::TrackElemType trackType) { return GetTrackPaintFunctionJuniorRCTemplate(trackType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionWaterRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWaterRC(OpenRCT2::TrackElemType trackType) { return GetTrackPaintFunctionJuniorRCTemplate(trackType); } diff --git a/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp b/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp index fbebbcf7ce..e394c064d2 100644 --- a/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp +++ b/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp @@ -18420,7 +18420,7 @@ static void LatticeTriangleTrackDiagBrakes( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLatticeTriangleTrack(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLatticeTriangleTrack(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -18909,6 +18909,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLatticeTriangleTrack(int32_t trackType case TrackElemType::DiagBlockBrakes: case TrackElemType::DiagBrakes: return LatticeTriangleTrackDiagBrakes; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/LayDownRollerCoasterInverted.cpp b/src/openrct2/paint/track/coaster/LayDownRollerCoasterInverted.cpp index 98cb6d1165..b904d0919c 100644 --- a/src/openrct2/paint/track/coaster/LayDownRollerCoasterInverted.cpp +++ b/src/openrct2/paint/track/coaster/LayDownRollerCoasterInverted.cpp @@ -8343,7 +8343,7 @@ static void LayDownRCTrackHalfLoopInvertedUp( } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLayDownRCInverted(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLayDownRCInverted(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -8550,6 +8550,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLayDownRCInverted(int32_t trackType) return LayDownRCTrackRightQuarterBankedHelixLargeDown; case TrackElemType::FlyerHalfLoopInvertedUp: return LayDownRCTrackHalfLoopInvertedUp; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp b/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp index d63010d724..392c7baf45 100644 --- a/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp @@ -5751,7 +5751,7 @@ static void LimLaunchedRCTrackBooster( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLimLaunchedRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLimLaunchedRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -6024,6 +6024,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLimLaunchedRC(int32_t trackType) return LimLaunchedRCTrackRightLargeZeroGRollDown; case TrackElemType::Booster: return LimLaunchedRCTrackBooster; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/LoopingRollerCoaster.cpp b/src/openrct2/paint/track/coaster/LoopingRollerCoaster.cpp index 10b4e18fc0..f827635a65 100644 --- a/src/openrct2/paint/track/coaster/LoopingRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/LoopingRollerCoaster.cpp @@ -10550,7 +10550,7 @@ static void LoopingRCTrackBooster( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLoopingRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLoopingRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -10831,6 +10831,8 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLoopingRC(int32_t trackType) case TrackElemType::DiagBrakes: case TrackElemType::DiagBlockBrakes: return LoopingRCTrackDiagBrakes; + + default: + return GetTrackPaintFunctionLimLaunchedRC(trackType); } - return GetTrackPaintFunctionLimLaunchedRC(trackType); } diff --git a/src/openrct2/paint/track/coaster/MineRide.cpp b/src/openrct2/paint/track/coaster/MineRide.cpp index 32887b4873..c99a7bc413 100644 --- a/src/openrct2/paint/track/coaster/MineRide.cpp +++ b/src/openrct2/paint/track/coaster/MineRide.cpp @@ -5589,7 +5589,7 @@ static void MineRideTrackDiagRightBank( } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineRide(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineRide(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -5735,6 +5735,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineRide(int32_t trackType) return MineRideTrackDiagLeftBank; case TrackElemType::DiagRightBank: return MineRideTrackDiagRightBank; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/MineTrainCoaster.cpp b/src/openrct2/paint/track/coaster/MineTrainCoaster.cpp index 5580609057..f3c82cadae 100644 --- a/src/openrct2/paint/track/coaster/MineTrainCoaster.cpp +++ b/src/openrct2/paint/track/coaster/MineTrainCoaster.cpp @@ -7326,7 +7326,7 @@ static void MineTrainRCTrack60DegDownToFlatLongBase( session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineTrainRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineTrainRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -7528,6 +7528,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineTrainRC(int32_t trackType) return MineTrainRCTrackFlatTo60DegDownLongBase; case TrackElemType::Down60ToFlatLongBase: return MineTrainRCTrack60DegDownToFlatLongBase; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/MiniRollerCoaster.cpp b/src/openrct2/paint/track/coaster/MiniRollerCoaster.cpp index 5d08179063..975b10afab 100644 --- a/src/openrct2/paint/track/coaster/MiniRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/MiniRollerCoaster.cpp @@ -9234,7 +9234,7 @@ static void MiniRCTrackBooster( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -9510,6 +9510,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniRC(int32_t trackType) return MiniRCTrackRightCurvedLiftHill; case TrackElemType::Booster: return MiniRCTrackBooster; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/MiniSuspendedCoaster.cpp b/src/openrct2/paint/track/coaster/MiniSuspendedCoaster.cpp index 9e2a5e9ef3..5a01d07542 100644 --- a/src/openrct2/paint/track/coaster/MiniSuspendedCoaster.cpp +++ b/src/openrct2/paint/track/coaster/MiniSuspendedCoaster.cpp @@ -2242,7 +2242,7 @@ static void MiniSuspendedRCTrackDiag25DegDownToFlat( } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniSuspendedRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniSuspendedRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -2298,6 +2298,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniSuspendedRC(int32_t trackType) return MiniSuspendedRCTrackDiagFlatTo25DegDown; case TrackElemType::DiagDown25ToFlat: return MiniSuspendedRCTrackDiag25DegDownToFlat; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/MultiDimensionRollerCoaster.cpp b/src/openrct2/paint/track/coaster/MultiDimensionRollerCoaster.cpp index 855e259719..c453ff36ad 100644 --- a/src/openrct2/paint/track/coaster/MultiDimensionRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/MultiDimensionRollerCoaster.cpp @@ -14960,7 +14960,7 @@ static void MultiDimensionRCTrackMultidimInverted90DegUpToFlatQuarterLoop( } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMultiDimensionRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMultiDimensionRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -15167,6 +15167,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMultiDimensionRC(int32_t trackType) return MultiDimensionRCTrackDiagBrakes; case TrackElemType::DiagBlockBrakes: return MultiDimensionRCTrackDiagBlockBrakes; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/ReverseFreefallCoaster.cpp b/src/openrct2/paint/track/coaster/ReverseFreefallCoaster.cpp index 1d7d18cb4d..2d39bddadd 100644 --- a/src/openrct2/paint/track/coaster/ReverseFreefallCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ReverseFreefallCoaster.cpp @@ -426,7 +426,7 @@ static void PaintReverseFreefallRCOnridePhoto( TrackPaintUtilOnridePhotoPaint2(session, direction, trackElement, height); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverseFreefallRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverseFreefallRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -442,6 +442,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverseFreefallRC(int32_t trackType) return PaintReverseFreefallRCVertical; case TrackElemType::OnRidePhoto: return PaintReverseFreefallRCOnridePhoto; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/ReverserRollerCoaster.cpp b/src/openrct2/paint/track/coaster/ReverserRollerCoaster.cpp index d414fb4c5e..256959a84d 100644 --- a/src/openrct2/paint/track/coaster/ReverserRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ReverserRollerCoaster.cpp @@ -1379,7 +1379,7 @@ static void ReverserRCTrackRightReverser( } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverserRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverserRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1419,6 +1419,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverserRC(int32_t trackType) return ReverserRCTrackLeftReverser; case TrackElemType::RightReverser: return ReverserRCTrackRightReverser; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/SideFrictionRollerCoaster.cpp b/src/openrct2/paint/track/coaster/SideFrictionRollerCoaster.cpp index 7ae2c7464f..dac5c98c5a 100644 --- a/src/openrct2/paint/track/coaster/SideFrictionRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/SideFrictionRollerCoaster.cpp @@ -2909,7 +2909,7 @@ static void SideFrictionRCTrackDiag60DegDownTo25DegDown( session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); }; -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSideFrictionRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSideFrictionRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -2994,6 +2994,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionSideFrictionRC(int32_t trackType) return SideFrictionRCTrackDiag25DegUpTo60DegUp; case TrackElemType::DiagDown60ToDown25: return SideFrictionRCTrackDiag60DegDownTo25DegDown; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/SingleRailRollerCoaster.cpp b/src/openrct2/paint/track/coaster/SingleRailRollerCoaster.cpp index a4daa977c6..b26dce9901 100644 --- a/src/openrct2/paint/track/coaster/SingleRailRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/SingleRailRollerCoaster.cpp @@ -18530,7 +18530,7 @@ namespace OpenRCT2::SingleRailRC PaintUtilSetGeneralSupportHeight(session, height + 56); } - TRACK_PAINT_FUNCTION GetTrackPaintFunction(int32_t trackType) + TRACK_PAINT_FUNCTION GetTrackPaintFunction(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -19013,8 +19013,9 @@ namespace OpenRCT2::SingleRailRC return TrackRightEighthBankToOrthogonalDown25; case TrackElemType::Down25Brakes: return Track25DegDownBrakes; + default: + return nullptr; } - return nullptr; } } // namespace OpenRCT2::SingleRailRC diff --git a/src/openrct2/paint/track/coaster/StandUpRollerCoaster.cpp b/src/openrct2/paint/track/coaster/StandUpRollerCoaster.cpp index 7702572561..968cfaad13 100644 --- a/src/openrct2/paint/track/coaster/StandUpRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/StandUpRollerCoaster.cpp @@ -9515,7 +9515,7 @@ static void StandUpRCTrackBlockBrakes( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionStandUpRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionStandUpRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -9725,6 +9725,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionStandUpRC(int32_t trackType) return StandUpRCTrackDiagBrakes; case TrackElemType::DiagBlockBrakes: return StandUpRCTrackDiagBlockBrakes; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/Steeplechase.cpp b/src/openrct2/paint/track/coaster/Steeplechase.cpp index c311658f6c..59e805b47d 100644 --- a/src/openrct2/paint/track/coaster/Steeplechase.cpp +++ b/src/openrct2/paint/track/coaster/Steeplechase.cpp @@ -2237,7 +2237,7 @@ static void SteeplechaseTrackBlockBrakes( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSteeplechase(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSteeplechase(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -2300,6 +2300,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionSteeplechase(int32_t trackType) case TrackElemType::DiagBrakes: case TrackElemType::DiagBlockBrakes: return SteeplechaseTrackDiagBrakes; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/SuspendedSwingingCoaster.cpp b/src/openrct2/paint/track/coaster/SuspendedSwingingCoaster.cpp index 79d0bca522..81088d5f68 100644 --- a/src/openrct2/paint/track/coaster/SuspendedSwingingCoaster.cpp +++ b/src/openrct2/paint/track/coaster/SuspendedSwingingCoaster.cpp @@ -4788,7 +4788,7 @@ static void SuspendedSwingingRCTrackBlockBrakes( PaintUtilSetGeneralSupportHeight(session, height + 48); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedSwingingRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedSwingingRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -4896,6 +4896,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedSwingingRC(int32_t trackType) return SuspendedSwingingRCTrackDiag25DegDownToFlat; case TrackElemType::BlockBrakes: return SuspendedSwingingRCTrackBlockBrakes; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/TwisterRollerCoaster.cpp b/src/openrct2/paint/track/coaster/TwisterRollerCoaster.cpp index 5c5a04bcef..99e89353ff 100644 --- a/src/openrct2/paint/track/coaster/TwisterRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/TwisterRollerCoaster.cpp @@ -14581,7 +14581,7 @@ static void TwisterRCTrackFlyerHalfLoopUp( } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwisterRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwisterRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -14967,6 +14967,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwisterRC(int32_t trackType) return TwisterRCTrackRightFlyerTwistUp; case TrackElemType::FlyerHalfLoopUninvertedUp: return TwisterRCTrackFlyerHalfLoopUp; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/VirginiaReel.cpp b/src/openrct2/paint/track/coaster/VirginiaReel.cpp index 4c633a1190..6882cbd53d 100644 --- a/src/openrct2/paint/track/coaster/VirginiaReel.cpp +++ b/src/openrct2/paint/track/coaster/VirginiaReel.cpp @@ -480,7 +480,7 @@ static void PaintVirginiaReelTrackRightQuarterTurn1Tile( /** * rct2: 0x00811184 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionVirginiaReel(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionVirginiaReel(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -515,7 +515,8 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionVirginiaReel(int32_t trackType) return PaintVirginiaReelTrackLeftQuarterTurn1Tile; case TrackElemType::RightQuarterTurn1Tile: return PaintVirginiaReelTrackRightQuarterTurn1Tile; - } - return nullptr; + default: + return nullptr; + } } diff --git a/src/openrct2/paint/track/coaster/WildMouse.cpp b/src/openrct2/paint/track/coaster/WildMouse.cpp index c168309b7c..831345054f 100644 --- a/src/openrct2/paint/track/coaster/WildMouse.cpp +++ b/src/openrct2/paint/track/coaster/WildMouse.cpp @@ -205,7 +205,7 @@ static void WildMouseTrackStation( SPR_STATION_BASE_B_NW_SE, }; - int32_t trackType = trackElement.GetTrackType(); + auto trackType = trackElement.GetTrackType(); PaintAddImageAsParentRotated( session, direction, GetStationColourScheme(session, trackElement).WithIndex(baseImageIds[direction]), { 0, 0, height - 2 }, { { 0, 2, height }, { 32, 28, 2 } }); @@ -946,7 +946,7 @@ static void WildMouseTrackBlockBrakes( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionWildMouse(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWildMouse(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1010,6 +1010,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionWildMouse(int32_t trackType) return WildMouseTrackRotationControlToggle; case TrackElemType::BlockBrakes: return WildMouseTrackBlockBrakes; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp index 73d2b43075..b985f7501b 100644 --- a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp @@ -525,7 +525,7 @@ static void WoodenRCTrackStation( { SPR_WOODEN_RC_STATION_NW_SE, SPR_WOODEN_RC_STATION_RAILS_NW_SE }, }; - int32_t trackType = trackElement.GetTrackType(); + auto trackType = trackElement.GetTrackType(); if (trackType == TrackElemType::EndStation) { const auto brakeImg = trackElement.IsBrakeClosed() ? _wooden_rc_station_block_brakes_image_ids[direction][1] @@ -16616,7 +16616,7 @@ static void WoodenRCTrackBooster( PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); } -template TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenAndClassicWoodenRC(int32_t trackType) +template TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenAndClassicWoodenRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -16914,16 +16914,17 @@ template TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenAndClas return WoodenRCTrackDiagBrakes; case TrackElemType::DiagBlockBrakes: return WoodenRCTrackDiagBlockBrakes; + default: + return nullptr; } - return nullptr; } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenRC(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenRC(OpenRCT2::TrackElemType trackType) { return GetTrackPaintFunctionWoodenAndClassicWoodenRC(trackType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRCFallback(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRCFallback(OpenRCT2::TrackElemType trackType) { return GetTrackPaintFunctionWoodenAndClassicWoodenRC(trackType); } diff --git a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.h b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.h index 3111acc98c..be09c32a16 100644 --- a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.h +++ b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.h @@ -80,4 +80,4 @@ template void WoodenRCTrackPaintBb(PaintSession& session, const } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRCFallback(int32_t trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRCFallback(OpenRCT2::TrackElemType trackType); diff --git a/src/openrct2/paint/track/coaster/WoodenWildMouse.cpp b/src/openrct2/paint/track/coaster/WoodenWildMouse.cpp index 65b0c2a610..22e0efb390 100644 --- a/src/openrct2/paint/track/coaster/WoodenWildMouse.cpp +++ b/src/openrct2/paint/track/coaster/WoodenWildMouse.cpp @@ -720,7 +720,7 @@ static void WoodenWildMouseTrack60DegDownToFlat( WoodenWildMouseTrackFlatTo60DegUp(session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenWildMouse(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenWildMouse(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -770,6 +770,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenWildMouse(int32_t trackType) return WoodenWildMouseTrackFlatTo60DegDown; case TrackElemType::Down60ToFlat: return WoodenWildMouseTrack60DegDownToFlat; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/gentle/CarRide.cpp b/src/openrct2/paint/track/gentle/CarRide.cpp index cb4a3e168e..0978aa64ab 100644 --- a/src/openrct2/paint/track/gentle/CarRide.cpp +++ b/src/openrct2/paint/track/gentle/CarRide.cpp @@ -738,7 +738,7 @@ static void PaintCarRideTrackLogBumps( /** * rct2: 0x006F7000 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCarRide(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCarRide(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -791,7 +791,8 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionCarRide(int32_t trackType) case TrackElemType::SpinningTunnel: return PaintCarRideTrackSpinningTunnel; - } - return nullptr; + default: + return nullptr; + } } diff --git a/src/openrct2/paint/track/gentle/Circus.cpp b/src/openrct2/paint/track/gentle/Circus.cpp index 23c96d2bda..39942c54db 100644 --- a/src/openrct2/paint/track/gentle/Circus.cpp +++ b/src/openrct2/paint/track/gentle/Circus.cpp @@ -121,7 +121,7 @@ static void PaintCircus( PaintUtilSetGeneralSupportHeight(session, height + 128); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCircus(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCircus(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack3x3) { diff --git a/src/openrct2/paint/track/gentle/CrookedHouse.cpp b/src/openrct2/paint/track/gentle/CrookedHouse.cpp index b6174b1dc6..ca612b1b07 100644 --- a/src/openrct2/paint/track/gentle/CrookedHouse.cpp +++ b/src/openrct2/paint/track/gentle/CrookedHouse.cpp @@ -144,7 +144,7 @@ static void PaintCrookedHouse( PaintUtilSetGeneralSupportHeight(session, height + 128); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCrookedHouse(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCrookedHouse(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack3x3) { diff --git a/src/openrct2/paint/track/gentle/Dodgems.cpp b/src/openrct2/paint/track/gentle/Dodgems.cpp index 406683577b..d0dc980b24 100644 --- a/src/openrct2/paint/track/gentle/Dodgems.cpp +++ b/src/openrct2/paint/track/gentle/Dodgems.cpp @@ -109,7 +109,7 @@ static void PaintDodgems( /** * rct2: */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionDodgems(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionDodgems(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack4x4) { diff --git a/src/openrct2/paint/track/gentle/FerrisWheel.cpp b/src/openrct2/paint/track/gentle/FerrisWheel.cpp index cee9911f49..05c0a6c291 100644 --- a/src/openrct2/paint/track/gentle/FerrisWheel.cpp +++ b/src/openrct2/paint/track/gentle/FerrisWheel.cpp @@ -173,7 +173,7 @@ static void PaintFerrisWheel( PaintUtilSetGeneralSupportHeight(session, height + 176); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFerrisWheel(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFerrisWheel(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack1x4C) { diff --git a/src/openrct2/paint/track/gentle/FlyingSaucers.cpp b/src/openrct2/paint/track/gentle/FlyingSaucers.cpp index cd4bb89601..4bd9e63cd7 100644 --- a/src/openrct2/paint/track/gentle/FlyingSaucers.cpp +++ b/src/openrct2/paint/track/gentle/FlyingSaucers.cpp @@ -69,7 +69,7 @@ static void PaintFlyingSaucers( /** * rct2: 0x00887208 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingSaucers(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingSaucers(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack4x4) { diff --git a/src/openrct2/paint/track/gentle/GhostTrain.cpp b/src/openrct2/paint/track/gentle/GhostTrain.cpp index 59e5638b2a..8a5c793209 100644 --- a/src/openrct2/paint/track/gentle/GhostTrain.cpp +++ b/src/openrct2/paint/track/gentle/GhostTrain.cpp @@ -561,7 +561,7 @@ static void PaintGhostTrainTrackBrakes( /** * rct2: 0x00770924 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionGhostTrain(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionGhostTrain(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -602,7 +602,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionGhostTrain(int32_t trackType) case TrackElemType::SpinningTunnel: return PaintGhostTrainTrackSpinningTunnel; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/gentle/HauntedHouse.cpp b/src/openrct2/paint/track/gentle/HauntedHouse.cpp index 273db85710..cfde3f21b8 100644 --- a/src/openrct2/paint/track/gentle/HauntedHouse.cpp +++ b/src/openrct2/paint/track/gentle/HauntedHouse.cpp @@ -125,7 +125,7 @@ static void PaintHauntedHouse( PaintUtilSetGeneralSupportHeight(session, height + 128); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionHauntedHouse(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionHauntedHouse(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack3x3) { diff --git a/src/openrct2/paint/track/gentle/Maze.cpp b/src/openrct2/paint/track/gentle/Maze.cpp index fc59814f92..1707fb68ba 100644 --- a/src/openrct2/paint/track/gentle/Maze.cpp +++ b/src/openrct2/paint/track/gentle/Maze.cpp @@ -187,7 +187,7 @@ static void MazePaintSetup( /** * rct2: 0x008A81E8 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMaze(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMaze(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::Maze) { diff --git a/src/openrct2/paint/track/gentle/MerryGoRound.cpp b/src/openrct2/paint/track/gentle/MerryGoRound.cpp index f4f6f73fc1..f568614730 100644 --- a/src/openrct2/paint/track/gentle/MerryGoRound.cpp +++ b/src/openrct2/paint/track/gentle/MerryGoRound.cpp @@ -175,7 +175,7 @@ static void PaintMerryGoRound( PaintUtilSetGeneralSupportHeight(session, height + 64); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMerryGoRound(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMerryGoRound(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack3x3) { diff --git a/src/openrct2/paint/track/gentle/MiniGolf.cpp b/src/openrct2/paint/track/gentle/MiniGolf.cpp index 9b9897fb99..76dbc5883f 100644 --- a/src/openrct2/paint/track/gentle/MiniGolf.cpp +++ b/src/openrct2/paint/track/gentle/MiniGolf.cpp @@ -1085,7 +1085,7 @@ static void PaintMiniGolfHoleE( /** * rct2: 0x0087EDC4 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniGolf(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniGolf(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1126,7 +1126,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniGolf(int32_t trackType) return PaintMiniGolfHoleD; case TrackElemType::MinigolfHoleE: return PaintMiniGolfHoleE; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/gentle/MiniHelicopters.cpp b/src/openrct2/paint/track/gentle/MiniHelicopters.cpp index 5f0c931ce3..3ea29a988f 100644 --- a/src/openrct2/paint/track/gentle/MiniHelicopters.cpp +++ b/src/openrct2/paint/track/gentle/MiniHelicopters.cpp @@ -373,7 +373,7 @@ static void PaintMiniHelicoptersTrackSpinningTunnel( /** * rct2: 0x0081F268 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniHelicopters(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniHelicopters(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -411,7 +411,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniHelicopters(int32_t trackType) case TrackElemType::SpinningTunnel: return PaintMiniHelicoptersTrackSpinningTunnel; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/gentle/MonorailCycles.cpp b/src/openrct2/paint/track/gentle/MonorailCycles.cpp index 57663625e0..fdad557b00 100644 --- a/src/openrct2/paint/track/gentle/MonorailCycles.cpp +++ b/src/openrct2/paint/track/gentle/MonorailCycles.cpp @@ -610,7 +610,7 @@ static void PaintMonorailCyclesTrackSBendRight( /** * rct2: 0x0088ac88 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorailCycles(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorailCycles(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -636,7 +636,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorailCycles(int32_t trackType) return PaintMonorailCyclesTrackLeftQuarterTurn3Tiles; case TrackElemType::RightQuarterTurn3Tiles: return PaintMonorailCyclesTrackRightQuarterTurn3Tiles; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/gentle/ObservationTower.cpp b/src/openrct2/paint/track/gentle/ObservationTower.cpp index 3548655aab..ad1828a109 100644 --- a/src/openrct2/paint/track/gentle/ObservationTower.cpp +++ b/src/openrct2/paint/track/gentle/ObservationTower.cpp @@ -142,7 +142,7 @@ static void PaintObservationTowerSection( /** * rct2: 0x0070DC5C */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionObservationTower(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionObservationTower(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -151,7 +151,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionObservationTower(int32_t trackType) case TrackElemType::TowerSection: return PaintObservationTowerSection; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/gentle/SpaceRings.cpp b/src/openrct2/paint/track/gentle/SpaceRings.cpp index 6eebee03d1..3938538fc5 100644 --- a/src/openrct2/paint/track/gentle/SpaceRings.cpp +++ b/src/openrct2/paint/track/gentle/SpaceRings.cpp @@ -190,7 +190,7 @@ static void PaintSpaceRings( /** * rct2: 0x0x00767A40 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSpaceRings(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSpaceRings(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack3x3) { diff --git a/src/openrct2/paint/track/gentle/SpiralSlide.cpp b/src/openrct2/paint/track/gentle/SpiralSlide.cpp index 673d08b95b..5475ddb9e7 100644 --- a/src/openrct2/paint/track/gentle/SpiralSlide.cpp +++ b/src/openrct2/paint/track/gentle/SpiralSlide.cpp @@ -253,7 +253,7 @@ static void PaintSpiralSlide( /** * rct2: 0x0074840C */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSpiralSlide(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSpiralSlide(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack2x2) { diff --git a/src/openrct2/paint/track/shops/Facility.cpp b/src/openrct2/paint/track/shops/Facility.cpp index 4ff6f5ef67..936149757c 100644 --- a/src/openrct2/paint/track/shops/Facility.cpp +++ b/src/openrct2/paint/track/shops/Facility.cpp @@ -81,12 +81,13 @@ static void PaintFacility( } /* 0x00762D44 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFacility(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFacility(OpenRCT2::TrackElemType trackType) { switch (trackType) { case TrackElemType::FlatTrack1x1A: return PaintFacility; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/shops/Shop.cpp b/src/openrct2/paint/track/shops/Shop.cpp index 2d880cdd3e..16ff2d7484 100644 --- a/src/openrct2/paint/track/shops/Shop.cpp +++ b/src/openrct2/paint/track/shops/Shop.cpp @@ -65,13 +65,14 @@ static void PaintShop( PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionShop(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionShop(OpenRCT2::TrackElemType trackType) { switch (trackType) { case TrackElemType::FlatTrack1x1A: case TrackElemType::FlatTrack1x1B: return PaintShop; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/thrill/3dCinema.cpp b/src/openrct2/paint/track/thrill/3dCinema.cpp index 1a3c592683..46ec0d0bb2 100644 --- a/src/openrct2/paint/track/thrill/3dCinema.cpp +++ b/src/openrct2/paint/track/thrill/3dCinema.cpp @@ -121,7 +121,7 @@ static void Paint3dCinema( PaintUtilSetGeneralSupportHeight(session, height + 128); } -TRACK_PAINT_FUNCTION GetTrackPaintFunction3dCinema(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunction3dCinema(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack3x3) { diff --git a/src/openrct2/paint/track/thrill/Enterprise.cpp b/src/openrct2/paint/track/thrill/Enterprise.cpp index 9631a714e8..830248374c 100644 --- a/src/openrct2/paint/track/thrill/Enterprise.cpp +++ b/src/openrct2/paint/track/thrill/Enterprise.cpp @@ -173,7 +173,7 @@ static void PaintEnterprise( PaintUtilSetGeneralSupportHeight(session, height + 160); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionEnterprise(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionEnterprise(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack4x4) { diff --git a/src/openrct2/paint/track/thrill/GoKarts.cpp b/src/openrct2/paint/track/thrill/GoKarts.cpp index ebd732dd7d..80f074d6a0 100644 --- a/src/openrct2/paint/track/thrill/GoKarts.cpp +++ b/src/openrct2/paint/track/thrill/GoKarts.cpp @@ -541,7 +541,7 @@ static void PaintGoKartsTrackRightQuarterTurn1Tile( /** * rct2: 0x0074A668 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionGoKarts(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionGoKarts(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -571,7 +571,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionGoKarts(int32_t trackType) return PaintGoKartsTrackLeftQuarterTurn1Tile; case TrackElemType::RightQuarterTurn1Tile: return PaintGoKartsTrackRightQuarterTurn1Tile; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp b/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp index 2bdd2b00cd..754fd26a9b 100644 --- a/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp +++ b/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp @@ -142,7 +142,7 @@ static void PaintLaunchedFreefallTowerSection( /** * rct2: 0x006FD0E8 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLaunchedFreefall(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLaunchedFreefall(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -151,7 +151,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLaunchedFreefall(int32_t trackType) case TrackElemType::TowerSection: return PaintLaunchedFreefallTowerSection; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/thrill/MagicCarpet.cpp b/src/openrct2/paint/track/thrill/MagicCarpet.cpp index 0d8732fc47..d25b104a52 100644 --- a/src/openrct2/paint/track/thrill/MagicCarpet.cpp +++ b/src/openrct2/paint/track/thrill/MagicCarpet.cpp @@ -255,12 +255,13 @@ static void PaintMagicCarpet( PaintUtilSetGeneralSupportHeight(session, height + 176); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMagicCarpet(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMagicCarpet(OpenRCT2::TrackElemType trackType) { switch (trackType) { case TrackElemType::FlatTrack1x4A: return PaintMagicCarpet; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/thrill/MotionSimulator.cpp b/src/openrct2/paint/track/thrill/MotionSimulator.cpp index a387b35a5d..f66303ce82 100644 --- a/src/openrct2/paint/track/thrill/MotionSimulator.cpp +++ b/src/openrct2/paint/track/thrill/MotionSimulator.cpp @@ -145,12 +145,13 @@ static void PaintMotionSimulator( * * rct2: 0x00763520 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMotionsimulator(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMotionsimulator(OpenRCT2::TrackElemType trackType) { switch (trackType) { case TrackElemType::FlatTrack2x2: return PaintMotionSimulator; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/thrill/RotoDrop.cpp b/src/openrct2/paint/track/thrill/RotoDrop.cpp index 9e372c137a..b999444da3 100644 --- a/src/openrct2/paint/track/thrill/RotoDrop.cpp +++ b/src/openrct2/paint/track/thrill/RotoDrop.cpp @@ -155,7 +155,7 @@ static void PaintRotoDropTowerSection( /** * rct2: 0x00886074 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionRotoDrop(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionRotoDrop(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -164,7 +164,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionRotoDrop(int32_t trackType) case TrackElemType::TowerSection: return PaintRotoDropTowerSection; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/thrill/SwingingInverterShip.cpp b/src/openrct2/paint/track/thrill/SwingingInverterShip.cpp index e29bd107f3..7100b6bdac 100644 --- a/src/openrct2/paint/track/thrill/SwingingInverterShip.cpp +++ b/src/openrct2/paint/track/thrill/SwingingInverterShip.cpp @@ -188,7 +188,7 @@ static void PaintSwingingInverterShip( PaintUtilSetGeneralSupportHeight(session, height + 176); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSwingingInverterShip(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSwingingInverterShip(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack1x4B) { diff --git a/src/openrct2/paint/track/thrill/SwingingShip.cpp b/src/openrct2/paint/track/thrill/SwingingShip.cpp index 537363e518..6fd16c4b08 100644 --- a/src/openrct2/paint/track/thrill/SwingingShip.cpp +++ b/src/openrct2/paint/track/thrill/SwingingShip.cpp @@ -298,7 +298,7 @@ static void PaintSwingingShip( PaintUtilSetGeneralSupportHeight(session, height + 112); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSwingingShip(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSwingingShip(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack1x5) { diff --git a/src/openrct2/paint/track/thrill/TopSpin.cpp b/src/openrct2/paint/track/thrill/TopSpin.cpp index 91ad41638e..fe9468b9ca 100644 --- a/src/openrct2/paint/track/thrill/TopSpin.cpp +++ b/src/openrct2/paint/track/thrill/TopSpin.cpp @@ -250,7 +250,7 @@ static void PaintTopSpin( PaintUtilSetGeneralSupportHeight(session, height + 112); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionTopspin(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionTopspin(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack3x3) { diff --git a/src/openrct2/paint/track/thrill/Twist.cpp b/src/openrct2/paint/track/thrill/Twist.cpp index f2e2f4c728..45b06b640f 100644 --- a/src/openrct2/paint/track/thrill/Twist.cpp +++ b/src/openrct2/paint/track/thrill/Twist.cpp @@ -170,7 +170,7 @@ static void PaintTwist( /** * rct2: 0x0076D658 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwist(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwist(OpenRCT2::TrackElemType trackType) { if (trackType != TrackElemType::FlatTrack3x3) { diff --git a/src/openrct2/paint/track/transport/Chairlift.cpp b/src/openrct2/paint/track/transport/Chairlift.cpp index 74f42ee1a6..5f96579844 100644 --- a/src/openrct2/paint/track/transport/Chairlift.cpp +++ b/src/openrct2/paint/track/transport/Chairlift.cpp @@ -148,7 +148,7 @@ static const TrackElement* ChairliftPaintUtilMapGetTrackElementAtFromRideFuzzy( }; static bool ChairliftPaintUtilIsFirstTrack( - const Ride& ride, const TrackElement& trackElement, const CoordsXY& pos, track_type_t trackType) + const Ride& ride, const TrackElement& trackElement, const CoordsXY& pos, OpenRCT2::TrackElemType trackType) { if (trackElement.GetTrackType() != TrackElemType::BeginStation) { @@ -168,7 +168,7 @@ static bool ChairliftPaintUtilIsFirstTrack( } static bool ChairliftPaintUtilIsLastTrack( - const Ride& ride, const TrackElement& trackElement, const CoordsXY& pos, track_type_t trackType) + const Ride& ride, const TrackElement& trackElement, const CoordsXY& pos, OpenRCT2::TrackElemType trackType) { if (trackElement.GetTrackType() != TrackElemType::EndStation) { @@ -661,7 +661,7 @@ static void ChairliftPaintRightQuarterTurn1Tile( } /* 0x008AAA0C */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionChairlift(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionChairlift(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -691,7 +691,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionChairlift(int32_t trackType) return ChairliftPaintLeftQuarterTurn1Tile; case TrackElemType::RightQuarterTurn1Tile: return ChairliftPaintRightQuarterTurn1Tile; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/transport/Lift.cpp b/src/openrct2/paint/track/transport/Lift.cpp index 69444118a3..57dfcf228f 100644 --- a/src/openrct2/paint/track/transport/Lift.cpp +++ b/src/openrct2/paint/track/transport/Lift.cpp @@ -144,7 +144,7 @@ static void PaintLiftTowerSection( /** * rct2: 0x0076C5BC */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLift(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLift(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -153,7 +153,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLift(int32_t trackType) case TrackElemType::TowerSection: return PaintLiftTowerSection; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/transport/MiniatureRailway.cpp b/src/openrct2/paint/track/transport/MiniatureRailway.cpp index 66fa24eabd..95906b099c 100644 --- a/src/openrct2/paint/track/transport/MiniatureRailway.cpp +++ b/src/openrct2/paint/track/transport/MiniatureRailway.cpp @@ -2290,7 +2290,7 @@ static void MiniatureRailwayTrackDiag25DegDownToFlat( /** * rct2: 0x008ACE48 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniatureRailway(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniatureRailway(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -2354,7 +2354,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniatureRailway(int32_t trackType) return MiniatureRailwayTrackDiagFlatTo25DegDown; case TrackElemType::DiagDown25ToFlat: return MiniatureRailwayTrackDiag25DegDownToFlat; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/transport/Monorail.cpp b/src/openrct2/paint/track/transport/Monorail.cpp index 85d313aa60..ca0bc26e96 100644 --- a/src/openrct2/paint/track/transport/Monorail.cpp +++ b/src/openrct2/paint/track/transport/Monorail.cpp @@ -1234,7 +1234,7 @@ static void PaintMonorailTrackDiag25DegDownToFlat( /** * rct2: 0x008ADF34 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorail(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorail(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1300,7 +1300,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorail(int32_t trackType) return PaintMonorailTrackDiagFlatTo25DegDown; case TrackElemType::DiagDown25ToFlat: return PaintMonorailTrackDiag25DegDownToFlat; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/transport/SuspendedMonorail.cpp b/src/openrct2/paint/track/transport/SuspendedMonorail.cpp index 093cdf59d5..deabd24bfb 100644 --- a/src/openrct2/paint/track/transport/SuspendedMonorail.cpp +++ b/src/openrct2/paint/track/transport/SuspendedMonorail.cpp @@ -2023,7 +2023,7 @@ static void SuspendedMonorailTrackDiag25DegDownToFlat( } } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedMonorail(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedMonorail(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -2079,6 +2079,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedMonorail(int32_t trackType) return SuspendedMonorailTrackDiagFlatTo25DegDown; case TrackElemType::DiagDown25ToFlat: return SuspendedMonorailTrackDiag25DegDownToFlat; + default: + return nullptr; } - return nullptr; } diff --git a/src/openrct2/paint/track/water/BoatHire.cpp b/src/openrct2/paint/track/water/BoatHire.cpp index a9414e7a4a..022b8dedb4 100644 --- a/src/openrct2/paint/track/water/BoatHire.cpp +++ b/src/openrct2/paint/track/water/BoatHire.cpp @@ -142,7 +142,7 @@ static void PaintBoatHireTrackRightQuarterTurn1Tile( /** * rct2: 0x008B0D60 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionBoatHire(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionBoatHire(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -158,7 +158,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionBoatHire(int32_t trackType) return PaintBoatHireTrackLeftQuarterTurn1Tile; case TrackElemType::RightQuarterTurn1Tile: return PaintBoatHireTrackRightQuarterTurn1Tile; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/water/DinghySlide.cpp b/src/openrct2/paint/track/water/DinghySlide.cpp index c67860c3b3..36d560078e 100644 --- a/src/openrct2/paint/track/water/DinghySlide.cpp +++ b/src/openrct2/paint/track/water/DinghySlide.cpp @@ -1059,7 +1059,7 @@ static void DinghySlideTrackLeftQuarterTurn3( DinghySlideTrackRightQuarterTurn3(session, ride, trackSequence, (direction + 1) % 4, height, trackElement, supportType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlide(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlide(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1105,7 +1105,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlide(int32_t trackType) return DinghySlideTrackLeftQuarterTurn3; case TrackElemType::RightQuarterTurn3Tiles: return DinghySlideTrackRightQuarterTurn3; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/water/DinghySlideCovered.cpp b/src/openrct2/paint/track/water/DinghySlideCovered.cpp index 7f6aab6bff..b132d251dd 100644 --- a/src/openrct2/paint/track/water/DinghySlideCovered.cpp +++ b/src/openrct2/paint/track/water/DinghySlideCovered.cpp @@ -964,7 +964,7 @@ static void DinghySlideTrackCovered60DegDownTo25DegDown( session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlideCovered(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlideCovered(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1006,7 +1006,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlideCovered(int32_t trackType) return DinghySlideTrackCoveredLeftQuarterTurn3; case TrackElemType::RightQuarterTurn3Tiles: return DinghySlideTrackCoveredRightQuarterTurn3; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/water/LogFlume.cpp b/src/openrct2/paint/track/water/LogFlume.cpp index 7bfdcc780b..093b9eac8c 100644 --- a/src/openrct2/paint/track/water/LogFlume.cpp +++ b/src/openrct2/paint/track/water/LogFlume.cpp @@ -1003,7 +1003,7 @@ static void LogFlumeTrack60Down25( PaintUtilSetGeneralSupportHeight(session, height + 56); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLogFlume(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLogFlume(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1046,7 +1046,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLogFlume(int32_t trackType) return LogFlumeTrack60Down; case TrackElemType::Down60ToDown25: return LogFlumeTrack60Down25; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/water/RiverRapids.cpp b/src/openrct2/paint/track/water/RiverRapids.cpp index 69d67ef88f..30d2e90272 100644 --- a/src/openrct2/paint/track/water/RiverRapids.cpp +++ b/src/openrct2/paint/track/water/RiverRapids.cpp @@ -706,7 +706,7 @@ static void PaintRiverRapidsTrackWhirlpool( /** * rct2: 0x0075745C **/ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionRiverRapids(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionRiverRapids(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -748,7 +748,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionRiverRapids(int32_t trackType) case TrackElemType::Whirlpool: return PaintRiverRapidsTrackWhirlpool; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/water/SplashBoats.cpp b/src/openrct2/paint/track/water/SplashBoats.cpp index e013b85103..0492ea7d9b 100644 --- a/src/openrct2/paint/track/water/SplashBoats.cpp +++ b/src/openrct2/paint/track/water/SplashBoats.cpp @@ -1233,7 +1233,7 @@ static void PaintSplashBoatsTrackOnRidePhoto( TrackPaintUtilOnridePhotoPaint2(session, direction, trackElement, height); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSplashBoats(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSplashBoats(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -1281,7 +1281,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionSplashBoats(int32_t trackType) // Added by OpenRCT2 case TrackElemType::OnRidePhoto: return PaintSplashBoatsTrackOnRidePhoto; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/paint/track/water/SubmarineRide.cpp b/src/openrct2/paint/track/water/SubmarineRide.cpp index 84dcb6070a..e831632d32 100644 --- a/src/openrct2/paint/track/water/SubmarineRide.cpp +++ b/src/openrct2/paint/track/water/SubmarineRide.cpp @@ -180,7 +180,7 @@ static void SubmarineRidePaintTrackRightQuarterTurn1Tile( /** * rct2: 0x008995D4 */ -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSubmarineRide(int32_t trackType) +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSubmarineRide(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -201,7 +201,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionSubmarineRide(int32_t trackType) return SubmarineRidePaintTrackLeftQuarterTurn1Tile; case TrackElemType::RightQuarterTurn1Tile: return SubmarineRidePaintTrackRightQuarterTurn1Tile; + default: + return nullptr; } - - return nullptr; } diff --git a/src/openrct2/park/Legacy.cpp b/src/openrct2/park/Legacy.cpp index 24a06e321c..46a1a002f3 100644 --- a/src/openrct2/park/Legacy.cpp +++ b/src/openrct2/park/Legacy.cpp @@ -2266,7 +2266,7 @@ void UpdateFootpathsFromMapping( pathToRailingsMap[entryIndex] = railingIndex; } -bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, track_type_t trackType, int32_t parkFileVersion) +bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, OpenRCT2::TrackElemType trackType, int32_t parkFileVersion) { // Lots of Log Flumes exist where the downward slopes are simulated by using other track // types like the Splash Boats, but not actually made invisible, because they never needed @@ -2384,6 +2384,8 @@ bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, track_type_t trackType, case TrackElemType::LeftEighthBankToOrthogonalDown25: case TrackElemType::RightEighthBankToOrthogonalDown25: return true; + default: + break; } } else if ( @@ -2398,6 +2400,8 @@ bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, track_type_t trackType, case TrackElemType::FlatToDown60LongBase: case TrackElemType::Down60ToFlatLongBase: return true; + default: + break; } } diff --git a/src/openrct2/park/Legacy.h b/src/openrct2/park/Legacy.h index b9c50a9afe..f7ab269659 100644 --- a/src/openrct2/park/Legacy.h +++ b/src/openrct2/park/Legacy.h @@ -15,14 +15,18 @@ #include #include -namespace OpenRCT2::RCT2 +namespace OpenRCT2 { - struct FootpathMapping; -} + enum class TrackElemType : uint16_t; + + namespace RCT2 + { + struct FootpathMapping; + } +} // namespace OpenRCT2 struct ObjectEntryDescriptor; class ObjectList; using ride_type_t = uint16_t; -using track_type_t = uint16_t; std::string_view MapToNewObjectIdentifier(std::string_view s); std::optional GetDATPathName(std::string_view newPathName); @@ -43,4 +47,4 @@ void UpdateFootpathsFromMapping( * @param parkFileVersion The current park file version. Pass -1 when converting S4 or S6. * @return */ -bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, track_type_t trackType, int32_t parkFileVersion = -1); +bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, OpenRCT2::TrackElemType trackType, int32_t parkFileVersion = -1); diff --git a/src/openrct2/rct1/RCT1.h b/src/openrct2/rct1/RCT1.h index 981dc0a384..f02760cd8a 100644 --- a/src/openrct2/rct1/RCT1.h +++ b/src/openrct2/rct1/RCT1.h @@ -498,9 +498,9 @@ namespace OpenRCT2::RCT1 uint8_t RideSubtype; // 0xD6 uint8_t ColoursExtended; // 0xD7 - uint16_t GetTrackType() const + OpenRCT2::RCT12::TrackElemType GetTrackType() const { - return TrackTypeAndDirection >> 2; + return static_cast(TrackTypeAndDirection >> 2); } uint8_t GetTrackDirection() const @@ -1292,5 +1292,5 @@ namespace OpenRCT2::RCT1 RCT1_PATH_SUPPORT_TYPE_BAMBOO, }; - track_type_t RCT1TrackTypeToOpenRCT2(RCT12TrackType origTrackType, ride_type_t rideType); + OpenRCT2::TrackElemType RCT1TrackTypeToOpenRCT2(OpenRCT2::RCT12::TrackElemType origTrackType, ride_type_t rideType); } // namespace OpenRCT2::RCT1 diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index b5eaec8471..4135de6c70 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -2767,7 +2767,7 @@ namespace OpenRCT2::RCT1 { dst->BoatLocation = TileCoordsXY{ src->BoatLocation.x, src->BoatLocation.y }.ToCoordsXY(); dst->SetTrackDirection(0); - dst->SetTrackType(0); + dst->SetTrackType(OpenRCT2::TrackElemType::Flat); } dst->track_progress = src->TrackProgress; dst->vertical_drop_countdown = src->VerticalDropCountdown; diff --git a/src/openrct2/rct1/Tables.cpp b/src/openrct2/rct1/Tables.cpp index 44fb9cc0e8..8d20f630bf 100644 --- a/src/openrct2/rct1/Tables.cpp +++ b/src/openrct2/rct1/Tables.cpp @@ -1497,12 +1497,12 @@ namespace OpenRCT2::RCT1 } // clang-format on - track_type_t RCT1TrackTypeToOpenRCT2(RCT12TrackType origTrackType, ride_type_t rideType) + OpenRCT2::TrackElemType RCT1TrackTypeToOpenRCT2(OpenRCT2::RCT12::TrackElemType origTrackType, ride_type_t rideType) { if (GetRideTypeDescriptor(rideType).HasFlag(RtdFlag::isFlatRide)) return RCT12FlatTrackTypeToOpenRCT2(origTrackType); - return origTrackType; + return static_cast(origTrackType); } bool VehicleTypeIsReversed(const VehicleType vehicleType) diff --git a/src/openrct2/rct12/RCT12.cpp b/src/openrct2/rct12/RCT12.cpp index cc6ffc2a0f..d1ade8462e 100644 --- a/src/openrct2/rct12/RCT12.cpp +++ b/src/openrct2/rct12/RCT12.cpp @@ -203,7 +203,7 @@ uint8_t RCT12PathElement::GetRCT1SupportType() const return (Flags & 0b01100000) >> 5; } -uint8_t RCT12TrackElement::GetTrackType() const +OpenRCT2::RCT12::TrackElemType RCT12TrackElement::GetTrackType() const { return TrackType; } @@ -225,7 +225,7 @@ RideColourScheme RCT12TrackElement::GetColourScheme() const uint8_t RCT12TrackElement::GetStationIndex() const { - if (TrackTypeIsStation(TrackType) || TrackType == TrackElemType::TowerBase) + if (TrackTypeIsStation(TrackType) || TrackType == OpenRCT2::RCT12::TrackElemType::TowerBase) { return (Sequence & RCT12_TRACK_ELEMENT_SEQUENCE_STATION_INDEX_MASK) >> 4; } @@ -249,7 +249,7 @@ bool RCT12TrackElement::IsInverted() const uint8_t RCT12TrackElement::GetBrakeBoosterSpeed() const { - if (TrackTypeHasSpeedSetting(GetTrackType())) + if (TrackTypeHasSpeedSetting(TrackType)) { return (Sequence >> 4) << 1; } @@ -277,7 +277,7 @@ uint16_t RCT12TrackElement::GetMazeEntry() const uint8_t RCT12TrackElement::GetPhotoTimeout() const { - if (GetTrackType() == TrackElemType::OnRidePhoto) + if (TrackType == OpenRCT2::RCT12::TrackElemType::OnRidePhoto) { return Sequence >> 4; } @@ -663,62 +663,62 @@ std::string ConvertFormattedStringToOpenRCT2(std::string_view buffer) return result; } -track_type_t RCT12FlatTrackTypeToOpenRCT2(RCT12TrackType origTrackType) +OpenRCT2::TrackElemType RCT12FlatTrackTypeToOpenRCT2(OpenRCT2::RCT12::TrackElemType origTrackType) { switch (origTrackType) { - case TrackElemType::FlatTrack1x4A_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack1x4A_Alias: return TrackElemType::FlatTrack1x4A; - case TrackElemType::FlatTrack2x2_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack2x2_Alias: return TrackElemType::FlatTrack2x2; - case TrackElemType::FlatTrack4x4_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack4x4_Alias: return TrackElemType::FlatTrack4x4; - case TrackElemType::FlatTrack2x4_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack2x4_Alias: return TrackElemType::FlatTrack2x4; - case TrackElemType::FlatTrack1x5_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack1x5_Alias: return TrackElemType::FlatTrack1x5; - case TrackElemType::FlatTrack1x1A_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack1x1A_Alias: return TrackElemType::FlatTrack1x1A; - case TrackElemType::FlatTrack1x4B_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack1x4B_Alias: return TrackElemType::FlatTrack1x4B; - case TrackElemType::FlatTrack1x1B_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack1x1B_Alias: return TrackElemType::FlatTrack1x1B; - case TrackElemType::FlatTrack1x4C_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack1x4C_Alias: return TrackElemType::FlatTrack1x4C; - case TrackElemType::FlatTrack3x3_Alias: + case OpenRCT2::RCT12::TrackElemType::FlatTrack3x3_Alias: return TrackElemType::FlatTrack3x3; + default: + return static_cast(origTrackType); } - - return origTrackType; } -RCT12TrackType OpenRCT2FlatTrackTypeToRCT12(track_type_t origTrackType) +OpenRCT2::RCT12::TrackElemType OpenRCT2FlatTrackTypeToRCT12(OpenRCT2::TrackElemType origTrackType) { switch (origTrackType) { case TrackElemType::FlatTrack1x4A: - return TrackElemType::FlatTrack1x4A_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack1x4A_Alias; case TrackElemType::FlatTrack2x2: - return TrackElemType::FlatTrack2x2_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack2x2_Alias; case TrackElemType::FlatTrack4x4: - return TrackElemType::FlatTrack4x4_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack4x4_Alias; case TrackElemType::FlatTrack2x4: - return TrackElemType::FlatTrack2x4_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack2x4_Alias; case TrackElemType::FlatTrack1x5: - return TrackElemType::FlatTrack1x5_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack1x5_Alias; case TrackElemType::FlatTrack1x1A: - return TrackElemType::FlatTrack1x1A_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack1x1A_Alias; case TrackElemType::FlatTrack1x4B: - return TrackElemType::FlatTrack1x4B_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack1x4B_Alias; case TrackElemType::FlatTrack1x1B: - return TrackElemType::FlatTrack1x1B_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack1x1B_Alias; case TrackElemType::FlatTrack1x4C: - return TrackElemType::FlatTrack1x4C_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack1x4C_Alias; case TrackElemType::FlatTrack3x3: - return TrackElemType::FlatTrack3x3_Alias; + return OpenRCT2::RCT12::TrackElemType::FlatTrack3x3_Alias; + default: + return static_cast(origTrackType); } - - return origTrackType; } static constexpr std::string_view _stationStyles[] = { @@ -975,4 +975,22 @@ namespace OpenRCT2::RCT12 } return len; } + + bool TrackTypeHasSpeedSetting(TrackElemType trackType) + { + return trackType == TrackElemType::Booster || trackType == TrackElemType::Brakes; + } + + bool TrackTypeIsStation(TrackElemType trackType) + { + switch (trackType) + { + case TrackElemType::EndStation: + case TrackElemType::BeginStation: + case TrackElemType::MiddleStation: + return true; + default: + return false; + } + } } // namespace OpenRCT2::RCT12 diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h index 8a1388bafe..1fdaaa34cc 100644 --- a/src/openrct2/rct12/RCT12.h +++ b/src/openrct2/rct12/RCT12.h @@ -23,12 +23,288 @@ class ObjectList; -using track_type_t = uint16_t; -using RCT12TrackType = uint8_t; +namespace OpenRCT2 +{ + enum class TrackElemType : uint16_t; +} namespace OpenRCT2::RCT12 { class EntryList; -} + + enum class TrackElemType : uint8_t + { + Flat = 0, + EndStation = 1, + BeginStation = 2, + MiddleStation = 3, + Up25 = 4, + Up60 = 5, + FlatToUp25 = 6, + Up25ToUp60 = 7, + Up60ToUp25 = 8, + Up25ToFlat = 9, + Down25 = 10, + Down60 = 11, + FlatToDown25 = 12, + Down25ToDown60 = 13, + Down60ToDown25 = 14, + Down25ToFlat = 15, + LeftQuarterTurn5Tiles = 16, + RightQuarterTurn5Tiles = 17, + FlatToLeftBank = 18, + FlatToRightBank = 19, + LeftBankToFlat = 20, + RightBankToFlat = 21, + BankedLeftQuarterTurn5Tiles = 22, + BankedRightQuarterTurn5Tiles = 23, + LeftBankToUp25 = 24, + RightBankToUp25 = 25, + Up25ToLeftBank = 26, + Up25ToRightBank = 27, + LeftBankToDown25 = 28, + RightBankToDown25 = 29, + Down25ToLeftBank = 30, + Down25ToRightBank = 31, + LeftBank = 32, + RightBank = 33, + LeftQuarterTurn5TilesUp25 = 34, + RightQuarterTurn5TilesUp25 = 35, + LeftQuarterTurn5TilesDown25 = 36, + RightQuarterTurn5TilesDown25 = 37, + SBendLeft = 38, + SBendRight = 39, + LeftVerticalLoop = 40, + RightVerticalLoop = 41, + LeftQuarterTurn3Tiles = 42, + RightQuarterTurn3Tiles = 43, + LeftBankedQuarterTurn3Tiles = 44, + RightBankedQuarterTurn3Tiles = 45, + LeftQuarterTurn3TilesUp25 = 46, + RightQuarterTurn3TilesUp25 = 47, + LeftQuarterTurn3TilesDown25 = 48, + RightQuarterTurn3TilesDown25 = 49, + LeftQuarterTurn1Tile = 50, + RightQuarterTurn1Tile = 51, + LeftTwistDownToUp = 52, + RightTwistDownToUp = 53, + LeftTwistUpToDown = 54, + RightTwistUpToDown = 55, + HalfLoopUp = 56, + HalfLoopDown = 57, + LeftCorkscrewUp = 58, + RightCorkscrewUp = 59, + LeftCorkscrewDown = 60, + RightCorkscrewDown = 61, + FlatToUp60 = 62, + Up60ToFlat = 63, + FlatToDown60 = 64, + Down60ToFlat = 65, + TowerBase = 66, + TowerSection = 67, + FlatCovered = 68, + Up25Covered = 69, + Up60Covered = 70, + FlatToUp25Covered = 71, + Up25ToUp60Covered = 72, + Up60ToUp25Covered = 73, + Up25ToFlatCovered = 74, + Down25Covered = 75, + Down60Covered = 76, + FlatToDown25Covered = 77, + Down25ToDown60Covered = 78, + Down60ToDown25Covered = 79, + Down25ToFlatCovered = 80, + LeftQuarterTurn5TilesCovered = 81, + RightQuarterTurn5TilesCovered = 82, + SBendLeftCovered = 83, + SBendRightCovered = 84, + LeftQuarterTurn3TilesCovered = 85, + RightQuarterTurn3TilesCovered = 86, + LeftHalfBankedHelixUpSmall = 87, + RightHalfBankedHelixUpSmall = 88, + LeftHalfBankedHelixDownSmall = 89, + RightHalfBankedHelixDownSmall = 90, + LeftHalfBankedHelixUpLarge = 91, + RightHalfBankedHelixUpLarge = 92, + LeftHalfBankedHelixDownLarge = 93, + RightHalfBankedHelixDownLarge = 94, + LeftQuarterTurn1TileUp60 = 95, + RightQuarterTurn1TileUp60 = 96, + LeftQuarterTurn1TileDown60 = 97, + RightQuarterTurn1TileDown60 = 98, + Brakes = 99, + Booster = 100, + Maze = 101, + LeftQuarterBankedHelixLargeUp = 102, + RightQuarterBankedHelixLargeUp = 103, + LeftQuarterBankedHelixLargeDown = 104, + RightQuarterBankedHelixLargeDown = 105, + LeftQuarterHelixLargeUp = 106, + RightQuarterHelixLargeUp = 107, + LeftQuarterHelixLargeDown = 108, + RightQuarterHelixLargeDown = 109, + Up25LeftBanked = 110, + Up25RightBanked = 111, + Waterfall = 112, + Rapids = 113, + OnRidePhoto = 114, + Down25LeftBanked = 115, + Down25RightBanked = 116, + Watersplash = 117, + FlatToUp60LongBase = 118, + Up60ToFlatLongBase = 119, + Whirlpool = 120, + Down60ToFlatLongBase = 121, + FlatToDown60LongBase = 122, + CableLiftHill = 123, + ReverseFreefallSlope = 124, + ReverseFreefallVertical = 125, + Up90 = 126, + Down90 = 127, + Up60ToUp90 = 128, + Down90ToDown60 = 129, + Up90ToUp60 = 130, + Down60ToDown90 = 131, + BrakeForDrop = 132, + LeftEighthToDiag = 133, + RightEighthToDiag = 134, + LeftEighthToOrthogonal = 135, + RightEighthToOrthogonal = 136, + LeftEighthBankToDiag = 137, + RightEighthBankToDiag = 138, + LeftEighthBankToOrthogonal = 139, + RightEighthBankToOrthogonal = 140, + DiagFlat = 141, + DiagUp25 = 142, + DiagUp60 = 143, + DiagFlatToUp25 = 144, + DiagUp25ToUp60 = 145, + DiagUp60ToUp25 = 146, + DiagUp25ToFlat = 147, + DiagDown25 = 148, + DiagDown60 = 149, + DiagFlatToDown25 = 150, + DiagDown25ToDown60 = 151, + DiagDown60ToDown25 = 152, + DiagDown25ToFlat = 153, + DiagFlatToUp60 = 154, + DiagUp60ToFlat = 155, + DiagFlatToDown60 = 156, + DiagDown60ToFlat = 157, + DiagFlatToLeftBank = 158, + DiagFlatToRightBank = 159, + DiagLeftBankToFlat = 160, + DiagRightBankToFlat = 161, + DiagLeftBankToUp25 = 162, + DiagRightBankToUp25 = 163, + DiagUp25ToLeftBank = 164, + DiagUp25ToRightBank = 165, + DiagLeftBankToDown25 = 166, + DiagRightBankToDown25 = 167, + DiagDown25ToLeftBank = 168, + DiagDown25ToRightBank = 169, + DiagLeftBank = 170, + DiagRightBank = 171, + LogFlumeReverser = 172, + SpinningTunnel = 173, + LeftBarrelRollUpToDown = 174, + RightBarrelRollUpToDown = 175, + LeftBarrelRollDownToUp = 176, + RightBarrelRollDownToUp = 177, + LeftBankToLeftQuarterTurn3TilesUp25 = 178, + RightBankToRightQuarterTurn3TilesUp25 = 179, + LeftQuarterTurn3TilesDown25ToLeftBank = 180, + RightQuarterTurn3TilesDown25ToRightBank = 181, + PoweredLift = 182, + LeftLargeHalfLoopUp = 183, + RightLargeHalfLoopUp = 184, + LeftLargeHalfLoopDown = 185, + RightLargeHalfLoopDown = 186, + LeftFlyerTwistUp = 187, + RightFlyerTwistUp = 188, + LeftFlyerTwistDown = 189, + RightFlyerTwistDown = 190, + FlyerHalfLoopUninvertedUp = 191, + FlyerHalfLoopInvertedDown = 192, + LeftFlyerCorkscrewUp = 193, + RightFlyerCorkscrewUp = 194, + LeftFlyerCorkscrewDown = 195, + RightFlyerCorkscrewDown = 196, + HeartLineTransferUp = 197, + HeartLineTransferDown = 198, + LeftHeartLineRoll = 199, + RightHeartLineRoll = 200, + MinigolfHoleA = 201, + MinigolfHoleB = 202, + MinigolfHoleC = 203, + MinigolfHoleD = 204, + MinigolfHoleE = 205, + MultiDimInvertedFlatToDown90QuarterLoop = 206, + Up90ToInvertedFlatQuarterLoop = 207, + InvertedFlatToDown90QuarterLoop = 208, + LeftCurvedLiftHill = 209, + RightCurvedLiftHill = 210, + LeftReverser = 211, + RightReverser = 212, + AirThrustTopCap = 213, + AirThrustVerticalDown = 214, + AirThrustVerticalDownToLevel = 215, + BlockBrakes = 216, + LeftBankedQuarterTurn3TileUp25 = 217, + RightBankedQuarterTurn3TileUp25 = 218, + LeftBankedQuarterTurn3TileDown25 = 219, + RightBankedQuarterTurn3TileDown25 = 220, + LeftBankedQuarterTurn5TileUp25 = 221, + RightBankedQuarterTurn5TileUp25 = 222, + LeftBankedQuarterTurn5TileDown25 = 223, + RightBankedQuarterTurn5TileDown25 = 224, + Up25ToLeftBankedUp25 = 225, + Up25ToRightBankedUp25 = 226, + LeftBankedUp25ToUp25 = 227, + RightBankedUp25ToUp25 = 228, + Down25ToLeftBankedDown25 = 229, + Down25ToRightBankedDown25 = 230, + LeftBankedDown25ToDown25 = 231, + RightBankedDown25ToDown25 = 232, + LeftBankedFlatToLeftBankedUp25 = 233, + RightBankedFlatToRightBankedUp25 = 234, + LeftBankedUp25ToLeftBankedFlat = 235, + RightBankedUp25ToRightBankedFlat = 236, + LeftBankedFlatToLeftBankedDown25 = 237, + RightBankedFlatToRightBankedDown25 = 238, + LeftBankedDown25ToLeftBankedFlat = 239, + RightBankedDown25ToRightBankedFlat = 240, + FlatToLeftBankedUp25 = 241, + FlatToRightBankedUp25 = 242, + LeftBankedUp25ToFlat = 243, + RightBankedUp25ToFlat = 244, + FlatToLeftBankedDown25 = 245, + FlatToRightBankedDown25 = 246, + LeftBankedDown25ToFlat = 247, + RightBankedDown25ToFlat = 248, + LeftQuarterTurn1TileUp90 = 249, + RightQuarterTurn1TileUp90 = 250, + LeftQuarterTurn1TileDown90 = 251, + RightQuarterTurn1TileDown90 = 252, + MultiDimUp90ToInvertedFlatQuarterLoop = 253, + MultiDimFlatToDown90QuarterLoop = 254, + MultiDimInvertedUp90ToFlatQuarterLoop = 255, + + // SV6/TD6 element aliases + RotationControlToggleAlias = 100, + InvertedUp90ToFlatQuarterLoopAlias = 101, + FlatTrack1x4A_Alias = 95, + FlatTrack2x2_Alias = 110, + FlatTrack4x4_Alias = 111, + FlatTrack2x4_Alias = 115, + FlatTrack1x5_Alias = 116, + FlatTrack1x1A_Alias = 118, + FlatTrack1x4B_Alias = 119, + FlatTrack1x1B_Alias = 121, + FlatTrack1x4C_Alias = 122, + FlatTrack3x3_Alias = 123, + }; +} // namespace OpenRCT2::RCT12 constexpr uint8_t RCT2_STRING_FORMAT_ARG_START = 123; constexpr uint8_t RCT2_STRING_FORMAT_ARG_END = 141; @@ -264,8 +540,8 @@ static_assert(sizeof(TD46MazeElement) == 0x04); /* Track Element entry size: 0x02 */ struct TD46TrackElement { - uint8_t Type; // 0x00 - uint8_t Flags; // 0x01 + OpenRCT2::RCT12::TrackElemType Type; // 0x00 + uint8_t Flags; // 0x01 }; static_assert(sizeof(TD46TrackElement) == 0x02); @@ -508,7 +784,7 @@ static_assert(sizeof(RCT12PathElement) == 8); struct RCT12TrackElement : RCT12TileElementBase { private: - uint8_t TrackType; // 4 + OpenRCT2::RCT12::TrackElemType TrackType; // 4 union { struct @@ -531,7 +807,7 @@ private: }; uint8_t RideIndex; // 7 public: - uint8_t GetTrackType() const; + OpenRCT2::RCT12::TrackElemType GetTrackType() const; uint8_t GetSequenceIndex() const; uint8_t GetRideIndex() const; RideColourScheme GetColourScheme() const; @@ -908,8 +1184,8 @@ RideId RCT12RideIdToOpenRCT2RideId(const RCT12RideId rideId); bool IsLikelyUTF8(std::string_view s); std::string RCT12RemoveFormattingUTF8(std::string_view s); std::string ConvertFormattedStringToOpenRCT2(std::string_view buffer); -track_type_t RCT12FlatTrackTypeToOpenRCT2(RCT12TrackType origTrackType); -RCT12TrackType OpenRCT2FlatTrackTypeToRCT12(track_type_t origTrackType); +OpenRCT2::TrackElemType RCT12FlatTrackTypeToOpenRCT2(OpenRCT2::RCT12::TrackElemType origTrackType); +OpenRCT2::RCT12::TrackElemType OpenRCT2FlatTrackTypeToRCT12(OpenRCT2::TrackElemType origTrackType); std::string_view GetStationIdentifierFromStyle(uint8_t style); uint8_t GetStationStyleFromIdentifier(u8string_view identifier); std::optional GetStyleFromMusicIdentifier(std::string_view identifier); @@ -967,4 +1243,6 @@ namespace OpenRCT2::RCT12 * Handles single and multi-byte strings. */ size_t GetRCTStringBufferLen(const char* buffer, size_t maxBufferLen); + bool TrackTypeHasSpeedSetting(OpenRCT2::RCT12::TrackElemType trackType); + bool TrackTypeIsStation(OpenRCT2::RCT12::TrackElemType trackType); } // namespace OpenRCT2::RCT12 diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp index c0a5d58623..c5b184f9d5 100644 --- a/src/openrct2/rct12/ScenarioPatcher.cpp +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -207,7 +207,7 @@ static void ApplyWaterFixes(const json_t& scenarioPatch) } } -static track_type_t toTrackType(const u8string_view trackTypeString) +static OpenRCT2::TrackElemType toTrackType(const u8string_view trackTypeString) { if (trackTypeString == "flat") return OpenRCT2::TrackElemType::Flat; diff --git a/src/openrct2/rct2/RCT2.cpp b/src/openrct2/rct2/RCT2.cpp index 10f04fd704..fdefdf8f2c 100644 --- a/src/openrct2/rct2/RCT2.cpp +++ b/src/openrct2/rct2/RCT2.cpp @@ -97,39 +97,40 @@ namespace OpenRCT2::RCT2 return MinMaxCarsPerTrain & 0xF; } - void Ride::SetMinCarsPerTrain(uint8_t newValue) + OpenRCT2::TrackElemType RCT2TrackTypeToOpenRCT2( + OpenRCT2::RCT12::TrackElemType origTrackType, ride_type_t rideType, bool isFlatRide) { - MinMaxCarsPerTrain &= ~0xF0; - MinMaxCarsPerTrain |= (newValue << 4); + auto originalClass = OriginalRideClass::Regular; + if (rideType == RIDE_TYPE_STEEL_WILD_MOUSE || rideType == RIDE_TYPE_SPINNING_WILD_MOUSE) + originalClass = OriginalRideClass::WildMouse; + if (isFlatRide) + originalClass = OriginalRideClass::FlatRide; + + return RCT2TrackTypeToOpenRCT2(origTrackType, originalClass); } - void Ride::SetMaxCarsPerTrain(uint8_t newValue) + OpenRCT2::TrackElemType RCT2TrackTypeToOpenRCT2( + OpenRCT2::RCT12::TrackElemType origTrackType, OriginalRideClass originalClass) { - MinMaxCarsPerTrain &= ~0x0F; - MinMaxCarsPerTrain |= newValue & 0x0F; + switch (originalClass) + { + case OriginalRideClass::FlatRide: + return RCT12FlatTrackTypeToOpenRCT2(origTrackType); + case OriginalRideClass::WildMouse: + // Boosters share their ID with the Spinning Control track. + if (origTrackType == OpenRCT2::RCT12::TrackElemType::RotationControlToggleAlias) + return OpenRCT2::TrackElemType::RotationControlToggle; + return static_cast(origTrackType); + case OriginalRideClass::Regular: + default: + return static_cast(origTrackType); + } } - bool RCT2TrackTypeIsBooster(ride_type_t rideType, uint16_t trackType) - { - // Boosters share their ID with the Spinning Control track. - return rideType != RIDE_TYPE_SPINNING_WILD_MOUSE && rideType != RIDE_TYPE_STEEL_WILD_MOUSE - && trackType == TrackElemType::Booster; - } - - track_type_t RCT2TrackTypeToOpenRCT2(RCT12TrackType origTrackType, ride_type_t rideType, bool convertFlat) - { - if (convertFlat && GetRideTypeDescriptor(rideType).HasFlag(RtdFlag::isFlatRide)) - return RCT12FlatTrackTypeToOpenRCT2(origTrackType); - if (origTrackType == TrackElemType::RotationControlToggleAlias && !RCT2TrackTypeIsBooster(rideType, origTrackType)) - return TrackElemType::RotationControlToggle; - - return origTrackType; - } - - RCT12TrackType OpenRCT2TrackTypeToRCT2(track_type_t origTrackType) + OpenRCT2::RCT12::TrackElemType OpenRCT2TrackTypeToRCT2(OpenRCT2::TrackElemType origTrackType) { if (origTrackType == TrackElemType::RotationControlToggle) - return TrackElemType::RotationControlToggleAlias; + return OpenRCT2::RCT12::TrackElemType::RotationControlToggleAlias; // This function is safe to run this way round. return OpenRCT2FlatTrackTypeToRCT12(origTrackType); diff --git a/src/openrct2/rct2/RCT2.h b/src/openrct2/rct2/RCT2.h index 0994924a1b..645d3e94b2 100644 --- a/src/openrct2/rct2/RCT2.h +++ b/src/openrct2/rct2/RCT2.h @@ -278,8 +278,6 @@ namespace OpenRCT2::RCT2 uint8_t GetMinCarsPerTrain() const; uint8_t GetMaxCarsPerTrain() const; - void SetMinCarsPerTrain(uint8_t newValue); - void SetMaxCarsPerTrain(uint8_t newValue); }; static_assert(sizeof(Ride) == 0x260); @@ -506,19 +504,19 @@ namespace OpenRCT2::RCT2 uint8_t SeatRotation; // 0xD8 uint8_t TargetSeatRotation; // 0xD9 - uint16_t GetTrackType() const + OpenRCT2::RCT12::TrackElemType GetTrackType() const { - return TrackTypeAndDirection >> 2; + return static_cast(TrackTypeAndDirection >> 2); } uint8_t GetTrackDirection() const { return TrackTypeAndDirection & RCT12VehicleTrackDirectionMask; } - void SetTrackType(uint16_t trackType) + void SetTrackType(OpenRCT2::RCT12::TrackElemType trackType) { // set the upper 14 bits to 0 TrackTypeAndDirection &= ~RCT12VehicleTrackTypeMask; - TrackTypeAndDirection |= trackType << 2; + TrackTypeAndDirection |= EnumValue(trackType) << 2; } void SetTrackDirection(uint8_t trackDirection) { @@ -728,7 +726,7 @@ namespace OpenRCT2::RCT2 uint16_t ProximityStartZ; uint8_t CurrentRide; uint8_t State; - uint8_t ProximityTrackType; + OpenRCT2::RCT12::TrackElemType ProximityTrackType; uint8_t ProximityBaseHeight; uint16_t ProximityTotal; uint16_t ProximityScores[26]; @@ -1013,11 +1011,21 @@ namespace OpenRCT2::RCT2 #pragma pack(pop) ObjectEntryIndex RCT2RideTypeToOpenRCT2RideType(uint8_t rct2RideType, const RideObjectEntry& rideEntry); - bool RCT2TrackTypeIsBooster(ride_type_t rideType, uint16_t trackType); bool RCT2RideTypeNeedsConversion(uint8_t rct2RideType); uint8_t OpenRCT2RideTypeToRCT2RideType(ObjectEntryIndex openrct2Type); - track_type_t RCT2TrackTypeToOpenRCT2(RCT12TrackType origTrackType, ride_type_t rideType, bool convertFlat); - RCT12TrackType OpenRCT2TrackTypeToRCT2(track_type_t origTrackType); + + enum class OriginalRideClass + { + Regular, + WildMouse, + FlatRide, + }; + + OpenRCT2::TrackElemType RCT2TrackTypeToOpenRCT2( + OpenRCT2::RCT12::TrackElemType origTrackType, ride_type_t rideType, bool isFlatRide); + OpenRCT2::TrackElemType RCT2TrackTypeToOpenRCT2( + OpenRCT2::RCT12::TrackElemType origTrackType, OriginalRideClass originalClass); + OpenRCT2::RCT12::TrackElemType OpenRCT2TrackTypeToRCT2(OpenRCT2::TrackElemType origTrackType); struct FootpathMapping { diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 06476b20db..301b5d5cc1 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1003,10 +1003,14 @@ namespace OpenRCT2::RCT2 dst.CurrentRide = RCT12RideIdToOpenRCT2RideId(src.CurrentRide); dst.State = src.State; if (src.CurrentRide < Limits::kMaxRidesInPark && _s6.Rides[src.CurrentRide].Type < std::size(RideTypeDescriptors)) + { dst.ProximityTrackType = RCT2TrackTypeToOpenRCT2( src.ProximityTrackType, _s6.Rides[src.CurrentRide].Type, IsFlatRide(src.CurrentRide)); + } else - dst.ProximityTrackType = 0xFF; + { + dst.ProximityTrackType = TrackElemType::None; + } dst.ProximityBaseHeight = src.ProximityBaseHeight; dst.ProximityTotal = src.ProximityTotal; for (size_t i = 0; i < std::size(src.ProximityScores); i++) @@ -1325,9 +1329,11 @@ namespace OpenRCT2::RCT2 auto src2 = src->AsTrack(); auto rideType = _s6.Rides[src2->GetRideIndex()].Type; - track_type_t trackType = static_cast(src2->GetTrackType()); + auto oldTrackType = src2->GetTrackType(); + OpenRCT2::TrackElemType trackType = RCT2TrackTypeToOpenRCT2( + oldTrackType, rideType, IsFlatRide(src2->GetRideIndex())); - dst2->SetTrackType(RCT2TrackTypeToOpenRCT2(trackType, rideType, IsFlatRide(src2->GetRideIndex()))); + dst2->SetTrackType(trackType); dst2->SetRideType(rideType); dst2->SetSequenceIndex(src2->GetSequenceIndex()); dst2->SetRideIndex(RCT12RideIdToOpenRCT2RideId(src2->GetRideIndex())); @@ -1893,26 +1899,25 @@ namespace OpenRCT2::RCT2 { dst->BoatLocation.SetNull(); dst->SetTrackDirection(src->GetTrackDirection()); - dst->SetTrackType(src->GetTrackType()); + // Skipping OriginalRideClass::WildMouse - this is handled specifically. + auto originalClass = IsFlatRide(src->Ride) ? OriginalRideClass::FlatRide : OriginalRideClass::Regular; + auto convertedType = RCT2TrackTypeToOpenRCT2(src->GetTrackType(), originalClass); + dst->SetTrackType(convertedType); // RotationControlToggle and Booster are saved as the same track piece ID // Which one the vehicle is using must be determined - if (IsFlatRide(src->Ride)) - { - dst->SetTrackType(RCT12FlatTrackTypeToOpenRCT2(src->GetTrackType())); - } - else if (src->GetTrackType() == TrackElemType::RotationControlToggleAlias) + if (src->GetTrackType() == OpenRCT2::RCT12::TrackElemType::RotationControlToggleAlias) { // Merging hacks mean the track type that's appropriate for the ride type is not necessarily the track type the // ride is on. It's possible to create unwanted behavior if a user layers spinning control track on top of // booster track but this is unlikely since only two rides have spinning control track - by default they load as - // booster + // booster. TileElement* tileElement2 = MapGetTrackElementAtOfTypeSeq( dst->TrackLocation, TrackElemType::RotationControlToggle, 0); if (tileElement2 != nullptr) dst->SetTrackType(TrackElemType::RotationControlToggle); } - else if (src->GetTrackType() == TrackElemType::BlockBrakes) + else if (src->GetTrackType() == OpenRCT2::RCT12::TrackElemType::BlockBrakes) { dst->brake_speed = kRCT2DefaultBlockBrakeSpeed; } @@ -1921,7 +1926,7 @@ namespace OpenRCT2::RCT2 { dst->BoatLocation = TileCoordsXY{ src->BoatLocation.x, src->BoatLocation.y }.ToCoordsXY(); dst->SetTrackDirection(0); - dst->SetTrackType(0); + dst->SetTrackType(OpenRCT2::TrackElemType::Flat); } dst->next_vehicle_on_train = EntityId::FromUnderlying(src->NextVehicleOnTrain); diff --git a/src/openrct2/rct2/T6Exporter.cpp b/src/openrct2/rct2/T6Exporter.cpp index 59e524879d..25bcce1aef 100644 --- a/src/openrct2/rct2/T6Exporter.cpp +++ b/src/openrct2/rct2/T6Exporter.cpp @@ -140,9 +140,9 @@ namespace OpenRCT2::RCT2 for (const auto& trackElement : _trackDesign.trackElements) { auto trackType = OpenRCT2TrackTypeToRCT2(trackElement.type); - if (trackType == TrackElemType::MultiDimInvertedUp90ToFlatQuarterLoop) + if (trackElement.type == TrackElemType::MultiDimInvertedUp90ToFlatQuarterLoop) { - trackType = TrackElemType::InvertedUp90ToFlatQuarterLoopAlias; + trackType = OpenRCT2::RCT12::TrackElemType::InvertedUp90ToFlatQuarterLoopAlias; } tempStream.WriteValue(static_cast(trackType)); auto flags = ConvertToTD46Flags(trackElement); diff --git a/src/openrct2/rct2/T6Importer.cpp b/src/openrct2/rct2/T6Importer.cpp index f017f0c989..913e8e3923 100644 --- a/src/openrct2/rct2/T6Importer.cpp +++ b/src/openrct2/rct2/T6Importer.cpp @@ -154,11 +154,17 @@ namespace OpenRCT2::RCT2 _stream.Read(&t6TrackElement, sizeof(TD46TrackElement)); TrackDesignTrackElement trackElement{}; - track_type_t trackType = RCT2TrackTypeToOpenRCT2(t6TrackElement.Type, td->trackAndVehicle.rtdIndex, true); - if (trackType == TrackElemType::InvertedUp90ToFlatQuarterLoopAlias) + OpenRCT2::TrackElemType trackType; + if (t6TrackElement.Type == OpenRCT2::RCT12::TrackElemType::InvertedUp90ToFlatQuarterLoopAlias) { trackType = TrackElemType::MultiDimInvertedUp90ToFlatQuarterLoop; } + else + { + auto rideType = td->trackAndVehicle.rtdIndex; + const bool isFlatRide = GetRideTypeDescriptor(rideType).HasFlag(RtdFlag::isFlatRide); + trackType = RCT2TrackTypeToOpenRCT2(t6TrackElement.Type, rideType, isFlatRide); + } trackElement.type = trackType; ConvertFromTD46Flags(trackElement, t6TrackElement.Flags); diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index b19cd45540..d0dab6064d 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -2994,7 +2994,7 @@ static bool RideCheckStartAndEndIsStation(const CoordsXYE& input) */ static void RideSetBoatHireReturnPoint(Ride& ride, const CoordsXYE& startElement) { - int32_t trackType = -1; + auto trackType = TrackElemType::None; auto returnPos = startElement; int32_t startX = returnPos.x; int32_t startY = returnPos.y; @@ -3002,7 +3002,7 @@ static void RideSetBoatHireReturnPoint(Ride& ride, const CoordsXYE& startElement while (TrackBlockGetPrevious(returnPos, &trackBeginEnd)) { // If previous track is back to the starting x, y, then break loop (otherwise possible infinite loop) - if (trackType != -1 && startX == trackBeginEnd.begin_x && startY == trackBeginEnd.begin_y) + if (trackType != TrackElemType::None && startX == trackBeginEnd.begin_x && startY == trackBeginEnd.begin_y) break; auto trackCoords = CoordsXYZ{ trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_z }; @@ -3114,6 +3114,8 @@ static void RideOpenBlockBrakes(const CoordsXYE& startElement) case TrackElemType::Up60ToFlat: SetBrakeClosedMultiTile(*currentElement.element->AsTrack(), { currentElement.x, currentElement.y }, false); break; + default: + break; } } while (TrackBlockGetNext(¤tElement, ¤tElement, nullptr, nullptr) && currentElement.element != startElement.element); @@ -3587,6 +3589,8 @@ static void RideCreateVehiclesFindFirstBlock(const Ride& ride, CoordsXYE* outXYE case TrackElemType::BlockBrakes: *outXYElement = { trackPos, reinterpret_cast(trackElement) }; return; + default: + break; } } @@ -4971,7 +4975,7 @@ static std::optional RideGetSmallestStationLength(const Ride& ride) static int32_t RideGetTrackLength(const Ride& ride) { TileElement* tileElement = nullptr; - track_type_t trackType; + OpenRCT2::TrackElemType trackType; CoordsXYZ trackStart; bool foundTrack = false; diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp index 021e7ef1e9..2abe555480 100644 --- a/src/openrct2/ride/RideConstruction.cpp +++ b/src/openrct2/ride/RideConstruction.cpp @@ -62,14 +62,14 @@ RideId _currentRideIndex; CoordsXYZ _currentTrackBegin; uint8_t _currentTrackPieceDirection; -track_type_t _currentTrackPieceType; +OpenRCT2::TrackElemType _currentTrackPieceType; uint8_t _currentTrackSelectionFlags; uint32_t _rideConstructionNextArrowPulse = 0; TrackPitch _currentTrackPitchEnd; TrackRoll _currentTrackRollEnd; bool _currentTrackHasLiftHill; OpenRCT2::SelectedAlternative _currentTrackAlternative{}; -track_type_t _selectedTrackType; +OpenRCT2::TrackElemType _selectedTrackType; TrackRoll _previousTrackRollEnd; TrackPitch _previousTrackPitchEnd; @@ -375,7 +375,8 @@ void RideClearBlockedTiles(const Ride& ride) * bp : flags */ std::optional GetTrackElementOriginAndApplyChanges( - const CoordsXYZD& location, track_type_t type, uint16_t extra_params, TileElement** output_element, uint16_t flags) + const CoordsXYZD& location, OpenRCT2::TrackElemType type, uint16_t extra_params, TileElement** output_element, + uint16_t flags) { // Find the relevant track piece, prefer sequence 0 (this ensures correct behaviour for diagonal track pieces) auto trackElement = MapGetTrackElementAtOfTypeSeq(location, type, 0); @@ -573,7 +574,8 @@ void RideConstructionSetDefaultNextPiece() const auto& rtd = ride->GetRideTypeDescriptor(); - int32_t z, direction, trackType; + int32_t z, direction; + OpenRCT2::TrackElemType trackType; TrackBeginEnd trackBeginEnd; CoordsXYE xyElement; TileElement* tileElement; @@ -700,7 +702,7 @@ void RideSelectNextSection() { RideConstructionInvalidateCurrentTrack(); int32_t direction = _currentTrackPieceDirection; - int32_t type = _currentTrackPieceType; + auto type = _currentTrackPieceType; TileElement* tileElement; auto newCoords = GetTrackElementOriginAndApplyChanges( { _currentTrackBegin, static_cast(direction & 3) }, type, 0, &tileElement, 0); @@ -758,7 +760,7 @@ void RideSelectPreviousSection() { RideConstructionInvalidateCurrentTrack(); int32_t direction = _currentTrackPieceDirection; - int32_t type = _currentTrackPieceType; + auto type = _currentTrackPieceType; TileElement* tileElement; auto newCoords = GetTrackElementOriginAndApplyChanges( { _currentTrackBegin, static_cast(direction & 3) }, type, 0, &tileElement, 0); @@ -1475,7 +1477,7 @@ TrackDrawerEntry getCurrentTrackDrawerEntry(const RideTypeDescriptor& rtd) return getTrackDrawerEntry(rtd, isInverted, isCovered); } -track_type_t GetTrackTypeFromCurve( +OpenRCT2::TrackElemType GetTrackTypeFromCurve( TrackCurve curve, bool startsDiagonal, TrackPitch startSlope, TrackPitch endSlope, TrackRoll startBank, TrackRoll endBank) { for (uint32_t i = 0; i < std::size(gTrackDescriptors); i++) diff --git a/src/openrct2/ride/RideConstruction.h b/src/openrct2/ride/RideConstruction.h index 82fd5bcb25..502d81d90f 100644 --- a/src/openrct2/ride/RideConstruction.h +++ b/src/openrct2/ride/RideConstruction.h @@ -18,8 +18,6 @@ #include #include -using track_type_t = uint16_t; - struct TileElement; struct CoordsXYE; struct RideTypeDescriptor; @@ -65,14 +63,14 @@ extern RideId _currentRideIndex; extern CoordsXYZ _currentTrackBegin; extern uint8_t _currentTrackPieceDirection; -extern track_type_t _currentTrackPieceType; +extern OpenRCT2::TrackElemType _currentTrackPieceType; extern uint8_t _currentTrackSelectionFlags; extern uint32_t _rideConstructionNextArrowPulse; extern TrackPitch _currentTrackPitchEnd; extern TrackRoll _currentTrackRollEnd; extern bool _currentTrackHasLiftHill; extern OpenRCT2::SelectedAlternative _currentTrackAlternative; -extern track_type_t _selectedTrackType; +extern OpenRCT2::TrackElemType _selectedTrackType; extern TrackRoll _previousTrackRollEnd; extern TrackPitch _previousTrackPitchEnd; @@ -111,5 +109,5 @@ void RideConstructionStart(Ride& ride); TrackDrawerDescriptor getCurrentTrackDrawerDescriptor(const RideTypeDescriptor& rtd); TrackDrawerEntry getCurrentTrackDrawerEntry(const RideTypeDescriptor& rtd); -track_type_t GetTrackTypeFromCurve( +OpenRCT2::TrackElemType GetTrackTypeFromCurve( TrackCurve curve, bool startsDiagonal, TrackPitch startSlope, TrackPitch endSlope, TrackRoll startBank, TrackRoll endBank); diff --git a/src/openrct2/ride/RideData.h b/src/openrct2/ride/RideData.h index 4f66406ee7..083ee615db 100644 --- a/src/openrct2/ride/RideData.h +++ b/src/openrct2/ride/RideData.h @@ -275,7 +275,7 @@ using StartRideMusicFunction = void (*)(const OpenRCT2::RideAudio::ViewportRideM using LightFXAddLightsMagicVehicleFunction = void (*)(const Vehicle* vehicle); using RideLocationFunction = CoordsXY (*)(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation); using RideUpdateFunction = void (*)(Ride& ride); -using RideUpdateMeasurementsSpecialElementsFunc = void (*)(Ride& ride, const track_type_t trackType); +using RideUpdateMeasurementsSpecialElementsFunc = void (*)(Ride& ride, const OpenRCT2::TrackElemType trackType); using MusicTrackOffsetLengthFunc = std::pair (*)(const Ride& ride); using SpecialElementRatingAdjustmentFunc = void (*)(const Ride& ride, int32_t& excitement, int32_t& intensity, int32_t& nausea); @@ -454,7 +454,7 @@ struct RideTypeDescriptor { uint8_t Category{}; /** rct2: 0x0097CC68 */ - track_type_t StartTrackPiece{}; + OpenRCT2::TrackElemType StartTrackPiece{}; TrackDrawerDescriptor TrackPaintFunctions{}; TrackDrawerDescriptor InvertedTrackPaintFunctions{}; uint64_t Flags{}; diff --git a/src/openrct2/ride/RideRatings.cpp b/src/openrct2/ride/RideRatings.cpp index 3c3d38c656..aeab7e76ff 100644 --- a/src/openrct2/ride/RideRatings.cpp +++ b/src/openrct2/ride/RideRatings.cpp @@ -352,7 +352,7 @@ static void ride_ratings_update_state_2(RideRatingUpdateState& state) } auto loc = state.Proximity; - track_type_t trackType = state.ProximityTrackType; + OpenRCT2::TrackElemType trackType = state.ProximityTrackType; TileElement* tileElement = MapGetFirstElementAt(loc); if (tileElement == nullptr) @@ -458,7 +458,7 @@ static void ride_ratings_update_state_5(RideRatingUpdateState& state) } auto loc = state.Proximity; - track_type_t trackType = state.ProximityTrackType; + OpenRCT2::TrackElemType trackType = state.ProximityTrackType; TileElement* tileElement = MapGetFirstElementAt(loc); if (tileElement == nullptr) @@ -863,6 +863,8 @@ static void ride_ratings_score_close_proximity(RideRatingUpdateState& state, Til case TrackElemType::RightReverser: state.AmountOfReversers++; break; + default: + break; } } diff --git a/src/openrct2/ride/RideRatings.h b/src/openrct2/ride/RideRatings.h index 1e3394b1f8..bcef677b30 100644 --- a/src/openrct2/ride/RideRatings.h +++ b/src/openrct2/ride/RideRatings.h @@ -15,7 +15,10 @@ #include "RideTypes.h" using ride_rating = fixed16_2dp; -using track_type_t = uint16_t; +namespace OpenRCT2 +{ + enum class TrackElemType : uint16_t; +} // Convenience function for writing ride ratings. The result is a 16 bit signed // integer. To create the ride rating 3.65 type RIDE_RATING(3,65) @@ -49,7 +52,7 @@ struct RideRatingUpdateState CoordsXYZ ProximityStart; RideId CurrentRide; uint8_t State; - track_type_t ProximityTrackType; + OpenRCT2::TrackElemType ProximityTrackType; uint8_t ProximityBaseHeight; uint16_t ProximityTotal; uint16_t ProximityScores[26]; diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index 7b04d0878c..d3c2b6f7d5 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -41,13 +41,13 @@ using namespace OpenRCT2; using namespace OpenRCT2::TrackMetaData; -PitchAndRoll TrackPitchAndRollStart(track_type_t trackType) +PitchAndRoll TrackPitchAndRollStart(OpenRCT2::TrackElemType trackType) { const auto& ted = GetTrackElementDescriptor(trackType); return { ted.definition.pitchStart, ted.definition.rollStart }; } -PitchAndRoll TrackPitchAndRollEnd(track_type_t trackType) +PitchAndRoll TrackPitchAndRollEnd(OpenRCT2::TrackElemType trackType) { const auto& ted = GetTrackElementDescriptor(trackType); return { ted.definition.pitchEnd, ted.definition.rollEnd }; @@ -217,7 +217,7 @@ ResultWithMessage TrackAddStationElement(CoordsXYZD loc, RideId rideIndex, int32 stationElement = find_station_element(loc, rideIndex); if (stationElement != nullptr) { - track_type_t targetTrackType; + OpenRCT2::TrackElemType targetTrackType; if (stationFrontLoc == loc) { auto stationIndex = RideGetFirstEmptyStationStart(*ride); @@ -352,7 +352,7 @@ ResultWithMessage TrackRemoveStationElement(const CoordsXYZD& loc, RideId rideIn stationElement = find_station_element(currentLoc, rideIndex); if (stationElement != nullptr) { - track_type_t targetTrackType; + OpenRCT2::TrackElemType targetTrackType; if ((currentLoc == stationFrontLoc) || (currentLoc + CoordsDirectionDelta[currentLoc.direction] == removeLoc)) { auto stationIndex = RideGetFirstEmptyStationStart(*ride); @@ -563,6 +563,8 @@ bool TrackElement::IsBlockStart() const return true; } break; + default: + break; } return false; } @@ -615,7 +617,7 @@ bool TrackElement::IsStation() const return TrackTypeIsStation(GetTrackType()); } -bool TrackTypeIsStation(track_type_t trackType) +bool TrackTypeIsStation(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -628,7 +630,7 @@ bool TrackTypeIsStation(track_type_t trackType) } } -bool TrackTypeIsBrakes(track_type_t trackType) +bool TrackTypeIsBrakes(OpenRCT2::TrackElemType trackType) { switch (trackType) { @@ -641,17 +643,17 @@ bool TrackTypeIsBrakes(track_type_t trackType) } } -bool TrackTypeIsBlockBrakes(track_type_t trackType) +bool TrackTypeIsBlockBrakes(OpenRCT2::TrackElemType trackType) { return (trackType == TrackElemType::BlockBrakes) || (trackType == TrackElemType::DiagBlockBrakes); } -bool TrackTypeIsBooster(track_type_t trackType) +bool TrackTypeIsBooster(OpenRCT2::TrackElemType trackType) { return trackType == TrackElemType::Booster; } -bool TrackElementIsCovered(track_type_t trackElementType) +bool TrackElementIsCovered(OpenRCT2::TrackElemType trackElementType) { switch (trackElementType) { @@ -680,7 +682,7 @@ bool TrackElementIsCovered(track_type_t trackElementType) } } -track_type_t UncoverTrackElement(track_type_t trackElementType) +OpenRCT2::TrackElemType UncoverTrackElement(OpenRCT2::TrackElemType trackElementType) { switch (trackElementType) { @@ -727,12 +729,12 @@ track_type_t UncoverTrackElement(track_type_t trackElementType) } } -bool TrackTypeHasSpeedSetting(track_type_t trackType) +bool TrackTypeHasSpeedSetting(OpenRCT2::TrackElemType trackType) { return TrackTypeIsBooster(trackType) || TrackTypeIsBrakes(trackType) || TrackTypeIsBlockBrakes(trackType); } -bool TrackTypeIsHelix(track_type_t trackType) +bool TrackTypeIsHelix(OpenRCT2::TrackElemType trackType) { if (trackType >= TrackElemType::LeftHalfBankedHelixUpSmall && trackType <= TrackElemType::RightHalfBankedHelixDownLarge) return true; @@ -829,12 +831,12 @@ void TrackElement::MazeEntrySubtract(uint16_t subVal) UMaze.MazeEntry &= ~subVal; } -track_type_t TrackElement::GetTrackType() const +OpenRCT2::TrackElemType TrackElement::GetTrackType() const { return TrackType; } -void TrackElement::SetTrackType(uint16_t newType) +void TrackElement::SetTrackType(OpenRCT2::TrackElemType newType) { TrackType = newType; } diff --git a/src/openrct2/ride/Track.h b/src/openrct2/ride/Track.h index 6a891e51dd..e6f47cefe0 100644 --- a/src/openrct2/ride/Track.h +++ b/src/openrct2/ride/Track.h @@ -22,7 +22,10 @@ constexpr int32_t kBlockBrakeSpeedOffset = kBlockBrakeBaseSpeed - (kRCT2DefaultB constexpr uint8_t kMaximumTrackSpeed = 30; -using track_type_t = uint16_t; +namespace OpenRCT2 +{ + enum class TrackElemType : uint16_t; +} struct ResultWithMessage; @@ -260,379 +263,368 @@ enum TRACK_ELEM_FLAG_CAN_BE_PARTLY_UNDERGROUND = (1 << 16), }; -namespace OpenRCT2::TrackElemType +namespace OpenRCT2 { - constexpr track_type_t Flat = 0; - constexpr track_type_t EndStation = 1; - constexpr track_type_t BeginStation = 2; - constexpr track_type_t MiddleStation = 3; - constexpr track_type_t Up25 = 4; - constexpr track_type_t Up60 = 5; - constexpr track_type_t FlatToUp25 = 6; - constexpr track_type_t Up25ToUp60 = 7; - constexpr track_type_t Up60ToUp25 = 8; - constexpr track_type_t Up25ToFlat = 9; - constexpr track_type_t Down25 = 10; - constexpr track_type_t Down60 = 11; - constexpr track_type_t FlatToDown25 = 12; - constexpr track_type_t Down25ToDown60 = 13; - constexpr track_type_t Down60ToDown25 = 14; - constexpr track_type_t Down25ToFlat = 15; - constexpr track_type_t LeftQuarterTurn5Tiles = 16; - constexpr track_type_t RightQuarterTurn5Tiles = 17; - constexpr track_type_t FlatToLeftBank = 18; - constexpr track_type_t FlatToRightBank = 19; - constexpr track_type_t LeftBankToFlat = 20; - constexpr track_type_t RightBankToFlat = 21; - constexpr track_type_t BankedLeftQuarterTurn5Tiles = 22; - constexpr track_type_t BankedRightQuarterTurn5Tiles = 23; - constexpr track_type_t LeftBankToUp25 = 24; - constexpr track_type_t RightBankToUp25 = 25; - constexpr track_type_t Up25ToLeftBank = 26; - constexpr track_type_t Up25ToRightBank = 27; - constexpr track_type_t LeftBankToDown25 = 28; - constexpr track_type_t RightBankToDown25 = 29; - constexpr track_type_t Down25ToLeftBank = 30; - constexpr track_type_t Down25ToRightBank = 31; - constexpr track_type_t LeftBank = 32; - constexpr track_type_t RightBank = 33; - constexpr track_type_t LeftQuarterTurn5TilesUp25 = 34; - constexpr track_type_t RightQuarterTurn5TilesUp25 = 35; - constexpr track_type_t LeftQuarterTurn5TilesDown25 = 36; - constexpr track_type_t RightQuarterTurn5TilesDown25 = 37; - constexpr track_type_t SBendLeft = 38; - constexpr track_type_t SBendRight = 39; - constexpr track_type_t LeftVerticalLoop = 40; - constexpr track_type_t RightVerticalLoop = 41; - constexpr track_type_t LeftQuarterTurn3Tiles = 42; - constexpr track_type_t RightQuarterTurn3Tiles = 43; - constexpr track_type_t LeftBankedQuarterTurn3Tiles = 44; - constexpr track_type_t RightBankedQuarterTurn3Tiles = 45; - constexpr track_type_t LeftQuarterTurn3TilesUp25 = 46; - constexpr track_type_t RightQuarterTurn3TilesUp25 = 47; - constexpr track_type_t LeftQuarterTurn3TilesDown25 = 48; - constexpr track_type_t RightQuarterTurn3TilesDown25 = 49; - constexpr track_type_t LeftQuarterTurn1Tile = 50; - constexpr track_type_t RightQuarterTurn1Tile = 51; - constexpr track_type_t LeftTwistDownToUp = 52; - constexpr track_type_t RightTwistDownToUp = 53; - constexpr track_type_t LeftTwistUpToDown = 54; - constexpr track_type_t RightTwistUpToDown = 55; - constexpr track_type_t HalfLoopUp = 56; - constexpr track_type_t HalfLoopDown = 57; - constexpr track_type_t LeftCorkscrewUp = 58; - constexpr track_type_t RightCorkscrewUp = 59; - constexpr track_type_t LeftCorkscrewDown = 60; - constexpr track_type_t RightCorkscrewDown = 61; - constexpr track_type_t FlatToUp60 = 62; - constexpr track_type_t Up60ToFlat = 63; - constexpr track_type_t FlatToDown60 = 64; - constexpr track_type_t Down60ToFlat = 65; - constexpr track_type_t TowerBase = 66; - constexpr track_type_t TowerSection = 67; - constexpr track_type_t FlatCovered = 68; - constexpr track_type_t Up25Covered = 69; - constexpr track_type_t Up60Covered = 70; - constexpr track_type_t FlatToUp25Covered = 71; - constexpr track_type_t Up25ToUp60Covered = 72; - constexpr track_type_t Up60ToUp25Covered = 73; - constexpr track_type_t Up25ToFlatCovered = 74; - constexpr track_type_t Down25Covered = 75; - constexpr track_type_t Down60Covered = 76; - constexpr track_type_t FlatToDown25Covered = 77; - constexpr track_type_t Down25ToDown60Covered = 78; - constexpr track_type_t Down60ToDown25Covered = 79; - constexpr track_type_t Down25ToFlatCovered = 80; - constexpr track_type_t LeftQuarterTurn5TilesCovered = 81; - constexpr track_type_t RightQuarterTurn5TilesCovered = 82; - constexpr track_type_t SBendLeftCovered = 83; - constexpr track_type_t SBendRightCovered = 84; - constexpr track_type_t LeftQuarterTurn3TilesCovered = 85; - constexpr track_type_t RightQuarterTurn3TilesCovered = 86; - constexpr track_type_t LeftHalfBankedHelixUpSmall = 87; - constexpr track_type_t RightHalfBankedHelixUpSmall = 88; - constexpr track_type_t LeftHalfBankedHelixDownSmall = 89; - constexpr track_type_t RightHalfBankedHelixDownSmall = 90; - constexpr track_type_t LeftHalfBankedHelixUpLarge = 91; - constexpr track_type_t RightHalfBankedHelixUpLarge = 92; - constexpr track_type_t LeftHalfBankedHelixDownLarge = 93; - constexpr track_type_t RightHalfBankedHelixDownLarge = 94; - constexpr track_type_t LeftQuarterTurn1TileUp60 = 95; - constexpr track_type_t RightQuarterTurn1TileUp60 = 96; - constexpr track_type_t LeftQuarterTurn1TileDown60 = 97; - constexpr track_type_t RightQuarterTurn1TileDown60 = 98; - constexpr track_type_t Brakes = 99; - constexpr track_type_t RotationControlToggleAlias = 100; - constexpr track_type_t Booster = 100; - constexpr track_type_t Maze = 101; - constexpr track_type_t LeftQuarterBankedHelixLargeUp = 102; - constexpr track_type_t RightQuarterBankedHelixLargeUp = 103; - constexpr track_type_t LeftQuarterBankedHelixLargeDown = 104; - constexpr track_type_t RightQuarterBankedHelixLargeDown = 105; - constexpr track_type_t LeftQuarterHelixLargeUp = 106; - constexpr track_type_t RightQuarterHelixLargeUp = 107; - constexpr track_type_t LeftQuarterHelixLargeDown = 108; - constexpr track_type_t RightQuarterHelixLargeDown = 109; - constexpr track_type_t Up25LeftBanked = 110; - constexpr track_type_t Up25RightBanked = 111; - constexpr track_type_t Waterfall = 112; - constexpr track_type_t Rapids = 113; - constexpr track_type_t OnRidePhoto = 114; - constexpr track_type_t Down25LeftBanked = 115; - constexpr track_type_t Down25RightBanked = 116; - constexpr track_type_t Watersplash = 117; - constexpr track_type_t FlatToUp60LongBase = 118; - constexpr track_type_t Up60ToFlatLongBase = 119; - constexpr track_type_t Whirlpool = 120; - constexpr track_type_t Down60ToFlatLongBase = 121; - constexpr track_type_t FlatToDown60LongBase = 122; - constexpr track_type_t CableLiftHill = 123; - constexpr track_type_t ReverseFreefallSlope = 124; - constexpr track_type_t ReverseFreefallVertical = 125; - constexpr track_type_t Up90 = 126; - constexpr track_type_t Down90 = 127; - constexpr track_type_t Up60ToUp90 = 128; - constexpr track_type_t Down90ToDown60 = 129; - constexpr track_type_t Up90ToUp60 = 130; - constexpr track_type_t Down60ToDown90 = 131; - constexpr track_type_t BrakeForDrop = 132; - constexpr track_type_t LeftEighthToDiag = 133; - constexpr track_type_t RightEighthToDiag = 134; - constexpr track_type_t LeftEighthToOrthogonal = 135; - constexpr track_type_t RightEighthToOrthogonal = 136; - constexpr track_type_t LeftEighthBankToDiag = 137; - constexpr track_type_t RightEighthBankToDiag = 138; - constexpr track_type_t LeftEighthBankToOrthogonal = 139; - constexpr track_type_t RightEighthBankToOrthogonal = 140; - constexpr track_type_t DiagFlat = 141; - constexpr track_type_t DiagUp25 = 142; - constexpr track_type_t DiagUp60 = 143; - constexpr track_type_t DiagFlatToUp25 = 144; - constexpr track_type_t DiagUp25ToUp60 = 145; - constexpr track_type_t DiagUp60ToUp25 = 146; - constexpr track_type_t DiagUp25ToFlat = 147; - constexpr track_type_t DiagDown25 = 148; - constexpr track_type_t DiagDown60 = 149; - constexpr track_type_t DiagFlatToDown25 = 150; - constexpr track_type_t DiagDown25ToDown60 = 151; - constexpr track_type_t DiagDown60ToDown25 = 152; - constexpr track_type_t DiagDown25ToFlat = 153; - constexpr track_type_t DiagFlatToUp60 = 154; - constexpr track_type_t DiagUp60ToFlat = 155; - constexpr track_type_t DiagFlatToDown60 = 156; - constexpr track_type_t DiagDown60ToFlat = 157; - constexpr track_type_t DiagFlatToLeftBank = 158; - constexpr track_type_t DiagFlatToRightBank = 159; - constexpr track_type_t DiagLeftBankToFlat = 160; - constexpr track_type_t DiagRightBankToFlat = 161; - constexpr track_type_t DiagLeftBankToUp25 = 162; - constexpr track_type_t DiagRightBankToUp25 = 163; - constexpr track_type_t DiagUp25ToLeftBank = 164; - constexpr track_type_t DiagUp25ToRightBank = 165; - constexpr track_type_t DiagLeftBankToDown25 = 166; - constexpr track_type_t DiagRightBankToDown25 = 167; - constexpr track_type_t DiagDown25ToLeftBank = 168; - constexpr track_type_t DiagDown25ToRightBank = 169; - constexpr track_type_t DiagLeftBank = 170; - constexpr track_type_t DiagRightBank = 171; - constexpr track_type_t LogFlumeReverser = 172; - constexpr track_type_t SpinningTunnel = 173; - constexpr track_type_t LeftBarrelRollUpToDown = 174; - constexpr track_type_t RightBarrelRollUpToDown = 175; - constexpr track_type_t LeftBarrelRollDownToUp = 176; - constexpr track_type_t RightBarrelRollDownToUp = 177; - constexpr track_type_t LeftBankToLeftQuarterTurn3TilesUp25 = 178; - constexpr track_type_t RightBankToRightQuarterTurn3TilesUp25 = 179; - constexpr track_type_t LeftQuarterTurn3TilesDown25ToLeftBank = 180; - constexpr track_type_t RightQuarterTurn3TilesDown25ToRightBank = 181; - constexpr track_type_t PoweredLift = 182; - constexpr track_type_t LeftLargeHalfLoopUp = 183; - constexpr track_type_t RightLargeHalfLoopUp = 184; - constexpr track_type_t LeftLargeHalfLoopDown = 185; - constexpr track_type_t RightLargeHalfLoopDown = 186; - constexpr track_type_t LeftFlyerTwistUp = 187; - constexpr track_type_t RightFlyerTwistUp = 188; - constexpr track_type_t LeftFlyerTwistDown = 189; - constexpr track_type_t RightFlyerTwistDown = 190; - constexpr track_type_t FlyerHalfLoopUninvertedUp = 191; - constexpr track_type_t FlyerHalfLoopInvertedDown = 192; - constexpr track_type_t LeftFlyerCorkscrewUp = 193; - constexpr track_type_t RightFlyerCorkscrewUp = 194; - constexpr track_type_t LeftFlyerCorkscrewDown = 195; - constexpr track_type_t RightFlyerCorkscrewDown = 196; - constexpr track_type_t HeartLineTransferUp = 197; - constexpr track_type_t HeartLineTransferDown = 198; - constexpr track_type_t LeftHeartLineRoll = 199; - constexpr track_type_t RightHeartLineRoll = 200; - constexpr track_type_t MinigolfHoleA = 201; - constexpr track_type_t MinigolfHoleB = 202; - constexpr track_type_t MinigolfHoleC = 203; - constexpr track_type_t MinigolfHoleD = 204; - constexpr track_type_t MinigolfHoleE = 205; - constexpr track_type_t MultiDimInvertedFlatToDown90QuarterLoop = 206; - constexpr track_type_t Up90ToInvertedFlatQuarterLoop = 207; - constexpr track_type_t InvertedFlatToDown90QuarterLoop = 208; - constexpr track_type_t LeftCurvedLiftHill = 209; - constexpr track_type_t RightCurvedLiftHill = 210; - constexpr track_type_t LeftReverser = 211; - constexpr track_type_t RightReverser = 212; - constexpr track_type_t AirThrustTopCap = 213; - constexpr track_type_t AirThrustVerticalDown = 214; - constexpr track_type_t AirThrustVerticalDownToLevel = 215; - constexpr track_type_t BlockBrakes = 216; - constexpr track_type_t LeftBankedQuarterTurn3TileUp25 = 217; - constexpr track_type_t RightBankedQuarterTurn3TileUp25 = 218; - constexpr track_type_t LeftBankedQuarterTurn3TileDown25 = 219; - constexpr track_type_t RightBankedQuarterTurn3TileDown25 = 220; - constexpr track_type_t LeftBankedQuarterTurn5TileUp25 = 221; - constexpr track_type_t RightBankedQuarterTurn5TileUp25 = 222; - constexpr track_type_t LeftBankedQuarterTurn5TileDown25 = 223; - constexpr track_type_t RightBankedQuarterTurn5TileDown25 = 224; - constexpr track_type_t Up25ToLeftBankedUp25 = 225; - constexpr track_type_t Up25ToRightBankedUp25 = 226; - constexpr track_type_t LeftBankedUp25ToUp25 = 227; - constexpr track_type_t RightBankedUp25ToUp25 = 228; - constexpr track_type_t Down25ToLeftBankedDown25 = 229; - constexpr track_type_t Down25ToRightBankedDown25 = 230; - constexpr track_type_t LeftBankedDown25ToDown25 = 231; - constexpr track_type_t RightBankedDown25ToDown25 = 232; - constexpr track_type_t LeftBankedFlatToLeftBankedUp25 = 233; - constexpr track_type_t RightBankedFlatToRightBankedUp25 = 234; - constexpr track_type_t LeftBankedUp25ToLeftBankedFlat = 235; - constexpr track_type_t RightBankedUp25ToRightBankedFlat = 236; - constexpr track_type_t LeftBankedFlatToLeftBankedDown25 = 237; - constexpr track_type_t RightBankedFlatToRightBankedDown25 = 238; - constexpr track_type_t LeftBankedDown25ToLeftBankedFlat = 239; - constexpr track_type_t RightBankedDown25ToRightBankedFlat = 240; - constexpr track_type_t FlatToLeftBankedUp25 = 241; - constexpr track_type_t FlatToRightBankedUp25 = 242; - constexpr track_type_t LeftBankedUp25ToFlat = 243; - constexpr track_type_t RightBankedUp25ToFlat = 244; - constexpr track_type_t FlatToLeftBankedDown25 = 245; - constexpr track_type_t FlatToRightBankedDown25 = 246; - constexpr track_type_t LeftBankedDown25ToFlat = 247; - constexpr track_type_t RightBankedDown25ToFlat = 248; - constexpr track_type_t LeftQuarterTurn1TileUp90 = 249; - constexpr track_type_t RightQuarterTurn1TileUp90 = 250; - constexpr track_type_t LeftQuarterTurn1TileDown90 = 251; - constexpr track_type_t RightQuarterTurn1TileDown90 = 252; - constexpr track_type_t MultiDimUp90ToInvertedFlatQuarterLoop = 253; - constexpr track_type_t MultiDimFlatToDown90QuarterLoop = 254; - constexpr track_type_t MultiDimInvertedUp90ToFlatQuarterLoop = 255; - constexpr track_type_t RotationControlToggle = 256; + enum class TrackElemType : uint16_t + { + Flat = 0, + EndStation = 1, + BeginStation = 2, + MiddleStation = 3, + Up25 = 4, + Up60 = 5, + FlatToUp25 = 6, + Up25ToUp60 = 7, + Up60ToUp25 = 8, + Up25ToFlat = 9, + Down25 = 10, + Down60 = 11, + FlatToDown25 = 12, + Down25ToDown60 = 13, + Down60ToDown25 = 14, + Down25ToFlat = 15, + LeftQuarterTurn5Tiles = 16, + RightQuarterTurn5Tiles = 17, + FlatToLeftBank = 18, + FlatToRightBank = 19, + LeftBankToFlat = 20, + RightBankToFlat = 21, + BankedLeftQuarterTurn5Tiles = 22, + BankedRightQuarterTurn5Tiles = 23, + LeftBankToUp25 = 24, + RightBankToUp25 = 25, + Up25ToLeftBank = 26, + Up25ToRightBank = 27, + LeftBankToDown25 = 28, + RightBankToDown25 = 29, + Down25ToLeftBank = 30, + Down25ToRightBank = 31, + LeftBank = 32, + RightBank = 33, + LeftQuarterTurn5TilesUp25 = 34, + RightQuarterTurn5TilesUp25 = 35, + LeftQuarterTurn5TilesDown25 = 36, + RightQuarterTurn5TilesDown25 = 37, + SBendLeft = 38, + SBendRight = 39, + LeftVerticalLoop = 40, + RightVerticalLoop = 41, + LeftQuarterTurn3Tiles = 42, + RightQuarterTurn3Tiles = 43, + LeftBankedQuarterTurn3Tiles = 44, + RightBankedQuarterTurn3Tiles = 45, + LeftQuarterTurn3TilesUp25 = 46, + RightQuarterTurn3TilesUp25 = 47, + LeftQuarterTurn3TilesDown25 = 48, + RightQuarterTurn3TilesDown25 = 49, + LeftQuarterTurn1Tile = 50, + RightQuarterTurn1Tile = 51, + LeftTwistDownToUp = 52, + RightTwistDownToUp = 53, + LeftTwistUpToDown = 54, + RightTwistUpToDown = 55, + HalfLoopUp = 56, + HalfLoopDown = 57, + LeftCorkscrewUp = 58, + RightCorkscrewUp = 59, + LeftCorkscrewDown = 60, + RightCorkscrewDown = 61, + FlatToUp60 = 62, + Up60ToFlat = 63, + FlatToDown60 = 64, + Down60ToFlat = 65, + TowerBase = 66, + TowerSection = 67, + FlatCovered = 68, + Up25Covered = 69, + Up60Covered = 70, + FlatToUp25Covered = 71, + Up25ToUp60Covered = 72, + Up60ToUp25Covered = 73, + Up25ToFlatCovered = 74, + Down25Covered = 75, + Down60Covered = 76, + FlatToDown25Covered = 77, + Down25ToDown60Covered = 78, + Down60ToDown25Covered = 79, + Down25ToFlatCovered = 80, + LeftQuarterTurn5TilesCovered = 81, + RightQuarterTurn5TilesCovered = 82, + SBendLeftCovered = 83, + SBendRightCovered = 84, + LeftQuarterTurn3TilesCovered = 85, + RightQuarterTurn3TilesCovered = 86, + LeftHalfBankedHelixUpSmall = 87, + RightHalfBankedHelixUpSmall = 88, + LeftHalfBankedHelixDownSmall = 89, + RightHalfBankedHelixDownSmall = 90, + LeftHalfBankedHelixUpLarge = 91, + RightHalfBankedHelixUpLarge = 92, + LeftHalfBankedHelixDownLarge = 93, + RightHalfBankedHelixDownLarge = 94, + LeftQuarterTurn1TileUp60 = 95, + RightQuarterTurn1TileUp60 = 96, + LeftQuarterTurn1TileDown60 = 97, + RightQuarterTurn1TileDown60 = 98, + Brakes = 99, + Booster = 100, + Maze = 101, + LeftQuarterBankedHelixLargeUp = 102, + RightQuarterBankedHelixLargeUp = 103, + LeftQuarterBankedHelixLargeDown = 104, + RightQuarterBankedHelixLargeDown = 105, + LeftQuarterHelixLargeUp = 106, + RightQuarterHelixLargeUp = 107, + LeftQuarterHelixLargeDown = 108, + RightQuarterHelixLargeDown = 109, + Up25LeftBanked = 110, + Up25RightBanked = 111, + Waterfall = 112, + Rapids = 113, + OnRidePhoto = 114, + Down25LeftBanked = 115, + Down25RightBanked = 116, + Watersplash = 117, + FlatToUp60LongBase = 118, + Up60ToFlatLongBase = 119, + Whirlpool = 120, + Down60ToFlatLongBase = 121, + FlatToDown60LongBase = 122, + CableLiftHill = 123, + ReverseFreefallSlope = 124, + ReverseFreefallVertical = 125, + Up90 = 126, + Down90 = 127, + Up60ToUp90 = 128, + Down90ToDown60 = 129, + Up90ToUp60 = 130, + Down60ToDown90 = 131, + BrakeForDrop = 132, + LeftEighthToDiag = 133, + RightEighthToDiag = 134, + LeftEighthToOrthogonal = 135, + RightEighthToOrthogonal = 136, + LeftEighthBankToDiag = 137, + RightEighthBankToDiag = 138, + LeftEighthBankToOrthogonal = 139, + RightEighthBankToOrthogonal = 140, + DiagFlat = 141, + DiagUp25 = 142, + DiagUp60 = 143, + DiagFlatToUp25 = 144, + DiagUp25ToUp60 = 145, + DiagUp60ToUp25 = 146, + DiagUp25ToFlat = 147, + DiagDown25 = 148, + DiagDown60 = 149, + DiagFlatToDown25 = 150, + DiagDown25ToDown60 = 151, + DiagDown60ToDown25 = 152, + DiagDown25ToFlat = 153, + DiagFlatToUp60 = 154, + DiagUp60ToFlat = 155, + DiagFlatToDown60 = 156, + DiagDown60ToFlat = 157, + DiagFlatToLeftBank = 158, + DiagFlatToRightBank = 159, + DiagLeftBankToFlat = 160, + DiagRightBankToFlat = 161, + DiagLeftBankToUp25 = 162, + DiagRightBankToUp25 = 163, + DiagUp25ToLeftBank = 164, + DiagUp25ToRightBank = 165, + DiagLeftBankToDown25 = 166, + DiagRightBankToDown25 = 167, + DiagDown25ToLeftBank = 168, + DiagDown25ToRightBank = 169, + DiagLeftBank = 170, + DiagRightBank = 171, + LogFlumeReverser = 172, + SpinningTunnel = 173, + LeftBarrelRollUpToDown = 174, + RightBarrelRollUpToDown = 175, + LeftBarrelRollDownToUp = 176, + RightBarrelRollDownToUp = 177, + LeftBankToLeftQuarterTurn3TilesUp25 = 178, + RightBankToRightQuarterTurn3TilesUp25 = 179, + LeftQuarterTurn3TilesDown25ToLeftBank = 180, + RightQuarterTurn3TilesDown25ToRightBank = 181, + PoweredLift = 182, + LeftLargeHalfLoopUp = 183, + RightLargeHalfLoopUp = 184, + LeftLargeHalfLoopDown = 185, + RightLargeHalfLoopDown = 186, + LeftFlyerTwistUp = 187, + RightFlyerTwistUp = 188, + LeftFlyerTwistDown = 189, + RightFlyerTwistDown = 190, + FlyerHalfLoopUninvertedUp = 191, + FlyerHalfLoopInvertedDown = 192, + LeftFlyerCorkscrewUp = 193, + RightFlyerCorkscrewUp = 194, + LeftFlyerCorkscrewDown = 195, + RightFlyerCorkscrewDown = 196, + HeartLineTransferUp = 197, + HeartLineTransferDown = 198, + LeftHeartLineRoll = 199, + RightHeartLineRoll = 200, + MinigolfHoleA = 201, + MinigolfHoleB = 202, + MinigolfHoleC = 203, + MinigolfHoleD = 204, + MinigolfHoleE = 205, + MultiDimInvertedFlatToDown90QuarterLoop = 206, + Up90ToInvertedFlatQuarterLoop = 207, + InvertedFlatToDown90QuarterLoop = 208, + LeftCurvedLiftHill = 209, + RightCurvedLiftHill = 210, + LeftReverser = 211, + RightReverser = 212, + AirThrustTopCap = 213, + AirThrustVerticalDown = 214, + AirThrustVerticalDownToLevel = 215, + BlockBrakes = 216, + LeftBankedQuarterTurn3TileUp25 = 217, + RightBankedQuarterTurn3TileUp25 = 218, + LeftBankedQuarterTurn3TileDown25 = 219, + RightBankedQuarterTurn3TileDown25 = 220, + LeftBankedQuarterTurn5TileUp25 = 221, + RightBankedQuarterTurn5TileUp25 = 222, + LeftBankedQuarterTurn5TileDown25 = 223, + RightBankedQuarterTurn5TileDown25 = 224, + Up25ToLeftBankedUp25 = 225, + Up25ToRightBankedUp25 = 226, + LeftBankedUp25ToUp25 = 227, + RightBankedUp25ToUp25 = 228, + Down25ToLeftBankedDown25 = 229, + Down25ToRightBankedDown25 = 230, + LeftBankedDown25ToDown25 = 231, + RightBankedDown25ToDown25 = 232, + LeftBankedFlatToLeftBankedUp25 = 233, + RightBankedFlatToRightBankedUp25 = 234, + LeftBankedUp25ToLeftBankedFlat = 235, + RightBankedUp25ToRightBankedFlat = 236, + LeftBankedFlatToLeftBankedDown25 = 237, + RightBankedFlatToRightBankedDown25 = 238, + LeftBankedDown25ToLeftBankedFlat = 239, + RightBankedDown25ToRightBankedFlat = 240, + FlatToLeftBankedUp25 = 241, + FlatToRightBankedUp25 = 242, + LeftBankedUp25ToFlat = 243, + RightBankedUp25ToFlat = 244, + FlatToLeftBankedDown25 = 245, + FlatToRightBankedDown25 = 246, + LeftBankedDown25ToFlat = 247, + RightBankedDown25ToFlat = 248, + LeftQuarterTurn1TileUp90 = 249, + RightQuarterTurn1TileUp90 = 250, + LeftQuarterTurn1TileDown90 = 251, + RightQuarterTurn1TileDown90 = 252, + MultiDimUp90ToInvertedFlatQuarterLoop = 253, + MultiDimFlatToDown90QuarterLoop = 254, + MultiDimInvertedUp90ToFlatQuarterLoop = 255, - constexpr track_type_t FlatTrack1x4A = 257; - constexpr track_type_t FlatTrack2x2 = 258; - constexpr track_type_t FlatTrack4x4 = 259; - constexpr track_type_t FlatTrack2x4 = 260; - constexpr track_type_t FlatTrack1x5 = 261; - constexpr track_type_t FlatTrack1x1A = 262; - constexpr track_type_t FlatTrack1x4B = 263; - constexpr track_type_t FlatTrack1x1B = 264; - constexpr track_type_t FlatTrack1x4C = 265; - constexpr track_type_t FlatTrack3x3 = 266; + // Elements that shared an ID with another piece in RCT1/2. + RotationControlToggle = 256, + FlatTrack1x4A = 257, + FlatTrack2x2 = 258, + FlatTrack4x4 = 259, + FlatTrack2x4 = 260, + FlatTrack1x5 = 261, + FlatTrack1x1A = 262, + FlatTrack1x4B = 263, + FlatTrack1x1B = 264, + FlatTrack1x4C = 265, + FlatTrack3x3 = 266, - // SV6/TD6 element aliases - constexpr track_type_t InvertedUp90ToFlatQuarterLoopAlias = 101; - constexpr track_type_t FlatTrack1x4A_Alias = 95; - constexpr track_type_t FlatTrack2x2_Alias = 110; - constexpr track_type_t FlatTrack4x4_Alias = 111; - constexpr track_type_t FlatTrack2x4_Alias = 115; - constexpr track_type_t FlatTrack1x5_Alias = 116; - constexpr track_type_t FlatTrack1x1A_Alias = 118; - constexpr track_type_t FlatTrack1x4B_Alias = 119; - constexpr track_type_t FlatTrack1x1B_Alias = 121; - constexpr track_type_t FlatTrack1x4C_Alias = 122; - constexpr track_type_t FlatTrack3x3_Alias = 123; + // Highest track element ID that has a TD6 alias + HighestAlias = 266, - // Highest track element ID that has a TD6 alias - constexpr track_type_t HighestAlias = 266; + // Track Elements specific to OpenRCT2 + LeftLargeCorkscrewUp = 267, + RightLargeCorkscrewUp = 268, + LeftLargeCorkscrewDown = 269, + RightLargeCorkscrewDown = 270, + LeftMediumHalfLoopUp = 271, + RightMediumHalfLoopUp = 272, + LeftMediumHalfLoopDown = 273, + RightMediumHalfLoopDown = 274, + LeftZeroGRollUp = 275, + RightZeroGRollUp = 276, + LeftZeroGRollDown = 277, + RightZeroGRollDown = 278, + LeftLargeZeroGRollUp = 279, + RightLargeZeroGRollUp = 280, + LeftLargeZeroGRollDown = 281, + RightLargeZeroGRollDown = 282, - // Track Elements specific to OpenRCT2 - constexpr track_type_t LeftLargeCorkscrewUp = 267; - constexpr track_type_t RightLargeCorkscrewUp = 268; - constexpr track_type_t LeftLargeCorkscrewDown = 269; - constexpr track_type_t RightLargeCorkscrewDown = 270; - constexpr track_type_t LeftMediumHalfLoopUp = 271; - constexpr track_type_t RightMediumHalfLoopUp = 272; - constexpr track_type_t LeftMediumHalfLoopDown = 273; - constexpr track_type_t RightMediumHalfLoopDown = 274; - constexpr track_type_t LeftZeroGRollUp = 275; - constexpr track_type_t RightZeroGRollUp = 276; - constexpr track_type_t LeftZeroGRollDown = 277; - constexpr track_type_t RightZeroGRollDown = 278; - constexpr track_type_t LeftLargeZeroGRollUp = 279; - constexpr track_type_t RightLargeZeroGRollUp = 280; - constexpr track_type_t LeftLargeZeroGRollDown = 281; - constexpr track_type_t RightLargeZeroGRollDown = 282; + LeftFlyerLargeHalfLoopUninvertedUp = 283, + RightFlyerLargeHalfLoopUninvertedUp = 284, + LeftFlyerLargeHalfLoopInvertedDown = 285, + RightFlyerLargeHalfLoopInvertedDown = 286, + LeftFlyerLargeHalfLoopInvertedUp = 287, + RightFlyerLargeHalfLoopInvertedUp = 288, + LeftFlyerLargeHalfLoopUninvertedDown = 289, + RightFlyerLargeHalfLoopUninvertedDown = 290, - constexpr track_type_t LeftFlyerLargeHalfLoopUninvertedUp = 283; - constexpr track_type_t RightFlyerLargeHalfLoopUninvertedUp = 284; - constexpr track_type_t LeftFlyerLargeHalfLoopInvertedDown = 285; - constexpr track_type_t RightFlyerLargeHalfLoopInvertedDown = 286; - constexpr track_type_t LeftFlyerLargeHalfLoopInvertedUp = 287; - constexpr track_type_t RightFlyerLargeHalfLoopInvertedUp = 288; - constexpr track_type_t LeftFlyerLargeHalfLoopUninvertedDown = 289; - constexpr track_type_t RightFlyerLargeHalfLoopUninvertedDown = 290; + FlyerHalfLoopInvertedUp = 291, + FlyerHalfLoopUninvertedDown = 292, - constexpr track_type_t FlyerHalfLoopInvertedUp = 291; - constexpr track_type_t FlyerHalfLoopUninvertedDown = 292; + LeftEighthToDiagUp25 = 293, + RightEighthToDiagUp25 = 294, + LeftEighthToDiagDown25 = 295, + RightEighthToDiagDown25 = 296, + LeftEighthToOrthogonalUp25 = 297, + RightEighthToOrthogonalUp25 = 298, + LeftEighthToOrthogonalDown25 = 299, + RightEighthToOrthogonalDown25 = 300, - constexpr track_type_t LeftEighthToDiagUp25 = 293; - constexpr track_type_t RightEighthToDiagUp25 = 294; - constexpr track_type_t LeftEighthToDiagDown25 = 295; - constexpr track_type_t RightEighthToDiagDown25 = 296; - constexpr track_type_t LeftEighthToOrthogonalUp25 = 297; - constexpr track_type_t RightEighthToOrthogonalUp25 = 298; - constexpr track_type_t LeftEighthToOrthogonalDown25 = 299; - constexpr track_type_t RightEighthToOrthogonalDown25 = 300; + DiagUp25ToLeftBankedUp25 = 301, + DiagUp25ToRightBankedUp25 = 302, + DiagLeftBankedUp25ToUp25 = 303, + DiagRightBankedUp25ToUp25 = 304, + DiagDown25ToLeftBankedDown25 = 305, + DiagDown25ToRightBankedDown25 = 306, + DiagLeftBankedDown25ToDown25 = 307, + DiagRightBankedDown25ToDown25 = 308, + DiagLeftBankedFlatToLeftBankedUp25 = 309, + DiagRightBankedFlatToRightBankedUp25 = 310, + DiagLeftBankedUp25ToLeftBankedFlat = 311, + DiagRightBankedUp25ToRightBankedFlat = 312, + DiagLeftBankedFlatToLeftBankedDown25 = 313, + DiagRightBankedFlatToRightBankedDown25 = 314, + DiagLeftBankedDown25ToLeftBankedFlat = 315, + DiagRightBankedDown25ToRightBankedFlat = 316, + DiagFlatToLeftBankedUp25 = 317, + DiagFlatToRightBankedUp25 = 318, + DiagLeftBankedUp25ToFlat = 319, + DiagRightBankedUp25ToFlat = 320, + DiagFlatToLeftBankedDown25 = 321, + DiagFlatToRightBankedDown25 = 322, + DiagLeftBankedDown25ToFlat = 323, + DiagRightBankedDown25ToFlat = 324, + DiagUp25LeftBanked = 325, + DiagUp25RightBanked = 326, + DiagDown25LeftBanked = 327, + DiagDown25RightBanked = 328, - constexpr track_type_t DiagUp25ToLeftBankedUp25 = 301; - constexpr track_type_t DiagUp25ToRightBankedUp25 = 302; - constexpr track_type_t DiagLeftBankedUp25ToUp25 = 303; - constexpr track_type_t DiagRightBankedUp25ToUp25 = 304; - constexpr track_type_t DiagDown25ToLeftBankedDown25 = 305; - constexpr track_type_t DiagDown25ToRightBankedDown25 = 306; - constexpr track_type_t DiagLeftBankedDown25ToDown25 = 307; - constexpr track_type_t DiagRightBankedDown25ToDown25 = 308; - constexpr track_type_t DiagLeftBankedFlatToLeftBankedUp25 = 309; - constexpr track_type_t DiagRightBankedFlatToRightBankedUp25 = 310; - constexpr track_type_t DiagLeftBankedUp25ToLeftBankedFlat = 311; - constexpr track_type_t DiagRightBankedUp25ToRightBankedFlat = 312; - constexpr track_type_t DiagLeftBankedFlatToLeftBankedDown25 = 313; - constexpr track_type_t DiagRightBankedFlatToRightBankedDown25 = 314; - constexpr track_type_t DiagLeftBankedDown25ToLeftBankedFlat = 315; - constexpr track_type_t DiagRightBankedDown25ToRightBankedFlat = 316; - constexpr track_type_t DiagFlatToLeftBankedUp25 = 317; - constexpr track_type_t DiagFlatToRightBankedUp25 = 318; - constexpr track_type_t DiagLeftBankedUp25ToFlat = 319; - constexpr track_type_t DiagRightBankedUp25ToFlat = 320; - constexpr track_type_t DiagFlatToLeftBankedDown25 = 321; - constexpr track_type_t DiagFlatToRightBankedDown25 = 322; - constexpr track_type_t DiagLeftBankedDown25ToFlat = 323; - constexpr track_type_t DiagRightBankedDown25ToFlat = 324; - constexpr track_type_t DiagUp25LeftBanked = 325; - constexpr track_type_t DiagUp25RightBanked = 326; - constexpr track_type_t DiagDown25LeftBanked = 327; - constexpr track_type_t DiagDown25RightBanked = 328; + LeftEighthBankToDiagUp25 = 329, + RightEighthBankToDiagUp25 = 330, + LeftEighthBankToDiagDown25 = 331, + RightEighthBankToDiagDown25 = 332, + LeftEighthBankToOrthogonalUp25 = 333, + RightEighthBankToOrthogonalUp25 = 334, + LeftEighthBankToOrthogonalDown25 = 335, + RightEighthBankToOrthogonalDown25 = 336, - constexpr track_type_t LeftEighthBankToDiagUp25 = 329; - constexpr track_type_t RightEighthBankToDiagUp25 = 330; - constexpr track_type_t LeftEighthBankToDiagDown25 = 331; - constexpr track_type_t RightEighthBankToDiagDown25 = 332; - constexpr track_type_t LeftEighthBankToOrthogonalUp25 = 333; - constexpr track_type_t RightEighthBankToOrthogonalUp25 = 334; - constexpr track_type_t LeftEighthBankToOrthogonalDown25 = 335; - constexpr track_type_t RightEighthBankToOrthogonalDown25 = 336; + DiagBrakes = 337, + DiagBlockBrakes = 338, + Down25Brakes = 339, - constexpr track_type_t DiagBrakes = 337; - constexpr track_type_t DiagBlockBrakes = 338; - constexpr track_type_t Down25Brakes = 339; - - constexpr track_type_t Count = 340; - constexpr track_type_t None = 65535; - -}; // namespace OpenRCT2::TrackElemType + Count = 340, + None = 65535, + }; +} enum { @@ -665,10 +657,10 @@ struct TrackCircuitIterator struct TypeOrCurve { - bool isTrackType = true; // true if a track_type_t is selected, false if a TrackCurve is selected; + bool isTrackType = true; // true if a OpenRCT2::TrackElemType is selected, false if a TrackCurve is selected; union { - track_type_t trackType = OpenRCT2::TrackElemType::None; + OpenRCT2::TrackElemType trackType = OpenRCT2::TrackElemType::None; TrackCurve curve; }; @@ -678,7 +670,7 @@ struct TypeOrCurve curve = TrackCurve::None; } - constexpr bool operator==(track_type_t rhs) + constexpr bool operator==(OpenRCT2::TrackElemType rhs) { return isTrackType && (trackType == rhs); } @@ -688,13 +680,13 @@ struct TypeOrCurve return !isTrackType && (curve == rhs); } - constexpr TypeOrCurve(track_type_t _type) noexcept + constexpr TypeOrCurve(OpenRCT2::TrackElemType _type) noexcept { isTrackType = true; trackType = _type; } - constexpr TypeOrCurve& operator=(track_type_t rhs) noexcept + constexpr TypeOrCurve& operator=(OpenRCT2::TrackElemType rhs) noexcept { isTrackType = true; trackType = rhs; @@ -715,8 +707,8 @@ struct TypeOrCurve } }; -PitchAndRoll TrackPitchAndRollStart(track_type_t trackType); -PitchAndRoll TrackPitchAndRollEnd(track_type_t trackType); +PitchAndRoll TrackPitchAndRollStart(OpenRCT2::TrackElemType trackType); +PitchAndRoll TrackPitchAndRollEnd(OpenRCT2::TrackElemType trackType); int32_t TrackIsConnectedByShape(TileElement* a, TileElement* b); @@ -728,15 +720,16 @@ bool TrackCircuitIteratorsMatch(const TrackCircuitIterator* firstIt, const Track void TrackGetBack(const CoordsXYE& input, CoordsXYE* output); void TrackGetFront(const CoordsXYE& input, CoordsXYE* output); -bool TrackElementIsCovered(track_type_t trackElementType); -track_type_t UncoverTrackElement(track_type_t trackElementType); -bool TrackTypeIsStation(track_type_t trackType); -bool TrackTypeIsBrakes(track_type_t trackType); -bool TrackTypeIsBlockBrakes(track_type_t trackType); -bool TrackTypeIsBooster(track_type_t trackType); +bool TrackElementIsCovered(OpenRCT2::TrackElemType trackElementType); +OpenRCT2::TrackElemType UncoverTrackElement(OpenRCT2::TrackElemType trackElementType); +bool TrackTypeIsStation(OpenRCT2::TrackElemType trackType); +bool TrackTypeIsBrakes(OpenRCT2::TrackElemType trackType); +bool TrackTypeIsBlockBrakes(OpenRCT2::TrackElemType trackType); +bool TrackTypeIsBooster(OpenRCT2::TrackElemType trackType); std::optional GetTrackElementOriginAndApplyChanges( - const CoordsXYZD& location, track_type_t type, uint16_t extra_params, TileElement** output_element, uint16_t flags); + const CoordsXYZD& location, OpenRCT2::TrackElemType type, uint16_t extra_params, TileElement** output_element, + uint16_t flags); TrackRoll TrackGetActualBank(TileElement* tileElement, TrackRoll bank); TrackRoll TrackGetActualBank2(int32_t rideType, bool isInverted, TrackRoll bank); @@ -745,6 +738,6 @@ TrackRoll TrackGetActualBank3(bool useInvertedSprites, TileElement* tileElement) ResultWithMessage TrackAddStationElement(CoordsXYZD loc, RideId rideIndex, int32_t flags, bool fromTrackDesign); ResultWithMessage TrackRemoveStationElement(const CoordsXYZD& loc, RideId rideIndex, int32_t flags); -bool TrackTypeHasSpeedSetting(track_type_t trackType); -bool TrackTypeIsHelix(track_type_t trackType); +bool TrackTypeHasSpeedSetting(OpenRCT2::TrackElemType trackType); +bool TrackTypeIsHelix(OpenRCT2::TrackElemType trackType); std::optional GetTrackSegmentOrigin(const CoordsXYE& posEl); diff --git a/src/openrct2/ride/TrackData.cpp b/src/openrct2/ride/TrackData.cpp index 09f1a909dd..5f3ad85df7 100644 --- a/src/openrct2/ride/TrackData.cpp +++ b/src/openrct2/ride/TrackData.cpp @@ -369,7 +369,7 @@ namespace OpenRCT2::TrackMetaData { 4, 4, 0, 0, -32, 32 }, // TrackElemType::DiagBlockBrakes { 0, 0, 16, 0, 0, 0 } // TrackElemType::Down25Brakes }; - static_assert(std::size(_trackCoordinates) == TrackElemType::Count); + static_assert(std::size(_trackCoordinates) == EnumValue(TrackElemType::Count)); static constexpr uint8_t TrackPieceLengths[] = { 32, // TrackElemType::Flat @@ -713,7 +713,7 @@ namespace OpenRCT2::TrackMetaData 45, // TrackElemType::DiagBlockBrakes 33, // TrackElemType::Down25Brakes }; - static_assert(std::size(TrackPieceLengths) == TrackElemType::Count); + static_assert(std::size(TrackPieceLengths) == EnumValue(TrackElemType::Count)); // rct2: 0x00998C95 static constexpr TrackCurveChain gTrackCurveChain[] = { @@ -1058,7 +1058,7 @@ namespace OpenRCT2::TrackMetaData { TrackCurve::None, TrackCurve::None }, // TrackElemType::DiagBlockBrakes { TrackElemType::Down25Brakes, TrackElemType::Down25Brakes }, // TrackElemType::Down25Brakes }; - static_assert(std::size(gTrackCurveChain) == TrackElemType::Count); + static_assert(std::size(gTrackCurveChain) == EnumValue(TrackElemType::Count)); const TrackDescriptor gTrackDescriptors[186] = { { true, TrackPitch::Down60, TrackRoll::None, TrackCurve::None, TrackPitch::Down60, TrackRoll::None, TrackElemType::DiagDown60 }, @@ -1250,7 +1250,7 @@ namespace OpenRCT2::TrackMetaData }; /** rct2: 0x00993D1C */ - static constexpr track_type_t AlternativeTrackTypes[] = { + static constexpr OpenRCT2::TrackElemType AlternativeTrackTypes[] = { TrackElemType::FlatCovered, // TrackElemType::Flat TrackElemType::None, TrackElemType::None, @@ -1592,7 +1592,7 @@ namespace OpenRCT2::TrackMetaData TrackElemType::None, // TrackElemType::DiagBlockBrakes TrackElemType::None, // TrackElemType::Down25Brakes }; - static_assert(std::size(AlternativeTrackTypes) == TrackElemType::Count); + static_assert(std::size(AlternativeTrackTypes) == EnumValue(TrackElemType::Count)); /** rct2: 0x0099DA34 */ static constexpr money64 TrackPricing[] = { @@ -1937,10 +1937,10 @@ namespace OpenRCT2::TrackMetaData 123456, // TrackElemType::DiagBlockBrakes 109824, // TrackElemType::Down25Brakes }; - static_assert(std::size(TrackPricing) == TrackElemType::Count); + static_assert(std::size(TrackPricing) == EnumValue(TrackElemType::Count)); /** rct2: 0x0099EA1C */ - static constexpr track_type_t TrackElementMirrorMap[] = { + static constexpr OpenRCT2::TrackElemType TrackElementMirrorMap[] = { TrackElemType::Flat, TrackElemType::EndStation, TrackElemType::BeginStation, @@ -2282,7 +2282,7 @@ namespace OpenRCT2::TrackMetaData TrackElemType::DiagBlockBrakes, TrackElemType::Down25Brakes, }; - static_assert(std::size(TrackElementMirrorMap) == TrackElemType::Count); + static_assert(std::size(TrackElementMirrorMap) == EnumValue(TrackElemType::Count)); /** rct2: 0x00999694 */ static constexpr uint32_t TrackHeightMarkerPositions[] = { @@ -2627,7 +2627,7 @@ namespace OpenRCT2::TrackMetaData (1 << 0), // TrackElemType::DiagBlockBrakes (1 << 0), // TrackElemType::Down25Brakes }; - static_assert(std::size(TrackHeightMarkerPositions) == TrackElemType::Count); + static_assert(std::size(TrackHeightMarkerPositions) == EnumValue(TrackElemType::Count)); @@ -2975,7 +2975,7 @@ namespace OpenRCT2::TrackMetaData /* TrackElemType::DiagBlockBrakes */ 0, /* TrackElemType::Down25Brakes */ TRACK_ELEM_FLAG_DOWN | TRACK_ELEM_FLAG_STARTS_AT_HALF_HEIGHT, }; - static_assert(std::size(TrackFlags) == TrackElemType::Count); + static_assert(std::size(TrackFlags) == EnumValue(TrackElemType::Count)); // clang-format on /** rct2: 0x00997C9D */ @@ -3324,7 +3324,7 @@ namespace OpenRCT2::TrackMetaData { TrackGroup::diagBlockBrakes, TrackPitch::None, TrackPitch::None, TrackRoll::None, TrackRoll::None, 0 }, // TrackElemType::DiagBlockBrakes { TrackGroup::inclinedBrakes, TrackPitch::Down25, TrackPitch::Down25, TrackRoll::None, TrackRoll::None, 0 }, // TrackElemType::Down25Brakes }; - static_assert(std::size(TrackDefinitions) == TrackElemType::Count); + static_assert(std::size(TrackDefinitions) == EnumValue(TrackElemType::Count)); // clang-format on @@ -3387,7 +3387,7 @@ namespace OpenRCT2::TrackMetaData SpinFunction::R9, SpinFunction::L9, SpinFunction::R9, SpinFunction::L9, SpinFunction::R9, SpinFunction::L9, SpinFunction::R9, SpinFunction::None, SpinFunction::None, SpinFunction::None }; - static_assert(std::size(TrackTypeToSpinFunction) == TrackElemType::Count); + static_assert(std::size(TrackTypeToSpinFunction) == EnumValue(TrackElemType::Count)); template static int32_t EvaluatorConst(const int16_t) { @@ -3547,7 +3547,7 @@ namespace OpenRCT2::TrackMetaData return (progress < 48) ? -98 : 98; } - static constexpr TrackComputeFunction GetLateralFunction(const uint16_t type) + static constexpr TrackComputeFunction GetLateralFunction(TrackElemType type) { switch (type) { @@ -3939,7 +3939,7 @@ namespace OpenRCT2::TrackMetaData } } - static constexpr TrackComputeFunction GetVerticalFunction(const uint16_t type) + static constexpr TrackComputeFunction GetVerticalFunction(TrackElemType type) { switch (type) { @@ -4680,7 +4680,7 @@ namespace OpenRCT2::TrackMetaData STR_BLOCK_BRAKES, // TrackElemType::DiagBlockBrakes STR_BRAKES, // TrackElemType::Down25Brakes }; - static_assert(std::size(RideConfigurationStringIds) == TrackElemType::Count); + static_assert(std::size(RideConfigurationStringIds) == EnumValue(TrackElemType::Count)); static constexpr SequenceDescriptor kFlatSeq0 = { .clearance = { 0, 0, 0, 0, { 0b1111, 0 }, 0 }, @@ -12600,9 +12600,9 @@ namespace OpenRCT2::TrackMetaData static constexpr auto BuildDescriptorTable() { - std::array res{}; + std::array res{}; - for (int i = 0; i < TrackElemType::Count; i++) + for (int i = 0; i < EnumValue(TrackElemType::Count); i++) { TrackElementDescriptor& desc = res[i]; desc.description = RideConfigurationStringIds[i]; @@ -12616,8 +12616,8 @@ namespace OpenRCT2::TrackMetaData desc.priceModifier = TrackPricing[i]; desc.definition = TrackDefinitions[i]; desc.spinFunction = TrackTypeToSpinFunction[i]; - desc.verticalFactor = GetVerticalFunction(i); - desc.lateralFactor = GetLateralFunction(i); + desc.verticalFactor = GetVerticalFunction(static_cast(i)); + desc.lateralFactor = GetLateralFunction(static_cast(i)); desc.numSequences = kSequenceDescriptorsByElement[i].numSequences; for (uint8_t sequenceIndex = 0; sequenceIndex < kMaxSequencesPerPiece; sequenceIndex++) @@ -12631,11 +12631,11 @@ namespace OpenRCT2::TrackMetaData static constexpr auto _trackElementDescriptors = BuildDescriptorTable(); - const TrackElementDescriptor& GetTrackElementDescriptor(const uint32_t type) + const TrackElementDescriptor& GetTrackElementDescriptor(OpenRCT2::TrackElemType type) { - if (type >= _trackElementDescriptors.size()) + if (EnumValue(type) >= _trackElementDescriptors.size()) return _trackElementDescriptors[0]; - return _trackElementDescriptors[type]; + return _trackElementDescriptors[EnumValue(type)]; } } // namespace OpenRCT2::TrackMetaData diff --git a/src/openrct2/ride/TrackData.h b/src/openrct2/ride/TrackData.h index 2947272015..56ff05c251 100644 --- a/src/openrct2/ride/TrackData.h +++ b/src/openrct2/ride/TrackData.h @@ -35,7 +35,7 @@ namespace OpenRCT2::TrackMetaData TrackCurve trackCurve; TrackPitch slopeEnd; TrackRoll rollEnd; - track_type_t trackElement; + OpenRCT2::TrackElemType trackElement; }; enum class SpinFunction : uint8_t @@ -65,7 +65,7 @@ namespace OpenRCT2::TrackMetaData uint8_t bottom; }; - constexpr DodgemsTrackSize GetDodgemsTrackSize(track_type_t type) + constexpr DodgemsTrackSize GetDodgemsTrackSize(OpenRCT2::TrackElemType type) { if (type == OpenRCT2::TrackElemType::FlatTrack2x2) return { 4, 4, 59, 59 }; @@ -108,11 +108,11 @@ namespace OpenRCT2::TrackMetaData uint8_t pieceLength; TrackCurveChain curveChain; - track_type_t alternativeType; + OpenRCT2::TrackElemType alternativeType; // Price Modifier should be used as in the following calculation: // (RideTrackPrice * TED::PriceModifier) / 65536 uint32_t priceModifier; - track_type_t mirrorElement; + OpenRCT2::TrackElemType mirrorElement; uint32_t heightMarkerPositions; uint32_t flags; @@ -126,5 +126,5 @@ namespace OpenRCT2::TrackMetaData TrackComputeFunction lateralFactor; }; - const TrackElementDescriptor& GetTrackElementDescriptor(const uint32_t type); + const TrackElementDescriptor& GetTrackElementDescriptor(OpenRCT2::TrackElemType type); } // namespace OpenRCT2::TrackMetaData diff --git a/src/openrct2/ride/TrackDesign.h b/src/openrct2/ride/TrackDesign.h index 6ccee312cd..e51b4c4d57 100644 --- a/src/openrct2/ride/TrackDesign.h +++ b/src/openrct2/ride/TrackDesign.h @@ -13,6 +13,7 @@ #include "../actions/GameActionResult.h" #include "../object/Object.h" #include "../ride/RideColour.h" +#include "../ride/Track.h" #include "../world/Map.h" #include "RideRatings.h" #include "VehicleColour.h" @@ -99,7 +100,7 @@ enum class TrackDesignTrackElementFlag : uint8_t struct TrackDesignTrackElement { - track_type_t type = 0; + OpenRCT2::TrackElemType type = OpenRCT2::TrackElemType::Flat; uint8_t flags = 0; uint8_t colourScheme = 0; ::StationIndex stationIndex = StationIndex::FromUnderlying(0); diff --git a/src/openrct2/ride/TrackPaint.h b/src/openrct2/ride/TrackPaint.h index 95b81aab58..8c87898015 100644 --- a/src/openrct2/ride/TrackPaint.h +++ b/src/openrct2/ride/TrackPaint.h @@ -548,92 +548,92 @@ void DrawSBendRightSupports( using TRACK_PAINT_FUNCTION = void (*)( PaintSession& session, const Ride& ride, uint8_t trackSequence, Direction direction, int32_t height, const TrackElement& trackElement, SupportType supportType); -using TRACK_PAINT_FUNCTION_GETTER = TRACK_PAINT_FUNCTION (*)(int32_t trackType); +using TRACK_PAINT_FUNCTION_GETTER = TRACK_PAINT_FUNCTION (*)(OpenRCT2::TrackElemType trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionStandUpRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedSwingingRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorail(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniSuspendedRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniatureRailway(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionBoatHire(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenWildMouse(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSteeplechase(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCarRide(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLaunchedFreefall(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionBobsleighRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionObservationTower(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLoopingRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlide(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlideCovered(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineTrainRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionChairlift(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMaze(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSpiralSlide(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionGoKarts(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLogFlume(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionRiverRapids(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionDodgems(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSwingingShip(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSwingingInverterShip(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFerrisWheel(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMotionsimulator(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunction3dCinema(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionTopspin(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSpaceRings(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverseFreefallRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLift(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionShop(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMerryGoRound(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFacility(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwist(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionHauntedHouse(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCircus(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionGhostTrain(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSideFrictionRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionWildMouse(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMultiDimensionRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRCInverted(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionVirginiaReel(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSplashBoats(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniHelicopters(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLayDownRCInverted(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedMonorail(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverserRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionHeartlineTwisterRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniGolf(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLatticeTriangleTrack(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionRotoDrop(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingSaucers(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCrookedHouse(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorailCycles(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCompactInvertedRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionWaterRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionAirPoweredVerticalRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedHairpinRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMagicCarpet(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionSubmarineRide(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionEnterprise(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedImpulseRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineRide(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionLimLaunchedRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwisterRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(int32_t trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionStandUpRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedSwingingRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorail(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniSuspendedRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniatureRailway(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionBoatHire(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenWildMouse(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSteeplechase(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCarRide(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLaunchedFreefall(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionBobsleighRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionObservationTower(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLoopingRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlide(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionDinghySlideCovered(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineTrainRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionChairlift(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMaze(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSpiralSlide(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionGoKarts(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLogFlume(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionRiverRapids(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionDodgems(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSwingingShip(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSwingingInverterShip(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFerrisWheel(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMotionsimulator(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunction3dCinema(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionTopspin(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSpaceRings(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverseFreefallRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLift(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionShop(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMerryGoRound(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFacility(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwist(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionHauntedHouse(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCircus(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionGhostTrain(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSideFrictionRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWildMouse(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMultiDimensionRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingRCInverted(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionVirginiaReel(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSplashBoats(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniHelicopters(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLayDownRCInverted(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSuspendedMonorail(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverserRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionHeartlineTwisterRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniGolf(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLatticeTriangleTrack(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionRotoDrop(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingSaucers(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCrookedHouse(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMonorailCycles(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCompactInvertedRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWaterRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionAirPoweredVerticalRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedHairpinRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMagicCarpet(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionSubmarineRide(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionEnterprise(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedImpulseRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineRide(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLimLaunchedRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionTwisterRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(OpenRCT2::TrackElemType trackType); namespace OpenRCT2::HybridRC { - TRACK_PAINT_FUNCTION GetTrackPaintFunction(int32_t trackType); + TRACK_PAINT_FUNCTION GetTrackPaintFunction(OpenRCT2::TrackElemType trackType); } namespace OpenRCT2::SingleRailRC { - TRACK_PAINT_FUNCTION GetTrackPaintFunction(int32_t trackType); + TRACK_PAINT_FUNCTION GetTrackPaintFunction(OpenRCT2::TrackElemType trackType); } namespace OpenRCT2::AlpineRC { - TRACK_PAINT_FUNCTION GetTrackPaintFunction(int32_t trackType); + TRACK_PAINT_FUNCTION GetTrackPaintFunction(OpenRCT2::TrackElemType trackType); } -TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRC(int32_t trackType); -TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicStandUpRC(int32_t trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRC(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicStandUpRC(OpenRCT2::TrackElemType trackType); diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 24ccefca8b..f1a2a5203f 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -475,9 +475,9 @@ static void InvokeVehicleCrashHook(const EntityId vehicleId, const std::string_v #endif static bool vehicle_move_info_valid( - VehicleTrackSubposition trackSubposition, track_type_t type, uint8_t direction, int32_t offset) + VehicleTrackSubposition trackSubposition, OpenRCT2::TrackElemType type, uint8_t direction, int32_t offset) { - uint16_t typeAndDirection = (type << 2) | (direction & 3); + uint16_t typeAndDirection = (EnumValue(type) << 2) | (direction & 3); if (trackSubposition >= VehicleTrackSubposition{ std::size(gTrackVehicleInfo) }) { @@ -530,9 +530,9 @@ static bool vehicle_move_info_valid( } static const VehicleInfo* vehicle_get_move_info( - VehicleTrackSubposition trackSubposition, track_type_t type, uint8_t direction, int32_t offset) + VehicleTrackSubposition trackSubposition, OpenRCT2::TrackElemType type, uint8_t direction, int32_t offset) { - uint16_t typeAndDirection = (type << 2) | (direction & 3); + uint16_t typeAndDirection = (EnumValue(type) << 2) | (direction & 3); if (!vehicle_move_info_valid(trackSubposition, type, direction, offset)) { @@ -547,9 +547,9 @@ const VehicleInfo* Vehicle::GetMoveInfo() const return vehicle_get_move_info(TrackSubposition, GetTrackType(), GetTrackDirection(), track_progress); } -uint16_t VehicleGetMoveInfoSize(VehicleTrackSubposition trackSubposition, track_type_t type, uint8_t direction) +uint16_t VehicleGetMoveInfoSize(VehicleTrackSubposition trackSubposition, OpenRCT2::TrackElemType type, uint8_t direction) { - uint16_t typeAndDirection = (type << 2) | (direction & 3); + uint16_t typeAndDirection = (EnumValue(type) << 2) | (direction & 3); if (!vehicle_move_info_valid(trackSubposition, type, direction, 0)) { @@ -778,7 +778,7 @@ bool Vehicle::OpenRestraints() return restraintsOpen; } -void RideUpdateMeasurementsSpecialElements_Default(Ride& ride, const track_type_t trackType) +void RideUpdateMeasurementsSpecialElements_Default(Ride& ride, const OpenRCT2::TrackElemType trackType) { const auto& ted = GetTrackElementDescriptor(trackType); uint16_t trackFlags = ted.flags; @@ -789,7 +789,7 @@ void RideUpdateMeasurementsSpecialElements_Default(Ride& ride, const track_type_ } } -void RideUpdateMeasurementsSpecialElements_MiniGolf(Ride& ride, const track_type_t trackType) +void RideUpdateMeasurementsSpecialElements_MiniGolf(Ride& ride, const OpenRCT2::TrackElemType trackType) { const auto& ted = GetTrackElementDescriptor(trackType); uint16_t trackFlags = ted.flags; @@ -800,7 +800,7 @@ void RideUpdateMeasurementsSpecialElements_MiniGolf(Ride& ride, const track_type } } -void RideUpdateMeasurementsSpecialElements_WaterCoaster(Ride& ride, const track_type_t trackType) +void RideUpdateMeasurementsSpecialElements_WaterCoaster(Ride& ride, const OpenRCT2::TrackElemType trackType) { if (trackType >= TrackElemType::FlatCovered && trackType <= TrackElemType::RightQuarterTurn3TilesCovered) { @@ -935,6 +935,8 @@ void Vehicle::UpdateMeasurements() { curRide->special_track_elements |= RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; } + default: + break; } const auto& ted = GetTrackElementDescriptor(trackElemType); @@ -2427,7 +2429,7 @@ void Vehicle::UpdateTravellingBoatHireSetup() var_35 = 0; // No longer on a track so reset to 0 for import/export SetTrackDirection(0); - SetTrackType(0); + SetTrackType(TrackElemType::Flat); SetState(Vehicle::Status::TravellingBoat); remaining_distance += 27924; @@ -5300,7 +5302,7 @@ int32_t Vehicle::UpdateMotionDodgems() * rct2: 0x006DD365 */ static bool wouldCollideWithDodgemsTrackEdge( - const CoordsXY& coords, const CoordsXY& trackLocation, uint32_t trackType, uint16_t dodgemsCarRadius) + const CoordsXY& coords, const CoordsXY& trackLocation, TrackElemType trackType, uint16_t dodgemsCarRadius) { int16_t rideLeft = trackLocation.x + GetDodgemsTrackSize(trackType).left; int16_t rideRight = trackLocation.x + GetDodgemsTrackSize(trackType).right; @@ -5532,6 +5534,8 @@ void Vehicle::CheckAndApplyBlockSectionStopSite() } } break; + default: + break; } } @@ -5632,8 +5636,7 @@ static void block_brakes_open_previous_section( int32_t Vehicle::GetSwingAmount() const { - auto trackType = GetTrackType(); - switch (trackType) + switch (GetTrackType()) { case TrackElemType::LeftQuarterTurn5Tiles: case TrackElemType::BankedLeftQuarterTurn5Tiles: @@ -5740,8 +5743,9 @@ int32_t Vehicle::GetSwingAmount() const case TrackElemType::RightEighthBankToOrthogonal: // Loc6D67F6 return -15; + default: + return 0; } - return 0; } static uint8_t GetSwingSprite(int16_t swingPosition) @@ -5837,6 +5841,8 @@ void Vehicle::UpdateSwingingCar() dx = 819; cx = -10831; break; + default: + break; } if (TrackTypeIsStation(trackType) || TrackTypeIsBrakes(trackType) || TrackTypeIsBlockBrakes(trackType)) @@ -6875,7 +6881,8 @@ void Vehicle::PopulateBrakeSpeed(const CoordsXYZ& vehicleTrackLocation, TrackEle * * rct2: 0x006DB08C */ -bool Vehicle::UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, const Ride& curRide, const RideObjectEntry& rideEntry) +bool Vehicle::UpdateTrackMotionForwardsGetNewTrack( + TrackElemType trackType, const Ride& curRide, const RideObjectEntry& rideEntry) { CoordsXYZD location = {}; @@ -7295,7 +7302,8 @@ bool Vehicle::UpdateTrackMotionForwards(const CarEntry* carEntry, const Ride& cu } } -static PitchAndRoll PitchAndRollEnd(const Ride& curRide, bool useInvertedSprites, uint16_t trackType, TileElement* tileElement) +static PitchAndRoll PitchAndRollEnd( + const Ride& curRide, bool useInvertedSprites, TrackElemType trackType, TileElement* tileElement) { bool isInverted = useInvertedSprites ^ tileElement->AsTrack()->IsInverted(); const auto& ted = GetTrackElementDescriptor(trackType); @@ -7306,7 +7314,7 @@ static PitchAndRoll PitchAndRollEnd(const Ride& curRide, bool useInvertedSprites * * rct2: 0x006DBAA6 */ -bool Vehicle::UpdateTrackMotionBackwardsGetNewTrack(uint16_t trackType, const Ride& curRide, uint16_t* progress) +bool Vehicle::UpdateTrackMotionBackwardsGetNewTrack(TrackElemType trackType, const Ride& curRide, uint16_t* progress) { auto pitchAndRollStart = TrackPitchAndRollStart(trackType); TileElement* tileElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, trackType, 0); @@ -8304,7 +8312,7 @@ int32_t Vehicle::UpdateTrackMotionMiniGolf(int32_t* outStation) * * rct2: 0x006DC1E4 */ -static uint8_t modified_speed(uint16_t trackType, VehicleTrackSubposition trackSubposition, uint8_t speed) +static uint8_t modified_speed(TrackElemType trackType, VehicleTrackSubposition trackSubposition, uint8_t speed) { enum { diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index 7f2ec05343..322ef164ed 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -23,8 +23,6 @@ #include #include -using track_type_t = uint16_t; - struct Ride; struct RideObjectEntry; struct CarEntry; @@ -238,20 +236,20 @@ struct Vehicle : EntityBase * Instantly moves the specific car forward or backwards along the track. */ void MoveRelativeDistance(int32_t distance); - track_type_t GetTrackType() const + OpenRCT2::TrackElemType GetTrackType() const { - return TrackTypeAndDirection >> 2; + return static_cast(TrackTypeAndDirection >> 2); } bool IsOnCoveredTrack() const; uint8_t GetTrackDirection() const { return TrackTypeAndDirection & VehicleTrackDirectionMask; } - void SetTrackType(track_type_t trackType) + void SetTrackType(OpenRCT2::TrackElemType trackType) { // set the upper 14 bits to 0, then set track type TrackTypeAndDirection &= ~VehicleTrackTypeMask; - TrackTypeAndDirection |= trackType << 2; + TrackTypeAndDirection |= EnumValue(trackType) << 2; } void SetTrackDirection(uint8_t trackDirection) { @@ -365,8 +363,9 @@ private: int32_t UpdateTrackMotionMiniGolfCalculateAcceleration(const CarEntry& carEntry); int32_t UpdateTrackMotionMiniGolf(int32_t* outStation); void UpdateTrackMotionMiniGolfVehicle(const Ride& curRide, const RideObjectEntry& rideEntry, const CarEntry* carEntry); - bool UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, const Ride& curRide, const RideObjectEntry& rideEntry); - bool UpdateTrackMotionBackwardsGetNewTrack(uint16_t trackType, const Ride& curRide, uint16_t* progress); + bool UpdateTrackMotionForwardsGetNewTrack( + OpenRCT2::TrackElemType trackType, const Ride& curRide, const RideObjectEntry& rideEntry); + bool UpdateTrackMotionBackwardsGetNewTrack(OpenRCT2::TrackElemType trackType, const Ride& curRide, uint16_t* progress); bool UpdateMotionCollisionDetection(const CoordsXYZ& loc, EntityId* otherVehicleIndex); void UpdateGoKartAttemptSwitchLanes(); void UpdateSceneryDoor() const; @@ -536,11 +535,11 @@ constexpr uint8_t kVehicleSeatNumMask = 0x7F; Vehicle* TryGetVehicle(EntityId spriteIndex); void VehicleUpdateAll(); void VehicleSoundsUpdate(); -uint16_t VehicleGetMoveInfoSize(VehicleTrackSubposition trackSubposition, track_type_t type, uint8_t direction); +uint16_t VehicleGetMoveInfoSize(VehicleTrackSubposition trackSubposition, OpenRCT2::TrackElemType type, uint8_t direction); -void RideUpdateMeasurementsSpecialElements_Default(Ride& ride, const track_type_t trackType); -void RideUpdateMeasurementsSpecialElements_MiniGolf(Ride& ride, const track_type_t trackType); -void RideUpdateMeasurementsSpecialElements_WaterCoaster(Ride& ride, const track_type_t trackType); +void RideUpdateMeasurementsSpecialElements_Default(Ride& ride, const OpenRCT2::TrackElemType trackType); +void RideUpdateMeasurementsSpecialElements_MiniGolf(Ride& ride, const OpenRCT2::TrackElemType trackType); +void RideUpdateMeasurementsSpecialElements_WaterCoaster(Ride& ride, const OpenRCT2::TrackElemType trackType); extern Vehicle* gCurrentVehicle; extern StationIndex _vehicleStationIndex; diff --git a/src/openrct2/ride/VehicleSubpositionData.h b/src/openrct2/ride/VehicleSubpositionData.h index 9c0e0e1e2f..dd74c5cc24 100644 --- a/src/openrct2/ride/VehicleSubpositionData.h +++ b/src/openrct2/ride/VehicleSubpositionData.h @@ -13,7 +13,8 @@ #include -constexpr const size_t VehicleTrackSubpositionSizeDefault = OpenRCT2::TrackElemType::Count * kNumOrthogonalDirections; +constexpr const size_t VehicleTrackSubpositionSizeDefault = EnumValue(OpenRCT2::TrackElemType::Count) + * kNumOrthogonalDirections; struct VehicleInfo; diff --git a/src/openrct2/scripting/bindings/entity/ScVehicle.cpp b/src/openrct2/scripting/bindings/entity/ScVehicle.cpp index dde7643833..edf18218f8 100644 --- a/src/openrct2/scripting/bindings/entity/ScVehicle.cpp +++ b/src/openrct2/scripting/bindings/entity/ScVehicle.cpp @@ -390,7 +390,7 @@ namespace OpenRCT2::Scripting dukCoords.Set("y", vehicle->TrackLocation.y); dukCoords.Set("z", vehicle->TrackLocation.z); dukCoords.Set("direction", vehicle->GetTrackDirection()); - dukCoords.Set("trackType", vehicle->GetTrackType()); + dukCoords.Set("trackType", EnumValue(vehicle->GetTrackType())); return dukCoords.Take(); } return ToDuk(ctx, nullptr); @@ -406,7 +406,7 @@ namespace OpenRCT2::Scripting auto z = AsOrDefault(value["z"], 0); vehicle->TrackLocation = CoordsXYZ(x, y, z); vehicle->SetTrackDirection(AsOrDefault(value["direction"], 0)); - vehicle->SetTrackType(AsOrDefault(value["trackType"], 0)); + vehicle->SetTrackType(static_cast(AsOrDefault(value["trackType"], 0))); } } diff --git a/src/openrct2/scripting/bindings/game/ScContext.hpp b/src/openrct2/scripting/bindings/game/ScContext.hpp index 5a06de9371..8760ea6373 100644 --- a/src/openrct2/scripting/bindings/game/ScContext.hpp +++ b/src/openrct2/scripting/bindings/game/ScContext.hpp @@ -186,16 +186,16 @@ namespace OpenRCT2::Scripting return objectManager.getAllObjects(typez); } - DukValue getTrackSegment(track_type_t type) + DukValue getTrackSegment(uint16_t type) { auto ctx = GetContext()->GetScriptEngine().GetContext(); - if (type >= TrackElemType::Count) + if (type >= EnumValue(TrackElemType::Count)) { return ToDuk(ctx, nullptr); } else { - return GetObjectAsDukValue(ctx, std::make_shared(type)); + return GetObjectAsDukValue(ctx, std::make_shared(static_cast(type))); } } @@ -204,9 +204,9 @@ namespace OpenRCT2::Scripting auto ctx = GetContext()->GetScriptEngine().GetContext(); std::vector result; - for (track_type_t type = 0; type < TrackElemType::Count; type++) + for (uint16_t type = 0; type < EnumValue(TrackElemType::Count); type++) { - auto obj = std::make_shared(type); + auto obj = std::make_shared(static_cast(type)); if (obj != nullptr) { result.push_back(GetObjectAsDukValue(ctx, obj)); diff --git a/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp b/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp index ccbd50ccef..fe984a3c1d 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp +++ b/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp @@ -33,7 +33,7 @@ std::shared_ptr ScTrackIterator::FromElement(const CoordsXY& po return std::make_shared(*origin, trackEl->GetTrackType(), trackEl->GetRideIndex()); } -ScTrackIterator::ScTrackIterator(const CoordsXYZD& position, track_type_t type, RideId ride) +ScTrackIterator::ScTrackIterator(const CoordsXYZD& position, OpenRCT2::TrackElemType type, RideId ride) : _position(position) , _type(type) , _ride(ride) diff --git a/src/openrct2/scripting/bindings/ride/ScTrackIterator.h b/src/openrct2/scripting/bindings/ride/ScTrackIterator.h index 1d7cc78368..9880586175 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackIterator.h +++ b/src/openrct2/scripting/bindings/ride/ScTrackIterator.h @@ -24,14 +24,14 @@ namespace OpenRCT2::Scripting { private: CoordsXYZD _position; - track_type_t _type; + OpenRCT2::TrackElemType _type; [[maybe_unused]] RideId _ride; public: static std::shared_ptr FromElement(const CoordsXY& position, int32_t elementIndex); static void Register(duk_context* ctx); - ScTrackIterator(const CoordsXYZD& position, track_type_t type, RideId ride); + ScTrackIterator(const CoordsXYZD& position, OpenRCT2::TrackElemType type, RideId ride); private: DukValue position_get() const; diff --git a/src/openrct2/scripting/bindings/ride/ScTrackSegment.cpp b/src/openrct2/scripting/bindings/ride/ScTrackSegment.cpp index 840521cd2a..cfc971a979 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackSegment.cpp +++ b/src/openrct2/scripting/bindings/ride/ScTrackSegment.cpp @@ -19,7 +19,7 @@ using namespace OpenRCT2::Scripting; using namespace OpenRCT2::TrackMetaData; -ScTrackSegment::ScTrackSegment(track_type_t type) +ScTrackSegment::ScTrackSegment(OpenRCT2::TrackElemType type) : _type(type) { } @@ -72,7 +72,7 @@ void ScTrackSegment::Register(duk_context* ctx) int32_t ScTrackSegment::type_get() const { - return _type; + return EnumValue(_type); } std::string ScTrackSegment::description_get() const @@ -184,7 +184,7 @@ std::vector ScTrackSegment::getSubpositions(uint8_t trackSubposition, { const auto ctx = GetContext()->GetScriptEngine().GetContext(); const uint16_t size = getSubpositionLength(trackSubposition, direction); - const uint16_t typeAndDirection = (_type << 2) | (direction & 3); + const uint16_t typeAndDirection = (EnumValue(_type) << 2) | (direction & 3); std::vector result; @@ -220,7 +220,7 @@ DukValue ScTrackSegment::nextCurveElement_get() const auto nextInChain = ted.curveChain.next; if (nextInChain.isTrackType) - return ToDuk(ctx, nextInChain.trackType); + return ToDuk(ctx, EnumValue(nextInChain.trackType)); return _trackCurveToString(ctx, nextInChain.curve); } @@ -232,7 +232,7 @@ DukValue ScTrackSegment::previousCurveElement_get() const auto previousInChain = ted.curveChain.previous; if (previousInChain.isTrackType) - return ToDuk(ctx, previousInChain.trackType); + return ToDuk(ctx, EnumValue(previousInChain.trackType)); return _trackCurveToString(ctx, previousInChain.curve); } @@ -243,7 +243,7 @@ DukValue ScTrackSegment::getMirrorElement() const const auto& ted = GetTrackElementDescriptor(_type); if (ted.mirrorElement == TrackElemType::None) return ToDuk(ctx, nullptr); - return ToDuk(ctx, ted.mirrorElement); + return ToDuk(ctx, EnumValue(ted.mirrorElement)); } DukValue ScTrackSegment::getAlternativeElement() const @@ -252,7 +252,7 @@ DukValue ScTrackSegment::getAlternativeElement() const const auto& ted = GetTrackElementDescriptor(_type); if (ted.alternativeType == TrackElemType::None) return ToDuk(ctx, nullptr); - return ToDuk(ctx, ted.alternativeType); + return ToDuk(ctx, EnumValue(ted.alternativeType)); } int32_t ScTrackSegment::getPriceModifier() const diff --git a/src/openrct2/scripting/bindings/ride/ScTrackSegment.h b/src/openrct2/scripting/bindings/ride/ScTrackSegment.h index e1cd429a0a..769fcd95e9 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackSegment.h +++ b/src/openrct2/scripting/bindings/ride/ScTrackSegment.h @@ -34,10 +34,10 @@ namespace OpenRCT2::Scripting class ScTrackSegment { private: - track_type_t _type; + OpenRCT2::TrackElemType _type; public: - ScTrackSegment(track_type_t type); + ScTrackSegment(OpenRCT2::TrackElemType type); static void Register(duk_context* ctx); diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.cpp b/src/openrct2/scripting/bindings/world/ScTileElement.cpp index 0ee51b394a..bb6e0dbf8b 100644 --- a/src/openrct2/scripting/bindings/world/ScTileElement.cpp +++ b/src/openrct2/scripting/bindings/world/ScTileElement.cpp @@ -418,7 +418,7 @@ namespace OpenRCT2::Scripting auto* el = _element->AsTrack(); if (el != nullptr) { - duk_push_int(ctx, el->GetTrackType()); + duk_push_int(ctx, EnumValue(el->GetTrackType())); } else { @@ -438,7 +438,7 @@ namespace OpenRCT2::Scripting return; } - el->SetTrackType(value); + el->SetTrackType(static_cast(value)); Invalidate(); } diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 3730807b1a..7510ec1fef 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1907,7 +1907,7 @@ TrackElement* MapGetTrackElementAt(const CoordsXYZ& trackPos) * @param y y units, not tiles. * @param z Base height. */ -TileElement* MapGetTrackElementAtOfType(const CoordsXYZ& trackPos, track_type_t trackType) +TileElement* MapGetTrackElementAtOfType(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType) { TileElement* tileElement = MapGetFirstElementAt(trackPos); if (tileElement == nullptr) @@ -1934,7 +1934,7 @@ TileElement* MapGetTrackElementAtOfType(const CoordsXYZ& trackPos, track_type_t * @param y y units, not tiles. * @param z Base height. */ -TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, track_type_t trackType, int32_t sequence) +TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, int32_t sequence) { TileElement* tileElement = MapGetFirstElementAt(trackPos); auto trackTilePos = TileCoordsXYZ{ trackPos }; @@ -1957,7 +1957,7 @@ TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, track_type return nullptr; } -TrackElement* MapGetTrackElementAtOfType(const CoordsXYZD& location, track_type_t trackType) +TrackElement* MapGetTrackElementAtOfType(const CoordsXYZD& location, OpenRCT2::TrackElemType trackType) { auto tileElement = MapGetFirstElementAt(location); if (tileElement != nullptr) @@ -1980,7 +1980,7 @@ TrackElement* MapGetTrackElementAtOfType(const CoordsXYZD& location, track_type_ return nullptr; } -TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, track_type_t trackType, int32_t sequence) +TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, int32_t sequence) { auto tileElement = MapGetFirstElementAt(location); if (tileElement != nullptr) @@ -2011,7 +2011,7 @@ TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, track_ty * @param y y units, not tiles. * @param z Base height. */ -TileElement* MapGetTrackElementAtOfTypeFromRide(const CoordsXYZ& trackPos, track_type_t trackType, RideId rideIndex) +TileElement* MapGetTrackElementAtOfTypeFromRide(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, RideId rideIndex) { TileElement* tileElement = MapGetFirstElementAt(trackPos); if (tileElement == nullptr) diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index d877aa6aae..2e53f1f74a 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -221,11 +221,11 @@ std::optional MapLargeSceneryGetOrigin( const CoordsXYZD& sceneryPos, int32_t sequence, LargeSceneryElement** outElement); TrackElement* MapGetTrackElementAt(const CoordsXYZ& trackPos); -TileElement* MapGetTrackElementAtOfType(const CoordsXYZ& trackPos, track_type_t trackType); -TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, track_type_t trackType, int32_t sequence); -TrackElement* MapGetTrackElementAtOfType(const CoordsXYZD& location, track_type_t trackType); -TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, track_type_t trackType, int32_t sequence); -TileElement* MapGetTrackElementAtOfTypeFromRide(const CoordsXYZ& trackPos, track_type_t trackType, RideId rideIndex); +TileElement* MapGetTrackElementAtOfType(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType); +TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, int32_t sequence); +TrackElement* MapGetTrackElementAtOfType(const CoordsXYZD& location, OpenRCT2::TrackElemType trackType); +TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, int32_t sequence); +TileElement* MapGetTrackElementAtOfTypeFromRide(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, RideId rideIndex); TileElement* MapGetTrackElementAtFromRide(const CoordsXYZ& trackPos, RideId rideIndex); TileElement* MapGetTrackElementAtWithDirectionFromRide(const CoordsXYZD& trackPos, RideId rideIndex); diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index 46ff7bdae4..e3741c38c5 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -704,6 +704,8 @@ void MapAnimationAutoCreateAtTileElement(TileCoordsXY coords, TileElement* el) case TrackElemType::SpinningTunnel: MapAnimationCreate(MAP_ANIMATION_TYPE_TRACK_SPINNINGTUNNEL, loc); break; + default: + break; } break; } diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index e7487ef2b1..48bec6028f 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -31,7 +31,10 @@ class FootpathObject; class FootpathSurfaceObject; class FootpathRailingsObject; enum class RideColourScheme : uint8_t; -using track_type_t = uint16_t; +namespace OpenRCT2 +{ + enum class TrackElemType : uint16_t; +} constexpr uint8_t MAX_ELEMENT_HEIGHT = 255; constexpr uint8_t OWNER_MASK = 0b00001111; @@ -285,7 +288,7 @@ struct TrackElement : TileElementBase static constexpr TileElementType ElementType = TileElementType::Track; private: - track_type_t TrackType; + OpenRCT2::TrackElemType TrackType; union { struct @@ -313,8 +316,8 @@ private: ride_type_t RideType; public: - track_type_t GetTrackType() const; - void SetTrackType(track_type_t newEntryIndex); + OpenRCT2::TrackElemType GetTrackType() const; + void SetTrackType(OpenRCT2::TrackElemType newEntryIndex); ride_type_t GetRideType() const; void SetRideType(const ride_type_t rideType); From 2c9509f988bb419502a8777aed6e859bba7903ac Mon Sep 17 00:00:00 2001 From: Mathias Gibbens Date: Fri, 11 Oct 2024 13:37:12 -0600 Subject: [PATCH 12/97] Add Linux searchable paths created by game-data-packager With the changes in #22819, it seems reasonable to add a couple of default searchable paths for Linux that are created by the `game-data-packager` utility, available in Debian and its various derivatives. Signed-off-by: Mathias Gibbens --- src/openrct2/platform/Platform.Linux.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/openrct2/platform/Platform.Linux.cpp b/src/openrct2/platform/Platform.Linux.cpp index 4d4853d9e7..1cfcaf45d6 100644 --- a/src/openrct2/platform/Platform.Linux.cpp +++ b/src/openrct2/platform/Platform.Linux.cpp @@ -335,12 +335,18 @@ namespace OpenRCT2::Platform std::vector GetSearchablePathsRCT1() { - return {}; + return { + // game-data-packager uses this path when installing game files + "/usr/share/games/roller-coaster-tycoon", + }; } std::vector GetSearchablePathsRCT2() { - return {}; + return { + // game-data-packager uses this path when installing game files + "/usr/share/games/roller-coaster-tycoon2", + }; } # ifndef NO_TTF From 2666a9937e1dffd3707842bfc8b64ec3b19a78e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:34:05 +0300 Subject: [PATCH 13/97] Refactor the spatial indexing into a separate phase --- src/openrct2/Context.cpp | 3 ++ src/openrct2/entity/EntityBase.h | 1 + src/openrct2/entity/EntityRegistry.cpp | 58 +++++++++++++++++++------- src/openrct2/entity/EntityRegistry.h | 1 + 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 9eff422afe..b1a46bb472 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -1322,6 +1322,7 @@ namespace OpenRCT2 if (ShouldDraw()) { + UpdateEntitiesSpatialIndex(); Draw(); } } @@ -1358,6 +1359,8 @@ namespace OpenRCT2 const float alpha = std::min(_ticksAccumulator / kGameUpdateTimeMS, 1.0f); tweener.Tween(alpha); + UpdateEntitiesSpatialIndex(); + Draw(); } } diff --git a/src/openrct2/entity/EntityBase.h b/src/openrct2/entity/EntityBase.h index 9c43108192..bee06c1021 100644 --- a/src/openrct2/entity/EntityBase.h +++ b/src/openrct2/entity/EntityBase.h @@ -44,6 +44,7 @@ struct EntityBase EntitySpriteData SpriteData; // Used as direction or rotation depending on the entity. uint8_t Orientation; + uint32_t SpatialIndex; /** * Moves a sprite to a new location, invalidates the current position if valid diff --git a/src/openrct2/entity/EntityRegistry.cpp b/src/openrct2/entity/EntityRegistry.cpp index 18ffc5b881..38303df7b8 100644 --- a/src/openrct2/entity/EntityRegistry.cpp +++ b/src/openrct2/entity/EntityRegistry.cpp @@ -48,12 +48,14 @@ static bool _entityFlashingList[MAX_ENTITIES]; constexpr const uint32_t SPATIAL_INDEX_SIZE = (kMaximumMapSizeTechnical * kMaximumMapSizeTechnical) + 1; constexpr uint32_t SPATIAL_INDEX_LOCATION_NULL = SPATIAL_INDEX_SIZE - 1; +static constexpr uint32_t kInvalidSpatialIndex = 0xFFFFFFFFu; +static constexpr uint32_t kSpatialIndexDirtyMask = 1u << 31; static std::array, SPATIAL_INDEX_SIZE> gEntitySpatialIndex; static void FreeEntity(EntityBase& entity); -static constexpr size_t GetSpatialIndexOffset(const CoordsXY& loc) +static constexpr uint32_t ComputeSpatialIndex(const CoordsXY& loc) { if (loc.IsNull()) return SPATIAL_INDEX_LOCATION_NULL; @@ -68,6 +70,11 @@ static constexpr size_t GetSpatialIndexOffset(const CoordsXY& loc) return tileX * kMaximumMapSizeTechnical + tileY; } +static constexpr uint32_t GetSpatialIndex(EntityBase* entity) +{ + return entity->SpatialIndex & ~kSpatialIndexDirtyMask; +} + constexpr bool EntityTypeIsMiscEntity(const EntityType type) { switch (type) @@ -121,7 +128,7 @@ EntityBase* GetEntity(EntityId entityIndex) const std::vector& GetEntityTileList(const CoordsXY& spritePos) { - return gEntitySpatialIndex[GetSpatialIndexOffset(spritePos)]; + return gEntitySpatialIndex[ComputeSpatialIndex(spritePos)]; } static void ResetEntityLists() @@ -204,10 +211,10 @@ void ResetEntitySpatialIndices() } for (EntityId::UnderlyingType i = 0; i < MAX_ENTITIES; i++) { - auto* spr = GetEntity(EntityId::FromUnderlying(i)); - if (spr != nullptr && spr->Type != EntityType::Null) + auto* entity = GetEntity(EntityId::FromUnderlying(i)); + if (entity != nullptr && entity->Type != EntityType::Null) { - EntitySpatialInsert(spr, { spr->x, spr->y }); + EntitySpatialInsert(entity, { entity->x, entity->y }); } } } @@ -312,6 +319,7 @@ static void PrepareNewEntity(EntityBase* base, const EntityType type) base->SpriteData.HeightMin = 0x14; base->SpriteData.HeightMax = 0x8; base->SpriteData.SpriteRect = {}; + base->SpatialIndex = kInvalidSpatialIndex; EntitySpatialInsert(base, { kLocationNull, 0 }); } @@ -405,15 +413,19 @@ void UpdateMoneyEffect() // Performs a search to ensure that insert keeps next_in_quadrant in sprite_index order static void EntitySpatialInsert(EntityBase* entity, const CoordsXY& newLoc) { - size_t newIndex = GetSpatialIndexOffset(newLoc); + const auto newIndex = ComputeSpatialIndex(newLoc); + auto& spatialVector = gEntitySpatialIndex[newIndex]; auto index = std::lower_bound(std::begin(spatialVector), std::end(spatialVector), entity->Id); spatialVector.insert(index, entity->Id); + + entity->SpatialIndex = newIndex; } static void EntitySpatialRemove(EntityBase* entity) { - size_t currentIndex = GetSpatialIndexOffset({ entity->x, entity->y }); + const auto currentIndex = GetSpatialIndex(entity); + auto& spatialVector = gEntitySpatialIndex[currentIndex]; auto index = BinaryFind(std::begin(spatialVector), std::end(spatialVector), entity->Id); if (index != std::end(spatialVector)) @@ -425,17 +437,28 @@ static void EntitySpatialRemove(EntityBase* entity) LOG_WARNING("Bad sprite spatial index. Rebuilding the spatial index..."); ResetEntitySpatialIndices(); } + + entity->SpatialIndex = kInvalidSpatialIndex; } -static void EntitySpatialMove(EntityBase* entity, const CoordsXY& newLoc) +void UpdateEntitiesSpatialIndex() { - size_t newIndex = GetSpatialIndexOffset(newLoc); - size_t currentIndex = GetSpatialIndexOffset({ entity->x, entity->y }); - if (newIndex == currentIndex) - return; + // TODO: This is not optimal, we should only iterate active entities. + for (EntityId::UnderlyingType i = 0; i < MAX_ENTITIES; i++) + { + auto* entity = GetEntity(EntityId::FromUnderlying(i)); + if (entity == nullptr || entity->Type == EntityType::Null) + continue; - EntitySpatialRemove(entity); - EntitySpatialInsert(entity, newLoc); + if (entity->SpatialIndex & kSpatialIndexDirtyMask) + { + if (entity->SpatialIndex != kInvalidSpatialIndex) + { + EntitySpatialRemove(entity); + } + EntitySpatialInsert(entity, { entity->x, entity->y }); + } + } } void EntityBase::MoveTo(const CoordsXYZ& newLocation) @@ -452,7 +475,12 @@ void EntityBase::MoveTo(const CoordsXYZ& newLocation) loc.x = kLocationNull; } - EntitySpatialMove(this, loc); + // EntitySpatialMove(this, loc); + const auto newSpatialIndex = ComputeSpatialIndex(loc); + if (newSpatialIndex != GetSpatialIndex(this)) + { + SpatialIndex |= kSpatialIndexDirtyMask; + } if (loc.x == kLocationNull) { diff --git a/src/openrct2/entity/EntityRegistry.h b/src/openrct2/entity/EntityRegistry.h index 68affac7e7..7fea52cd94 100644 --- a/src/openrct2/entity/EntityRegistry.h +++ b/src/openrct2/entity/EntityRegistry.h @@ -66,6 +66,7 @@ void UpdateMoneyEffect(); void EntitySetCoordinates(const CoordsXYZ& entityPos, EntityBase* entity); void EntityRemove(EntityBase* entity); uint16_t RemoveFloatingEntities(); +void UpdateEntitiesSpatialIndex(); #pragma pack(push, 1) struct EntitiesChecksum From dfb053e2864ae7f26053b3fda8d7e92647849909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:40:18 +0300 Subject: [PATCH 14/97] Only iterate over active entities --- src/openrct2/entity/EntityRegistry.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/openrct2/entity/EntityRegistry.cpp b/src/openrct2/entity/EntityRegistry.cpp index 38303df7b8..37db189881 100644 --- a/src/openrct2/entity/EntityRegistry.cpp +++ b/src/openrct2/entity/EntityRegistry.cpp @@ -443,20 +443,22 @@ static void EntitySpatialRemove(EntityBase* entity) void UpdateEntitiesSpatialIndex() { - // TODO: This is not optimal, we should only iterate active entities. - for (EntityId::UnderlyingType i = 0; i < MAX_ENTITIES; i++) + for (auto& entityList : gEntityLists) { - auto* entity = GetEntity(EntityId::FromUnderlying(i)); - if (entity == nullptr || entity->Type == EntityType::Null) - continue; - - if (entity->SpatialIndex & kSpatialIndexDirtyMask) + for (auto& entityId : entityList) { - if (entity->SpatialIndex != kInvalidSpatialIndex) + auto* entity = GetEntity(entityId); + if (entity == nullptr || entity->Type == EntityType::Null) + continue; + + if (entity->SpatialIndex & kSpatialIndexDirtyMask) { - EntitySpatialRemove(entity); + if (entity->SpatialIndex != kInvalidSpatialIndex) + { + EntitySpatialRemove(entity); + } + EntitySpatialInsert(entity, { entity->x, entity->y }); } - EntitySpatialInsert(entity, { entity->x, entity->y }); } } } From eda0a75fb859ae061c31d3580db5812421e69574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:43:02 +0300 Subject: [PATCH 15/97] Code style changes --- src/openrct2/entity/EntityRegistry.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/openrct2/entity/EntityRegistry.cpp b/src/openrct2/entity/EntityRegistry.cpp index 37db189881..10cf957f78 100644 --- a/src/openrct2/entity/EntityRegistry.cpp +++ b/src/openrct2/entity/EntityRegistry.cpp @@ -46,26 +46,27 @@ static std::vector _freeIdList; static bool _entityFlashingList[MAX_ENTITIES]; -constexpr const uint32_t SPATIAL_INDEX_SIZE = (kMaximumMapSizeTechnical * kMaximumMapSizeTechnical) + 1; -constexpr uint32_t SPATIAL_INDEX_LOCATION_NULL = SPATIAL_INDEX_SIZE - 1; +static constexpr const uint32_t kSpatialIndexSize = (kMaximumMapSizeTechnical * kMaximumMapSizeTechnical) + 1; +static constexpr uint32_t kSpatialIndexNullBucket = kSpatialIndexSize - 1; + static constexpr uint32_t kInvalidSpatialIndex = 0xFFFFFFFFu; static constexpr uint32_t kSpatialIndexDirtyMask = 1u << 31; -static std::array, SPATIAL_INDEX_SIZE> gEntitySpatialIndex; +static std::array, kSpatialIndexSize> gEntitySpatialIndex; static void FreeEntity(EntityBase& entity); static constexpr uint32_t ComputeSpatialIndex(const CoordsXY& loc) { if (loc.IsNull()) - return SPATIAL_INDEX_LOCATION_NULL; + return kSpatialIndexNullBucket; // NOTE: The input coordinate is rotated and can have negative components. const auto tileX = std::abs(loc.x) / kCoordsXYStep; const auto tileY = std::abs(loc.y) / kCoordsXYStep; if (tileX >= kMaximumMapSizeTechnical || tileY >= kMaximumMapSizeTechnical) - return SPATIAL_INDEX_LOCATION_NULL; + return kSpatialIndexNullBucket; return tileX * kMaximumMapSizeTechnical + tileY; } From 551a6b527503c2c2e73bc23b7af26c43f73a576c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:18:29 +0300 Subject: [PATCH 16/97] Move the call to UpdateEntitiesSpatialIndex to more appropriate places --- src/openrct2/Context.cpp | 3 --- src/openrct2/GameState.cpp | 2 ++ src/openrct2/entity/EntityTweener.cpp | 12 +++++------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index b1a46bb472..9eff422afe 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -1322,7 +1322,6 @@ namespace OpenRCT2 if (ShouldDraw()) { - UpdateEntitiesSpatialIndex(); Draw(); } } @@ -1359,8 +1358,6 @@ namespace OpenRCT2 const float alpha = std::min(_ticksAccumulator / kGameUpdateTimeMS, 1.0f); tweener.Tween(alpha); - UpdateEntitiesSpatialIndex(); - Draw(); } } diff --git a/src/openrct2/GameState.cpp b/src/openrct2/GameState.cpp index 9fe9a21a36..7196278d68 100644 --- a/src/openrct2/GameState.cpp +++ b/src/openrct2/GameState.cpp @@ -332,6 +332,8 @@ namespace OpenRCT2 // Update windows // WindowDispatchUpdateAll(); + UpdateEntitiesSpatialIndex(); + // Start autosave timer after update if (gLastAutoSaveUpdate == kAutosavePause) { diff --git a/src/openrct2/entity/EntityTweener.cpp b/src/openrct2/entity/EntityTweener.cpp index bfd40100a6..52bc453237 100644 --- a/src/openrct2/entity/EntityTweener.cpp +++ b/src/openrct2/entity/EntityTweener.cpp @@ -97,14 +97,12 @@ void EntityTweener::Tween(float alpha) if (posA == posB) continue; - ent->Invalidate(); - EntitySetCoordinates( - { static_cast(std::round(posB.x * alpha + posA.x * inv)), - static_cast(std::round(posB.y * alpha + posA.y * inv)), - static_cast(std::round(posB.z * alpha + posA.z * inv)) }, - ent); - ent->Invalidate(); + ent->MoveTo({ static_cast(std::round(posB.x * alpha + posA.x * inv)), + static_cast(std::round(posB.y * alpha + posA.y * inv)), + static_cast(std::round(posB.z * alpha + posA.z * inv)) }); } + + UpdateEntitiesSpatialIndex(); } void EntityTweener::Restore() From 92ac65720aac09443bd84ff3bb2b1a88e90a455c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:19:37 +0300 Subject: [PATCH 17/97] Remove comment --- src/openrct2/entity/EntityRegistry.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openrct2/entity/EntityRegistry.cpp b/src/openrct2/entity/EntityRegistry.cpp index 10cf957f78..10ae01abb9 100644 --- a/src/openrct2/entity/EntityRegistry.cpp +++ b/src/openrct2/entity/EntityRegistry.cpp @@ -478,7 +478,6 @@ void EntityBase::MoveTo(const CoordsXYZ& newLocation) loc.x = kLocationNull; } - // EntitySpatialMove(this, loc); const auto newSpatialIndex = ComputeSpatialIndex(loc); if (newSpatialIndex != GetSpatialIndex(this)) { From 6a90e91237cbf85a3d923e6eef78f5a8429fae6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Sat, 12 Oct 2024 04:18:41 +0300 Subject: [PATCH 18/97] Bump up network version --- src/openrct2/network/NetworkBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 8cc33fafcb..a1c1edf24d 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -49,7 +49,7 @@ using namespace OpenRCT2; // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -constexpr uint8_t kNetworkStreamVersion = 6; +constexpr uint8_t kNetworkStreamVersion = 7; const std::string kNetworkStreamID = std::string(OPENRCT2_VERSION) + "-" + std::to_string(kNetworkStreamVersion); From 698a6491fc567c7504850f75bf54fca1dff31c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Sat, 12 Oct 2024 04:57:19 +0300 Subject: [PATCH 19/97] Ensure the spatial index invalidates when moving the entity position --- src/openrct2/entity/EntityBase.cpp | 12 ------------ src/openrct2/entity/EntityRegistry.cpp | 23 ++++++++++++++--------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/openrct2/entity/EntityBase.cpp b/src/openrct2/entity/EntityBase.cpp index 7b61eb001c..862211a732 100644 --- a/src/openrct2/entity/EntityBase.cpp +++ b/src/openrct2/entity/EntityBase.cpp @@ -20,18 +20,6 @@ template<> bool EntityBase::Is() const return true; } -CoordsXYZ EntityBase::GetLocation() const -{ - return { x, y, z }; -} - -void EntityBase::SetLocation(const CoordsXYZ& newLocation) -{ - x = newLocation.x; - y = newLocation.y; - z = newLocation.z; -} - void EntityBase::Invalidate() { if (x == kLocationNull) diff --git a/src/openrct2/entity/EntityRegistry.cpp b/src/openrct2/entity/EntityRegistry.cpp index 10ae01abb9..3a0104a815 100644 --- a/src/openrct2/entity/EntityRegistry.cpp +++ b/src/openrct2/entity/EntityRegistry.cpp @@ -464,6 +464,19 @@ void UpdateEntitiesSpatialIndex() } } +CoordsXYZ EntityBase::GetLocation() const +{ + return { x, y, z }; +} + +void EntityBase::SetLocation(const CoordsXYZ& newLocation) +{ + x = newLocation.x; + y = newLocation.y; + z = newLocation.z; + SpatialIndex |= kSpatialIndexDirtyMask; +} + void EntityBase::MoveTo(const CoordsXYZ& newLocation) { if (x != kLocationNull) @@ -478,17 +491,9 @@ void EntityBase::MoveTo(const CoordsXYZ& newLocation) loc.x = kLocationNull; } - const auto newSpatialIndex = ComputeSpatialIndex(loc); - if (newSpatialIndex != GetSpatialIndex(this)) - { - SpatialIndex |= kSpatialIndexDirtyMask; - } - if (loc.x == kLocationNull) { - x = loc.x; - y = loc.y; - z = loc.z; + SetLocation(loc); } else { From 5bbed4adc29d632eea396d0c1ac3277e413f5c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Sat, 12 Oct 2024 05:00:23 +0300 Subject: [PATCH 20/97] Update replay --- CMakeLists.txt | 4 ++-- openrct2.proj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 729764dfc3..3e83b17257 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,9 +80,9 @@ set(OPENMSX_VERSION "1.6") set(OPENMSX_URL "https://github.com/OpenRCT2/OpenMusic/releases/download/v${OPENMSX_VERSION}/openmusic.zip") set(OPENMSX_SHA1 "ba170fa6d777b309c15420f4b6eb3fa25082a9d1") -set(REPLAYS_VERSION "0.0.81") +set(REPLAYS_VERSION "0.0.83") set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip") -set(REPLAYS_SHA1 "F698526D1D2DABEF80F350A6363223D67DBC96B1") +set(REPLAYS_SHA1 "FFC98C36AFEC68DC6A48E863413D4E2364A202B3") 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 46c0fbb70d..6d9bf56efd 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -51,8 +51,8 @@ b1b1f1b241d2cbff63a1889c4dc5a09bdf769bfb https://github.com/OpenRCT2/OpenMusic/releases/download/v1.6/openmusic.zip ba170fa6d777b309c15420f4b6eb3fa25082a9d1 - https://github.com/OpenRCT2/replays/releases/download/v0.0.81/replays.zip - F698526D1D2DABEF80F350A6363223D67DBC96B1 + https://github.com/OpenRCT2/replays/releases/download/v0.0.83/replays.zip + FFC98C36AFEC68DC6A48E863413D4E2364A202B3 From af7a2de72c0baed38b529ccdada14dc24048b111 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 12 Oct 2024 22:49:19 +0200 Subject: [PATCH 21/97] Fix fuzzy horizontal-to-vertical line transitions in charts (#22962) * Fix drawLine being off by one in horizontal-to-vertical transitions * Rename no_pixels local to length * Amend changelog --- distribution/changelog.txt | 1 + src/openrct2/drawing/Line.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 7666eae8f7..84c31d16a0 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -2,6 +2,7 @@ ------------------------------------------------------------------------ - Fix: [#22918] Zooming with keyboard moves the view off centre. - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. +- Fix: [#22962] Fuzzy horizontal-to-vertical line transitions in charts. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2/drawing/Line.cpp b/src/openrct2/drawing/Line.cpp index a3208b30da..def36a2ab5 100644 --- a/src/openrct2/drawing/Line.cpp +++ b/src/openrct2/drawing/Line.cpp @@ -139,7 +139,7 @@ void GfxDrawLineSoftware(DrawPixelInfo& dpi, const ScreenLine& line, int32_t col else y_step = -1; - for (int32_t x = x1, x_start = x1, no_pixels = 1; x < x2; ++x, ++no_pixels) + for (int32_t x = x1, x_start = x1, length = 1; x < x2; ++x, ++length) { // Vertical lines are drawn 1 pixel at a time if (steep) @@ -150,11 +150,11 @@ void GfxDrawLineSoftware(DrawPixelInfo& dpi, const ScreenLine& line, int32_t col { // Non vertical lines are drawn with as many pixels in a horizontal line as possible if (!steep) - GfxDrawLineOnBuffer(dpi, colour, { x_start, y }, no_pixels); + GfxDrawLineOnBuffer(dpi, colour, { x_start, y }, length); // Reset non vertical line vars x_start = x + 1; - no_pixels = 1; + length = 0; // NB: will be incremented in next iteration y += y_step; error += delta_x; } @@ -162,7 +162,7 @@ void GfxDrawLineSoftware(DrawPixelInfo& dpi, const ScreenLine& line, int32_t col // Catch the case of the last line if (x + 1 == x2 && !steep) { - GfxDrawLineOnBuffer(dpi, colour, { x_start, y }, no_pixels); + GfxDrawLineOnBuffer(dpi, colour, { x_start, y }, length); } } } From 2e877aa58133765f09852e2f8dd4a689fa6f6d27 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Mon, 14 Oct 2024 08:13:08 +0200 Subject: [PATCH 22/97] Eliminate Loc6DBF3E --- src/openrct2/ride/Vehicle.cpp | 145 +++++++++++++++++----------------- src/openrct2/ride/Vehicle.h | 2 + 2 files changed, 76 insertions(+), 71 deletions(-) diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index f1a2a5203f..0deb3701bb 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -8415,6 +8415,78 @@ int32_t Vehicle::UpdateTrackMotionPoweredRideAcceleration( return curAcceleration + poweredAcceleration; } +void Vehicle::UpdateTrackMotionPreUpdate( + Vehicle& car, const Ride& curRide, const RideObjectEntry& rideEntry, const CarEntry* carEntry) +{ + // Swinging cars + if (carEntry->flags & CAR_ENTRY_FLAG_SWINGING) + { + car.UpdateSwingingCar(); + } + // Spinning cars + if (carEntry->flags & CAR_ENTRY_FLAG_SPINNING) + { + car.UpdateSpinningCar(); + } + // Rider sprites?? animation?? + if ((carEntry->flags & CAR_ENTRY_FLAG_VEHICLE_ANIMATION) || (carEntry->flags & CAR_ENTRY_FLAG_RIDER_ANIMATION)) + { + car.UpdateAdditionalAnimation(); + } + car.acceleration = AccelerationFromPitch[car.Pitch]; + _vehicleUnkF64E10 = 1; + + if (!car.HasFlag(VehicleFlags::MoveSingleCar)) + { + car.remaining_distance += _vehicleVelocityF64E0C; + } + + car.sound2_flags &= ~VEHICLE_SOUND2_FLAGS_LIFT_HILL; + _vehicleCurPosition.x = car.x; + _vehicleCurPosition.y = car.y; + _vehicleCurPosition.z = car.z; + car.Invalidate(); + + while (true) + { + if (car.remaining_distance < 0) + { + // Backward loop + if (car.UpdateTrackMotionBackwards(carEntry, curRide, rideEntry)) + { + break; + } + + if (car.remaining_distance < 0x368A) + { + break; + } + car.acceleration += AccelerationFromPitch[car.Pitch]; + _vehicleUnkF64E10++; + continue; + } + if (car.remaining_distance < 0x368A) + { + // Location found + return; + } + if (car.UpdateTrackMotionForwards(carEntry, curRide, rideEntry)) + { + break; + } + + if (car.remaining_distance >= 0) + { + break; + } + car.acceleration = AccelerationFromPitch[car.Pitch]; + _vehicleUnkF64E10++; + continue; + } + // Loc6DBF20 + car.MoveTo(_vehicleCurPosition); +} + /** * * rct2: 0x006DAB4C @@ -8465,80 +8537,11 @@ int32_t Vehicle::UpdateTrackMotion(int32_t* outStation) break; } carEntry = car->Entry(); - if (carEntry == nullptr) + if (carEntry != nullptr) { - goto Loc6DBF3E; + UpdateTrackMotionPreUpdate(*car, *curRide, *rideEntry, carEntry); } - // Swinging cars - if (carEntry->flags & CAR_ENTRY_FLAG_SWINGING) - { - car->UpdateSwingingCar(); - } - // Spinning cars - if (carEntry->flags & CAR_ENTRY_FLAG_SPINNING) - { - car->UpdateSpinningCar(); - } - // Rider sprites?? animation?? - if ((carEntry->flags & CAR_ENTRY_FLAG_VEHICLE_ANIMATION) || (carEntry->flags & CAR_ENTRY_FLAG_RIDER_ANIMATION)) - { - car->UpdateAdditionalAnimation(); - } - car->acceleration = AccelerationFromPitch[car->Pitch]; - _vehicleUnkF64E10 = 1; - - if (!car->HasFlag(VehicleFlags::MoveSingleCar)) - { - car->remaining_distance += _vehicleVelocityF64E0C; - } - - car->sound2_flags &= ~VEHICLE_SOUND2_FLAGS_LIFT_HILL; - _vehicleCurPosition.x = car->x; - _vehicleCurPosition.y = car->y; - _vehicleCurPosition.z = car->z; - car->Invalidate(); - - while (true) - { - if (car->remaining_distance < 0) - { - // Backward loop - if (car->UpdateTrackMotionBackwards(carEntry, *curRide, *rideEntry)) - { - break; - } - - if (car->remaining_distance < 0x368A) - { - break; - } - car->acceleration += AccelerationFromPitch[car->Pitch]; - _vehicleUnkF64E10++; - continue; - } - if (car->remaining_distance < 0x368A) - { - // Location found - goto Loc6DBF3E; - } - if (car->UpdateTrackMotionForwards(carEntry, *curRide, *rideEntry)) - { - break; - } - - if (car->remaining_distance >= 0) - { - break; - } - car->acceleration = AccelerationFromPitch[car->Pitch]; - _vehicleUnkF64E10++; - continue; - } - // Loc6DBF20 - car->MoveTo(_vehicleCurPosition); - - Loc6DBF3E: car->Sub6DBF3E(); // Loc6DC0F7 diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index 322ef164ed..b54284750d 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -386,6 +386,8 @@ private: stop, }; UpdateMiniGolfFlagsStatus UpdateTrackMotionMiniGolfFlagsStatus(const Ride& curRide); + void UpdateTrackMotionPreUpdate( + Vehicle& car, const Ride& curRide, const RideObjectEntry& rideEntry, const CarEntry* carEntry); }; static_assert(sizeof(Vehicle) <= 512); From 71ce725a2ab00906065f29673df6cc294b9b22c6 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:26:10 +0200 Subject: [PATCH 23/97] Split off BannerElement and TrackElement (#22955) --- .../interface/ViewportInteraction.cpp | 2 + src/openrct2-ui/ride/Construction.cpp | 1 + src/openrct2-ui/windows/Banner.cpp | 1 + src/openrct2-ui/windows/Map.cpp | 1 + src/openrct2-ui/windows/Ride.cpp | 1 + src/openrct2-ui/windows/RideConstruction.cpp | 1 + src/openrct2-ui/windows/Scenery.cpp | 1 + src/openrct2-ui/windows/TileInspector.cpp | 2 + src/openrct2/EditorObjectSelectionSession.cpp | 1 + src/openrct2/actions/BannerPlaceAction.cpp | 1 + src/openrct2/actions/BannerRemoveAction.cpp | 1 + .../actions/BannerSetColourAction.cpp | 1 + src/openrct2/actions/BannerSetNameAction.cpp | 1 + src/openrct2/actions/BannerSetStyleAction.cpp | 1 + src/openrct2/actions/FootpathRemoveAction.cpp | 1 + src/openrct2/actions/LandSetHeightAction.cpp | 1 + src/openrct2/actions/MazePlaceTrackAction.cpp | 1 + src/openrct2/actions/MazeSetTrackAction.cpp | 1 + src/openrct2/actions/RideDemolishAction.cpp | 1 + src/openrct2/actions/TrackPlaceAction.cpp | 1 + src/openrct2/actions/TrackRemoveAction.cpp | 1 + .../actions/TrackSetBrakeSpeedAction.cpp | 1 + src/openrct2/actions/WallPlaceAction.cpp | 1 + src/openrct2/core/DataSerialiserTraits.h | 1 + src/openrct2/entity/Balloon.cpp | 1 + src/openrct2/entity/Guest.cpp | 1 + src/openrct2/entity/Peep.cpp | 1 + src/openrct2/entity/Staff.cpp | 1 + src/openrct2/libopenrct2.vcxproj | 16 +- .../paint/tile_element/Paint.Banner.cpp | 1 + .../paint/tile_element/Paint.Path.cpp | 1 + .../coaster/AirPoweredVerticalCoaster.cpp | 1 + .../paint/track/coaster/AlpineCoaster.cpp | 1 + .../paint/track/coaster/BobsleighCoaster.cpp | 1 + .../coaster/ClassicStandUpRollerCoaster.cpp | 1 + .../coaster/ClassicWoodenRollerCoaster.cpp | 1 + .../track/coaster/CompactInvertedCoaster.cpp | 1 + .../track/coaster/CorkscrewRollerCoaster.cpp | 1 + .../track/coaster/FlyingRollerCoaster.cpp | 1 + .../coaster/FlyingRollerCoasterInverted.cpp | 1 + .../track/coaster/HeartlineTwisterCoaster.cpp | 1 + .../paint/track/coaster/HybridCoaster.cpp | 1 + .../track/coaster/InvertedHairpinCoaster.cpp | 1 + .../track/coaster/InvertedImpulseCoaster.cpp | 1 + .../track/coaster/InvertedRollerCoaster.cpp | 1 + .../track/coaster/JuniorRollerCoaster.cpp | 1 + .../track/coaster/LatticeTriangleTrack.cpp | 1 + .../coaster/LayDownRollerCoasterInverted.cpp | 1 + .../coaster/LimLaunchedRollerCoaster.cpp | 1 + .../track/coaster/LoopingRollerCoaster.cpp | 1 + src/openrct2/paint/track/coaster/MineRide.cpp | 1 + .../paint/track/coaster/MineTrainCoaster.cpp | 1 + .../paint/track/coaster/MiniRollerCoaster.cpp | 1 + .../track/coaster/MiniSuspendedCoaster.cpp | 1 + .../coaster/MultiDimensionRollerCoaster.cpp | 1 + .../track/coaster/ReverseFreefallCoaster.cpp | 1 + .../track/coaster/ReverserRollerCoaster.cpp | 1 + .../coaster/SideFrictionRollerCoaster.cpp | 1 + .../track/coaster/SingleRailRollerCoaster.cpp | 1 + .../track/coaster/StandUpRollerCoaster.cpp | 1 + .../paint/track/coaster/Steeplechase.cpp | 1 + .../coaster/SuspendedSwingingCoaster.cpp | 1 + .../track/coaster/TwisterRollerCoaster.cpp | 1 + .../paint/track/coaster/VirginiaReel.cpp | 1 + .../paint/track/coaster/WildMouse.cpp | 1 + .../track/coaster/WoodenRollerCoaster.cpp | 1 + .../paint/track/coaster/WoodenWildMouse.cpp | 1 + .../paint/track/gentle/CrookedHouse.cpp | 1 + .../paint/track/gentle/GhostTrain.cpp | 1 + src/openrct2/paint/track/gentle/Maze.cpp | 1 + src/openrct2/paint/track/gentle/MiniGolf.cpp | 1 + .../paint/track/gentle/ObservationTower.cpp | 1 + src/openrct2/paint/track/shops/Facility.cpp | 1 + src/openrct2/paint/track/shops/Shop.cpp | 1 + .../paint/track/thrill/Enterprise.cpp | 1 + src/openrct2/paint/track/thrill/GoKarts.cpp | 1 + .../paint/track/thrill/LaunchedFreefall.cpp | 1 + src/openrct2/paint/track/thrill/RotoDrop.cpp | 1 + .../paint/track/transport/Chairlift.cpp | 1 + .../track/transport/MiniatureRailway.cpp | 1 + .../paint/track/water/DinghySlide.cpp | 1 + src/openrct2/park/ParkFile.cpp | 1 + src/openrct2/peep/GuestPathfinding.cpp | 2 + src/openrct2/rct1/S4Importer.cpp | 2 + src/openrct2/rct12/ScenarioPatcher.cpp | 1 + src/openrct2/rct2/S6Importer.cpp | 2 + src/openrct2/ride/CableLift.cpp | 1 + src/openrct2/ride/Ride.cpp | 1 + src/openrct2/ride/RideConstruction.cpp | 1 + src/openrct2/ride/RideRatings.cpp | 1 + src/openrct2/ride/Station.cpp | 1 + src/openrct2/ride/Track.cpp | 294 +---------------- src/openrct2/ride/Track.h | 21 -- src/openrct2/ride/TrackDesign.cpp | 1 + src/openrct2/ride/TrackDesignSave.cpp | 1 + src/openrct2/ride/TrackPaint.cpp | 1 + src/openrct2/ride/Vehicle.cpp | 1 + src/openrct2/scenario/Scenario.cpp | 1 + .../bindings/ride/ScTrackIterator.cpp | 1 + .../bindings/world/ScTileElement.cpp | 2 + src/openrct2/world/Banner.cpp | 53 +-- src/openrct2/world/ConstructionClearance.cpp | 1 + src/openrct2/world/Entrance.cpp | 1 + src/openrct2/world/Footpath.cpp | 2 + src/openrct2/world/Map.cpp | 2 + src/openrct2/world/MapAnimation.cpp | 1 + src/openrct2/world/TileElement.cpp | 2 + src/openrct2/world/TileElement.h | 138 -------- src/openrct2/world/TileInspector.cpp | 2 + .../world/tile_element/BannerElement.cpp | 57 ++++ .../world/tile_element/BannerElement.h | 44 +++ .../world/tile_element/TileElementBase.cpp | 2 + .../world/tile_element/TrackElement.cpp | 304 ++++++++++++++++++ .../world/tile_element/TrackElement.h | 145 +++++++++ .../world/tile_element/WallElement.cpp | 1 + test/tests/TileElements.cpp | 1 + test/tests/TileElementsView.cpp | 2 + 117 files changed, 683 insertions(+), 509 deletions(-) create mode 100644 src/openrct2/world/tile_element/BannerElement.cpp create mode 100644 src/openrct2/world/tile_element/BannerElement.h create mode 100644 src/openrct2/world/tile_element/TrackElement.cpp create mode 100644 src/openrct2/world/tile_element/TrackElement.h diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 34be65ac1f..4327d11ef9 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -52,7 +52,9 @@ #include #include #include +#include #include +#include #include using namespace OpenRCT2; diff --git a/src/openrct2-ui/ride/Construction.cpp b/src/openrct2-ui/ride/Construction.cpp index 3ce3ff129f..35d3417c4a 100644 --- a/src/openrct2-ui/ride/Construction.cpp +++ b/src/openrct2-ui/ride/Construction.cpp @@ -18,6 +18,7 @@ #include #include #include +#include using namespace OpenRCT2::TrackMetaData; diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index 5d8cab9350..7a5d104a00 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/Map.cpp b/src/openrct2-ui/windows/Map.cpp index c625ff92fb..28bb1d4d9b 100644 --- a/src/openrct2-ui/windows/Map.cpp +++ b/src/openrct2-ui/windows/Map.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index fa46041d9c..a8d1b8363c 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 52a2159c26..70da1e91b7 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -50,6 +50,7 @@ #include #include #include +#include constexpr int8_t kDefaultSpeedIncrement = 2; constexpr int8_t kDefaultMinimumSpeed = 2; diff --git a/src/openrct2-ui/windows/Scenery.cpp b/src/openrct2-ui/windows/Scenery.cpp index 4b0ac2cb4a..663a85ddc6 100644 --- a/src/openrct2-ui/windows/Scenery.cpp +++ b/src/openrct2-ui/windows/Scenery.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index 3c09fe15c9..6e8735f370 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -41,8 +41,10 @@ #include #include #include +#include #include #include +#include #include namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp index 79b41c0ebd..f860e462fd 100644 --- a/src/openrct2/EditorObjectSelectionSession.cpp +++ b/src/openrct2/EditorObjectSelectionSession.cpp @@ -30,6 +30,7 @@ #include "windows/Intent.h" #include "world/Footpath.h" #include "world/Scenery.h" +#include "world/tile_element/BannerElement.h" #include "world/tile_element/EntranceElement.h" #include "world/tile_element/WallElement.h" diff --git a/src/openrct2/actions/BannerPlaceAction.cpp b/src/openrct2/actions/BannerPlaceAction.cpp index 88efacd5fa..ead853ba0d 100644 --- a/src/openrct2/actions/BannerPlaceAction.cpp +++ b/src/openrct2/actions/BannerPlaceAction.cpp @@ -17,6 +17,7 @@ #include "../world/MapAnimation.h" #include "../world/Scenery.h" #include "../world/TileElementsView.h" +#include "../world/tile_element/BannerElement.h" #include "GameAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/BannerRemoveAction.cpp b/src/openrct2/actions/BannerRemoveAction.cpp index ab82af5784..9c40d69152 100644 --- a/src/openrct2/actions/BannerRemoveAction.cpp +++ b/src/openrct2/actions/BannerRemoveAction.cpp @@ -17,6 +17,7 @@ #include "../world/MapAnimation.h" #include "../world/Scenery.h" #include "../world/TileElementsView.h" +#include "../world/tile_element/BannerElement.h" #include "GameAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/BannerSetColourAction.cpp b/src/openrct2/actions/BannerSetColourAction.cpp index cbb562f1a3..e7e2625752 100644 --- a/src/openrct2/actions/BannerSetColourAction.cpp +++ b/src/openrct2/actions/BannerSetColourAction.cpp @@ -14,6 +14,7 @@ #include "../management/Finance.h" #include "../windows/Intent.h" #include "../world/Banner.h" +#include "../world/tile_element/BannerElement.h" #include "GameAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/BannerSetNameAction.cpp b/src/openrct2/actions/BannerSetNameAction.cpp index 6859eb183b..639a0ff446 100644 --- a/src/openrct2/actions/BannerSetNameAction.cpp +++ b/src/openrct2/actions/BannerSetNameAction.cpp @@ -17,6 +17,7 @@ #include "../ui/UiContext.h" #include "../windows/Intent.h" #include "../world/Banner.h" +#include "../world/tile_element/BannerElement.h" #include "GameAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/BannerSetStyleAction.cpp b/src/openrct2/actions/BannerSetStyleAction.cpp index 18225ca1d8..eaf2c9ca8d 100644 --- a/src/openrct2/actions/BannerSetStyleAction.cpp +++ b/src/openrct2/actions/BannerSetStyleAction.cpp @@ -15,6 +15,7 @@ #include "../util/Util.h" #include "../windows/Intent.h" #include "../world/Banner.h" +#include "../world/tile_element/BannerElement.h" #include "GameAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/FootpathRemoveAction.cpp b/src/openrct2/actions/FootpathRemoveAction.cpp index 21b5b5ec9d..8297d31899 100644 --- a/src/openrct2/actions/FootpathRemoveAction.cpp +++ b/src/openrct2/actions/FootpathRemoveAction.cpp @@ -19,6 +19,7 @@ #include "../world/Footpath.h" #include "../world/Location.hpp" #include "../world/Park.h" +#include "../world/tile_element/BannerElement.h" #include "BannerRemoveAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LandSetHeightAction.cpp b/src/openrct2/actions/LandSetHeightAction.cpp index eb7bf19262..31ec643d7c 100644 --- a/src/openrct2/actions/LandSetHeightAction.cpp +++ b/src/openrct2/actions/LandSetHeightAction.cpp @@ -25,6 +25,7 @@ #include "../world/TileElementsView.h" #include "../world/Wall.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/TrackElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/MazePlaceTrackAction.cpp b/src/openrct2/actions/MazePlaceTrackAction.cpp index 5ae8c13497..32b4495696 100644 --- a/src/openrct2/actions/MazePlaceTrackAction.cpp +++ b/src/openrct2/actions/MazePlaceTrackAction.cpp @@ -16,6 +16,7 @@ #include "../ride/TrackData.h" #include "../world/ConstructionClearance.h" #include "../world/Wall.h" +#include "../world/tile_element/TrackElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/MazeSetTrackAction.cpp b/src/openrct2/actions/MazeSetTrackAction.cpp index ffae52ea7e..4e70b682b4 100644 --- a/src/openrct2/actions/MazeSetTrackAction.cpp +++ b/src/openrct2/actions/MazeSetTrackAction.cpp @@ -24,6 +24,7 @@ #include "../world/Footpath.h" #include "../world/Park.h" #include "../world/Wall.h" +#include "../world/tile_element/TrackElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/RideDemolishAction.cpp b/src/openrct2/actions/RideDemolishAction.cpp index 11eab3d14a..9ae83fbee3 100644 --- a/src/openrct2/actions/RideDemolishAction.cpp +++ b/src/openrct2/actions/RideDemolishAction.cpp @@ -26,6 +26,7 @@ #include "../world/Banner.h" #include "../world/Park.h" #include "../world/TileElementsView.h" +#include "../world/tile_element/TrackElement.h" #include "MazeSetTrackAction.h" #include "TrackRemoveAction.h" diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index d8f4824825..0b24eab99d 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -24,6 +24,7 @@ #include "../world/Surface.h" #include "../world/Wall.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/TrackElement.h" #include "RideSetSettingAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/TrackRemoveAction.cpp b/src/openrct2/actions/TrackRemoveAction.cpp index 65ee27bf43..a2577cd454 100644 --- a/src/openrct2/actions/TrackRemoveAction.cpp +++ b/src/openrct2/actions/TrackRemoveAction.cpp @@ -19,6 +19,7 @@ #include "../util/Util.h" #include "../world/MapAnimation.h" #include "../world/Surface.h" +#include "../world/tile_element/TrackElement.h" #include "RideSetSettingAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp b/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp index 46eca92412..08c68b199c 100644 --- a/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp +++ b/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp @@ -11,6 +11,7 @@ #include "../Diagnostic.h" #include "../management/Finance.h" +#include "../world/tile_element/TrackElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/WallPlaceAction.cpp b/src/openrct2/actions/WallPlaceAction.cpp index 7f8d74eb0e..1eae718b4b 100644 --- a/src/openrct2/actions/WallPlaceAction.cpp +++ b/src/openrct2/actions/WallPlaceAction.cpp @@ -25,6 +25,7 @@ #include "../world/Surface.h" #include "../world/Wall.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index 05531e8ce8..e818e276db 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -16,6 +16,7 @@ #include "../object/Object.h" #include "../ride/RideColour.h" #include "../ride/TrackDesign.h" +#include "../world/Banner.h" #include "../world/Location.hpp" #include "../world/TileElement.h" #include "DataSerialiserTag.h" diff --git a/src/openrct2/entity/Balloon.cpp b/src/openrct2/entity/Balloon.cpp index b12cd067a0..3bc32aaade 100644 --- a/src/openrct2/entity/Balloon.cpp +++ b/src/openrct2/entity/Balloon.cpp @@ -17,6 +17,7 @@ #include "../profiling/Profiling.h" #include "../scenario/Scenario.h" #include "../util/Util.h" +#include "../world/tile_element/TrackElement.h" #include "EntityRegistry.h" template<> bool EntityBase::Is() const diff --git a/src/openrct2/entity/Guest.cpp b/src/openrct2/entity/Guest.cpp index 35cd3e777f..202d60954d 100644 --- a/src/openrct2/entity/Guest.cpp +++ b/src/openrct2/entity/Guest.cpp @@ -61,6 +61,7 @@ #include "../world/Surface.h" #include "../world/TileElementsView.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include "Peep.h" #include "Staff.h" diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index 5c9f354de6..8ead7e9184 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -57,6 +57,7 @@ #include "../world/Scenery.h" #include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/TrackElement.h" #include "PatrolArea.h" #include "Staff.h" diff --git a/src/openrct2/entity/Staff.cpp b/src/openrct2/entity/Staff.cpp index b06525ac80..58b78d76ca 100644 --- a/src/openrct2/entity/Staff.cpp +++ b/src/openrct2/entity/Staff.cpp @@ -45,6 +45,7 @@ #include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/TrackElement.h" #include "PatrolArea.h" #include "Peep.h" diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 2d729f224a..bcd41886a1 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -599,9 +599,6 @@ - - - @@ -624,6 +621,11 @@ + + + + + @@ -1086,8 +1088,6 @@ - - @@ -1106,6 +1106,10 @@ + + + + @@ -1116,4 +1120,4 @@ - \ No newline at end of file + diff --git a/src/openrct2/paint/tile_element/Paint.Banner.cpp b/src/openrct2/paint/tile_element/Paint.Banner.cpp index 79e987d9e8..8c23b68438 100644 --- a/src/openrct2/paint/tile_element/Paint.Banner.cpp +++ b/src/openrct2/paint/tile_element/Paint.Banner.cpp @@ -23,6 +23,7 @@ #include "../../world/Banner.h" #include "../../world/Scenery.h" #include "../../world/TileInspector.h" +#include "../../world/tile_element/BannerElement.h" #include "Paint.TileElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/paint/tile_element/Paint.Path.cpp b/src/openrct2/paint/tile_element/Paint.Path.cpp index c4f8635a68..3e4975facc 100644 --- a/src/openrct2/paint/tile_element/Paint.Path.cpp +++ b/src/openrct2/paint/tile_element/Paint.Path.cpp @@ -34,6 +34,7 @@ #include "../../world/Surface.h" #include "../../world/TileInspector.h" #include "../../world/tile_element/Slope.h" +#include "../../world/tile_element/TrackElement.h" #include "../Boundbox.h" #include "../Paint.SessionFlags.h" #include "../support/MetalSupports.h" diff --git a/src/openrct2/paint/track/coaster/AirPoweredVerticalCoaster.cpp b/src/openrct2/paint/track/coaster/AirPoweredVerticalCoaster.cpp index b218474a0c..558cce737e 100644 --- a/src/openrct2/paint/track/coaster/AirPoweredVerticalCoaster.cpp +++ b/src/openrct2/paint/track/coaster/AirPoweredVerticalCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/coaster/AlpineCoaster.cpp b/src/openrct2/paint/track/coaster/AlpineCoaster.cpp index e2e21cae21..d0ffec2e31 100644 --- a/src/openrct2/paint/track/coaster/AlpineCoaster.cpp +++ b/src/openrct2/paint/track/coaster/AlpineCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/paint/track/coaster/BobsleighCoaster.cpp b/src/openrct2/paint/track/coaster/BobsleighCoaster.cpp index dae12fe76d..393a8f6175 100644 --- a/src/openrct2/paint/track/coaster/BobsleighCoaster.cpp +++ b/src/openrct2/paint/track/coaster/BobsleighCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp b/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp index 61c6c39f26..3686d97e24 100644 --- a/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp @@ -10,6 +10,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../tile_element/Segment.h" #include "../../track/Segment.h" #include "../../track/Support.h" diff --git a/src/openrct2/paint/track/coaster/ClassicWoodenRollerCoaster.cpp b/src/openrct2/paint/track/coaster/ClassicWoodenRollerCoaster.cpp index 87e1c72ce4..1f851fb61e 100644 --- a/src/openrct2/paint/track/coaster/ClassicWoodenRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ClassicWoodenRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/coaster/CompactInvertedCoaster.cpp b/src/openrct2/paint/track/coaster/CompactInvertedCoaster.cpp index 4d128d5843..6fafc02d0f 100644 --- a/src/openrct2/paint/track/coaster/CompactInvertedCoaster.cpp +++ b/src/openrct2/paint/track/coaster/CompactInvertedCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp b/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp index d358931e57..f61f868de0 100644 --- a/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/FlyingRollerCoaster.cpp b/src/openrct2/paint/track/coaster/FlyingRollerCoaster.cpp index 5298d82e31..e3747ac6d0 100644 --- a/src/openrct2/paint/track/coaster/FlyingRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/FlyingRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp b/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp index 2bc4fb98f5..e5d8f682ae 100644 --- a/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp +++ b/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp @@ -10,6 +10,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../track/Segment.h" #include diff --git a/src/openrct2/paint/track/coaster/HeartlineTwisterCoaster.cpp b/src/openrct2/paint/track/coaster/HeartlineTwisterCoaster.cpp index 99f104b6c1..a4e9e85ea4 100644 --- a/src/openrct2/paint/track/coaster/HeartlineTwisterCoaster.cpp +++ b/src/openrct2/paint/track/coaster/HeartlineTwisterCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/coaster/HybridCoaster.cpp b/src/openrct2/paint/track/coaster/HybridCoaster.cpp index 66d3249e5e..114fd90af8 100644 --- a/src/openrct2/paint/track/coaster/HybridCoaster.cpp +++ b/src/openrct2/paint/track/coaster/HybridCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/paint/track/coaster/InvertedHairpinCoaster.cpp b/src/openrct2/paint/track/coaster/InvertedHairpinCoaster.cpp index 9598850d12..6a67654674 100644 --- a/src/openrct2/paint/track/coaster/InvertedHairpinCoaster.cpp +++ b/src/openrct2/paint/track/coaster/InvertedHairpinCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/InvertedImpulseCoaster.cpp b/src/openrct2/paint/track/coaster/InvertedImpulseCoaster.cpp index 3a1647fa0f..57f45d406d 100644 --- a/src/openrct2/paint/track/coaster/InvertedImpulseCoaster.cpp +++ b/src/openrct2/paint/track/coaster/InvertedImpulseCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/InvertedRollerCoaster.cpp b/src/openrct2/paint/track/coaster/InvertedRollerCoaster.cpp index b9fdbc695b..7a057271f3 100644 --- a/src/openrct2/paint/track/coaster/InvertedRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/InvertedRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp b/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp index 6b0003f652..71ef1bb951 100644 --- a/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp @@ -15,6 +15,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp b/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp index e394c064d2..2e8ecaacc3 100644 --- a/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp +++ b/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/LayDownRollerCoasterInverted.cpp b/src/openrct2/paint/track/coaster/LayDownRollerCoasterInverted.cpp index b904d0919c..ee5970e395 100644 --- a/src/openrct2/paint/track/coaster/LayDownRollerCoasterInverted.cpp +++ b/src/openrct2/paint/track/coaster/LayDownRollerCoasterInverted.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp b/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp index 392c7baf45..d911783da7 100644 --- a/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/LoopingRollerCoaster.cpp b/src/openrct2/paint/track/coaster/LoopingRollerCoaster.cpp index f827635a65..9751e23e59 100644 --- a/src/openrct2/paint/track/coaster/LoopingRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/LoopingRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/MineRide.cpp b/src/openrct2/paint/track/coaster/MineRide.cpp index c99a7bc413..6872c900d4 100644 --- a/src/openrct2/paint/track/coaster/MineRide.cpp +++ b/src/openrct2/paint/track/coaster/MineRide.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/MineTrainCoaster.cpp b/src/openrct2/paint/track/coaster/MineTrainCoaster.cpp index f3c82cadae..b930a5a498 100644 --- a/src/openrct2/paint/track/coaster/MineTrainCoaster.cpp +++ b/src/openrct2/paint/track/coaster/MineTrainCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/coaster/MiniRollerCoaster.cpp b/src/openrct2/paint/track/coaster/MiniRollerCoaster.cpp index 975b10afab..d91f643fa2 100644 --- a/src/openrct2/paint/track/coaster/MiniRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/MiniRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/MiniSuspendedCoaster.cpp b/src/openrct2/paint/track/coaster/MiniSuspendedCoaster.cpp index 5a01d07542..53b61de720 100644 --- a/src/openrct2/paint/track/coaster/MiniSuspendedCoaster.cpp +++ b/src/openrct2/paint/track/coaster/MiniSuspendedCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/MultiDimensionRollerCoaster.cpp b/src/openrct2/paint/track/coaster/MultiDimensionRollerCoaster.cpp index c453ff36ad..a18790e874 100644 --- a/src/openrct2/paint/track/coaster/MultiDimensionRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/MultiDimensionRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/ReverseFreefallCoaster.cpp b/src/openrct2/paint/track/coaster/ReverseFreefallCoaster.cpp index 2d39bddadd..d8270ff88b 100644 --- a/src/openrct2/paint/track/coaster/ReverseFreefallCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ReverseFreefallCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/coaster/ReverserRollerCoaster.cpp b/src/openrct2/paint/track/coaster/ReverserRollerCoaster.cpp index 256959a84d..596a4abe41 100644 --- a/src/openrct2/paint/track/coaster/ReverserRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ReverserRollerCoaster.cpp @@ -15,6 +15,7 @@ #include "../../../ride/Vehicle.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/coaster/SideFrictionRollerCoaster.cpp b/src/openrct2/paint/track/coaster/SideFrictionRollerCoaster.cpp index dac5c98c5a..95c0b2c189 100644 --- a/src/openrct2/paint/track/coaster/SideFrictionRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/SideFrictionRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/coaster/SingleRailRollerCoaster.cpp b/src/openrct2/paint/track/coaster/SingleRailRollerCoaster.cpp index b26dce9901..59fecf84b4 100644 --- a/src/openrct2/paint/track/coaster/SingleRailRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/SingleRailRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/paint/track/coaster/StandUpRollerCoaster.cpp b/src/openrct2/paint/track/coaster/StandUpRollerCoaster.cpp index 968cfaad13..2d6a0d4c10 100644 --- a/src/openrct2/paint/track/coaster/StandUpRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/StandUpRollerCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/Steeplechase.cpp b/src/openrct2/paint/track/coaster/Steeplechase.cpp index 59e805b47d..5e726b1dc2 100644 --- a/src/openrct2/paint/track/coaster/Steeplechase.cpp +++ b/src/openrct2/paint/track/coaster/Steeplechase.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/SuspendedSwingingCoaster.cpp b/src/openrct2/paint/track/coaster/SuspendedSwingingCoaster.cpp index 81088d5f68..5e8461943c 100644 --- a/src/openrct2/paint/track/coaster/SuspendedSwingingCoaster.cpp +++ b/src/openrct2/paint/track/coaster/SuspendedSwingingCoaster.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/TwisterRollerCoaster.cpp b/src/openrct2/paint/track/coaster/TwisterRollerCoaster.cpp index 99e89353ff..de70dc8eab 100644 --- a/src/openrct2/paint/track/coaster/TwisterRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/TwisterRollerCoaster.cpp @@ -16,6 +16,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/VirginiaReel.cpp b/src/openrct2/paint/track/coaster/VirginiaReel.cpp index 6882cbd53d..165466c7fa 100644 --- a/src/openrct2/paint/track/coaster/VirginiaReel.cpp +++ b/src/openrct2/paint/track/coaster/VirginiaReel.cpp @@ -11,6 +11,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/coaster/WildMouse.cpp b/src/openrct2/paint/track/coaster/WildMouse.cpp index 831345054f..3e627e3487 100644 --- a/src/openrct2/paint/track/coaster/WildMouse.cpp +++ b/src/openrct2/paint/track/coaster/WildMouse.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp index b985f7501b..c8be2c8805 100644 --- a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp @@ -17,6 +17,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Boundbox.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/coaster/WoodenWildMouse.cpp b/src/openrct2/paint/track/coaster/WoodenWildMouse.cpp index 22e0efb390..e1b2ca732c 100644 --- a/src/openrct2/paint/track/coaster/WoodenWildMouse.cpp +++ b/src/openrct2/paint/track/coaster/WoodenWildMouse.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.hpp" #include "../../tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/track/gentle/CrookedHouse.cpp b/src/openrct2/paint/track/gentle/CrookedHouse.cpp index ca612b1b07..70a8199132 100644 --- a/src/openrct2/paint/track/gentle/CrookedHouse.cpp +++ b/src/openrct2/paint/track/gentle/CrookedHouse.cpp @@ -14,6 +14,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Boundbox.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/gentle/GhostTrain.cpp b/src/openrct2/paint/track/gentle/GhostTrain.cpp index 8a5c793209..5a85761ae2 100644 --- a/src/openrct2/paint/track/gentle/GhostTrain.cpp +++ b/src/openrct2/paint/track/gentle/GhostTrain.cpp @@ -12,6 +12,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/gentle/Maze.cpp b/src/openrct2/paint/track/gentle/Maze.cpp index 1707fb68ba..37b4d36311 100644 --- a/src/openrct2/paint/track/gentle/Maze.cpp +++ b/src/openrct2/paint/track/gentle/Maze.cpp @@ -15,6 +15,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../tile_element/Paint.Surface.h" diff --git a/src/openrct2/paint/track/gentle/MiniGolf.cpp b/src/openrct2/paint/track/gentle/MiniGolf.cpp index 76dbc5883f..d0efbd75c5 100644 --- a/src/openrct2/paint/track/gentle/MiniGolf.cpp +++ b/src/openrct2/paint/track/gentle/MiniGolf.cpp @@ -15,6 +15,7 @@ #include "../../../world/Map.h" #include "../../../world/Surface.h" #include "../../../world/tile_element/Slope.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.SessionFlags.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" diff --git a/src/openrct2/paint/track/gentle/ObservationTower.cpp b/src/openrct2/paint/track/gentle/ObservationTower.cpp index ad1828a109..9b5682f684 100644 --- a/src/openrct2/paint/track/gentle/ObservationTower.cpp +++ b/src/openrct2/paint/track/gentle/ObservationTower.cpp @@ -13,6 +13,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/paint/track/shops/Facility.cpp b/src/openrct2/paint/track/shops/Facility.cpp index 936149757c..c2c990b1b9 100644 --- a/src/openrct2/paint/track/shops/Facility.cpp +++ b/src/openrct2/paint/track/shops/Facility.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Boundbox.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/shops/Shop.cpp b/src/openrct2/paint/track/shops/Shop.cpp index 16ff2d7484..306fb2e73d 100644 --- a/src/openrct2/paint/track/shops/Shop.cpp +++ b/src/openrct2/paint/track/shops/Shop.cpp @@ -14,6 +14,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Boundbox.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/thrill/Enterprise.cpp b/src/openrct2/paint/track/thrill/Enterprise.cpp index 830248374c..f389b66080 100644 --- a/src/openrct2/paint/track/thrill/Enterprise.cpp +++ b/src/openrct2/paint/track/thrill/Enterprise.cpp @@ -14,6 +14,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Boundbox.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/thrill/GoKarts.cpp b/src/openrct2/paint/track/thrill/GoKarts.cpp index 80f074d6a0..4b01c2534a 100644 --- a/src/openrct2/paint/track/thrill/GoKarts.cpp +++ b/src/openrct2/paint/track/thrill/GoKarts.cpp @@ -12,6 +12,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../support/WoodenSupports.hpp" diff --git a/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp b/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp index 754fd26a9b..841fda7e08 100644 --- a/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp +++ b/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp @@ -12,6 +12,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/paint/track/thrill/RotoDrop.cpp b/src/openrct2/paint/track/thrill/RotoDrop.cpp index b999444da3..0ffc4e5b49 100644 --- a/src/openrct2/paint/track/thrill/RotoDrop.cpp +++ b/src/openrct2/paint/track/thrill/RotoDrop.cpp @@ -12,6 +12,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/paint/track/transport/Chairlift.cpp b/src/openrct2/paint/track/transport/Chairlift.cpp index 5f96579844..a091e12492 100644 --- a/src/openrct2/paint/track/transport/Chairlift.cpp +++ b/src/openrct2/paint/track/transport/Chairlift.cpp @@ -13,6 +13,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/transport/MiniatureRailway.cpp b/src/openrct2/paint/track/transport/MiniatureRailway.cpp index 95906b099c..64318bc93f 100644 --- a/src/openrct2/paint/track/transport/MiniatureRailway.cpp +++ b/src/openrct2/paint/track/transport/MiniatureRailway.cpp @@ -13,6 +13,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/paint/track/water/DinghySlide.cpp b/src/openrct2/paint/track/water/DinghySlide.cpp index 36d560078e..8ce42c5f08 100644 --- a/src/openrct2/paint/track/water/DinghySlide.cpp +++ b/src/openrct2/paint/track/water/DinghySlide.cpp @@ -10,6 +10,7 @@ #include "../../../interface/Viewport.h" #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" +#include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" #include "../../tile_element/Segment.h" diff --git a/src/openrct2/park/ParkFile.cpp b/src/openrct2/park/ParkFile.cpp index 9b2e1980f3..9154b81107 100644 --- a/src/openrct2/park/ParkFile.cpp +++ b/src/openrct2/park/ParkFile.cpp @@ -56,6 +56,7 @@ #include "../world/Map.h" #include "../world/Park.h" #include "../world/Scenery.h" +#include "../world/tile_element/TrackElement.h" #include "Legacy.h" #include diff --git a/src/openrct2/peep/GuestPathfinding.cpp b/src/openrct2/peep/GuestPathfinding.cpp index 5a66ee54d6..22f4a8f1b9 100644 --- a/src/openrct2/peep/GuestPathfinding.cpp +++ b/src/openrct2/peep/GuestPathfinding.cpp @@ -22,7 +22,9 @@ #include "../util/Util.h" #include "../world/Entrance.h" #include "../world/Footpath.h" +#include "../world/tile_element/BannerElement.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/TrackElement.h" #include #include diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 4135de6c70..1756e49080 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -72,7 +72,9 @@ #include "../world/Surface.h" #include "../world/TilePointerIndex.hpp" #include "../world/Wall.h" +#include "../world/tile_element/BannerElement.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include "RCT1.h" #include "Tables.h" diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp index c5b184f9d5..b621b20806 100644 --- a/src/openrct2/rct12/ScenarioPatcher.cpp +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -29,6 +29,7 @@ #include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" #include "../world/tile_element/TileElementType.h" +#include "../world/tile_element/TrackElement.h" #ifdef DISABLE_NETWORK # include diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 301b5d5cc1..428d3161e3 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -77,7 +77,9 @@ #include "../world/Scenery.h" #include "../world/Surface.h" #include "../world/TilePointerIndex.hpp" +#include "../world/tile_element/BannerElement.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include diff --git a/src/openrct2/ride/CableLift.cpp b/src/openrct2/ride/CableLift.cpp index 9c2fdde27e..fe27561c85 100644 --- a/src/openrct2/ride/CableLift.cpp +++ b/src/openrct2/ride/CableLift.cpp @@ -13,6 +13,7 @@ #include "../entity/EntityList.h" #include "../rct12/RCT12.h" #include "../util/Util.h" +#include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" #include "Track.h" diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index d0dab6064d..112cd79325 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -63,6 +63,7 @@ #include "../world/Scenery.h" #include "../world/TileElementsView.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/TrackElement.h" #include "CableLift.h" #include "RideAudio.h" #include "RideConstruction.h" diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp index 2abe555480..62e96b586b 100644 --- a/src/openrct2/ride/RideConstruction.cpp +++ b/src/openrct2/ride/RideConstruction.cpp @@ -41,6 +41,7 @@ #include "../world/Scenery.h" #include "../world/TileElementsView.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" #include "Track.h" diff --git a/src/openrct2/ride/RideRatings.cpp b/src/openrct2/ride/RideRatings.cpp index aeab7e76ff..256281587e 100644 --- a/src/openrct2/ride/RideRatings.cpp +++ b/src/openrct2/ride/RideRatings.cpp @@ -20,6 +20,7 @@ #include "../world/Footpath.h" #include "../world/Map.h" #include "../world/Surface.h" +#include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" #include "Station.h" diff --git a/src/openrct2/ride/Station.cpp b/src/openrct2/ride/Station.cpp index 01d785290d..2e487b7693 100644 --- a/src/openrct2/ride/Station.cpp +++ b/src/openrct2/ride/Station.cpp @@ -14,6 +14,7 @@ #include "../entity/Guest.h" #include "../scenario/Scenario.h" #include "../world/Location.hpp" +#include "../world/tile_element/TrackElement.h" #include "RideEntry.h" #include "Track.h" #include "Vehicle.h" diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index d3c2b6f7d5..68efe948b4 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -29,6 +29,7 @@ #include "../world/Park.h" #include "../world/Scenery.h" #include "../world/Surface.h" +#include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" #include "RideRatings.h" @@ -523,52 +524,6 @@ void TrackGetFront(const CoordsXYE& input, CoordsXYE* output) *output = lastTrack; } -bool TrackElement::HasChain() const -{ - return Flags2 & TRACK_ELEMENT_FLAGS2_CHAIN_LIFT; -} - -void TrackElement::SetHasChain(bool on) -{ - if (on) - { - Flags2 |= TRACK_ELEMENT_FLAGS2_CHAIN_LIFT; - } - else - { - Flags2 &= ~TRACK_ELEMENT_FLAGS2_CHAIN_LIFT; - } -} - -/** - * Checks if a track element is recognised as the beginning of a block. - * A beginning of a block can be the end of a station, the end of a lift hill, - * or a block brake. - */ -bool TrackElement::IsBlockStart() const -{ - switch (GetTrackType()) - { - case TrackElemType::EndStation: - case TrackElemType::CableLiftHill: - case TrackElemType::BlockBrakes: - case TrackElemType::DiagBlockBrakes: - return true; - case TrackElemType::Up25ToFlat: - case TrackElemType::Up60ToFlat: - case TrackElemType::DiagUp25ToFlat: - case TrackElemType::DiagUp60ToFlat: - if (HasChain()) - { - return true; - } - break; - default: - break; - } - return false; -} - TrackRoll TrackGetActualBank(TileElement* tileElement, TrackRoll bank) { auto ride = GetRide(tileElement->AsTrack()->GetRideIndex()); @@ -612,11 +567,6 @@ TrackRoll TrackGetActualBank3(bool useInvertedSprites, TileElement* tileElement) return TrackGetActualBank2(ride->type, isInverted, bankStart); } -bool TrackElement::IsStation() const -{ - return TrackTypeIsStation(GetTrackType()); -} - bool TrackTypeIsStation(OpenRCT2::TrackElemType trackType) { switch (trackType) @@ -770,245 +720,3 @@ std::optional GetTrackSegmentOrigin(const CoordsXYE& posEl) return CoordsXYZD(coords, direction); } - -uint8_t TrackElement::GetSeatRotation() const -{ - const auto* ride = GetRide(GetRideIndex()); - if (ride != nullptr && ride->GetRideTypeDescriptor().HasFlag(RtdFlag::hasLandscapeDoors)) - return DEFAULT_SEAT_ROTATION; - - return URide.ColourScheme >> 4; -} - -void TrackElement::SetSeatRotation(uint8_t newSeatRotation) -{ - URide.ColourScheme &= ~TRACK_ELEMENT_COLOUR_SEAT_ROTATION_MASK; - URide.ColourScheme |= (newSeatRotation << 4); -} - -bool TrackElement::IsTakingPhoto() const -{ - return URide.OnridePhotoBits != 0; -} - -void TrackElement::SetPhotoTimeout() -{ - URide.OnridePhotoBits = 3; -} - -void TrackElement::SetPhotoTimeout(uint8_t value) -{ - URide.OnridePhotoBits = value; -} - -uint8_t TrackElement::GetPhotoTimeout() const -{ - return URide.OnridePhotoBits; -} - -void TrackElement::DecrementPhotoTimeout() -{ - URide.OnridePhotoBits = std::max(0, URide.OnridePhotoBits - 1); -} - -uint16_t TrackElement::GetMazeEntry() const -{ - return UMaze.MazeEntry; -} - -void TrackElement::SetMazeEntry(uint16_t newMazeEntry) -{ - UMaze.MazeEntry = newMazeEntry; -} - -void TrackElement::MazeEntryAdd(uint16_t addVal) -{ - UMaze.MazeEntry |= addVal; -} - -void TrackElement::MazeEntrySubtract(uint16_t subVal) -{ - UMaze.MazeEntry &= ~subVal; -} - -OpenRCT2::TrackElemType TrackElement::GetTrackType() const -{ - return TrackType; -} - -void TrackElement::SetTrackType(OpenRCT2::TrackElemType newType) -{ - TrackType = newType; -} - -ride_type_t TrackElement::GetRideType() const -{ - return RideType; -} - -void TrackElement::SetRideType(const ride_type_t rideType) -{ - RideType = rideType; -} - -uint8_t TrackElement::GetSequenceIndex() const -{ - return URide.Sequence; -} - -void TrackElement::SetSequenceIndex(uint8_t newSequenceIndex) -{ - URide.Sequence = newSequenceIndex; -} - -StationIndex TrackElement::GetStationIndex() const -{ - return URide.stationIndex; -} - -void TrackElement::SetStationIndex(StationIndex newStationIndex) -{ - URide.stationIndex = newStationIndex; -} - -uint8_t TrackElement::GetDoorAState() const -{ - return (URide.ColourScheme & TRACK_ELEMENT_COLOUR_DOOR_A_MASK) >> 2; -} - -uint8_t TrackElement::GetDoorBState() const -{ - return (URide.ColourScheme & TRACK_ELEMENT_COLOUR_DOOR_B_MASK) >> 5; -} - -void TrackElement::SetDoorAState(uint8_t newState) -{ - URide.ColourScheme &= ~TRACK_ELEMENT_COLOUR_DOOR_A_MASK; - URide.ColourScheme |= ((newState << 2) & TRACK_ELEMENT_COLOUR_DOOR_A_MASK); -} - -void TrackElement::SetDoorBState(uint8_t newState) -{ - URide.ColourScheme &= ~TRACK_ELEMENT_COLOUR_DOOR_B_MASK; - URide.ColourScheme |= ((newState << 5) & TRACK_ELEMENT_COLOUR_DOOR_B_MASK); -} - -RideId TrackElement::GetRideIndex() const -{ - return RideIndex; -} - -void TrackElement::SetRideIndex(RideId newRideIndex) -{ - RideIndex = newRideIndex; -} - -uint8_t TrackElement::GetColourScheme() const -{ - return URide.ColourScheme & TRACK_ELEMENT_COLOUR_SCHEME_MASK; -} - -void TrackElement::SetColourScheme(RideColourScheme newColourScheme) -{ - URide.ColourScheme &= ~TRACK_ELEMENT_COLOUR_SCHEME_MASK; - URide.ColourScheme |= (EnumValue(newColourScheme) & TRACK_ELEMENT_COLOUR_SCHEME_MASK); -} - -bool TrackElement::HasCableLift() const -{ - return Flags2 & TRACK_ELEMENT_FLAGS2_CABLE_LIFT; -} - -void TrackElement::SetHasCableLift(bool on) -{ - Flags2 &= ~TRACK_ELEMENT_FLAGS2_CABLE_LIFT; - if (on) - Flags2 |= TRACK_ELEMENT_FLAGS2_CABLE_LIFT; -} - -bool TrackElement::IsInverted() const -{ - return Flags2 & TRACK_ELEMENT_FLAGS2_INVERTED; -} - -void TrackElement::SetInverted(bool inverted) -{ - if (inverted) - { - Flags2 |= TRACK_ELEMENT_FLAGS2_INVERTED; - } - else - { - Flags2 &= ~TRACK_ELEMENT_FLAGS2_INVERTED; - } -} - -bool TrackElement::IsBrakeClosed() const -{ - return (Flags2 & TRACK_ELEMENT_FLAGS2_BRAKE_CLOSED) != 0; -} - -void TrackElement::SetBrakeClosed(bool isClosed) -{ - if (isClosed) - { - Flags2 |= TRACK_ELEMENT_FLAGS2_BRAKE_CLOSED; - } - else - { - Flags2 &= ~TRACK_ELEMENT_FLAGS2_BRAKE_CLOSED; - } -} - -bool TrackElement::IsIndestructible() const -{ - return (Flags2 & TRACK_ELEMENT_FLAGS2_INDESTRUCTIBLE_TRACK_PIECE) != 0 && !GetGameState().Cheats.MakeAllDestructible; -} - -void TrackElement::SetIsIndestructible(bool isIndestructible) -{ - if (isIndestructible) - { - Flags2 |= TRACK_ELEMENT_FLAGS2_INDESTRUCTIBLE_TRACK_PIECE; - } - else - { - Flags2 &= ~TRACK_ELEMENT_FLAGS2_INDESTRUCTIBLE_TRACK_PIECE; - } -} - -uint8_t TrackElement::GetBrakeBoosterSpeed() const -{ - return URide.BrakeBoosterSpeed << 1; -} - -void TrackElement::SetBrakeBoosterSpeed(uint8_t speed) -{ - URide.BrakeBoosterSpeed = (speed >> 1); -} - -bool TrackElement::HasGreenLight() const -{ - return (Flags2 & TRACK_ELEMENT_FLAGS2_HAS_GREEN_LIGHT) != 0; -} - -void TrackElement::SetHasGreenLight(bool on) -{ - Flags2 &= ~TRACK_ELEMENT_FLAGS2_HAS_GREEN_LIGHT; - if (on) - { - Flags2 |= TRACK_ELEMENT_FLAGS2_HAS_GREEN_LIGHT; - } -} - -bool TrackElement::IsHighlighted() const -{ - return (Flags2 & TRACK_ELEMENT_FLAGS2_HIGHLIGHT); -} - -void TrackElement::SetHighlight(bool on) -{ - Flags2 &= ~TRACK_ELEMENT_FLAGS2_HIGHLIGHT; - if (on) - Flags2 |= TRACK_ELEMENT_FLAGS2_HIGHLIGHT; -} diff --git a/src/openrct2/ride/Track.h b/src/openrct2/ride/Track.h index e6f47cefe0..627a5b24c8 100644 --- a/src/openrct2/ride/Track.h +++ b/src/openrct2/ride/Track.h @@ -201,27 +201,6 @@ enum RCT_PREVIEW_TRACK_FLAG_IS_VERTICAL = (1 << 2), }; -enum -{ - TRACK_ELEMENT_FLAGS2_CHAIN_LIFT = 1 << 0, - TRACK_ELEMENT_FLAGS2_INVERTED = 1 << 1, - // Used for giga coaster - TRACK_ELEMENT_FLAGS2_CABLE_LIFT = 1 << 2, - TRACK_ELEMENT_FLAGS2_HIGHLIGHT = 1 << 3, - TRACK_ELEMENT_FLAGS2_HAS_GREEN_LIGHT = 1 << 4, - TRACK_ELEMENT_FLAGS2_BRAKE_CLOSED = 1 << 5, - TRACK_ELEMENT_FLAGS2_INDESTRUCTIBLE_TRACK_PIECE = 1 << 6, -}; - -enum -{ - TRACK_ELEMENT_COLOUR_SCHEME_MASK = 0b00000011, - // Not colour related, but shares the field. - TRACK_ELEMENT_COLOUR_DOOR_A_MASK = 0b00011100, - TRACK_ELEMENT_COLOUR_DOOR_B_MASK = 0b11100000, - TRACK_ELEMENT_COLOUR_SEAT_ROTATION_MASK = 0b11110000, -}; - constexpr int8_t kMaxStationPlatformLength = 32; constexpr uint16_t const MAX_TRACK_HEIGHT = 254 * kCoordsZStep; constexpr uint8_t const DEFAULT_SEAT_ROTATION = 4; diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 6dda14b77e..3de439adc9 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -59,6 +59,7 @@ #include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" #include "Track.h" diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 2ba0111554..367183ed8c 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -26,6 +26,7 @@ #include "../world/Footpath.h" #include "../world/Scenery.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include "RideData.h" #include "Station.h" diff --git a/src/openrct2/ride/TrackPaint.cpp b/src/openrct2/ride/TrackPaint.cpp index 9a0ed97947..587b6ade6c 100644 --- a/src/openrct2/ride/TrackPaint.cpp +++ b/src/openrct2/ride/TrackPaint.cpp @@ -29,6 +29,7 @@ #include "../scenario/Scenario.h" #include "../sprites.h" #include "../world/Map.h" +#include "../world/tile_element/TrackElement.h" #include "RideData.h" #include "Station.h" #include "TrackData.h" diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 0deb3701bb..5a59047a95 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -47,6 +47,7 @@ #include "../world/Park.h" #include "../world/Scenery.h" #include "../world/Surface.h" +#include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include "CableLift.h" #include "Ride.h" diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index f10562b086..9820fc9e80 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -54,6 +54,7 @@ #include "../world/Map.h" #include "../world/Park.h" #include "../world/Scenery.h" +#include "../world/tile_element/TrackElement.h" #include "ScenarioRepository.h" #include "ScenarioSources.h" diff --git a/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp b/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp index fe984a3c1d..a54e151b83 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp +++ b/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp @@ -14,6 +14,7 @@ # include "../../../Context.h" # include "../../../ride/Ride.h" # include "../../../ride/TrackData.h" +# include "../../../world/tile_element/TrackElement.h" # include "../../ScriptEngine.h" # include "ScTrackSegment.h" diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.cpp b/src/openrct2/scripting/bindings/world/ScTileElement.cpp index bb6e0dbf8b..1760f3f52f 100644 --- a/src/openrct2/scripting/bindings/world/ScTileElement.cpp +++ b/src/openrct2/scripting/bindings/world/ScTileElement.cpp @@ -22,7 +22,9 @@ # include "../../../world/Footpath.h" # include "../../../world/Scenery.h" # include "../../../world/Surface.h" +# include "../../../world/tile_element/BannerElement.h" # include "../../../world/tile_element/EntranceElement.h" +# include "../../../world/tile_element/TrackElement.h" # include "../../../world/tile_element/WallElement.h" # include "../../Duktape.hpp" # include "../../ScriptEngine.h" diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp index dc1e6dec07..6145a408c3 100644 --- a/src/openrct2/world/Banner.cpp +++ b/src/openrct2/world/Banner.cpp @@ -32,6 +32,8 @@ #include "Park.h" #include "Scenery.h" #include "TileElementsView.h" +#include "tile_element/BannerElement.h" +#include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" #include @@ -369,57 +371,6 @@ void BannerApplyFixes() BannerDeallocateUnlinked(); } -Banner* BannerElement::GetBanner() const -{ - return ::GetBanner(GetIndex()); -} - -const BannerSceneryEntry* BannerElement::GetEntry() const -{ - auto banner = GetBanner(); - if (banner != nullptr) - { - return OpenRCT2::ObjectManager::GetObjectEntry(banner->type); - } - return nullptr; -} - -BannerIndex BannerElement::GetIndex() const -{ - return index; -} - -void BannerElement::SetIndex(BannerIndex newIndex) -{ - index = newIndex; -} - -uint8_t BannerElement::GetPosition() const -{ - return position; -} - -void BannerElement::SetPosition(uint8_t newPosition) -{ - position = newPosition; -} - -uint8_t BannerElement::GetAllowedEdges() const -{ - return AllowedEdges & 0b00001111; -} - -void BannerElement::SetAllowedEdges(uint8_t newEdges) -{ - AllowedEdges &= ~0b00001111; - AllowedEdges |= (newEdges & 0b00001111); -} - -void BannerElement::ResetAllowedEdges() -{ - AllowedEdges |= 0b00001111; -} - void UnlinkAllRideBanners() { auto& gameState = GetGameState(); diff --git a/src/openrct2/world/ConstructionClearance.cpp b/src/openrct2/world/ConstructionClearance.cpp index 428deec5cf..76bc023792 100644 --- a/src/openrct2/world/ConstructionClearance.cpp +++ b/src/openrct2/world/ConstructionClearance.cpp @@ -24,6 +24,7 @@ #include "Surface.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" +#include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/world/Entrance.cpp b/src/openrct2/world/Entrance.cpp index fbcdb7d669..20da58468a 100644 --- a/src/openrct2/world/Entrance.cpp +++ b/src/openrct2/world/Entrance.cpp @@ -31,6 +31,7 @@ #include "MapAnimation.h" #include "Park.h" #include "tile_element/EntranceElement.h" +#include "tile_element/TrackElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 84be49f337..b97574c451 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -38,8 +38,10 @@ #include "MapAnimation.h" #include "Surface.h" #include "TileElement.h" +#include "tile_element/BannerElement.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" +#include "tile_element/TrackElement.h" #include #include diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 7510ec1fef..209c025d32 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -57,8 +57,10 @@ #include "Surface.h" #include "TileElementsView.h" #include "TileInspector.h" +#include "tile_element/BannerElement.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" +#include "tile_element/TrackElement.h" #include #include diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index e3741c38c5..a5762ac0b4 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -29,6 +29,7 @@ #include "Map.h" #include "Scenery.h" #include "tile_element/EntranceElement.h" +#include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/world/TileElement.cpp b/src/openrct2/world/TileElement.cpp index c98f5b35ed..c5c98518de 100644 --- a/src/openrct2/world/TileElement.cpp +++ b/src/openrct2/world/TileElement.cpp @@ -18,8 +18,10 @@ #include "Banner.h" #include "Location.hpp" #include "Scenery.h" +#include "tile_element/BannerElement.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" +#include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index 48bec6028f..ea7c779642 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -12,7 +12,6 @@ #include "../Identifiers.h" #include "../ride/RideTypes.h" #include "../ride/Station.h" -#include "Banner.h" #include "Footpath.h" #include "tile_element/TileElementType.h" @@ -22,7 +21,6 @@ struct LargeSceneryEntry; struct SmallSceneryEntry; struct WallSceneryEntry; struct PathAdditionEntry; -struct BannerSceneryEntry; struct FootpathEntry; class LargeSceneryObject; class TerrainSurfaceObject; @@ -283,107 +281,6 @@ public: }; static_assert(sizeof(PathElement) == 16); -struct TrackElement : TileElementBase -{ - static constexpr TileElementType ElementType = TileElementType::Track; - -private: - OpenRCT2::TrackElemType TrackType; - union - { - struct - { - uint8_t Sequence; - uint8_t ColourScheme; - union - { - // - Bits 3 and 4 are never set - // - Bits 1 and 2 are set when a vehicle triggers the on-ride photo and act like a countdown from 3. - // - If any of the bits 1-4 are set, the game counts it as a photo being taken. - uint8_t OnridePhotoBits; - // Contains the brake/booster speed, divided by 2. - uint8_t BrakeBoosterSpeed; - }; - StationIndex stationIndex; - } URide; - struct - { - uint16_t MazeEntry; // 6 - } UMaze; - }; - uint8_t Flags2; - RideId RideIndex; - ride_type_t RideType; - -public: - OpenRCT2::TrackElemType GetTrackType() const; - void SetTrackType(OpenRCT2::TrackElemType newEntryIndex); - - ride_type_t GetRideType() const; - void SetRideType(const ride_type_t rideType); - - uint8_t GetSequenceIndex() const; - void SetSequenceIndex(uint8_t newSequenceIndex); - - RideId GetRideIndex() const; - void SetRideIndex(RideId newRideIndex); - - uint8_t GetColourScheme() const; - void SetColourScheme(RideColourScheme newColourScheme); - - StationIndex GetStationIndex() const; - void SetStationIndex(StationIndex newStationIndex); - - bool HasChain() const; - void SetHasChain(bool on); - - bool HasCableLift() const; - void SetHasCableLift(bool on); - - bool IsInverted() const; - void SetInverted(bool inverted); - - bool IsBrakeClosed() const; - void SetBrakeClosed(bool isClosed); - - bool IsIndestructible() const; - void SetIsIndestructible(bool isIndestructible); - - uint8_t GetBrakeBoosterSpeed() const; - void SetBrakeBoosterSpeed(uint8_t speed); - - bool HasGreenLight() const; - void SetHasGreenLight(bool on); - - uint8_t GetSeatRotation() const; - void SetSeatRotation(uint8_t newSeatRotation); - - uint16_t GetMazeEntry() const; - void SetMazeEntry(uint16_t newMazeEntry); - void MazeEntryAdd(uint16_t addVal); - void MazeEntrySubtract(uint16_t subVal); - - bool IsTakingPhoto() const; - void SetPhotoTimeout(); - void SetPhotoTimeout(uint8_t newValue); - void DecrementPhotoTimeout(); - uint8_t GetPhotoTimeout() const; - - bool IsHighlighted() const; - void SetHighlight(bool on); - - // Used by ghost train, RCT1 feature, will be reintroduced at some point. - // (See https://github.com/OpenRCT2/OpenRCT2/issues/7059) - uint8_t GetDoorAState() const; - uint8_t GetDoorBState() const; - void SetDoorAState(uint8_t newState); - void SetDoorBState(uint8_t newState); - - bool IsStation() const; - bool IsBlockStart() const; -}; -static_assert(sizeof(TrackElement) == 16); - struct SmallSceneryElement : TileElementBase { static constexpr TileElementType ElementType = TileElementType::SmallScenery; @@ -459,34 +356,6 @@ public: }; static_assert(sizeof(LargeSceneryElement) == 16); -struct BannerElement : TileElementBase -{ - static constexpr TileElementType ElementType = TileElementType::Banner; - -private: - BannerIndex index; // 5 - uint8_t position; // 7 - uint8_t AllowedEdges; // 8 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-private-field" - uint8_t Pad09[7]; -#pragma clang diagnostic pop -public: - Banner* GetBanner() const; - const BannerSceneryEntry* GetEntry() const; - - BannerIndex GetIndex() const; - void SetIndex(BannerIndex newIndex); - - uint8_t GetPosition() const; - void SetPosition(uint8_t newPosition); - - uint8_t GetAllowedEdges() const; - void SetAllowedEdges(uint8_t newEdges); - void ResetAllowedEdges(); -}; -static_assert(sizeof(BannerElement) == 16); - #pragma pack(pop) enum @@ -526,11 +395,4 @@ constexpr uint8_t kTileElementTypeMask = 0b00111100; constexpr uint8_t kTileElementDirectionMask = 0b00000011; constexpr uint8_t kTileElementOccupiedQuadrantsMask = 0b00001111; -enum -{ - LANDSCAPE_DOOR_CLOSED = 0, - LANDSCAPE_DOOR_HALF_OPEN = 2, - LANDSCAPE_DOOR_OPEN = 3, -}; - bool TileElementIsUnderground(TileElement* tileElement); diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index cf7445d784..996461a6b4 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -25,8 +25,10 @@ #include "Park.h" #include "Scenery.h" #include "Surface.h" +#include "tile_element/BannerElement.h" #include "tile_element/EntranceElement.h" #include "tile_element/Slope.h" +#include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" #include diff --git a/src/openrct2/world/tile_element/BannerElement.cpp b/src/openrct2/world/tile_element/BannerElement.cpp new file mode 100644 index 0000000000..5f7bfbaea4 --- /dev/null +++ b/src/openrct2/world/tile_element/BannerElement.cpp @@ -0,0 +1,57 @@ +#include "BannerElement.h" + +#include "../../object/BannerSceneryEntry.h" +#include "../../object/ObjectEntryManager.h" +#include "../../object/ObjectManager.h" +#include "../Banner.h" + +Banner* BannerElement::GetBanner() const +{ + return ::GetBanner(GetIndex()); +} + +const BannerSceneryEntry* BannerElement::GetEntry() const +{ + auto banner = GetBanner(); + if (banner != nullptr) + { + return OpenRCT2::ObjectManager::GetObjectEntry(banner->type); + } + return nullptr; +} + +BannerIndex BannerElement::GetIndex() const +{ + return index; +} + +void BannerElement::SetIndex(BannerIndex newIndex) +{ + index = newIndex; +} + +uint8_t BannerElement::GetPosition() const +{ + return position; +} + +void BannerElement::SetPosition(uint8_t newPosition) +{ + position = newPosition; +} + +uint8_t BannerElement::GetAllowedEdges() const +{ + return AllowedEdges & 0b00001111; +} + +void BannerElement::SetAllowedEdges(uint8_t newEdges) +{ + AllowedEdges &= ~0b00001111; + AllowedEdges |= (newEdges & 0b00001111); +} + +void BannerElement::ResetAllowedEdges() +{ + AllowedEdges |= 0b00001111; +} diff --git a/src/openrct2/world/tile_element/BannerElement.h b/src/openrct2/world/tile_element/BannerElement.h new file mode 100644 index 0000000000..a0bfe2d01b --- /dev/null +++ b/src/openrct2/world/tile_element/BannerElement.h @@ -0,0 +1,44 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../TileElement.h" + +struct BannerSceneryEntry; + +#pragma pack(push, 1) +struct BannerElement : TileElementBase +{ + static constexpr TileElementType ElementType = TileElementType::Banner; + +private: + BannerIndex index; // 5 + uint8_t position; // 7 + uint8_t AllowedEdges; // 8 +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" + uint8_t Pad09[7]; +#pragma clang diagnostic pop +public: + Banner* GetBanner() const; + const BannerSceneryEntry* GetEntry() const; + + BannerIndex GetIndex() const; + void SetIndex(BannerIndex newIndex); + + uint8_t GetPosition() const; + void SetPosition(uint8_t newPosition); + + uint8_t GetAllowedEdges() const; + void SetAllowedEdges(uint8_t newEdges); + void ResetAllowedEdges(); +}; +static_assert(sizeof(BannerElement) == kTileElementSize); +#pragma pack(pop) diff --git a/src/openrct2/world/tile_element/TileElementBase.cpp b/src/openrct2/world/tile_element/TileElementBase.cpp index a8af4cacd5..9e8a1215cb 100644 --- a/src/openrct2/world/tile_element/TileElementBase.cpp +++ b/src/openrct2/world/tile_element/TileElementBase.cpp @@ -9,7 +9,9 @@ #include "../Map.h" #include "../TileElement.h" +#include "BannerElement.h" #include "EntranceElement.h" +#include "TrackElement.h" #include "WallElement.h" TileElementType TileElementBase::GetType() const diff --git a/src/openrct2/world/tile_element/TrackElement.cpp b/src/openrct2/world/tile_element/TrackElement.cpp new file mode 100644 index 0000000000..0e96088da3 --- /dev/null +++ b/src/openrct2/world/tile_element/TrackElement.cpp @@ -0,0 +1,304 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "TrackElement.h" + +#include "../../GameState.h" +#include "../../ride/RideData.h" +#include "../../ride/Track.h" + +using namespace OpenRCT2; + +bool TrackElement::HasChain() const +{ + return Flags2 & TRACK_ELEMENT_FLAGS2_CHAIN_LIFT; +} + +void TrackElement::SetHasChain(bool on) +{ + if (on) + { + Flags2 |= TRACK_ELEMENT_FLAGS2_CHAIN_LIFT; + } + else + { + Flags2 &= ~TRACK_ELEMENT_FLAGS2_CHAIN_LIFT; + } +} + +/** + * Checks if a track element is recognised as the beginning of a block. + * A beginning of a block can be the end of a station, the end of a lift hill, + * or a block brake. + */ +bool TrackElement::IsBlockStart() const +{ + switch (GetTrackType()) + { + case TrackElemType::EndStation: + case TrackElemType::CableLiftHill: + case TrackElemType::BlockBrakes: + case TrackElemType::DiagBlockBrakes: + return true; + case TrackElemType::Up25ToFlat: + case TrackElemType::Up60ToFlat: + case TrackElemType::DiagUp25ToFlat: + case TrackElemType::DiagUp60ToFlat: + return HasChain(); + default: + return false; + } +} + +bool TrackElement::IsStation() const +{ + return TrackTypeIsStation(GetTrackType()); +} + +uint8_t TrackElement::GetSeatRotation() const +{ + const auto* ride = GetRide(GetRideIndex()); + if (ride != nullptr && ride->GetRideTypeDescriptor().HasFlag(RtdFlag::hasLandscapeDoors)) + return DEFAULT_SEAT_ROTATION; + + return URide.ColourScheme >> 4; +} + +void TrackElement::SetSeatRotation(uint8_t newSeatRotation) +{ + URide.ColourScheme &= ~TRACK_ELEMENT_COLOUR_SEAT_ROTATION_MASK; + URide.ColourScheme |= (newSeatRotation << 4); +} + +bool TrackElement::IsTakingPhoto() const +{ + return URide.OnridePhotoBits != 0; +} + +void TrackElement::SetPhotoTimeout() +{ + URide.OnridePhotoBits = 3; +} + +void TrackElement::SetPhotoTimeout(uint8_t value) +{ + URide.OnridePhotoBits = value; +} + +uint8_t TrackElement::GetPhotoTimeout() const +{ + return URide.OnridePhotoBits; +} + +void TrackElement::DecrementPhotoTimeout() +{ + URide.OnridePhotoBits = std::max(0, URide.OnridePhotoBits - 1); +} + +uint16_t TrackElement::GetMazeEntry() const +{ + return UMaze.MazeEntry; +} + +void TrackElement::SetMazeEntry(uint16_t newMazeEntry) +{ + UMaze.MazeEntry = newMazeEntry; +} + +void TrackElement::MazeEntryAdd(uint16_t addVal) +{ + UMaze.MazeEntry |= addVal; +} + +void TrackElement::MazeEntrySubtract(uint16_t subVal) +{ + UMaze.MazeEntry &= ~subVal; +} + +OpenRCT2::TrackElemType TrackElement::GetTrackType() const +{ + return TrackType; +} + +void TrackElement::SetTrackType(OpenRCT2::TrackElemType newType) +{ + TrackType = newType; +} + +ride_type_t TrackElement::GetRideType() const +{ + return RideType; +} + +void TrackElement::SetRideType(const ride_type_t rideType) +{ + RideType = rideType; +} + +uint8_t TrackElement::GetSequenceIndex() const +{ + return URide.Sequence; +} + +void TrackElement::SetSequenceIndex(uint8_t newSequenceIndex) +{ + URide.Sequence = newSequenceIndex; +} + +StationIndex TrackElement::GetStationIndex() const +{ + return URide.stationIndex; +} + +void TrackElement::SetStationIndex(StationIndex newStationIndex) +{ + URide.stationIndex = newStationIndex; +} + +uint8_t TrackElement::GetDoorAState() const +{ + return (URide.ColourScheme & TRACK_ELEMENT_COLOUR_DOOR_A_MASK) >> 2; +} + +uint8_t TrackElement::GetDoorBState() const +{ + return (URide.ColourScheme & TRACK_ELEMENT_COLOUR_DOOR_B_MASK) >> 5; +} + +void TrackElement::SetDoorAState(uint8_t newState) +{ + URide.ColourScheme &= ~TRACK_ELEMENT_COLOUR_DOOR_A_MASK; + URide.ColourScheme |= ((newState << 2) & TRACK_ELEMENT_COLOUR_DOOR_A_MASK); +} + +void TrackElement::SetDoorBState(uint8_t newState) +{ + URide.ColourScheme &= ~TRACK_ELEMENT_COLOUR_DOOR_B_MASK; + URide.ColourScheme |= ((newState << 5) & TRACK_ELEMENT_COLOUR_DOOR_B_MASK); +} + +RideId TrackElement::GetRideIndex() const +{ + return RideIndex; +} + +void TrackElement::SetRideIndex(RideId newRideIndex) +{ + RideIndex = newRideIndex; +} + +uint8_t TrackElement::GetColourScheme() const +{ + return URide.ColourScheme & TRACK_ELEMENT_COLOUR_SCHEME_MASK; +} + +void TrackElement::SetColourScheme(RideColourScheme newColourScheme) +{ + URide.ColourScheme &= ~TRACK_ELEMENT_COLOUR_SCHEME_MASK; + URide.ColourScheme |= (EnumValue(newColourScheme) & TRACK_ELEMENT_COLOUR_SCHEME_MASK); +} + +bool TrackElement::HasCableLift() const +{ + return Flags2 & TRACK_ELEMENT_FLAGS2_CABLE_LIFT; +} + +void TrackElement::SetHasCableLift(bool on) +{ + Flags2 &= ~TRACK_ELEMENT_FLAGS2_CABLE_LIFT; + if (on) + Flags2 |= TRACK_ELEMENT_FLAGS2_CABLE_LIFT; +} + +bool TrackElement::IsInverted() const +{ + return Flags2 & TRACK_ELEMENT_FLAGS2_INVERTED; +} + +void TrackElement::SetInverted(bool inverted) +{ + if (inverted) + { + Flags2 |= TRACK_ELEMENT_FLAGS2_INVERTED; + } + else + { + Flags2 &= ~TRACK_ELEMENT_FLAGS2_INVERTED; + } +} + +bool TrackElement::IsBrakeClosed() const +{ + return (Flags2 & TRACK_ELEMENT_FLAGS2_BRAKE_CLOSED) != 0; +} + +void TrackElement::SetBrakeClosed(bool isClosed) +{ + if (isClosed) + { + Flags2 |= TRACK_ELEMENT_FLAGS2_BRAKE_CLOSED; + } + else + { + Flags2 &= ~TRACK_ELEMENT_FLAGS2_BRAKE_CLOSED; + } +} + +bool TrackElement::IsIndestructible() const +{ + return (Flags2 & TRACK_ELEMENT_FLAGS2_INDESTRUCTIBLE_TRACK_PIECE) != 0 && !GetGameState().Cheats.MakeAllDestructible; +} + +void TrackElement::SetIsIndestructible(bool isIndestructible) +{ + if (isIndestructible) + { + Flags2 |= TRACK_ELEMENT_FLAGS2_INDESTRUCTIBLE_TRACK_PIECE; + } + else + { + Flags2 &= ~TRACK_ELEMENT_FLAGS2_INDESTRUCTIBLE_TRACK_PIECE; + } +} + +uint8_t TrackElement::GetBrakeBoosterSpeed() const +{ + return URide.BrakeBoosterSpeed << 1; +} + +void TrackElement::SetBrakeBoosterSpeed(uint8_t speed) +{ + URide.BrakeBoosterSpeed = (speed >> 1); +} + +bool TrackElement::HasGreenLight() const +{ + return (Flags2 & TRACK_ELEMENT_FLAGS2_HAS_GREEN_LIGHT) != 0; +} + +void TrackElement::SetHasGreenLight(bool on) +{ + Flags2 &= ~TRACK_ELEMENT_FLAGS2_HAS_GREEN_LIGHT; + if (on) + { + Flags2 |= TRACK_ELEMENT_FLAGS2_HAS_GREEN_LIGHT; + } +} + +bool TrackElement::IsHighlighted() const +{ + return (Flags2 & TRACK_ELEMENT_FLAGS2_HIGHLIGHT); +} + +void TrackElement::SetHighlight(bool on) +{ + Flags2 &= ~TRACK_ELEMENT_FLAGS2_HIGHLIGHT; + if (on) + Flags2 |= TRACK_ELEMENT_FLAGS2_HIGHLIGHT; +} diff --git a/src/openrct2/world/tile_element/TrackElement.h b/src/openrct2/world/tile_element/TrackElement.h new file mode 100644 index 0000000000..460190be10 --- /dev/null +++ b/src/openrct2/world/tile_element/TrackElement.h @@ -0,0 +1,145 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../TileElement.h" + +enum +{ + TRACK_ELEMENT_FLAGS2_CHAIN_LIFT = 1 << 0, + TRACK_ELEMENT_FLAGS2_INVERTED = 1 << 1, + // Used for giga coaster + TRACK_ELEMENT_FLAGS2_CABLE_LIFT = 1 << 2, + TRACK_ELEMENT_FLAGS2_HIGHLIGHT = 1 << 3, + TRACK_ELEMENT_FLAGS2_HAS_GREEN_LIGHT = 1 << 4, + TRACK_ELEMENT_FLAGS2_BRAKE_CLOSED = 1 << 5, + TRACK_ELEMENT_FLAGS2_INDESTRUCTIBLE_TRACK_PIECE = 1 << 6, +}; + +enum +{ + TRACK_ELEMENT_COLOUR_SCHEME_MASK = 0b00000011, + // Not colour related, but shares the field. + TRACK_ELEMENT_COLOUR_DOOR_A_MASK = 0b00011100, + TRACK_ELEMENT_COLOUR_DOOR_B_MASK = 0b11100000, + TRACK_ELEMENT_COLOUR_SEAT_ROTATION_MASK = 0b11110000, +}; + +enum +{ + LANDSCAPE_DOOR_CLOSED = 0, + LANDSCAPE_DOOR_HALF_OPEN = 2, + LANDSCAPE_DOOR_OPEN = 3, +}; + +#pragma pack(push, 1) + +struct TrackElement : TileElementBase +{ + static constexpr TileElementType ElementType = TileElementType::Track; + +private: + OpenRCT2::TrackElemType TrackType; + union + { + struct + { + uint8_t Sequence; + uint8_t ColourScheme; + union + { + // - Bits 3 and 4 are never set + // - Bits 1 and 2 are set when a vehicle triggers the on-ride photo and act like a countdown from 3. + // - If any of the bits 1-4 are set, the game counts it as a photo being taken. + uint8_t OnridePhotoBits; + // Contains the brake/booster speed, divided by 2. + uint8_t BrakeBoosterSpeed; + }; + StationIndex stationIndex; + } URide; + struct + { + uint16_t MazeEntry; // 6 + } UMaze; + }; + uint8_t Flags2; + RideId RideIndex; + ride_type_t RideType; + +public: + OpenRCT2::TrackElemType GetTrackType() const; + void SetTrackType(OpenRCT2::TrackElemType newEntryIndex); + + ride_type_t GetRideType() const; + void SetRideType(const ride_type_t rideType); + + uint8_t GetSequenceIndex() const; + void SetSequenceIndex(uint8_t newSequenceIndex); + + RideId GetRideIndex() const; + void SetRideIndex(RideId newRideIndex); + + uint8_t GetColourScheme() const; + void SetColourScheme(RideColourScheme newColourScheme); + + StationIndex GetStationIndex() const; + void SetStationIndex(StationIndex newStationIndex); + + bool HasChain() const; + void SetHasChain(bool on); + + bool HasCableLift() const; + void SetHasCableLift(bool on); + + bool IsInverted() const; + void SetInverted(bool inverted); + + bool IsBrakeClosed() const; + void SetBrakeClosed(bool isClosed); + + bool IsIndestructible() const; + void SetIsIndestructible(bool isIndestructible); + + uint8_t GetBrakeBoosterSpeed() const; + void SetBrakeBoosterSpeed(uint8_t speed); + + bool HasGreenLight() const; + void SetHasGreenLight(bool on); + + uint8_t GetSeatRotation() const; + void SetSeatRotation(uint8_t newSeatRotation); + + uint16_t GetMazeEntry() const; + void SetMazeEntry(uint16_t newMazeEntry); + void MazeEntryAdd(uint16_t addVal); + void MazeEntrySubtract(uint16_t subVal); + + bool IsTakingPhoto() const; + void SetPhotoTimeout(); + void SetPhotoTimeout(uint8_t newValue); + void DecrementPhotoTimeout(); + uint8_t GetPhotoTimeout() const; + + bool IsHighlighted() const; + void SetHighlight(bool on); + + // Used by ghost train, RCT1 feature, will be reintroduced at some point. + // (See https://github.com/OpenRCT2/OpenRCT2/issues/7059) + uint8_t GetDoorAState() const; + uint8_t GetDoorBState() const; + void SetDoorAState(uint8_t newState); + void SetDoorBState(uint8_t newState); + + bool IsStation() const; + bool IsBlockStart() const; +}; +static_assert(sizeof(TrackElement) == kTileElementSize); + +#pragma pack(pop) diff --git a/src/openrct2/world/tile_element/WallElement.cpp b/src/openrct2/world/tile_element/WallElement.cpp index 0f34685ac6..af9a61ad8e 100644 --- a/src/openrct2/world/tile_element/WallElement.cpp +++ b/src/openrct2/world/tile_element/WallElement.cpp @@ -10,6 +10,7 @@ #include "../../object/ObjectEntryManager.h" #include "../../object/WallSceneryEntry.h" +#include "../Banner.h" uint8_t WallElement::GetSlope() const { diff --git a/test/tests/TileElements.cpp b/test/tests/TileElements.cpp index 8eb7b25166..41c18c4501 100644 --- a/test/tests/TileElements.cpp +++ b/test/tests/TileElements.cpp @@ -18,6 +18,7 @@ #include #include #include +#include using namespace OpenRCT2; diff --git a/test/tests/TileElementsView.cpp b/test/tests/TileElementsView.cpp index edc026eeb6..fb880e1f5f 100644 --- a/test/tests/TileElementsView.cpp +++ b/test/tests/TileElementsView.cpp @@ -18,7 +18,9 @@ #include #include #include +#include #include +#include #include using namespace OpenRCT2; From ff07f09fe7d6e68c5a0eb2b05aaa4b956522333b Mon Sep 17 00:00:00 2001 From: OpenRCT2 git bot Date: Tue, 15 Oct 2024 04:02:18 +0000 Subject: [PATCH 24/97] Merge Localisation/master into OpenRCT2/develop --- data/language/es-ES.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data/language/es-ES.txt b/data/language/es-ES.txt index 363038e1b6..a57cd979ce 100644 --- a/data/language/es-ES.txt +++ b/data/language/es-ES.txt @@ -3341,8 +3341,8 @@ STR_6250 :{WINDOW_COLOUR_1}¿Seguro quieres demoler {STRINGID} y ganar {CURRE STR_6251 :La atracción aún no está vacía STR_6255 :URL inválida. STR_6256 :Efectos al renderizar -STR_6257 :Translúcido -STR_6258 :Transparente +STR_6257 :Vítreo (translúcido) +STR_6258 :Claro (transparente) STR_6259 :Deshabilitado STR_6260 :Mostrar casillas bloqueadas STR_6261 :Mostrar senderos anchos @@ -3745,6 +3745,8 @@ STR_6669 :Mostrar trucos de empleados STR_6670 :Comportamiento de los visitantes STR_6671 :Mostrar nombres ‘reales’ de empleados STR_6672 :Alternar entre mostrar nombres ‘reales’ y números de empleados +STR_6673 :Translúcido +STR_6674 :{MONTH}, Año {COMMA16} ############## # Escenarios # From 498a2e349b26bb692c23bad50e0be71d730e29b5 Mon Sep 17 00:00:00 2001 From: mrmbernardi Date: Tue, 15 Oct 2024 20:11:47 +1100 Subject: [PATCH 25/97] CMake option to turn on the AddressSanitizer (#22985) --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e83b17257..4ff2d55734 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,8 @@ option(DISABLE_HTTP "Disable HTTP support.") option(DISABLE_NETWORK "Disable multiplayer functionality. Mainly for testing.") option(DISABLE_TTF "Disable support for TTF provided by freetype2.") option(ENABLE_SCRIPTING "Enable script / plugin support." ON) +option(ENABLE_ASAN "Enable the AddressSanitizer.") +option(ENABLE_UBSAN "Enable the UndefinedBehaviourSanitizer.") option(DISABLE_GUI "Don't build GUI. (Headless only.)") @@ -396,6 +398,14 @@ endif () if (ENABLE_SCRIPTING) target_compile_options(libopenrct2 PUBLIC -DENABLE_SCRIPTING) endif () +if (ENABLE_ASAN) + target_compile_options(libopenrct2 PUBLIC -fsanitize=address) + target_link_options(libopenrct2 PUBLIC -fsanitize=address) +endif () +if (ENABLE_UBSAN) + target_compile_options(libopenrct2 PUBLIC -fsanitize=undefined) + target_link_options(libopenrct2 PUBLIC -fsanitize=undefined) +endif () # g2 From aea385a6abd2293a47572b06bd0f8b3794170139 Mon Sep 17 00:00:00 2001 From: mrmbernardi Date: Tue, 15 Oct 2024 23:16:56 +1100 Subject: [PATCH 26/97] Fix PatrolArea and AudioSource memory leaks (#22992) --- src/openrct2-ui/audio/AudioContext.cpp | 2 ++ src/openrct2/Game.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/openrct2-ui/audio/AudioContext.cpp b/src/openrct2-ui/audio/AudioContext.cpp index 32d563591b..f2f9f05b1c 100644 --- a/src/openrct2-ui/audio/AudioContext.cpp +++ b/src/openrct2-ui/audio/AudioContext.cpp @@ -90,6 +90,7 @@ namespace OpenRCT2::Audio } catch (const std::exception& e) { + SDL_RWclose(rw); LOG_VERBOSE("Unable to create audio source: %s", e.what()); return nullptr; } @@ -119,6 +120,7 @@ namespace OpenRCT2::Audio } catch (const std::exception& e) { + SDL_RWclose(rw); LOG_VERBOSE("Unable to create audio source: %s", e.what()); return nullptr; } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 5ef61ffbb1..1ed4341d19 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -685,6 +685,7 @@ void GameLoadOrQuitNoSavePrompt() } default: GameUnloadScripts(); + ResetAllEntities(); OpenRCT2Finish(); break; } From 8a9d5edc2d2e11ffe964bb606c89a62ba12ce425 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:50:42 +0200 Subject: [PATCH 27/97] Fix #22615: Crash when drawing Space Rings with invalid ride entry --- distribution/changelog.txt | 1 + .../paint/track/gentle/SpaceRings.cpp | 69 ++++++++++--------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 84c31d16a0..494472ddaf 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.4.16 (in development) ------------------------------------------------------------------------ +- Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. - Fix: [#22918] Zooming with keyboard moves the view off centre. - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. - Fix: [#22962] Fuzzy horizontal-to-vertical line transitions in charts. diff --git a/src/openrct2/paint/track/gentle/SpaceRings.cpp b/src/openrct2/paint/track/gentle/SpaceRings.cpp index 3938538fc5..587d2bb908 100644 --- a/src/openrct2/paint/track/gentle/SpaceRings.cpp +++ b/src/openrct2/paint/track/gentle/SpaceRings.cpp @@ -42,44 +42,45 @@ static void PaintSpaceRingsStructure( PaintSession& session, const Ride& ride, uint8_t direction, uint32_t segment, int32_t height, ImageId stationColour) { uint32_t vehicleIndex = (segment - direction) & 0x3; - - if (ride.num_stations == 0 || vehicleIndex < ride.NumTrains) + const auto* rideEntry = GetRideEntryByIndex(ride.subtype); + if (rideEntry == nullptr || (ride.num_stations != 0 && vehicleIndex >= ride.NumTrains)) { - const auto* rideEntry = GetRideEntryByIndex(ride.subtype); + session.CurrentlyDrawnEntity = nullptr; + session.InteractionType = ViewportInteractionItem::Ride; + return; + } - int32_t frameNum = direction; + int32_t frameNum = direction; + uint32_t baseImageId = rideEntry->Cars[0].base_image_id; + auto vehicle = GetEntity(ride.vehicles[vehicleIndex]); + if (ride.lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK && vehicle != nullptr) + { + session.InteractionType = ViewportInteractionItem::Entity; + session.CurrentlyDrawnEntity = vehicle; + frameNum += static_cast(vehicle->Pitch) * 4; + } - uint32_t baseImageId = rideEntry->Cars[0].base_image_id; - auto vehicle = GetEntity(ride.vehicles[vehicleIndex]); - if (ride.lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK && vehicle != nullptr) + if (ride.vehicleColourSettings != VehicleColourSettings::perTrain) + { + vehicleIndex = 0; + } + + if (stationColour == TrackStationColour) + { + stationColour = ImageId(0, ride.vehicle_colours[vehicleIndex].Body, ride.vehicle_colours[vehicleIndex].Trim); + } + + auto imageId = stationColour.WithIndex(baseImageId + frameNum); + PaintAddImageAsParent(session, imageId, { 0, 0, height }, { { -10, -10, height }, { 20, 20, 23 } }); + + if (vehicle != nullptr && vehicle->num_peeps > 0) + { + auto* rider = GetEntity(vehicle->peep[0]); + if (rider != nullptr) { - session.InteractionType = ViewportInteractionItem::Entity; - session.CurrentlyDrawnEntity = vehicle; - frameNum += static_cast(vehicle->Pitch) * 4; - } - - if (ride.vehicleColourSettings != VehicleColourSettings::perTrain) - { - vehicleIndex = 0; - } - - if (stationColour == TrackStationColour) - { - stationColour = ImageId(0, ride.vehicle_colours[vehicleIndex].Body, ride.vehicle_colours[vehicleIndex].Trim); - } - - auto imageId = stationColour.WithIndex(baseImageId + frameNum); - PaintAddImageAsParent(session, imageId, { 0, 0, height }, { { -10, -10, height }, { 20, 20, 23 } }); - - if (vehicle != nullptr && vehicle->num_peeps > 0) - { - auto* rider = GetEntity(vehicle->peep[0]); - if (rider != nullptr) - { - stationColour = ImageId(0, rider->TshirtColour, rider->TrousersColour); - imageId = stationColour.WithIndex(baseImageId + 352 + frameNum); - PaintAddImageAsChild(session, imageId, { 0, 0, height }, { { -10, -10, height }, { 20, 20, 23 } }); - } + stationColour = ImageId(0, rider->TshirtColour, rider->TrousersColour); + imageId = stationColour.WithIndex(baseImageId + 352 + frameNum); + PaintAddImageAsChild(session, imageId, { 0, 0, height }, { { -10, -10, height }, { 20, 20, 23 } }); } } From 1ccef10b1966c1d971a9658593fbceec18bf18c8 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:01:46 +0200 Subject: [PATCH 28/97] Fix #22633: Crash when drawing loading screen with an outdated g2.dat --- distribution/changelog.txt | 1 + src/openrct2-ui/windows/ProgressWindow.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 494472ddaf..1765da97a3 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,6 +1,7 @@ 0.4.16 (in development) ------------------------------------------------------------------------ - Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. +- Fix: [#22633] Crash when drawing loading screen with an outdated g2.dat. - Fix: [#22918] Zooming with keyboard moves the view off centre. - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. - Fix: [#22962] Fuzzy horizontal-to-vertical line transitions in charts. diff --git a/src/openrct2-ui/windows/ProgressWindow.cpp b/src/openrct2-ui/windows/ProgressWindow.cpp index 95adab9b1d..0ca872e532 100644 --- a/src/openrct2-ui/windows/ProgressWindow.cpp +++ b/src/openrct2-ui/windows/ProgressWindow.cpp @@ -194,11 +194,12 @@ namespace OpenRCT2::Ui::Windows // Figure out where to position the vehicle to indicate progress auto* vehicle = GfxGetG1Element(variant.vehicle); + int16_t vehicleWidth = (vehicle != nullptr) ? vehicle->width : 0; int32_t position; if (_totalCount > 0) - position = (-vehicle->width + 2) + width * _currentProgress / _totalCount; + position = (-vehicleWidth + 2) + width * _currentProgress / _totalCount; else - position = (vehicle->width + width) / 2; + position = (vehicleWidth + width) / 2; GfxDrawSprite(clipDPI, variant.vehicle, ScreenCoordsXY(position, widget.bottom + 1)); } From 0ec76e09d429d9939ca85fbebfb5f755ee8cca23 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:39:54 +0200 Subject: [PATCH 29/97] Remove unused IStream::ReadString() function and fix includes --- src/openrct2/FileClassifier.cpp | 1 + src/openrct2/core/Crypt.CNG.cpp | 3 ++ src/openrct2/core/IStream.cpp | 18 -------- src/openrct2/core/IStream.hpp | 4 +- src/openrct2/core/MemoryStream.h | 1 + src/openrct2/core/OrcaStream.hpp | 1 + src/openrct2/core/ZipAndroid.cpp | 1 + src/openrct2/drawing/Drawing.Sprite.cpp | 1 + src/openrct2/network/NetworkKey.cpp | 1 + src/openrct2/object/AudioObject.cpp | 1 + src/openrct2/object/BannerObject.cpp | 1 + src/openrct2/object/EntranceObject.cpp | 1 + .../object/FootpathRailingsObject.cpp | 1 + src/openrct2/object/FootpathSurfaceObject.cpp | 1 + src/openrct2/object/ImageTable.cpp | 1 + src/openrct2/object/PathAdditionObject.cpp | 1 + src/openrct2/object/PeepNamesObject.cpp | 1 + src/openrct2/object/StationObject.cpp | 1 + src/openrct2/object/StringTable.cpp | 1 + src/openrct2/object/TerrainEdgeObject.cpp | 1 + src/openrct2/object/WallObject.cpp | 1 + test/tests/IniWriterTest.cpp | 46 ++++++++----------- 22 files changed, 41 insertions(+), 48 deletions(-) diff --git a/src/openrct2/FileClassifier.cpp b/src/openrct2/FileClassifier.cpp index 7760afa296..788e6ea97a 100644 --- a/src/openrct2/FileClassifier.cpp +++ b/src/openrct2/FileClassifier.cpp @@ -12,6 +12,7 @@ #include "Diagnostic.h" #include "core/Console.hpp" #include "core/FileStream.h" +#include "core/Memory.hpp" #include "core/Path.hpp" #include "core/String.hpp" #include "park/ParkFile.h" diff --git a/src/openrct2/core/Crypt.CNG.cpp b/src/openrct2/core/Crypt.CNG.cpp index 6befecd7e1..139d830fa9 100644 --- a/src/openrct2/core/Crypt.CNG.cpp +++ b/src/openrct2/core/Crypt.CNG.cpp @@ -14,7 +14,10 @@ # include "../platform/Platform.h" # include "IStream.hpp" +# include +# include # include +# include # include # include # include diff --git a/src/openrct2/core/IStream.cpp b/src/openrct2/core/IStream.cpp index 86d2c6c8fb..da0b8c8a27 100644 --- a/src/openrct2/core/IStream.cpp +++ b/src/openrct2/core/IStream.cpp @@ -9,30 +9,12 @@ #include "IStream.hpp" -#include "../object/Object.h" -#include "Memory.hpp" #include "String.hpp" #include namespace OpenRCT2 { - utf8* IStream::ReadString() - { - std::vector result; - - uint8_t ch; - while ((ch = ReadValue()) != 0) - { - result.push_back(ch); - } - result.push_back(0); - - utf8* resultString = Memory::AllocateArray(result.size()); - std::copy(result.begin(), result.end(), resultString); - return resultString; - } - std::string IStream::ReadStdString() { std::string result; diff --git a/src/openrct2/core/IStream.hpp b/src/openrct2/core/IStream.hpp index 3db2a154e4..bd99afc0ca 100644 --- a/src/openrct2/core/IStream.hpp +++ b/src/openrct2/core/IStream.hpp @@ -9,8 +9,7 @@ #pragma once -#include "../object/Object.h" -#include "Memory.hpp" +#include "StringTypes.h" #include #include @@ -204,7 +203,6 @@ namespace OpenRCT2 Write(buffer, sizeof(T) * count); } - utf8* ReadString(); std::string ReadStdString(); void WriteString(const utf8* str); void WriteString(const std::string_view string); diff --git a/src/openrct2/core/MemoryStream.h b/src/openrct2/core/MemoryStream.h index 33363a52fe..014a58ab29 100644 --- a/src/openrct2/core/MemoryStream.h +++ b/src/openrct2/core/MemoryStream.h @@ -11,6 +11,7 @@ #include "IStream.hpp" +#include #include namespace OpenRCT2 diff --git a/src/openrct2/core/OrcaStream.hpp b/src/openrct2/core/OrcaStream.hpp index c29435c53d..87250bcdfe 100644 --- a/src/openrct2/core/OrcaStream.hpp +++ b/src/openrct2/core/OrcaStream.hpp @@ -9,6 +9,7 @@ #pragma once +#include "../util/Util.h" #include "../world/Location.hpp" #include "Crypt.h" #include "FileStream.h" diff --git a/src/openrct2/core/ZipAndroid.cpp b/src/openrct2/core/ZipAndroid.cpp index cfd17ca736..a57d34293d 100644 --- a/src/openrct2/core/ZipAndroid.cpp +++ b/src/openrct2/core/ZipAndroid.cpp @@ -12,6 +12,7 @@ # include "../Diagnostic.h" # include "../platform/Platform.h" # include "IStream.hpp" +# include "Memory.hpp" # include "MemoryStream.h" # include "Zip.h" diff --git a/src/openrct2/drawing/Drawing.Sprite.cpp b/src/openrct2/drawing/Drawing.Sprite.cpp index 0c57839d34..3449239987 100644 --- a/src/openrct2/drawing/Drawing.Sprite.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.cpp @@ -15,6 +15,7 @@ #include "../PlatformEnvironment.h" #include "../config/Config.h" #include "../core/FileStream.h" +#include "../core/Guard.hpp" #include "../core/MemoryStream.h" #include "../core/Path.hpp" #include "../platform/Platform.h" diff --git a/src/openrct2/network/NetworkKey.cpp b/src/openrct2/network/NetworkKey.cpp index 6f0f715675..2ead9e479d 100644 --- a/src/openrct2/network/NetworkKey.cpp +++ b/src/openrct2/network/NetworkKey.cpp @@ -13,6 +13,7 @@ # include "../Diagnostic.h" # include "../core/Crypt.h" +# include "../core/Guard.hpp" # include "../core/IStream.hpp" # include "../core/String.hpp" diff --git a/src/openrct2/object/AudioObject.cpp b/src/openrct2/object/AudioObject.cpp index a9af658a3b..ae9658cf04 100644 --- a/src/openrct2/object/AudioObject.cpp +++ b/src/openrct2/object/AudioObject.cpp @@ -13,6 +13,7 @@ #include "../Context.h" #include "../PlatformEnvironment.h" #include "../audio/AudioContext.h" +#include "../core/Guard.hpp" #include "../core/Json.hpp" #include "../core/Path.hpp" diff --git a/src/openrct2/object/BannerObject.cpp b/src/openrct2/object/BannerObject.cpp index 96c16b047c..917ccc6c20 100644 --- a/src/openrct2/object/BannerObject.cpp +++ b/src/openrct2/object/BannerObject.cpp @@ -9,6 +9,7 @@ #include "BannerObject.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../drawing/Drawing.h" diff --git a/src/openrct2/object/EntranceObject.cpp b/src/openrct2/object/EntranceObject.cpp index d527b8b2f7..f1a9d1a4e0 100644 --- a/src/openrct2/object/EntranceObject.cpp +++ b/src/openrct2/object/EntranceObject.cpp @@ -9,6 +9,7 @@ #include "EntranceObject.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../core/String.hpp" diff --git a/src/openrct2/object/FootpathRailingsObject.cpp b/src/openrct2/object/FootpathRailingsObject.cpp index f739bd6218..50ee2b6d30 100644 --- a/src/openrct2/object/FootpathRailingsObject.cpp +++ b/src/openrct2/object/FootpathRailingsObject.cpp @@ -9,6 +9,7 @@ #include "FootpathRailingsObject.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" diff --git a/src/openrct2/object/FootpathSurfaceObject.cpp b/src/openrct2/object/FootpathSurfaceObject.cpp index 80c808f0e5..6b855eec4c 100644 --- a/src/openrct2/object/FootpathSurfaceObject.cpp +++ b/src/openrct2/object/FootpathSurfaceObject.cpp @@ -9,6 +9,7 @@ #include "FootpathSurfaceObject.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../drawing/Image.h" diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index b32a167692..184a18b96f 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -15,6 +15,7 @@ #include "../PlatformEnvironment.h" #include "../core/File.h" #include "../core/FileScanner.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../core/Path.hpp" diff --git a/src/openrct2/object/PathAdditionObject.cpp b/src/openrct2/object/PathAdditionObject.cpp index 59f225b6d3..a4697c8aa8 100644 --- a/src/openrct2/object/PathAdditionObject.cpp +++ b/src/openrct2/object/PathAdditionObject.cpp @@ -9,6 +9,7 @@ #include "PathAdditionObject.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../drawing/Drawing.h" diff --git a/src/openrct2/object/PeepNamesObject.cpp b/src/openrct2/object/PeepNamesObject.cpp index 16efcb49b7..415c39c562 100644 --- a/src/openrct2/object/PeepNamesObject.cpp +++ b/src/openrct2/object/PeepNamesObject.cpp @@ -11,6 +11,7 @@ #include "../Context.h" #include "../PlatformEnvironment.h" +#include "../core/Guard.hpp" #include "../core/Json.hpp" using namespace OpenRCT2; diff --git a/src/openrct2/object/StationObject.cpp b/src/openrct2/object/StationObject.cpp index c2cde52a1b..fc7dddbad0 100644 --- a/src/openrct2/object/StationObject.cpp +++ b/src/openrct2/object/StationObject.cpp @@ -9,6 +9,7 @@ #include "StationObject.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../core/String.hpp" diff --git a/src/openrct2/object/StringTable.cpp b/src/openrct2/object/StringTable.cpp index 66d3e3a5ca..13eb669c22 100644 --- a/src/openrct2/object/StringTable.cpp +++ b/src/openrct2/object/StringTable.cpp @@ -10,6 +10,7 @@ #include "StringTable.h" #include "../Context.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../core/String.hpp" diff --git a/src/openrct2/object/TerrainEdgeObject.cpp b/src/openrct2/object/TerrainEdgeObject.cpp index 5f34ad5849..e3b0d67d03 100644 --- a/src/openrct2/object/TerrainEdgeObject.cpp +++ b/src/openrct2/object/TerrainEdgeObject.cpp @@ -10,6 +10,7 @@ #include "TerrainEdgeObject.h" #include "../Context.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../core/String.hpp" diff --git a/src/openrct2/object/WallObject.cpp b/src/openrct2/object/WallObject.cpp index 16a0f8a790..43e7e5141f 100644 --- a/src/openrct2/object/WallObject.cpp +++ b/src/openrct2/object/WallObject.cpp @@ -9,6 +9,7 @@ #include "WallObject.h" +#include "../core/Guard.hpp" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../core/String.hpp" diff --git a/test/tests/IniWriterTest.cpp b/test/tests/IniWriterTest.cpp index 3bc732f2ed..606424c505 100644 --- a/test/tests/IniWriterTest.cpp +++ b/test/tests/IniWriterTest.cpp @@ -47,9 +47,8 @@ TEST_F(IniWriterTest, create_one_section) ASSERT_LE(ms.GetPosition(), 13); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); - ASSERT_STREQ(ini, "[OpenRCT2]" PLATFORM_NEWLINE); - Memory::Free(ini); + auto ini = ms.ReadStdString(); + ASSERT_STREQ(ini.c_str(), "[OpenRCT2]" PLATFORM_NEWLINE); } TEST_F(IniWriterTest, create_multiple_sections) @@ -67,12 +66,11 @@ TEST_F(IniWriterTest, create_multiple_sections) ASSERT_LE(ms.GetPosition(), 55); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); + auto ini = ms.ReadStdString(); ASSERT_STREQ( - ini, + ini.c_str(), "[OpenRCT1]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT2]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT3]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT4]" PLATFORM_NEWLINE); - Memory::Free(ini); } TEST_F(IniWriterTest, create_loose_bool_entry) @@ -87,9 +85,8 @@ TEST_F(IniWriterTest, create_loose_bool_entry) ASSERT_LE(ms.GetPosition(), 17); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); - ASSERT_STREQ(ini, "boolval = true" PLATFORM_NEWLINE); - Memory::Free(ini); + auto ini = ms.ReadStdString(); + ASSERT_STREQ(ini.c_str(), "boolval = true" PLATFORM_NEWLINE); } TEST_F(IniWriterTest, create_loose_enum_entry) @@ -105,9 +102,8 @@ TEST_F(IniWriterTest, create_loose_enum_entry) ASSERT_LE(ms.GetPosition(), 37); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); - ASSERT_STREQ(ini, "by_string = stringval" PLATFORM_NEWLINE "int32_t = 0" PLATFORM_NEWLINE); - Memory::Free(ini); + auto ini = ms.ReadStdString(); + ASSERT_STREQ(ini.c_str(), "by_string = stringval" PLATFORM_NEWLINE "int32_t = 0" PLATFORM_NEWLINE); } TEST_F(IniWriterTest, create_loose_float_entry) @@ -122,10 +118,9 @@ TEST_F(IniWriterTest, create_loose_float_entry) ASSERT_LE(ms.GetPosition(), 17); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); + auto ini = ms.ReadStdString(); // This will be non-fatal due to float. - EXPECT_STREQ(ini, "one = 1.000000" PLATFORM_NEWLINE); - Memory::Free(ini); + EXPECT_STREQ(ini.c_str(), "one = 1.000000" PLATFORM_NEWLINE); } TEST_F(IniWriterTest, create_loose_int32_t_entry) @@ -144,12 +139,11 @@ TEST_F(IniWriterTest, create_loose_int32_t_entry) ASSERT_LE(ms.GetPosition(), 78); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); + auto ini = ms.ReadStdString(); ASSERT_STREQ( - ini, + ini.c_str(), "one = 1" PLATFORM_NEWLINE "zero = 0" PLATFORM_NEWLINE "minusone = -1" PLATFORM_NEWLINE "intmin = -2147483648" PLATFORM_NEWLINE "intmax = 2147483647" PLATFORM_NEWLINE); - Memory::Free(ini); } TEST_F(IniWriterTest, create_loose_string_entry) @@ -164,9 +158,9 @@ TEST_F(IniWriterTest, create_loose_string_entry) ASSERT_LE(ms.GetPosition(), 44); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); - ASSERT_STREQ(ini, "path = \"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"" PLATFORM_NEWLINE); - Memory::Free(ini); + auto ini = ms.ReadStdString(); + ASSERT_STREQ( + ini.c_str(), "path = \"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"" PLATFORM_NEWLINE); } TEST_F(IniWriterTest, create_multiple_section_with_values) @@ -187,13 +181,12 @@ TEST_F(IniWriterTest, create_multiple_section_with_values) ASSERT_LE(ms.GetPosition(), 108); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); + auto ini = ms.ReadStdString(); ASSERT_STREQ( - ini, + ini.c_str(), "[bool]" PLATFORM_NEWLINE "boolval = true" PLATFORM_NEWLINE PLATFORM_NEWLINE "[int]" PLATFORM_NEWLINE "one = 1" PLATFORM_NEWLINE "zero = 0" PLATFORM_NEWLINE PLATFORM_NEWLINE "[string]" PLATFORM_NEWLINE "path = " "\"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"" PLATFORM_NEWLINE); - Memory::Free(ini); } TEST_F(IniWriterTest, create_duplicate_sections) @@ -210,10 +203,9 @@ TEST_F(IniWriterTest, create_duplicate_sections) ASSERT_LE(ms.GetPosition(), 43); // Accommodate for varying-sized newline (Windows) ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ms.SetPosition(0); - const char* ini = reinterpret_cast(ms.ReadString()); + auto ini = ms.ReadStdString(); ASSERT_STREQ( - ini, + ini.c_str(), "[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[section]" PLATFORM_NEWLINE); - Memory::Free(ini); } From 449d884434fd05b81f705bca3213cbf804e2c021 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Tue, 15 Oct 2024 17:43:05 +0200 Subject: [PATCH 30/97] Remove unused Collections::ToArray() --- src/openrct2/core/Collections.hpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/openrct2/core/Collections.hpp b/src/openrct2/core/Collections.hpp index 2fc851ae0b..4c0710bb81 100644 --- a/src/openrct2/core/Collections.hpp +++ b/src/openrct2/core/Collections.hpp @@ -9,7 +9,6 @@ #pragma once -#include "Memory.hpp" #include "String.hpp" #include @@ -78,23 +77,5 @@ namespace OpenRCT2::Collections collection, item, [ignoreCase](const char* a, const char* b) { return String::Equals(a, b, ignoreCase); }); } - template static typename TCollection::value_type* ToArray(const TCollection& collection) - { - size_t count = collection.size(); - if (count == 0) - { - return nullptr; - } - - auto* items = Memory::AllocateArray(count); - size_t i = 0; - for (const auto& item : collection) - { - items[i] = item; - i++; - } - return items; - } - #pragma endregion } // namespace OpenRCT2::Collections From 2599432b951c7e115c545ab115f95eb74d6a35fe Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Tue, 15 Oct 2024 17:43:34 +0200 Subject: [PATCH 31/97] Remove unused Memory.hpp array functions --- src/openrct2/core/Memory.hpp | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/openrct2/core/Memory.hpp b/src/openrct2/core/Memory.hpp index e24d410c06..eef2c28451 100644 --- a/src/openrct2/core/Memory.hpp +++ b/src/openrct2/core/Memory.hpp @@ -34,13 +34,6 @@ namespace OpenRCT2::Memory return result; } - template static T* AllocateArray(size_t count) - { - T* result = static_cast(malloc(count * sizeof(T))); - Guard::ArgumentNotNull(result, "Failed to allocate array of %zu * %s (%zu bytes)", count, typeid(T).name(), sizeof(T)); - return result; - } - template static T* Reallocate(T* ptr, size_t size) { T* result; @@ -56,33 +49,9 @@ namespace OpenRCT2::Memory return result; } - template static T* ReallocateArray(T* ptr, size_t count) - { - T* result; - if (ptr == nullptr) - { - result = static_cast(malloc(count * sizeof(T))); - } - else - { - result = static_cast(realloc(reinterpret_cast(ptr), count * sizeof(T))); - } - Guard::ArgumentNotNull( - result, "Failed to reallocate array at %x (%s) to have %zu entries", ptr, typeid(T).name(), count); - return result; - } - template static void Free(T* ptr) { free(const_cast(reinterpret_cast(ptr))); } - template static void FreeArray(T* ptr, size_t count) - { - for (size_t i = 0; i < count; i++) - { - ptr[i].~T(); - } - Free(ptr); - } } // namespace OpenRCT2::Memory From 66c1ddde9155f491e27229af0a3d687d5e9a1eaf Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Tue, 15 Oct 2024 17:47:45 +0200 Subject: [PATCH 32/97] Remove two unused functions from MemoryStream --- src/openrct2/core/MemoryStream.cpp | 13 ------------- src/openrct2/core/MemoryStream.h | 2 -- 2 files changed, 15 deletions(-) diff --git a/src/openrct2/core/MemoryStream.cpp b/src/openrct2/core/MemoryStream.cpp index a0da18d123..74f8b0e362 100644 --- a/src/openrct2/core/MemoryStream.cpp +++ b/src/openrct2/core/MemoryStream.cpp @@ -108,19 +108,6 @@ namespace OpenRCT2 return _data; } - void* MemoryStream::GetDataCopy() const - { - auto result = Memory::Allocate(_dataSize); - std::memcpy(result, _data, _dataSize); - return result; - } - - void* MemoryStream::TakeData() - { - _access &= ~MEMORY_ACCESS::OWNER; - return _data; - } - bool MemoryStream::CanRead() const { return (_access & MEMORY_ACCESS::READ) != 0; diff --git a/src/openrct2/core/MemoryStream.h b/src/openrct2/core/MemoryStream.h index 014a58ab29..871e0df962 100644 --- a/src/openrct2/core/MemoryStream.h +++ b/src/openrct2/core/MemoryStream.h @@ -48,8 +48,6 @@ namespace OpenRCT2 MemoryStream& operator=(MemoryStream&& mv) noexcept; const void* GetData() const override; - void* GetDataCopy() const; - void* TakeData(); /////////////////////////////////////////////////////////////////////////// // ISteam methods From a2ed0262644ea76407eb40f912e3e0d8cc13e88f Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Tue, 15 Oct 2024 22:02:31 +0200 Subject: [PATCH 33/97] Split up remaining tile elements --- src/openrct2-ui/interface/LandTool.cpp | 1 - .../interface/ViewportInteraction.cpp | 5 +- src/openrct2-ui/interface/ViewportQuery.cpp | 3 +- src/openrct2-ui/ride/VehicleSounds.cpp | 1 + src/openrct2-ui/windows/Cheats.cpp | 2 +- .../windows/EditorParkEntrance.cpp | 4 +- src/openrct2-ui/windows/Footpath.cpp | 4 +- src/openrct2-ui/windows/LandRights.cpp | 2 +- src/openrct2-ui/windows/Map.cpp | 2 +- src/openrct2-ui/windows/MapGen.cpp | 1 - src/openrct2-ui/windows/RideConstruction.cpp | 3 + src/openrct2-ui/windows/Scenery.cpp | 6 + src/openrct2-ui/windows/Sign.cpp | 1 + src/openrct2-ui/windows/TileInspector.cpp | 5 +- src/openrct2-ui/windows/TopToolbar.cpp | 1 - src/openrct2-ui/windows/TrackDesignPlace.cpp | 2 +- src/openrct2-ui/windows/Transparency.cpp | 1 - src/openrct2/Cheats.cpp | 1 - src/openrct2/EditorObjectSelectionSession.cpp | 7 +- src/openrct2/Game.cpp | 2 +- src/openrct2/actions/BannerPlaceAction.cpp | 2 + src/openrct2/actions/CheatSetAction.cpp | 4 +- src/openrct2/actions/ClearAction.cpp | 3 + .../actions/FootpathAdditionPlaceAction.cpp | 1 + .../actions/FootpathAdditionRemoveAction.cpp | 1 + .../actions/FootpathLayoutPlaceAction.cpp | 3 +- .../actions/FootpathLayoutPlaceAction.h | 1 + src/openrct2/actions/FootpathPlaceAction.cpp | 3 +- src/openrct2/actions/FootpathRemoveAction.cpp | 1 + src/openrct2/actions/LandBuyRightsAction.cpp | 2 +- src/openrct2/actions/LandLowerAction.cpp | 2 +- src/openrct2/actions/LandRaiseAction.cpp | 2 +- src/openrct2/actions/LandSetHeightAction.cpp | 5 +- src/openrct2/actions/LandSetRightsAction.cpp | 2 +- src/openrct2/actions/LandSmoothAction.cpp | 2 +- .../actions/LargeSceneryPlaceAction.cpp | 4 +- .../actions/LargeSceneryRemoveAction.cpp | 1 + .../actions/LargeScenerySetColourAction.cpp | 1 + src/openrct2/actions/MazePlaceTrackAction.cpp | 2 + src/openrct2/actions/MazeSetTrackAction.cpp | 1 + .../actions/ParkEntrancePlaceAction.cpp | 2 +- src/openrct2/actions/PeepSpawnPlaceAction.cpp | 2 +- src/openrct2/actions/SignSetStyleAction.cpp | 1 + .../actions/SmallSceneryPlaceAction.cpp | 5 +- .../actions/SmallSceneryPlaceAction.h | 1 - .../actions/SmallSceneryRemoveAction.cpp | 1 + .../actions/SmallSceneryRemoveAction.h | 1 - .../actions/SmallScenerySetColourAction.cpp | 3 +- .../actions/SurfaceSetStyleAction.cpp | 4 +- src/openrct2/actions/TrackPlaceAction.cpp | 4 +- src/openrct2/actions/TrackRemoveAction.cpp | 3 +- src/openrct2/actions/WallPlaceAction.cpp | 5 +- src/openrct2/actions/WallSetColourAction.cpp | 1 - src/openrct2/actions/WaterLowerAction.cpp | 1 + src/openrct2/actions/WaterRaiseAction.cpp | 1 + src/openrct2/actions/WaterSetHeightAction.cpp | 3 +- src/openrct2/audio/Audio.cpp | 1 + src/openrct2/core/DataSerialiserTraits.h | 2 +- src/openrct2/drawing/LightFX.cpp | 1 + src/openrct2/drawing/ScrollingText.cpp | 1 + src/openrct2/entity/Duck.cpp | 2 +- src/openrct2/entity/Fountain.cpp | 1 + src/openrct2/entity/Fountain.h | 1 + src/openrct2/entity/Guest.cpp | 4 +- src/openrct2/entity/Litter.cpp | 1 + src/openrct2/entity/Particle.cpp | 1 + src/openrct2/entity/Peep.cpp | 3 +- src/openrct2/entity/Staff.cpp | 4 +- src/openrct2/entity/Staff.h | 4 + src/openrct2/interface/Screenshot.cpp | 2 +- src/openrct2/interface/Viewport.cpp | 3 + src/openrct2/libopenrct2.vcxproj | 18 +- src/openrct2/network/NetworkPlayer.cpp | 1 + src/openrct2/network/NetworkPlayer.h | 1 + src/openrct2/paint/Paint.cpp | 1 + src/openrct2/paint/Paint.h | 1 + src/openrct2/paint/VirtualFloor.cpp | 2 + src/openrct2/paint/support/MetalSupports.cpp | 2 +- src/openrct2/paint/support/WoodenSupports.cpp | 1 - .../paint/tile_element/Paint.LargeScenery.cpp | 1 + .../paint/tile_element/Paint.Path.cpp | 4 +- .../paint/tile_element/Paint.PathAddition.cpp | 1 + .../paint/tile_element/Paint.PathAddition.h | 1 - .../paint/tile_element/Paint.SmallScenery.cpp | 1 + .../paint/tile_element/Paint.Surface.cpp | 3 +- .../paint/tile_element/Paint.TileElement.cpp | 3 +- .../paint/tile_element/Paint.Tunnel.cpp | 1 + .../coaster/ClassicStandUpRollerCoaster.cpp | 1 + .../coaster/FlyingRollerCoasterInverted.cpp | 1 + .../paint/track/gentle/CrookedHouse.cpp | 1 + src/openrct2/paint/track/gentle/MiniGolf.cpp | 2 +- .../paint/track/gentle/ObservationTower.cpp | 1 + .../paint/track/thrill/LaunchedFreefall.cpp | 1 + src/openrct2/paint/track/thrill/RotoDrop.cpp | 1 + .../paint/track/transport/Chairlift.cpp | 1 + .../track/transport/MiniatureRailway.cpp | 2 + src/openrct2/park/ParkFile.cpp | 2 + src/openrct2/peep/GuestPathfinding.cpp | 4 +- src/openrct2/rct1/S4Importer.cpp | 5 +- src/openrct2/rct1/Tables.cpp | 1 - src/openrct2/rct12/RCT12.cpp | 6 +- src/openrct2/rct12/RCT12.h | 5 + src/openrct2/rct12/ScenarioPatcher.cpp | 3 +- src/openrct2/rct2/S6Importer.cpp | 6 +- src/openrct2/ride/CableLift.cpp | 1 + src/openrct2/ride/MazeCost.cpp | 1 + src/openrct2/ride/Ride.cpp | 1 + src/openrct2/ride/Ride.h | 2 + src/openrct2/ride/RideConstruction.cpp | 1 + src/openrct2/ride/RideRatings.cpp | 3 +- src/openrct2/ride/Station.cpp | 1 + src/openrct2/ride/Track.cpp | 2 +- src/openrct2/ride/Track.h | 3 +- src/openrct2/ride/TrackDesign.cpp | 3 +- src/openrct2/ride/TrackDesignSave.cpp | 5 + src/openrct2/ride/TrackPaint.h | 1 + src/openrct2/ride/Vehicle.cpp | 5 +- src/openrct2/scenario/Scenario.cpp | 1 + .../scripting/bindings/ride/ScTrackIterator.h | 1 - .../scripting/bindings/ride/ScTrackSegment.h | 1 - .../scripting/bindings/world/ScTile.cpp | 2 +- .../bindings/world/ScTileElement.cpp | 5 +- .../bindings/world/ScTileElement.hpp | 1 - src/openrct2/world/Banner.cpp | 1 + src/openrct2/world/ConstructionClearance.cpp | 6 +- src/openrct2/world/ConstructionClearance.h | 7 + src/openrct2/world/Entrance.h | 15 +- src/openrct2/world/Footpath.cpp | 290 +------------ src/openrct2/world/Footpath.h | 35 -- src/openrct2/world/LargeScenery.h | 15 - src/openrct2/world/Map.cpp | 11 +- src/openrct2/world/Map.h | 19 +- src/openrct2/world/MapAnimation.cpp | 4 + src/openrct2/world/MapGen.cpp | 4 +- src/openrct2/world/MapHelpers.cpp | 2 +- src/openrct2/world/Park.cpp | 2 +- src/openrct2/world/Scenery.cpp | 2 + src/openrct2/world/SmallScenery.h | 15 - src/openrct2/world/Surface.h | 88 ---- src/openrct2/world/SurfaceData.cpp | 10 +- src/openrct2/world/TileElement.h | 398 ------------------ src/openrct2/world/TileElementsView.h | 1 - src/openrct2/world/TileInspector.cpp | 9 +- src/openrct2/world/TileInspector.h | 2 + src/openrct2/world/Wall.cpp | 1 + .../world/tile_element/BannerElement.h | 3 +- .../world/tile_element/EntranceElement.h | 18 +- .../LargeSceneryElement.cpp} | 12 +- .../world/tile_element/LargeSceneryElement.h | 64 +++ .../world/tile_element/PathElement.cpp | 306 ++++++++++++++ src/openrct2/world/tile_element/PathElement.h | 153 +++++++ .../SmallSceneryElement.cpp} | 33 +- .../world/tile_element/SmallSceneryElement.h | 57 +++ .../SurfaceElement.cpp} | 20 +- .../world/tile_element/SurfaceElement.h | 92 ++++ .../world/{ => tile_element}/TileElement.cpp | 47 +-- src/openrct2/world/tile_element/TileElement.h | 38 ++ .../world/tile_element/TileElementBase.cpp | 15 +- .../world/tile_element/TileElementBase.h | 120 ++++++ .../world/tile_element/TrackElement.h | 11 +- src/openrct2/world/tile_element/WallElement.h | 6 +- test/tests/Pathfinding.cpp | 1 + test/tests/TileElements.cpp | 1 + test/tests/TileElementsView.cpp | 5 + 164 files changed, 1216 insertions(+), 1014 deletions(-) delete mode 100644 src/openrct2/world/LargeScenery.h delete mode 100644 src/openrct2/world/SmallScenery.h delete mode 100644 src/openrct2/world/Surface.h delete mode 100644 src/openrct2/world/TileElement.h rename src/openrct2/world/{LargeScenery.cpp => tile_element/LargeSceneryElement.cpp} (91%) create mode 100644 src/openrct2/world/tile_element/LargeSceneryElement.h create mode 100644 src/openrct2/world/tile_element/PathElement.cpp create mode 100644 src/openrct2/world/tile_element/PathElement.h rename src/openrct2/world/{SmallScenery.cpp => tile_element/SmallSceneryElement.cpp} (84%) create mode 100644 src/openrct2/world/tile_element/SmallSceneryElement.h rename src/openrct2/world/{Surface.cpp => tile_element/SurfaceElement.cpp} (94%) create mode 100644 src/openrct2/world/tile_element/SurfaceElement.h rename src/openrct2/world/{ => tile_element}/TileElement.cpp (87%) create mode 100644 src/openrct2/world/tile_element/TileElement.h create mode 100644 src/openrct2/world/tile_element/TileElementBase.h diff --git a/src/openrct2-ui/interface/LandTool.cpp b/src/openrct2-ui/interface/LandTool.cpp index ea1853b5bd..a52541b77b 100644 --- a/src/openrct2-ui/interface/LandTool.cpp +++ b/src/openrct2-ui/interface/LandTool.cpp @@ -20,7 +20,6 @@ #include #include #include -#include using namespace OpenRCT2; using namespace OpenRCT2::Ui::Windows; diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 4327d11ef9..b7d15b726d 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -51,9 +51,12 @@ #include #include #include -#include #include #include +#include +#include +#include +#include #include #include diff --git a/src/openrct2-ui/interface/ViewportQuery.cpp b/src/openrct2-ui/interface/ViewportQuery.cpp index bd81178ff0..a143d67fc5 100644 --- a/src/openrct2-ui/interface/ViewportQuery.cpp +++ b/src/openrct2-ui/interface/ViewportQuery.cpp @@ -13,8 +13,9 @@ #include #include -#include #include +#include +#include namespace OpenRCT2::Ui { diff --git a/src/openrct2-ui/ride/VehicleSounds.cpp b/src/openrct2-ui/ride/VehicleSounds.cpp index dc302fcffe..2eed807354 100644 --- a/src/openrct2-ui/ride/VehicleSounds.cpp +++ b/src/openrct2-ui/ride/VehicleSounds.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace OpenRCT2::Audio { diff --git a/src/openrct2-ui/windows/Cheats.cpp b/src/openrct2-ui/windows/Cheats.cpp index fc5a47b23a..8b06add9be 100644 --- a/src/openrct2-ui/windows/Cheats.cpp +++ b/src/openrct2-ui/windows/Cheats.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/EditorParkEntrance.cpp b/src/openrct2-ui/windows/EditorParkEntrance.cpp index fbb16e0916..fcaa1fdd42 100644 --- a/src/openrct2-ui/windows/EditorParkEntrance.cpp +++ b/src/openrct2-ui/windows/EditorParkEntrance.cpp @@ -17,9 +17,11 @@ #include #include #include -#include #include +#include +#include #include +#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/Footpath.cpp b/src/openrct2-ui/windows/Footpath.cpp index 76102abbfd..2cefec0636 100644 --- a/src/openrct2-ui/windows/Footpath.cpp +++ b/src/openrct2-ui/windows/Footpath.cpp @@ -37,10 +37,12 @@ #include #include #include +#include #include #include -#include +#include #include +#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/LandRights.cpp b/src/openrct2-ui/windows/LandRights.cpp index d7b4624959..2d85fb0190 100644 --- a/src/openrct2-ui/windows/LandRights.cpp +++ b/src/openrct2-ui/windows/LandRights.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/Map.cpp b/src/openrct2-ui/windows/Map.cpp index 28bb1d4d9b..049532acc7 100644 --- a/src/openrct2-ui/windows/Map.cpp +++ b/src/openrct2-ui/windows/Map.cpp @@ -33,9 +33,9 @@ #include #include #include -#include #include #include +#include #include #include diff --git a/src/openrct2-ui/windows/MapGen.cpp b/src/openrct2-ui/windows/MapGen.cpp index 017fa07e48..086ea6c88e 100644 --- a/src/openrct2-ui/windows/MapGen.cpp +++ b/src/openrct2-ui/windows/MapGen.cpp @@ -26,7 +26,6 @@ #include #include #include -#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 70da1e91b7..43d6aa7419 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -47,9 +47,12 @@ #include #include #include +#include #include #include #include +#include +#include #include constexpr int8_t kDefaultSpeedIncrement = 2; diff --git a/src/openrct2-ui/windows/Scenery.cpp b/src/openrct2-ui/windows/Scenery.cpp index 663a85ddc6..1a38918b49 100644 --- a/src/openrct2-ui/windows/Scenery.cpp +++ b/src/openrct2-ui/windows/Scenery.cpp @@ -48,9 +48,15 @@ #include #include #include +#include +#include #include #include #include +#include +#include +#include +#include #include namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index 9deff0ae4d..2dcfb75f73 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index 6e8735f370..c2a141947d 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -39,11 +39,14 @@ #include #include #include -#include #include #include #include +#include +#include #include +#include +#include #include #include diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 7990116f8b..33b2e95096 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/windows/TrackDesignPlace.cpp b/src/openrct2-ui/windows/TrackDesignPlace.cpp index 8d3d9e29b0..c1c83bf06c 100644 --- a/src/openrct2-ui/windows/TrackDesignPlace.cpp +++ b/src/openrct2-ui/windows/TrackDesignPlace.cpp @@ -33,8 +33,8 @@ #include #include #include -#include #include +#include #include using namespace OpenRCT2::TrackMetaData; diff --git a/src/openrct2-ui/windows/Transparency.cpp b/src/openrct2-ui/windows/Transparency.cpp index 43e00729d8..e2bc14eec5 100644 --- a/src/openrct2-ui/windows/Transparency.cpp +++ b/src/openrct2-ui/windows/Transparency.cpp @@ -27,7 +27,6 @@ #include #include #include -#include namespace OpenRCT2::Ui::Windows { diff --git a/src/openrct2/Cheats.cpp b/src/openrct2/Cheats.cpp index 9e999bc7cf..58d86ba487 100644 --- a/src/openrct2/Cheats.cpp +++ b/src/openrct2/Cheats.cpp @@ -22,7 +22,6 @@ #include "world/Map.h" #include "world/Park.h" #include "world/Scenery.h" -#include "world/Surface.h" using namespace OpenRCT2; diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp index f860e462fd..292e2a5ed2 100644 --- a/src/openrct2/EditorObjectSelectionSession.cpp +++ b/src/openrct2/EditorObjectSelectionSession.cpp @@ -28,10 +28,13 @@ #include "ride/Vehicle.h" #include "scenario/Scenario.h" #include "windows/Intent.h" -#include "world/Footpath.h" -#include "world/Scenery.h" #include "world/tile_element/BannerElement.h" #include "world/tile_element/EntranceElement.h" +#include "world/tile_element/LargeSceneryElement.h" +#include "world/tile_element/PathElement.h" +#include "world/tile_element/SmallSceneryElement.h" +#include "world/tile_element/SurfaceElement.h" +#include "world/tile_element/TileElement.h" #include "world/tile_element/WallElement.h" #include diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 1ed4341d19..767e53ff75 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -70,7 +70,7 @@ #include "world/MapAnimation.h" #include "world/Park.h" #include "world/Scenery.h" -#include "world/Surface.h" +#include "world/tile_element/SurfaceElement.h" #include #include diff --git a/src/openrct2/actions/BannerPlaceAction.cpp b/src/openrct2/actions/BannerPlaceAction.cpp index ead853ba0d..4b19e4032c 100644 --- a/src/openrct2/actions/BannerPlaceAction.cpp +++ b/src/openrct2/actions/BannerPlaceAction.cpp @@ -14,10 +14,12 @@ #include "../object/BannerSceneryEntry.h" #include "../object/ObjectEntryManager.h" #include "../world/Banner.h" +#include "../world/Footpath.h" #include "../world/MapAnimation.h" #include "../world/Scenery.h" #include "../world/TileElementsView.h" #include "../world/tile_element/BannerElement.h" +#include "../world/tile_element/PathElement.h" #include "GameAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/CheatSetAction.cpp b/src/openrct2/actions/CheatSetAction.cpp index cc81dd174e..3106c75158 100644 --- a/src/openrct2/actions/CheatSetAction.cpp +++ b/src/openrct2/actions/CheatSetAction.cpp @@ -35,7 +35,9 @@ #include "../world/Map.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "ParkSetLoanAction.h" #include "ParkSetParameterAction.h" diff --git a/src/openrct2/actions/ClearAction.cpp b/src/openrct2/actions/ClearAction.cpp index b084c1e57d..662bb77e65 100644 --- a/src/openrct2/actions/ClearAction.cpp +++ b/src/openrct2/actions/ClearAction.cpp @@ -17,6 +17,9 @@ #include "../management/Finance.h" #include "../world/Location.hpp" #include "../world/Map.h" +#include "../world/tile_element/LargeSceneryElement.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SmallSceneryElement.h" #include "FootpathRemoveAction.h" #include "LargeSceneryRemoveAction.h" #include "SmallSceneryRemoveAction.h" diff --git a/src/openrct2/actions/FootpathAdditionPlaceAction.cpp b/src/openrct2/actions/FootpathAdditionPlaceAction.cpp index 9c75c5f2bf..d175b002ce 100644 --- a/src/openrct2/actions/FootpathAdditionPlaceAction.cpp +++ b/src/openrct2/actions/FootpathAdditionPlaceAction.cpp @@ -23,6 +23,7 @@ #include "../world/Location.hpp" #include "../world/Park.h" #include "../world/Scenery.h" +#include "../world/tile_element/PathElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/FootpathAdditionRemoveAction.cpp b/src/openrct2/actions/FootpathAdditionRemoveAction.cpp index d592ab7ba2..a9cfb875de 100644 --- a/src/openrct2/actions/FootpathAdditionRemoveAction.cpp +++ b/src/openrct2/actions/FootpathAdditionRemoveAction.cpp @@ -20,6 +20,7 @@ #include "../world/Footpath.h" #include "../world/Location.hpp" #include "../world/Park.h" +#include "../world/tile_element/PathElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/FootpathLayoutPlaceAction.cpp b/src/openrct2/actions/FootpathLayoutPlaceAction.cpp index b99740aa17..77a99bf527 100644 --- a/src/openrct2/actions/FootpathLayoutPlaceAction.cpp +++ b/src/openrct2/actions/FootpathLayoutPlaceAction.cpp @@ -22,9 +22,10 @@ #include "../world/Location.hpp" #include "../world/Park.h" #include "../world/QuarterTile.h" -#include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/FootpathLayoutPlaceAction.h b/src/openrct2/actions/FootpathLayoutPlaceAction.h index 130c540f22..63fd99851e 100644 --- a/src/openrct2/actions/FootpathLayoutPlaceAction.h +++ b/src/openrct2/actions/FootpathLayoutPlaceAction.h @@ -9,6 +9,7 @@ #pragma once +#include "../world/Footpath.h" #include "GameAction.h" class FootpathLayoutPlaceAction final : public GameActionBase diff --git a/src/openrct2/actions/FootpathPlaceAction.cpp b/src/openrct2/actions/FootpathPlaceAction.cpp index 14a19f47cf..5deeeb6ddc 100644 --- a/src/openrct2/actions/FootpathPlaceAction.cpp +++ b/src/openrct2/actions/FootpathPlaceAction.cpp @@ -27,11 +27,12 @@ #include "../world/Park.h" #include "../world/QuarterTile.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/TileElementsView.h" #include "../world/Wall.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" #include diff --git a/src/openrct2/actions/FootpathRemoveAction.cpp b/src/openrct2/actions/FootpathRemoveAction.cpp index 8297d31899..39eafb1a58 100644 --- a/src/openrct2/actions/FootpathRemoveAction.cpp +++ b/src/openrct2/actions/FootpathRemoveAction.cpp @@ -20,6 +20,7 @@ #include "../world/Location.hpp" #include "../world/Park.h" #include "../world/tile_element/BannerElement.h" +#include "../world/tile_element/PathElement.h" #include "BannerRemoveAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LandBuyRightsAction.cpp b/src/openrct2/actions/LandBuyRightsAction.cpp index 9c16f882d8..0e53666f3e 100644 --- a/src/openrct2/actions/LandBuyRightsAction.cpp +++ b/src/openrct2/actions/LandBuyRightsAction.cpp @@ -23,7 +23,7 @@ #include "../windows/Intent.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LandLowerAction.cpp b/src/openrct2/actions/LandLowerAction.cpp index 94e68219ea..7b3cf49f26 100644 --- a/src/openrct2/actions/LandLowerAction.cpp +++ b/src/openrct2/actions/LandLowerAction.cpp @@ -22,9 +22,9 @@ #include "../windows/Intent.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/SurfaceData.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LandRaiseAction.cpp b/src/openrct2/actions/LandRaiseAction.cpp index b32cd57612..adae6589b2 100644 --- a/src/openrct2/actions/LandRaiseAction.cpp +++ b/src/openrct2/actions/LandRaiseAction.cpp @@ -23,9 +23,9 @@ #include "../windows/Intent.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/SurfaceData.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LandSetHeightAction.cpp b/src/openrct2/actions/LandSetHeightAction.cpp index 31ec643d7c..c31217efca 100644 --- a/src/openrct2/actions/LandSetHeightAction.cpp +++ b/src/openrct2/actions/LandSetHeightAction.cpp @@ -19,12 +19,15 @@ #include "../ride/RideData.h" #include "../windows/Intent.h" #include "../world/ConstructionClearance.h" +#include "../world/Footpath.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/TileElementsView.h" #include "../world/Wall.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LandSetRightsAction.cpp b/src/openrct2/actions/LandSetRightsAction.cpp index 89c20b04b2..a6308a903b 100644 --- a/src/openrct2/actions/LandSetRightsAction.cpp +++ b/src/openrct2/actions/LandSetRightsAction.cpp @@ -23,9 +23,9 @@ #include "../windows/Intent.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/TileElementsView.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LandSmoothAction.cpp b/src/openrct2/actions/LandSmoothAction.cpp index e711144e77..23929488fc 100644 --- a/src/openrct2/actions/LandSmoothAction.cpp +++ b/src/openrct2/actions/LandSmoothAction.cpp @@ -23,9 +23,9 @@ #include "../windows/Intent.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/SurfaceData.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" #include diff --git a/src/openrct2/actions/LargeSceneryPlaceAction.cpp b/src/openrct2/actions/LargeSceneryPlaceAction.cpp index b4229620a9..36888238db 100644 --- a/src/openrct2/actions/LargeSceneryPlaceAction.cpp +++ b/src/openrct2/actions/LargeSceneryPlaceAction.cpp @@ -20,11 +20,13 @@ #include "../ride/RideConstruction.h" #include "../world/Banner.h" #include "../world/ConstructionClearance.h" +#include "../world/Footpath.h" #include "../world/MapAnimation.h" #include "../world/QuarterTile.h" -#include "../world/Surface.h" #include "../world/Wall.h" +#include "../world/tile_element/LargeSceneryElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LargeSceneryRemoveAction.cpp b/src/openrct2/actions/LargeSceneryRemoveAction.cpp index 7bce2ad289..998b5f470e 100644 --- a/src/openrct2/actions/LargeSceneryRemoveAction.cpp +++ b/src/openrct2/actions/LargeSceneryRemoveAction.cpp @@ -21,6 +21,7 @@ #include "../ride/Ride.h" #include "../world/Park.h" #include "../world/TileElementsView.h" +#include "../world/tile_element/LargeSceneryElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/LargeScenerySetColourAction.cpp b/src/openrct2/actions/LargeScenerySetColourAction.cpp index 36ab12a774..e7f73fdca3 100644 --- a/src/openrct2/actions/LargeScenerySetColourAction.cpp +++ b/src/openrct2/actions/LargeScenerySetColourAction.cpp @@ -15,6 +15,7 @@ #include "../management/Finance.h" #include "../object/LargeSceneryEntry.h" #include "../world/Scenery.h" +#include "../world/tile_element/LargeSceneryElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/MazePlaceTrackAction.cpp b/src/openrct2/actions/MazePlaceTrackAction.cpp index 32b4495696..5784aa74b3 100644 --- a/src/openrct2/actions/MazePlaceTrackAction.cpp +++ b/src/openrct2/actions/MazePlaceTrackAction.cpp @@ -15,7 +15,9 @@ #include "../ride/RideData.h" #include "../ride/TrackData.h" #include "../world/ConstructionClearance.h" +#include "../world/Footpath.h" #include "../world/Wall.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/MazeSetTrackAction.cpp b/src/openrct2/actions/MazeSetTrackAction.cpp index 4e70b682b4..e754f26134 100644 --- a/src/openrct2/actions/MazeSetTrackAction.cpp +++ b/src/openrct2/actions/MazeSetTrackAction.cpp @@ -24,6 +24,7 @@ #include "../world/Footpath.h" #include "../world/Park.h" #include "../world/Wall.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/ParkEntrancePlaceAction.cpp b/src/openrct2/actions/ParkEntrancePlaceAction.cpp index d52baca087..713d6f647d 100644 --- a/src/openrct2/actions/ParkEntrancePlaceAction.cpp +++ b/src/openrct2/actions/ParkEntrancePlaceAction.cpp @@ -20,8 +20,8 @@ #include "../world/Footpath.h" #include "../world/MapAnimation.h" #include "../world/Park.h" -#include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/PeepSpawnPlaceAction.cpp b/src/openrct2/actions/PeepSpawnPlaceAction.cpp index c27e534302..5e2898a692 100644 --- a/src/openrct2/actions/PeepSpawnPlaceAction.cpp +++ b/src/openrct2/actions/PeepSpawnPlaceAction.cpp @@ -17,7 +17,7 @@ #include "../management/Finance.h" #include "../world/Footpath.h" #include "../world/Park.h" -#include "../world/Surface.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/SignSetStyleAction.cpp b/src/openrct2/actions/SignSetStyleAction.cpp index df5cbf31d1..382fcdf53e 100644 --- a/src/openrct2/actions/SignSetStyleAction.cpp +++ b/src/openrct2/actions/SignSetStyleAction.cpp @@ -18,6 +18,7 @@ #include "../windows/Intent.h" #include "../world/Banner.h" #include "../world/Scenery.h" +#include "../world/tile_element/LargeSceneryElement.h" #include "../world/tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/SmallSceneryPlaceAction.cpp b/src/openrct2/actions/SmallSceneryPlaceAction.cpp index 3f6ee3302c..8e0a12cffe 100644 --- a/src/openrct2/actions/SmallSceneryPlaceAction.cpp +++ b/src/openrct2/actions/SmallSceneryPlaceAction.cpp @@ -22,14 +22,15 @@ #include "../ride/Ride.h" #include "../ride/TrackDesign.h" #include "../world/ConstructionClearance.h" +#include "../world/Footpath.h" #include "../world/MapAnimation.h" #include "../world/Park.h" #include "../world/QuarterTile.h" #include "../world/Scenery.h" -#include "../world/Surface.h" -#include "../world/TileElement.h" #include "../world/Wall.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "GameAction.h" #include "SmallSceneryRemoveAction.h" diff --git a/src/openrct2/actions/SmallSceneryPlaceAction.h b/src/openrct2/actions/SmallSceneryPlaceAction.h index 4c4d1ff3ee..b93fa2a72d 100644 --- a/src/openrct2/actions/SmallSceneryPlaceAction.h +++ b/src/openrct2/actions/SmallSceneryPlaceAction.h @@ -9,7 +9,6 @@ #pragma once -#include "../world/TileElement.h" #include "GameAction.h" struct SmallSceneryPlaceActionResult diff --git a/src/openrct2/actions/SmallSceneryRemoveAction.cpp b/src/openrct2/actions/SmallSceneryRemoveAction.cpp index f1ce345a18..443145bbb3 100644 --- a/src/openrct2/actions/SmallSceneryRemoveAction.cpp +++ b/src/openrct2/actions/SmallSceneryRemoveAction.cpp @@ -22,6 +22,7 @@ #include "../ride/Ride.h" #include "../world/Park.h" #include "../world/TileElementsView.h" +#include "../world/tile_element/SmallSceneryElement.h" #include "GameAction.h" #include "SmallSceneryPlaceAction.h" diff --git a/src/openrct2/actions/SmallSceneryRemoveAction.h b/src/openrct2/actions/SmallSceneryRemoveAction.h index 05308959b9..ba064e94a2 100644 --- a/src/openrct2/actions/SmallSceneryRemoveAction.h +++ b/src/openrct2/actions/SmallSceneryRemoveAction.h @@ -9,7 +9,6 @@ #pragma once -#include "../world/TileElement.h" #include "GameAction.h" class SmallSceneryRemoveAction final : public GameActionBase diff --git a/src/openrct2/actions/SmallScenerySetColourAction.cpp b/src/openrct2/actions/SmallScenerySetColourAction.cpp index cdaffe7891..5283e66107 100644 --- a/src/openrct2/actions/SmallScenerySetColourAction.cpp +++ b/src/openrct2/actions/SmallScenerySetColourAction.cpp @@ -21,8 +21,7 @@ #include "../ride/TrackDesign.h" #include "../world/MapAnimation.h" #include "../world/Park.h" -#include "../world/Surface.h" -#include "../world/TileElement.h" +#include "../world/tile_element/SmallSceneryElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/SurfaceSetStyleAction.cpp b/src/openrct2/actions/SurfaceSetStyleAction.cpp index 64e617c3bd..ac39d49afa 100644 --- a/src/openrct2/actions/SurfaceSetStyleAction.cpp +++ b/src/openrct2/actions/SurfaceSetStyleAction.cpp @@ -17,9 +17,9 @@ #include "../object/ObjectManager.h" #include "../object/TerrainEdgeObject.h" #include "../object/TerrainSurfaceObject.h" +#include "../world/Footpath.h" #include "../world/Park.h" -#include "../world/Surface.h" -#include "../world/TileElement.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index 0b24eab99d..4fcc2e39c6 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -19,11 +19,13 @@ #include "../ride/TrackDesign.h" #include "../util/Math.hpp" #include "../world/ConstructionClearance.h" +#include "../world/Footpath.h" #include "../world/MapAnimation.h" #include "../world/QuarterTile.h" -#include "../world/Surface.h" #include "../world/Wall.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "RideSetSettingAction.h" diff --git a/src/openrct2/actions/TrackRemoveAction.cpp b/src/openrct2/actions/TrackRemoveAction.cpp index a2577cd454..d3ec9ef4c9 100644 --- a/src/openrct2/actions/TrackRemoveAction.cpp +++ b/src/openrct2/actions/TrackRemoveAction.cpp @@ -17,8 +17,9 @@ #include "../ride/TrackData.h" #include "../ride/TrackDesign.h" #include "../util/Util.h" +#include "../world/Footpath.h" #include "../world/MapAnimation.h" -#include "../world/Surface.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "RideSetSettingAction.h" diff --git a/src/openrct2/actions/WallPlaceAction.cpp b/src/openrct2/actions/WallPlaceAction.cpp index 1eae718b4b..852a506d1a 100644 --- a/src/openrct2/actions/WallPlaceAction.cpp +++ b/src/openrct2/actions/WallPlaceAction.cpp @@ -22,9 +22,12 @@ #include "../world/Banner.h" #include "../world/ConstructionClearance.h" #include "../world/MapAnimation.h" -#include "../world/Surface.h" #include "../world/Wall.h" +#include "../world/tile_element/LargeSceneryElement.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" diff --git a/src/openrct2/actions/WallSetColourAction.cpp b/src/openrct2/actions/WallSetColourAction.cpp index e027958d42..9cbedcc2d3 100644 --- a/src/openrct2/actions/WallSetColourAction.cpp +++ b/src/openrct2/actions/WallSetColourAction.cpp @@ -19,7 +19,6 @@ #include "../world/Banner.h" #include "../world/MapAnimation.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/tile_element/WallElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/WaterLowerAction.cpp b/src/openrct2/actions/WaterLowerAction.cpp index d547ea6c3e..9005b0a01f 100644 --- a/src/openrct2/actions/WaterLowerAction.cpp +++ b/src/openrct2/actions/WaterLowerAction.cpp @@ -13,6 +13,7 @@ #include "../OpenRCT2.h" #include "../audio/audio.h" #include "../ride/RideConstruction.h" +#include "../world/tile_element/SurfaceElement.h" #include "WaterSetHeightAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/WaterRaiseAction.cpp b/src/openrct2/actions/WaterRaiseAction.cpp index 3bd26c4217..eede825891 100644 --- a/src/openrct2/actions/WaterRaiseAction.cpp +++ b/src/openrct2/actions/WaterRaiseAction.cpp @@ -13,6 +13,7 @@ #include "../OpenRCT2.h" #include "../audio/audio.h" #include "../ride/RideConstruction.h" +#include "../world/tile_element/SurfaceElement.h" #include "WaterSetHeightAction.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/WaterSetHeightAction.cpp b/src/openrct2/actions/WaterSetHeightAction.cpp index 283c96892a..129d8bc69d 100644 --- a/src/openrct2/actions/WaterSetHeightAction.cpp +++ b/src/openrct2/actions/WaterSetHeightAction.cpp @@ -14,9 +14,10 @@ #include "../OpenRCT2.h" #include "../management/Finance.h" #include "../world/ConstructionClearance.h" +#include "../world/Footpath.h" #include "../world/Park.h" -#include "../world/Surface.h" #include "../world/Wall.h" +#include "../world/tile_element/SurfaceElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/audio/Audio.cpp b/src/openrct2/audio/Audio.cpp index 4b9f01e1d3..1ba0d268e8 100644 --- a/src/openrct2/audio/Audio.cpp +++ b/src/openrct2/audio/Audio.cpp @@ -29,6 +29,7 @@ #include "../ui/UiContext.h" #include "../util/Util.h" #include "../world/Climate.h" +#include "../world/tile_element/SurfaceElement.h" #include "AudioChannel.h" #include "AudioContext.h" #include "AudioMixer.h" diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index e818e276db..b8257a2f81 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -18,7 +18,7 @@ #include "../ride/TrackDesign.h" #include "../world/Banner.h" #include "../world/Location.hpp" -#include "../world/TileElement.h" +#include "../world/tile_element/TileElement.h" #include "DataSerialiserTag.h" #include "Endianness.h" #include "MemoryStream.h" diff --git a/src/openrct2/drawing/LightFX.cpp b/src/openrct2/drawing/LightFX.cpp index 74a7a1c8f5..b1ee8e3cac 100644 --- a/src/openrct2/drawing/LightFX.cpp +++ b/src/openrct2/drawing/LightFX.cpp @@ -22,6 +22,7 @@ #include "../ride/RideData.h" #include "../ride/Vehicle.h" #include "../world/Map.h" +#include "../world/tile_element/TileElement.h" #include "Drawing.h" #include diff --git a/src/openrct2/drawing/ScrollingText.cpp b/src/openrct2/drawing/ScrollingText.cpp index 99043e3c05..4b85b67609 100644 --- a/src/openrct2/drawing/ScrollingText.cpp +++ b/src/openrct2/drawing/ScrollingText.cpp @@ -18,6 +18,7 @@ #include "../localisation/LocalisationService.h" #include "../paint/Paint.h" #include "../sprites.h" +#include "../util/Util.h" #include "Drawing.h" #include "TTF.h" diff --git a/src/openrct2/entity/Duck.cpp b/src/openrct2/entity/Duck.cpp index 48dcb9b62f..14f6cd2482 100644 --- a/src/openrct2/entity/Duck.cpp +++ b/src/openrct2/entity/Duck.cpp @@ -16,7 +16,7 @@ #include "../profiling/Profiling.h" #include "../scenario/Scenario.h" #include "../sprites.h" -#include "../world/Surface.h" +#include "../world/tile_element/SurfaceElement.h" #include "EntityRegistry.h" #include diff --git a/src/openrct2/entity/Fountain.cpp b/src/openrct2/entity/Fountain.cpp index d8e8ebc302..7125959be8 100644 --- a/src/openrct2/entity/Fountain.cpp +++ b/src/openrct2/entity/Fountain.cpp @@ -20,6 +20,7 @@ #include "../world/Location.hpp" #include "../world/Map.h" #include "../world/Scenery.h" +#include "../world/tile_element/PathElement.h" #include "EntityRegistry.h" using namespace OpenRCT2; diff --git a/src/openrct2/entity/Fountain.h b/src/openrct2/entity/Fountain.h index 9820afb8a3..39aa1e6cb6 100644 --- a/src/openrct2/entity/Fountain.h +++ b/src/openrct2/entity/Fountain.h @@ -13,6 +13,7 @@ #include "EntityBase.h" class DataSerialiser; +struct PaintSession; enum class JumpingFountainType : uint8_t { diff --git a/src/openrct2/entity/Guest.cpp b/src/openrct2/entity/Guest.cpp index 202d60954d..ca22b6f587 100644 --- a/src/openrct2/entity/Guest.cpp +++ b/src/openrct2/entity/Guest.cpp @@ -58,9 +58,11 @@ #include "../world/Map.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/TileElementsView.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/LargeSceneryElement.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include "Peep.h" diff --git a/src/openrct2/entity/Litter.cpp b/src/openrct2/entity/Litter.cpp index e544a7ec8c..0919ea9825 100644 --- a/src/openrct2/entity/Litter.cpp +++ b/src/openrct2/entity/Litter.cpp @@ -8,6 +8,7 @@ #include "../paint/Paint.h" #include "../profiling/Profiling.h" #include "../sprites.h" +#include "../world/Footpath.h" #include "../world/Map.h" #include "EntityList.h" #include "EntityRegistry.h" diff --git a/src/openrct2/entity/Particle.cpp b/src/openrct2/entity/Particle.cpp index d83a05acff..c648687298 100644 --- a/src/openrct2/entity/Particle.cpp +++ b/src/openrct2/entity/Particle.cpp @@ -14,6 +14,7 @@ #include "../profiling/Profiling.h" #include "../ride/VehicleColour.h" #include "../scenario/Scenario.h" +#include "../world/tile_element/SurfaceElement.h" #include "EntityRegistry.h" #include diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index 8ead7e9184..962221d2ce 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -55,8 +55,9 @@ #include "../world/Map.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "PatrolArea.h" #include "Staff.h" diff --git a/src/openrct2/entity/Staff.cpp b/src/openrct2/entity/Staff.cpp index 58b78d76ca..2bc911ab5f 100644 --- a/src/openrct2/entity/Staff.cpp +++ b/src/openrct2/entity/Staff.cpp @@ -42,9 +42,11 @@ #include "../world/Entrance.h" #include "../world/Footpath.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "PatrolArea.h" #include "Peep.h" diff --git a/src/openrct2/entity/Staff.h b/src/openrct2/entity/Staff.h index 2eea66d32a..1831002e8a 100644 --- a/src/openrct2/entity/Staff.h +++ b/src/openrct2/entity/Staff.h @@ -12,9 +12,13 @@ #include "../world/Map.h" #include "Peep.h" +#include + class DataSerialiser; class PatrolArea; +using colour_t = uint8_t; + struct Staff : Peep { static constexpr auto cEntityType = EntityType::Staff; diff --git a/src/openrct2/interface/Screenshot.cpp b/src/openrct2/interface/Screenshot.cpp index 19ab1d27e3..0778d15173 100644 --- a/src/openrct2/interface/Screenshot.cpp +++ b/src/openrct2/interface/Screenshot.cpp @@ -32,7 +32,7 @@ #include "../world/Climate.h" #include "../world/Map.h" #include "../world/Park.h" -#include "../world/Surface.h" +#include "../world/tile_element/SurfaceElement.h" #include "Viewport.h" #include diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 5baa7d259f..64c5b6b4d0 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -38,6 +38,9 @@ #include "../util/Math.hpp" #include "../world/Climate.h" #include "../world/Map.h" +#include "../world/tile_element/LargeSceneryElement.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/WallElement.h" #include "Colour.h" #include "Window.h" diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index bcd41886a1..74ea55ec6e 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -614,16 +614,19 @@ - - - + + + + + + @@ -1093,7 +1096,6 @@ - @@ -1101,13 +1103,15 @@ - - - + + + + + diff --git a/src/openrct2/network/NetworkPlayer.cpp b/src/openrct2/network/NetworkPlayer.cpp index ef221ddbf8..9bc4915d75 100644 --- a/src/openrct2/network/NetworkPlayer.cpp +++ b/src/openrct2/network/NetworkPlayer.cpp @@ -11,6 +11,7 @@ # include "NetworkPlayer.h" +# include "../core/Money.hpp" # include "../interface/Window.h" # include "NetworkPacket.h" diff --git a/src/openrct2/network/NetworkPlayer.h b/src/openrct2/network/NetworkPlayer.h index 6a816283ae..9f9bea7b56 100644 --- a/src/openrct2/network/NetworkPlayer.h +++ b/src/openrct2/network/NetworkPlayer.h @@ -10,6 +10,7 @@ #pragma once #include "../Game.h" +#include "../core/Money.hpp" #include "../world/Map.h" #include diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index 70919efbe3..209d317f1d 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -12,6 +12,7 @@ #include "../Context.h" #include "../config/Config.h" #include "../core/Guard.hpp" +#include "../core/Money.hpp" #include "../drawing/Drawing.h" #include "../interface/Viewport.h" #include "../localisation/Currency.h" diff --git a/src/openrct2/paint/Paint.h b/src/openrct2/paint/Paint.h index c8a9d16e50..250c6b834a 100644 --- a/src/openrct2/paint/Paint.h +++ b/src/openrct2/paint/Paint.h @@ -9,6 +9,7 @@ #pragma once +#include "../core/Money.hpp" #include "../drawing/Drawing.h" #include "../interface/Colour.h" #include "../world/Location.hpp" diff --git a/src/openrct2/paint/VirtualFloor.cpp b/src/openrct2/paint/VirtualFloor.cpp index da9cecdf96..2eb7285a92 100644 --- a/src/openrct2/paint/VirtualFloor.cpp +++ b/src/openrct2/paint/VirtualFloor.cpp @@ -21,6 +21,8 @@ #include "../world/Location.hpp" #include "../world/Map.h" #include "../world/TileElementsView.h" +#include "../world/tile_element/SurfaceElement.h" +#include "../world/tile_element/TileElement.h" #include "Paint.h" #include "VirtualFloor.h" #include "tile_element/Paint.TileElement.h" diff --git a/src/openrct2/paint/support/MetalSupports.cpp b/src/openrct2/paint/support/MetalSupports.cpp index 45a83fef36..a49be52f02 100644 --- a/src/openrct2/paint/support/MetalSupports.cpp +++ b/src/openrct2/paint/support/MetalSupports.cpp @@ -12,7 +12,7 @@ #include "../../drawing/Drawing.h" #include "../../interface/Viewport.h" #include "../../util/Util.h" -#include "../../world/Surface.h" +#include "../../world/Footpath.h" #include "../../world/tile_element/Slope.h" #include "../Paint.SessionFlags.h" #include "../Paint.h" diff --git a/src/openrct2/paint/support/WoodenSupports.cpp b/src/openrct2/paint/support/WoodenSupports.cpp index eaec306c5b..e6fac7d1e6 100644 --- a/src/openrct2/paint/support/WoodenSupports.cpp +++ b/src/openrct2/paint/support/WoodenSupports.cpp @@ -13,7 +13,6 @@ #include "../../ride/TrackData.h" #include "../../sprites.h" #include "../../world/Map.h" -#include "../../world/Surface.h" #include "../../world/tile_element/Slope.h" #include "../Boundbox.h" #include "../Paint.SessionFlags.h" diff --git a/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp b/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp index 1626c1fc64..7cdc0ca7ad 100644 --- a/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp +++ b/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp @@ -27,6 +27,7 @@ #include "../../world/Map.h" #include "../../world/Scenery.h" #include "../../world/TileInspector.h" +#include "../../world/tile_element/LargeSceneryElement.h" #include "../Boundbox.h" #include "../support/WoodenSupports.h" #include "Paint.TileElement.h" diff --git a/src/openrct2/paint/tile_element/Paint.Path.cpp b/src/openrct2/paint/tile_element/Paint.Path.cpp index 3e4975facc..cdb3e35834 100644 --- a/src/openrct2/paint/tile_element/Paint.Path.cpp +++ b/src/openrct2/paint/tile_element/Paint.Path.cpp @@ -31,9 +31,11 @@ #include "../../world/Footpath.h" #include "../../world/Map.h" #include "../../world/Scenery.h" -#include "../../world/Surface.h" #include "../../world/TileInspector.h" +#include "../../world/tile_element/PathElement.h" #include "../../world/tile_element/Slope.h" +#include "../../world/tile_element/SurfaceElement.h" +#include "../../world/tile_element/TileElement.h" #include "../../world/tile_element/TrackElement.h" #include "../Boundbox.h" #include "../Paint.SessionFlags.h" diff --git a/src/openrct2/paint/tile_element/Paint.PathAddition.cpp b/src/openrct2/paint/tile_element/Paint.PathAddition.cpp index 1f79c8002f..7578140bc6 100644 --- a/src/openrct2/paint/tile_element/Paint.PathAddition.cpp +++ b/src/openrct2/paint/tile_element/Paint.PathAddition.cpp @@ -14,6 +14,7 @@ #include "../../interface/Viewport.h" #include "../../object/PathAdditionEntry.h" #include "../../profiling/Profiling.h" +#include "../../world/tile_element/PathElement.h" #include "Paint.TileElement.h" using namespace OpenRCT2; diff --git a/src/openrct2/paint/tile_element/Paint.PathAddition.h b/src/openrct2/paint/tile_element/Paint.PathAddition.h index e36ac0e225..dc7d0fbda3 100644 --- a/src/openrct2/paint/tile_element/Paint.PathAddition.h +++ b/src/openrct2/paint/tile_element/Paint.PathAddition.h @@ -10,7 +10,6 @@ #pragma once #include "../../drawing/ImageId.hpp" -#include "../../world/TileElement.h" #include "../Paint.h" #include diff --git a/src/openrct2/paint/tile_element/Paint.SmallScenery.cpp b/src/openrct2/paint/tile_element/Paint.SmallScenery.cpp index 981fb48435..00cb9be4a4 100644 --- a/src/openrct2/paint/tile_element/Paint.SmallScenery.cpp +++ b/src/openrct2/paint/tile_element/Paint.SmallScenery.cpp @@ -20,6 +20,7 @@ #include "../../world/Map.h" #include "../../world/Scenery.h" #include "../../world/TileInspector.h" +#include "../../world/tile_element/SmallSceneryElement.h" #include "../support/WoodenSupports.h" #include "Paint.TileElement.h" #include "Segment.h" diff --git a/src/openrct2/paint/tile_element/Paint.Surface.cpp b/src/openrct2/paint/tile_element/Paint.Surface.cpp index a1eac2f7c1..81937e7172 100644 --- a/src/openrct2/paint/tile_element/Paint.Surface.cpp +++ b/src/openrct2/paint/tile_element/Paint.Surface.cpp @@ -27,8 +27,9 @@ #include "../../profiling/Profiling.h" #include "../../ride/TrackDesign.h" #include "../../sprites.h" -#include "../../world/Surface.h" #include "../../world/tile_element/Slope.h" +#include "../../world/tile_element/SurfaceElement.h" +#include "../../world/tile_element/TileElement.h" #include "../Boundbox.h" #include "../Paint.SessionFlags.h" #include "Paint.TileElement.h" diff --git a/src/openrct2/paint/tile_element/Paint.TileElement.cpp b/src/openrct2/paint/tile_element/Paint.TileElement.cpp index 34691e8d0d..c123239df9 100644 --- a/src/openrct2/paint/tile_element/Paint.TileElement.cpp +++ b/src/openrct2/paint/tile_element/Paint.TileElement.cpp @@ -25,8 +25,9 @@ #include "../../world/Footpath.h" #include "../../world/Map.h" #include "../../world/Scenery.h" -#include "../../world/Surface.h" #include "../../world/tile_element/Slope.h" +#include "../../world/tile_element/SurfaceElement.h" +#include "../../world/tile_element/TileElement.h" #include "../Paint.SessionFlags.h" #include "../Paint.h" #include "../VirtualFloor.h" diff --git a/src/openrct2/paint/tile_element/Paint.Tunnel.cpp b/src/openrct2/paint/tile_element/Paint.Tunnel.cpp index 9f0c739d9f..16cfd844bd 100644 --- a/src/openrct2/paint/tile_element/Paint.Tunnel.cpp +++ b/src/openrct2/paint/tile_element/Paint.Tunnel.cpp @@ -1,6 +1,7 @@ #include "Paint.Tunnel.h" +#include "../../util/Util.h" #include "../Paint.h" #include diff --git a/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp b/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp index 3686d97e24..f4749db671 100644 --- a/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/ClassicStandUpRollerCoaster.cpp @@ -7,6 +7,7 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ +#include "../../../ride/Ride.h" #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" diff --git a/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp b/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp index e5d8f682ae..c94457a7c2 100644 --- a/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp +++ b/src/openrct2/paint/track/coaster/FlyingRollerCoasterInverted.cpp @@ -7,6 +7,7 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ +#include "../../../ride/Ride.h" #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" diff --git a/src/openrct2/paint/track/gentle/CrookedHouse.cpp b/src/openrct2/paint/track/gentle/CrookedHouse.cpp index 70a8199132..4bd1540037 100644 --- a/src/openrct2/paint/track/gentle/CrookedHouse.cpp +++ b/src/openrct2/paint/track/gentle/CrookedHouse.cpp @@ -14,6 +14,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" +#include "../../../world/tile_element/TileElement.h" #include "../../../world/tile_element/TrackElement.h" #include "../../Boundbox.h" #include "../../Paint.h" diff --git a/src/openrct2/paint/track/gentle/MiniGolf.cpp b/src/openrct2/paint/track/gentle/MiniGolf.cpp index d0efbd75c5..c09cd5bb03 100644 --- a/src/openrct2/paint/track/gentle/MiniGolf.cpp +++ b/src/openrct2/paint/track/gentle/MiniGolf.cpp @@ -13,8 +13,8 @@ #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" #include "../../../world/Map.h" -#include "../../../world/Surface.h" #include "../../../world/tile_element/Slope.h" +#include "../../../world/tile_element/SurfaceElement.h" #include "../../../world/tile_element/TrackElement.h" #include "../../Paint.SessionFlags.h" #include "../../Paint.h" diff --git a/src/openrct2/paint/track/gentle/ObservationTower.cpp b/src/openrct2/paint/track/gentle/ObservationTower.cpp index 9b5682f684..8e9eae8b02 100644 --- a/src/openrct2/paint/track/gentle/ObservationTower.cpp +++ b/src/openrct2/paint/track/gentle/ObservationTower.cpp @@ -13,6 +13,7 @@ #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TileElement.h" #include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp b/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp index 841fda7e08..46a0968512 100644 --- a/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp +++ b/src/openrct2/paint/track/thrill/LaunchedFreefall.cpp @@ -12,6 +12,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" +#include "../../../world/tile_element/TileElement.h" #include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/thrill/RotoDrop.cpp b/src/openrct2/paint/track/thrill/RotoDrop.cpp index 0ffc4e5b49..9029cd1193 100644 --- a/src/openrct2/paint/track/thrill/RotoDrop.cpp +++ b/src/openrct2/paint/track/thrill/RotoDrop.cpp @@ -12,6 +12,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../ride/Vehicle.h" +#include "../../../world/tile_element/TileElement.h" #include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/paint/track/transport/Chairlift.cpp b/src/openrct2/paint/track/transport/Chairlift.cpp index a091e12492..728717a686 100644 --- a/src/openrct2/paint/track/transport/Chairlift.cpp +++ b/src/openrct2/paint/track/transport/Chairlift.cpp @@ -13,6 +13,7 @@ #include "../../../ride/Track.h" #include "../../../ride/TrackPaint.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/TileElement.h" #include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/MetalSupports.h" diff --git a/src/openrct2/paint/track/transport/MiniatureRailway.cpp b/src/openrct2/paint/track/transport/MiniatureRailway.cpp index 64318bc93f..252eb27813 100644 --- a/src/openrct2/paint/track/transport/MiniatureRailway.cpp +++ b/src/openrct2/paint/track/transport/MiniatureRailway.cpp @@ -13,6 +13,8 @@ #include "../../../ride/TrackPaint.h" #include "../../../sprites.h" #include "../../../world/Map.h" +#include "../../../world/tile_element/PathElement.h" +#include "../../../world/tile_element/TileElement.h" #include "../../../world/tile_element/TrackElement.h" #include "../../Paint.h" #include "../../support/WoodenSupports.h" diff --git a/src/openrct2/park/ParkFile.cpp b/src/openrct2/park/ParkFile.cpp index 9154b81107..5ce16b396f 100644 --- a/src/openrct2/park/ParkFile.cpp +++ b/src/openrct2/park/ParkFile.cpp @@ -56,6 +56,8 @@ #include "../world/Map.h" #include "../world/Park.h" #include "../world/Scenery.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SmallSceneryElement.h" #include "../world/tile_element/TrackElement.h" #include "Legacy.h" diff --git a/src/openrct2/peep/GuestPathfinding.cpp b/src/openrct2/peep/GuestPathfinding.cpp index 22f4a8f1b9..3bcbb584ca 100644 --- a/src/openrct2/peep/GuestPathfinding.cpp +++ b/src/openrct2/peep/GuestPathfinding.cpp @@ -24,6 +24,8 @@ #include "../world/Footpath.h" #include "../world/tile_element/BannerElement.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TrackElement.h" #include @@ -1823,7 +1825,7 @@ namespace OpenRCT2::PathFinding break; } - if (loc.z == MAX_ELEMENT_HEIGHT) + if (loc.z == kMaxTileElementHeight) return; tileElement = lastPathElement; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 1756e49080..553efaab6d 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -69,11 +69,14 @@ #include "../world/MapAnimation.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/TilePointerIndex.hpp" #include "../world/Wall.h" #include "../world/tile_element/BannerElement.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/LargeSceneryElement.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include "RCT1.h" diff --git a/src/openrct2/rct1/Tables.cpp b/src/openrct2/rct1/Tables.cpp index 8d20f630bf..23211ae6e4 100644 --- a/src/openrct2/rct1/Tables.cpp +++ b/src/openrct2/rct1/Tables.cpp @@ -15,7 +15,6 @@ #include "../object/ObjectManager.h" #include "../ride/Ride.h" #include "../ride/RideData.h" -#include "../world/Surface.h" #include "RCT1.h" #include diff --git a/src/openrct2/rct12/RCT12.cpp b/src/openrct2/rct12/RCT12.cpp index d1ade8462e..4cb535081d 100644 --- a/src/openrct2/rct12/RCT12.cpp +++ b/src/openrct2/rct12/RCT12.cpp @@ -22,11 +22,11 @@ #include "../scenario/Scenario.h" #include "../world/Banner.h" #include "../world/Footpath.h" -#include "../world/SmallScenery.h" -#include "../world/Surface.h" -#include "../world/TileElement.h" #include "../world/Wall.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/WallElement.h" #include "EntryList.h" diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h index 1fdaaa34cc..357c25390b 100644 --- a/src/openrct2/rct12/RCT12.h +++ b/src/openrct2/rct12/RCT12.h @@ -306,6 +306,11 @@ namespace OpenRCT2::RCT12 }; } // namespace OpenRCT2::RCT12 +enum +{ + MAP_ELEM_TRACK_SEQUENCE_GREEN_LIGHT = (1 << 7), +}; + constexpr uint8_t RCT2_STRING_FORMAT_ARG_START = 123; constexpr uint8_t RCT2_STRING_FORMAT_ARG_END = 141; constexpr uint8_t RCT2_STRING_FORMAT_COLOUR_START = 142; diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp index b621b20806..0f05fdcc6c 100644 --- a/src/openrct2/rct12/ScenarioPatcher.cpp +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -26,8 +26,9 @@ #include "../world/Footpath.h" #include "../world/Location.hpp" #include "../world/Map.h" -#include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/SurfaceElement.h" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TileElementType.h" #include "../world/tile_element/TrackElement.h" diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 428d3161e3..f698231114 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -75,10 +75,14 @@ #include "../world/MapAnimation.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/TilePointerIndex.hpp" #include "../world/tile_element/BannerElement.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/LargeSceneryElement.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" diff --git a/src/openrct2/ride/CableLift.cpp b/src/openrct2/ride/CableLift.cpp index fe27561c85..6dd960b5d3 100644 --- a/src/openrct2/ride/CableLift.cpp +++ b/src/openrct2/ride/CableLift.cpp @@ -13,6 +13,7 @@ #include "../entity/EntityList.h" #include "../rct12/RCT12.h" #include "../util/Util.h" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" diff --git a/src/openrct2/ride/MazeCost.cpp b/src/openrct2/ride/MazeCost.cpp index ef8e3108dc..04c54b37a7 100644 --- a/src/openrct2/ride/MazeCost.cpp +++ b/src/openrct2/ride/MazeCost.cpp @@ -11,6 +11,7 @@ #include "../core/Money.hpp" #include "../world/Location.hpp" +#include "../world/tile_element/SurfaceElement.h" #include "Ride.h" #include "RideData.h" #include "TrackData.h" diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 112cd79325..1275005c85 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -63,6 +63,7 @@ #include "../world/Scenery.h" #include "../world/TileElementsView.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/TrackElement.h" #include "CableLift.h" #include "RideAudio.h" diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index 3899b1937b..214cba38b6 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -40,6 +40,8 @@ struct Staff; struct Vehicle; struct RideObjectEntry; struct ResultWithMessage; +struct TileElement; +struct TrackElement; constexpr uint8_t kRideAdjacencyCheckDistance = 5; diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp index 62e96b586b..f5f57f7e5f 100644 --- a/src/openrct2/ride/RideConstruction.cpp +++ b/src/openrct2/ride/RideConstruction.cpp @@ -41,6 +41,7 @@ #include "../world/Scenery.h" #include "../world/TileElementsView.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" diff --git a/src/openrct2/ride/RideRatings.cpp b/src/openrct2/ride/RideRatings.cpp index 256281587e..20226b1a4c 100644 --- a/src/openrct2/ride/RideRatings.cpp +++ b/src/openrct2/ride/RideRatings.cpp @@ -19,7 +19,8 @@ #include "../scripting/ScriptEngine.h" #include "../world/Footpath.h" #include "../world/Map.h" -#include "../world/Surface.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" diff --git a/src/openrct2/ride/Station.cpp b/src/openrct2/ride/Station.cpp index 2e487b7693..cbf738a361 100644 --- a/src/openrct2/ride/Station.cpp +++ b/src/openrct2/ride/Station.cpp @@ -14,6 +14,7 @@ #include "../entity/Guest.h" #include "../scenario/Scenario.h" #include "../world/Location.hpp" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TrackElement.h" #include "RideEntry.h" #include "Track.h" diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index 68efe948b4..b03c3730c3 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -28,7 +28,7 @@ #include "../world/MapAnimation.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" diff --git a/src/openrct2/ride/Track.h b/src/openrct2/ride/Track.h index 627a5b24c8..9a37c76438 100644 --- a/src/openrct2/ride/Track.h +++ b/src/openrct2/ride/Track.h @@ -9,10 +9,10 @@ #pragma once +#include "../Identifiers.h" #include "../object/Object.h" #include "../world/Map.h" #include "../world/QuarterTile.h" -#include "../world/TileElement.h" #include @@ -28,6 +28,7 @@ namespace OpenRCT2 } struct ResultWithMessage; +struct TileElement; enum class TrackRoll : uint8_t { diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 3de439adc9..86a702b2dd 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -56,9 +56,10 @@ #include "../world/Footpath.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "Ride.h" #include "RideData.h" diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 367183ed8c..469e514a07 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -25,7 +25,12 @@ #include "../windows/Intent.h" #include "../world/Footpath.h" #include "../world/Scenery.h" +#include "../world/tile_element/BannerElement.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/LargeSceneryElement.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include "RideData.h" diff --git a/src/openrct2/ride/TrackPaint.h b/src/openrct2/ride/TrackPaint.h index 8c87898015..9519baab66 100644 --- a/src/openrct2/ride/TrackPaint.h +++ b/src/openrct2/ride/TrackPaint.h @@ -16,6 +16,7 @@ #include "../world/Map.h" class StationObject; +struct Ride; constexpr uint8_t kTrackMap2x2[][4] = { { 0, 1, 2, 3 }, diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 5a59047a95..c65cee8446 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -46,7 +46,10 @@ #include "../world/MapAnimation.h" #include "../world/Park.h" #include "../world/Scenery.h" -#include "../world/Surface.h" +#include "../world/tile_element/LargeSceneryElement.h" +#include "../world/tile_element/PathElement.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TrackElement.h" #include "../world/tile_element/WallElement.h" #include "CableLift.h" diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index 9820fc9e80..5500175e3b 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -54,6 +54,7 @@ #include "../world/Map.h" #include "../world/Park.h" #include "../world/Scenery.h" +#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TrackElement.h" #include "ScenarioRepository.h" #include "ScenarioSources.h" diff --git a/src/openrct2/scripting/bindings/ride/ScTrackIterator.h b/src/openrct2/scripting/bindings/ride/ScTrackIterator.h index 9880586175..b3a977e957 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackIterator.h +++ b/src/openrct2/scripting/bindings/ride/ScTrackIterator.h @@ -12,7 +12,6 @@ #ifdef ENABLE_SCRIPTING # include "../../../Identifiers.h" -# include "../../../world/TileElement.h" # include "../../Duktape.hpp" # include diff --git a/src/openrct2/scripting/bindings/ride/ScTrackSegment.h b/src/openrct2/scripting/bindings/ride/ScTrackSegment.h index 769fcd95e9..8e9a9ea00a 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackSegment.h +++ b/src/openrct2/scripting/bindings/ride/ScTrackSegment.h @@ -11,7 +11,6 @@ #ifdef ENABLE_SCRIPTING -# include "../../../world/TileElement.h" # include "../../Duktape.hpp" # include diff --git a/src/openrct2/scripting/bindings/world/ScTile.cpp b/src/openrct2/scripting/bindings/world/ScTile.cpp index e04fd9385b..795911e97c 100644 --- a/src/openrct2/scripting/bindings/world/ScTile.cpp +++ b/src/openrct2/scripting/bindings/world/ScTile.cpp @@ -18,7 +18,7 @@ # include "../../../ride/Track.h" # include "../../../world/Footpath.h" # include "../../../world/Scenery.h" -# include "../../../world/Surface.h" +# include "../../../world/tile_element/LargeSceneryElement.h" # include "../../Duktape.hpp" # include "../../ScriptEngine.h" # include "ScTileElement.hpp" diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.cpp b/src/openrct2/scripting/bindings/world/ScTileElement.cpp index 1760f3f52f..027a73a76b 100644 --- a/src/openrct2/scripting/bindings/world/ScTileElement.cpp +++ b/src/openrct2/scripting/bindings/world/ScTileElement.cpp @@ -21,9 +21,12 @@ # include "../../../ride/Track.h" # include "../../../world/Footpath.h" # include "../../../world/Scenery.h" -# include "../../../world/Surface.h" # include "../../../world/tile_element/BannerElement.h" # include "../../../world/tile_element/EntranceElement.h" +# include "../../../world/tile_element/LargeSceneryElement.h" +# include "../../../world/tile_element/PathElement.h" +# include "../../../world/tile_element/SmallSceneryElement.h" +# include "../../../world/tile_element/SurfaceElement.h" # include "../../../world/tile_element/TrackElement.h" # include "../../../world/tile_element/WallElement.h" # include "../../Duktape.hpp" diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.hpp b/src/openrct2/scripting/bindings/world/ScTileElement.hpp index 9ac6a6a0c5..b3c45e1343 100644 --- a/src/openrct2/scripting/bindings/world/ScTileElement.hpp +++ b/src/openrct2/scripting/bindings/world/ScTileElement.hpp @@ -17,7 +17,6 @@ # include "../../../ride/Track.h" # include "../../../world/Footpath.h" # include "../../../world/Scenery.h" -# include "../../../world/Surface.h" # include "../../Duktape.hpp" # include "../../ScriptEngine.h" diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp index 6145a408c3..0281b391c2 100644 --- a/src/openrct2/world/Banner.cpp +++ b/src/openrct2/world/Banner.cpp @@ -33,6 +33,7 @@ #include "Scenery.h" #include "TileElementsView.h" #include "tile_element/BannerElement.h" +#include "tile_element/TileElement.h" #include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" diff --git a/src/openrct2/world/ConstructionClearance.cpp b/src/openrct2/world/ConstructionClearance.cpp index 76bc023792..a3d65ad733 100644 --- a/src/openrct2/world/ConstructionClearance.cpp +++ b/src/openrct2/world/ConstructionClearance.cpp @@ -21,9 +21,13 @@ #include "Park.h" #include "QuarterTile.h" #include "Scenery.h" -#include "Surface.h" #include "tile_element/EntranceElement.h" +#include "tile_element/LargeSceneryElement.h" +#include "tile_element/PathElement.h" #include "tile_element/Slope.h" +#include "tile_element/SmallSceneryElement.h" +#include "tile_element/SurfaceElement.h" +#include "tile_element/TileElement.h" #include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" diff --git a/src/openrct2/world/ConstructionClearance.h b/src/openrct2/world/ConstructionClearance.h index 618592c8d0..0d68eb7759 100644 --- a/src/openrct2/world/ConstructionClearance.h +++ b/src/openrct2/world/ConstructionClearance.h @@ -21,6 +21,13 @@ class QuarterTile; using CLEAR_FUNC = int32_t (*)(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money64* price); +enum +{ + ELEMENT_IS_ABOVE_GROUND = 1 << 0, + ELEMENT_IS_UNDERGROUND = 1 << 1, + ELEMENT_IS_UNDERWATER = 1 << 2, +}; + // Used when calling MapCanConstructWithClearAt(); // This assumes that the caller has already done the check on the element it wants to place, // as this function can only check the element the player wants to build through. diff --git a/src/openrct2/world/Entrance.h b/src/openrct2/world/Entrance.h index 0ea355a279..9959c31ac4 100644 --- a/src/openrct2/world/Entrance.h +++ b/src/openrct2/world/Entrance.h @@ -11,21 +11,8 @@ #include "../Identifiers.h" #include "Location.hpp" -#include "Map.h" -struct TileElement; - -enum -{ - ENTRANCE_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY = (1 << 0), -}; - -namespace OpenRCT2::EntranceSequence -{ - constexpr uint8_t Centre = 0; - constexpr uint8_t Left = 1; - constexpr uint8_t Right = 2; -}; // namespace OpenRCT2::EntranceSequence +struct CoordsXYE; constexpr uint8_t ParkEntranceHeight = 12 * kCoordsZStep; constexpr uint8_t RideEntranceHeight = 7 * kCoordsZStep; diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index b97574c451..771050cb80 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -36,11 +36,11 @@ #include "Location.hpp" #include "Map.h" #include "MapAnimation.h" -#include "Surface.h" -#include "TileElement.h" #include "tile_element/BannerElement.h" #include "tile_element/EntranceElement.h" +#include "tile_element/PathElement.h" #include "tile_element/Slope.h" +#include "tile_element/SurfaceElement.h" #include "tile_element/TrackElement.h" #include @@ -1239,292 +1239,6 @@ int32_t FootpathIsConnectedToMapEdge(const CoordsXYZ& footpathPos, int32_t direc return FootpathIsConnectedToMapEdgeHelper(footpathPos, direction, flags); } -bool PathElement::IsSloped() const -{ - return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED) != 0; -} - -void PathElement::SetSloped(bool isSloped) -{ - Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED; - if (isSloped) - Flags2 |= FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED; -} - -bool PathElement::HasJunctionRailings() const -{ - return Flags2 & FOOTPATH_ELEMENT_FLAGS2_HAS_JUNCTION_RAILINGS; -} - -void PathElement::SetJunctionRailings(bool hasJunctionRailings) -{ - Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_HAS_JUNCTION_RAILINGS; - if (hasJunctionRailings) - Flags2 |= FOOTPATH_ELEMENT_FLAGS2_HAS_JUNCTION_RAILINGS; -} - -Direction PathElement::GetSlopeDirection() const -{ - return SlopeDirection; -} - -void PathElement::SetSlopeDirection(Direction newSlope) -{ - SlopeDirection = newSlope; -} - -bool PathElement::IsQueue() const -{ - return (Type & FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE) != 0; -} - -void PathElement::SetIsQueue(bool isQueue) -{ - Type &= ~FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE; - if (isQueue) - Type |= FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE; -} - -bool PathElement::HasQueueBanner() const -{ - return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER) != 0; -} - -void PathElement::SetHasQueueBanner(bool hasQueueBanner) -{ - Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER; - if (hasQueueBanner) - Flags2 |= FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER; -} - -bool PathElement::IsBroken() const -{ - return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN) != 0; -} - -void PathElement::SetIsBroken(bool isBroken) -{ - if (isBroken) - { - Flags2 |= FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN; - } - else - { - Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN; - } -} - -bool PathElement::IsBlockedByVehicle() const -{ - return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE) != 0; -} - -void PathElement::SetIsBlockedByVehicle(bool isBlocked) -{ - if (isBlocked) - { - Flags2 |= FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE; - } - else - { - Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE; - } -} - -::StationIndex PathElement::GetStationIndex() const -{ - return StationIndex; -} - -void PathElement::SetStationIndex(::StationIndex newStationIndex) -{ - StationIndex = newStationIndex; -} - -bool PathElement::IsWide() const -{ - return (Type & FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE) != 0; -} - -void PathElement::SetWide(bool isWide) -{ - Type &= ~FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE; - if (isWide) - Type |= FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE; -} - -bool PathElement::HasAddition() const -{ - return Additions != 0; -} - -uint8_t PathElement::GetAddition() const -{ - return Additions; -} - -ObjectEntryIndex PathElement::GetAdditionEntryIndex() const -{ - // `Additions` is set to 0 when there is no addition, so the value 1 corresponds with path addition slot 0, etc. - return GetAddition() - 1; -} - -const PathAdditionEntry* PathElement::GetAdditionEntry() const -{ - if (!HasAddition()) - return nullptr; - return OpenRCT2::ObjectManager::GetObjectEntry(GetAdditionEntryIndex()); -} - -void PathElement::SetAddition(uint8_t newAddition) -{ - Additions = newAddition; -} - -void PathElement::SetAdditionEntryIndex(ObjectEntryIndex entryIndex) -{ - // `Additions` is set to 0 when there is no addition, so the value 1 corresponds with path addition slot 0, etc. - Additions = entryIndex + 1; -} - -bool PathElement::AdditionIsGhost() const -{ - return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST) != 0; -} - -void PathElement::SetAdditionIsGhost(bool isGhost) -{ - Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST; - if (isGhost) - Flags2 |= FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST; -} - -ObjectEntryIndex PathElement::GetLegacyPathEntryIndex() const -{ - if (Flags2 & FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY) - return SurfaceIndex; - - return OBJECT_ENTRY_INDEX_NULL; -} - -const FootpathObject* PathElement::GetLegacyPathEntry() const -{ - return GetLegacyFootpathEntry(GetLegacyPathEntryIndex()); -} - -void PathElement::SetLegacyPathEntryIndex(ObjectEntryIndex newIndex) -{ - SurfaceIndex = newIndex; - RailingsIndex = OBJECT_ENTRY_INDEX_NULL; - Flags2 |= FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY; -} - -bool PathElement::HasLegacyPathEntry() const -{ - return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY) != 0; -} - -const PathSurfaceDescriptor* PathElement::GetSurfaceDescriptor() const -{ - if (HasLegacyPathEntry()) - { - const auto* legacyPathEntry = GetLegacyPathEntry(); - if (legacyPathEntry == nullptr) - return nullptr; - - if (IsQueue()) - return &legacyPathEntry->GetQueueSurfaceDescriptor(); - - return &legacyPathEntry->GetPathSurfaceDescriptor(); - } - - const auto* surfaceEntry = GetSurfaceEntry(); - if (surfaceEntry == nullptr) - return nullptr; - - return &surfaceEntry->GetDescriptor(); -} - -const PathRailingsDescriptor* PathElement::GetRailingsDescriptor() const -{ - if (HasLegacyPathEntry()) - { - const auto* legacyPathEntry = GetLegacyPathEntry(); - if (legacyPathEntry == nullptr) - return nullptr; - - return &legacyPathEntry->GetPathRailingsDescriptor(); - } - - const auto* railingsEntry = GetRailingsEntry(); - if (railingsEntry == nullptr) - return nullptr; - - return &railingsEntry->GetDescriptor(); -} - -ObjectEntryIndex PathElement::GetSurfaceEntryIndex() const -{ - if (Flags2 & FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY) - return OBJECT_ENTRY_INDEX_NULL; - - return SurfaceIndex; -} - -const FootpathSurfaceObject* PathElement::GetSurfaceEntry() const -{ - auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathSurface, GetSurfaceEntryIndex())); -} - -void PathElement::SetSurfaceEntryIndex(ObjectEntryIndex newIndex) -{ - SurfaceIndex = newIndex; - Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY; -} - -ObjectEntryIndex PathElement::GetRailingsEntryIndex() const -{ - if (Flags2 & FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY) - return OBJECT_ENTRY_INDEX_NULL; - - return RailingsIndex; -} - -const FootpathRailingsObject* PathElement::GetRailingsEntry() const -{ - auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathRailings, GetRailingsEntryIndex())); -} - -void PathElement::SetRailingsEntryIndex(ObjectEntryIndex newEntryIndex) -{ - RailingsIndex = newEntryIndex; - Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY; -} - -uint8_t PathElement::GetQueueBannerDirection() const -{ - return ((Type & FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK) >> 6); -} - -void PathElement::SetQueueBannerDirection(uint8_t direction) -{ - Type &= ~FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK; - Type |= (direction << 6); -} - -bool PathElement::ShouldDrawPathOverSupports() const -{ - // TODO: make this an actual decision of the tile element. - return (GetRailingsDescriptor()->Flags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS); -} - -void PathElement::SetShouldDrawPathOverSupports(bool on) -{ - LOG_VERBOSE("Setting 'draw path over supports' to %d", static_cast(on)); -} - /** * * rct2: 0x006A8B12 diff --git a/src/openrct2/world/Footpath.h b/src/openrct2/world/Footpath.h index 9db7eedced..295869d7a2 100644 --- a/src/openrct2/world/Footpath.h +++ b/src/openrct2/world/Footpath.h @@ -71,41 +71,6 @@ struct FootpathSelection } }; -// Masks for values stored in TileElement.type -enum -{ - FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE = (1 << 0), - FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE = (1 << 1), - FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK = (1 << 6) | (1 << 7), -}; - -// Masks and flags for values stored in TileElement.properties.path.type -enum -{ - FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK = (1 << 0) | (1 << 1), - FOOTPATH_PROPERTIES_FLAG_IS_SLOPED = (1 << 2), - FOOTPATH_PROPERTIES_FLAG_HAS_QUEUE_BANNER = (1 << 3), - FOOTPATH_PROPERTIES_TYPE_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7), -}; - -// Masks and flags for values stored in TileElement.properties.path.edges -enum -{ - FOOTPATH_PROPERTIES_EDGES_EDGES_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3), - FOOTPATH_PROPERTIES_EDGES_CORNERS_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7), -}; - -enum -{ - FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED = 1 << 0, - FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER = (1 << 1), - FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST = (1 << 2), - FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE = (1 << 3), - FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN = (1 << 4), - FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY = (1 << 5), - FOOTPATH_ELEMENT_FLAGS2_HAS_JUNCTION_RAILINGS = (1 << 6), -}; - enum { RAILING_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE = (1 << 0), diff --git a/src/openrct2/world/LargeScenery.h b/src/openrct2/world/LargeScenery.h deleted file mode 100644 index 904b625874..0000000000 --- a/src/openrct2/world/LargeScenery.h +++ /dev/null @@ -1,15 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2024 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#pragma once - -enum -{ - LARGE_SCENERY_ELEMENT_FLAGS2_ACCOUNTED = 1 << 0, -}; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 209c025d32..5c033abfc1 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -54,12 +54,15 @@ #include "MapAnimation.h" #include "Park.h" #include "Scenery.h" -#include "Surface.h" #include "TileElementsView.h" #include "TileInspector.h" #include "tile_element/BannerElement.h" #include "tile_element/EntranceElement.h" +#include "tile_element/LargeSceneryElement.h" +#include "tile_element/PathElement.h" #include "tile_element/Slope.h" +#include "tile_element/SmallSceneryElement.h" +#include "tile_element/SurfaceElement.h" #include "tile_element/TrackElement.h" #include @@ -1037,7 +1040,7 @@ void TileElementRemove(TileElement* tileElement) // Mark the latest element with the last element flag. (tileElement - 1)->SetLastForTile(true); - tileElement->BaseHeight = MAX_ELEMENT_HEIGHT; + tileElement->BaseHeight = kMaxTileElementHeight; _tileElementsInUse--; auto& gameState = GetGameState(); if (tileElement == &gameState.TileElements.back()) @@ -1205,7 +1208,7 @@ TileElement* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants, { // Copy over map element *newTileElement = *originalTileElement; - originalTileElement->BaseHeight = MAX_ELEMENT_HEIGHT; + originalTileElement->BaseHeight = kMaxTileElementHeight; originalTileElement++; newTileElement++; @@ -1240,7 +1243,7 @@ TileElement* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants, { // Copy over map element *newTileElement = *originalTileElement; - originalTileElement->BaseHeight = MAX_ELEMENT_HEIGHT; + originalTileElement->BaseHeight = kMaxTileElementHeight; originalTileElement++; newTileElement++; } while (!((newTileElement - 1)->IsLastForTile())); diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 2e53f1f74a..49f7da9cad 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -9,10 +9,12 @@ #pragma once +#include "../Identifiers.h" #include "Location.hpp" -#include "TileElement.h" +#include #include +#include #include constexpr uint8_t kMinimumLandHeight = 2; @@ -45,6 +47,21 @@ constexpr uint32_t MAX_TILE_ELEMENTS_WITH_SPARE_ROOM = 0x1000000; constexpr uint32_t MAX_TILE_ELEMENTS = MAX_TILE_ELEMENTS_WITH_SPARE_ROOM - 512; using PeepSpawn = CoordsXYZD; +struct BannerElement; +struct EntranceElement; +struct LargeSceneryElement; +struct PathElement; +struct SmallSceneryElement; +struct SurfaceElement; +struct TileElement; +struct TrackElement; +struct WallElement; +enum class TileElementType : uint8_t; + +namespace OpenRCT2 +{ + enum class TrackElemType : uint16_t; +} struct CoordsXYE : public CoordsXY { diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index a5762ac0b4..58dee1417d 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -29,6 +29,10 @@ #include "Map.h" #include "Scenery.h" #include "tile_element/EntranceElement.h" +#include "tile_element/LargeSceneryElement.h" +#include "tile_element/PathElement.h" +#include "tile_element/SmallSceneryElement.h" +#include "tile_element/TileElement.h" #include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" diff --git a/src/openrct2/world/MapGen.cpp b/src/openrct2/world/MapGen.cpp index fa61cecd59..25bb70d59c 100644 --- a/src/openrct2/world/MapGen.cpp +++ b/src/openrct2/world/MapGen.cpp @@ -26,10 +26,12 @@ #include "../platform/Platform.h" #include "../util/Util.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SmallSceneryElement.h" +#include "../world/tile_element/SurfaceElement.h" +#include "../world/tile_element/TileElement.h" #include "Map.h" #include "MapHelpers.h" #include "Scenery.h" -#include "Surface.h" #include #include diff --git a/src/openrct2/world/MapHelpers.cpp b/src/openrct2/world/MapHelpers.cpp index 6c26578d3d..d75cdf34f5 100644 --- a/src/openrct2/world/MapHelpers.cpp +++ b/src/openrct2/world/MapHelpers.cpp @@ -10,8 +10,8 @@ #include "MapHelpers.h" #include "../world/tile_element/Slope.h" +#include "../world/tile_element/SurfaceElement.h" #include "Map.h" -#include "Surface.h" #include diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index a4756a2018..4eef41a9ef 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -38,8 +38,8 @@ #include "../windows/Intent.h" #include "Entrance.h" #include "Map.h" -#include "Surface.h" #include "tile_element/EntranceElement.h" +#include "tile_element/SurfaceElement.h" #include #include diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index c2c5a424b6..d070fd4c79 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -36,6 +36,8 @@ #include "Footpath.h" #include "Map.h" #include "Park.h" +#include "tile_element/PathElement.h" +#include "tile_element/SmallSceneryElement.h" uint8_t gSceneryQuadrant; diff --git a/src/openrct2/world/SmallScenery.h b/src/openrct2/world/SmallScenery.h deleted file mode 100644 index dba542218f..0000000000 --- a/src/openrct2/world/SmallScenery.h +++ /dev/null @@ -1,15 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2024 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#pragma once - -enum -{ - MAP_ELEM_SMALL_SCENERY_FLAGS2_NEEDS_SUPPORTS = (1 << 0), -}; diff --git a/src/openrct2/world/Surface.h b/src/openrct2/world/Surface.h deleted file mode 100644 index d2d48698da..0000000000 --- a/src/openrct2/world/Surface.h +++ /dev/null @@ -1,88 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2024 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#pragma once - -#include "TileElement.h" - -enum -{ - TERRAIN_GRASS, - TERRAIN_SAND, - TERRAIN_DIRT, - TERRAIN_ROCK, - TERRAIN_MARTIAN, - TERRAIN_CHECKERBOARD, - TERRAIN_GRASS_CLUMPS, - TERRAIN_ICE, - TERRAIN_GRID_RED, - TERRAIN_GRID_YELLOW, - TERRAIN_GRID_BLUE, - TERRAIN_GRID_GREEN, - TERRAIN_SAND_DARK, - TERRAIN_SAND_LIGHT, - - TERRAIN_RCT2_COUNT, - - TERRAIN_ROOF_BROWN = TERRAIN_RCT2_COUNT, - TERRAIN_ROOF_GREY, - TERRAIN_ROOF_IRON, - TERRAIN_ROOF_LOG, - TERRAIN_COUNT_REGULAR, // The amount of surface types the user can actually select - what follows are technical types - // Technical types (not selectable) - TERRAIN_CHECKERBOARD_INVERTED = TERRAIN_COUNT_REGULAR, - TERRAIN_UNDERGROUND_VIEW, -}; - -enum -{ - TERRAIN_EDGE_ROCK, - TERRAIN_EDGE_WOOD_RED, - TERRAIN_EDGE_WOOD_BLACK, - TERRAIN_EDGE_ICE, - - TERRAIN_EDGE_RCT2_COUNT, - - TERRAIN_EDGE_BRICK = TERRAIN_EDGE_RCT2_COUNT, - TERRAIN_EDGE_IRON, - TERRAIN_EDGE_GREY, - TERRAIN_EDGE_YELLOW, - TERRAIN_EDGE_RED, - TERRAIN_EDGE_PURPLE, - TERRAIN_EDGE_GREEN, - TERRAIN_EDGE_STONE_BROWN, - TERRAIN_EDGE_STONE_GREY, - TERRAIN_EDGE_SKYSCRAPER_A, - TERRAIN_EDGE_SKYSCRAPER_B, - - TERRAIN_EDGE_COUNT -}; - -enum -{ - GRASS_LENGTH_MOWED, - GRASS_LENGTH_CLEAR_0, - GRASS_LENGTH_CLEAR_1, - GRASS_LENGTH_CLEAR_2, - GRASS_LENGTH_CLUMPS_0, - GRASS_LENGTH_CLUMPS_1, - GRASS_LENGTH_CLUMPS_2 -}; - -enum -{ - OWNERSHIP_UNOWNED = 0, - OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED = (1 << 4), - OWNERSHIP_OWNED = (1 << 5), - OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE = (1 << 6), - OWNERSHIP_AVAILABLE = (1 << 7) -}; - -constexpr uint8_t kTileElementSurfaceOwnershipMask = 0xF0; -constexpr uint8_t kTileElementSurfaceParkFenceMask = 0x0F; diff --git a/src/openrct2/world/SurfaceData.cpp b/src/openrct2/world/SurfaceData.cpp index 1417e4f8b2..85394bd05f 100644 --- a/src/openrct2/world/SurfaceData.cpp +++ b/src/openrct2/world/SurfaceData.cpp @@ -1,6 +1,14 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + #include "SurfaceData.h" -#include "Surface.h" #include "tile_element/Slope.h" // 0x00981A1E diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h deleted file mode 100644 index ea7c779642..0000000000 --- a/src/openrct2/world/TileElement.h +++ /dev/null @@ -1,398 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2024 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#pragma once - -#include "../Identifiers.h" -#include "../ride/RideTypes.h" -#include "../ride/Station.h" -#include "Footpath.h" -#include "tile_element/TileElementType.h" - -struct Banner; -struct CoordsXY; -struct LargeSceneryEntry; -struct SmallSceneryEntry; -struct WallSceneryEntry; -struct PathAdditionEntry; -struct FootpathEntry; -class LargeSceneryObject; -class TerrainSurfaceObject; -class TerrainEdgeObject; -class FootpathObject; -class FootpathSurfaceObject; -class FootpathRailingsObject; -enum class RideColourScheme : uint8_t; -namespace OpenRCT2 -{ - enum class TrackElemType : uint16_t; -} - -constexpr uint8_t MAX_ELEMENT_HEIGHT = 255; -constexpr uint8_t OWNER_MASK = 0b00001111; -constexpr uint8_t kTileElementSize = 16; - -#pragma pack(push, 1) - -struct TileElement; -struct SurfaceElement; -struct PathElement; -struct TrackElement; -struct SmallSceneryElement; -struct LargeSceneryElement; -struct WallElement; -struct EntranceElement; -struct BannerElement; - -struct TileElementBase -{ - uint8_t Type; // 0 - uint8_t Flags; // 1. Upper nibble: flags. Lower nibble: occupied quadrants (one bit per quadrant). - uint8_t BaseHeight; // 2 - uint8_t ClearanceHeight; // 3 - uint8_t Owner; // 4 - - void Remove(); - - TileElementType GetType() const; - void SetType(TileElementType newType); - - Direction GetDirection() const; - void SetDirection(Direction direction); - Direction GetDirectionWithOffset(uint8_t offset) const; - - bool IsLastForTile() const; - void SetLastForTile(bool on); - bool IsGhost() const; - void SetGhost(bool isGhost); - bool IsInvisible() const; - void SetInvisible(bool on); - - uint8_t GetOccupiedQuadrants() const; - void SetOccupiedQuadrants(uint8_t quadrants); - - int32_t GetBaseZ() const; - void SetBaseZ(int32_t newZ); - - int32_t GetClearanceZ() const; - void SetClearanceZ(int32_t newZ); - - uint8_t GetOwner() const; - void SetOwner(uint8_t newOwner); - - template const TType* as() const - { - if constexpr (std::is_same_v) - return reinterpret_cast(this); - else - return GetType() == TType::ElementType ? reinterpret_cast(this) : nullptr; - } - - template TType* as() - { - if constexpr (std::is_same_v) - return reinterpret_cast(this); - else - return GetType() == TType::ElementType ? reinterpret_cast(this) : nullptr; - } - - const SurfaceElement* AsSurface() const; - SurfaceElement* AsSurface(); - const PathElement* AsPath() const; - PathElement* AsPath(); - const TrackElement* AsTrack() const; - TrackElement* AsTrack(); - const SmallSceneryElement* AsSmallScenery() const; - SmallSceneryElement* AsSmallScenery(); - const LargeSceneryElement* AsLargeScenery() const; - LargeSceneryElement* AsLargeScenery(); - const WallElement* AsWall() const; - WallElement* AsWall(); - const EntranceElement* AsEntrance() const; - EntranceElement* AsEntrance(); - const BannerElement* AsBanner() const; - BannerElement* AsBanner(); -}; - -/** - * Map element structure - * size: 0x10 - */ -struct TileElement : public TileElementBase -{ - uint8_t Pad05[3]; - uint8_t Pad08[8]; - - void ClearAs(TileElementType newType); - - RideId GetRideIndex() const; - - void SetBannerIndex(BannerIndex newIndex); - void RemoveBannerEntry(); - BannerIndex GetBannerIndex() const; -}; -static_assert(sizeof(TileElement) == 16); - -struct SurfaceElement : TileElementBase -{ - static constexpr TileElementType ElementType = TileElementType::Surface; - -private: - uint8_t Slope; - uint8_t WaterHeight; - uint8_t GrassLength; - uint8_t Ownership; - uint8_t SurfaceStyle; - uint8_t EdgeObjectIndex; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-private-field" - uint8_t Pad0B[5]; -#pragma clang diagnostic pop - -public: - uint8_t GetSlope() const; - void SetSlope(uint8_t newSlope); - - ObjectEntryIndex GetSurfaceObjectIndex() const; - TerrainSurfaceObject* GetSurfaceObject() const; - void SetSurfaceObjectIndex(ObjectEntryIndex newStyle); - - ObjectEntryIndex GetEdgeObjectIndex() const; - TerrainEdgeObject* GetEdgeObject() const; - void SetEdgeObjectIndex(ObjectEntryIndex newStyle); - - bool CanGrassGrow() const; - uint8_t GetGrassLength() const; - void SetGrassLength(uint8_t newLength); - void SetGrassLengthAndInvalidate(uint8_t newLength, const CoordsXY& coords); - void UpdateGrassLength(const CoordsXY& coords); - - uint8_t GetOwnership() const; - void SetOwnership(uint8_t newOwnership); - - int32_t GetWaterHeight() const; - void SetWaterHeight(int32_t newWaterHeight); - - uint8_t GetParkFences() const; - void SetParkFences(uint8_t newParkFences); - - bool HasTrackThatNeedsWater() const; - void SetHasTrackThatNeedsWater(bool on); -}; -static_assert(sizeof(SurfaceElement) == 16); - -struct PathElement : TileElementBase -{ - static constexpr TileElementType ElementType = TileElementType::Path; - -private: - ObjectEntryIndex SurfaceIndex; // 5 - ObjectEntryIndex RailingsIndex; // 7 - uint8_t Additions; // 9 (0 means no addition) - uint8_t EdgesAndCorners; // 10 (edges in lower 4 bits, corners in upper 4) - uint8_t Flags2; // 11 - uint8_t SlopeDirection; // 12 - union - { - uint8_t AdditionStatus; // 13, only used for litter bins - RideId rideIndex; // 13 - }; - ::StationIndex StationIndex; // 15 - -public: - ObjectEntryIndex GetLegacyPathEntryIndex() const; - const FootpathObject* GetLegacyPathEntry() const; - void SetLegacyPathEntryIndex(ObjectEntryIndex newIndex); - bool HasLegacyPathEntry() const; - - ObjectEntryIndex GetSurfaceEntryIndex() const; - const FootpathSurfaceObject* GetSurfaceEntry() const; - void SetSurfaceEntryIndex(ObjectEntryIndex newIndex); - - ObjectEntryIndex GetRailingsEntryIndex() const; - const FootpathRailingsObject* GetRailingsEntry() const; - void SetRailingsEntryIndex(ObjectEntryIndex newIndex); - - const PathSurfaceDescriptor* GetSurfaceDescriptor() const; - const PathRailingsDescriptor* GetRailingsDescriptor() const; - - uint8_t GetQueueBannerDirection() const; - void SetQueueBannerDirection(uint8_t direction); - - bool IsSloped() const; - void SetSloped(bool isSloped); - - bool HasJunctionRailings() const; - void SetJunctionRailings(bool hasJunctionRailings); - - Direction GetSlopeDirection() const; - void SetSlopeDirection(Direction newSlope); - - RideId GetRideIndex() const; - void SetRideIndex(RideId newRideIndex); - - ::StationIndex GetStationIndex() const; - void SetStationIndex(::StationIndex newStationIndex); - - bool IsWide() const; - void SetWide(bool isWide); - - bool IsQueue() const; - void SetIsQueue(bool isQueue); - bool HasQueueBanner() const; - void SetHasQueueBanner(bool hasQueueBanner); - - bool IsBroken() const; - void SetIsBroken(bool isBroken); - - bool IsBlockedByVehicle() const; - void SetIsBlockedByVehicle(bool isBlocked); - - uint8_t GetEdges() const; - void SetEdges(uint8_t newEdges); - uint8_t GetCorners() const; - void SetCorners(uint8_t newCorners); - uint8_t GetEdgesAndCorners() const; - void SetEdgesAndCorners(uint8_t newEdgesAndCorners); - - bool HasAddition() const; - uint8_t GetAddition() const; - ObjectEntryIndex GetAdditionEntryIndex() const; - const PathAdditionEntry* GetAdditionEntry() const; - void SetAddition(uint8_t newAddition); - void SetAdditionEntryIndex(ObjectEntryIndex entryIndex); - - bool AdditionIsGhost() const; - void SetAdditionIsGhost(bool isGhost); - - uint8_t GetAdditionStatus() const; - void SetAdditionStatus(uint8_t newStatus); - - bool ShouldDrawPathOverSupports() const; - void SetShouldDrawPathOverSupports(bool on); - - bool IsLevelCrossing(const CoordsXY& coords) const; -}; -static_assert(sizeof(PathElement) == 16); - -struct SmallSceneryElement : TileElementBase -{ - static constexpr TileElementType ElementType = TileElementType::SmallScenery; - -private: - ObjectEntryIndex entryIndex; // 5 - uint8_t age; // 7 - uint8_t Colour[3]; // 8 - uint8_t Flags2; // B -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-private-field" - uint8_t Pad0B[4]; -#pragma clang diagnostic pop - -public: - ObjectEntryIndex GetEntryIndex() const; - void SetEntryIndex(ObjectEntryIndex newIndex); - const SmallSceneryEntry* GetEntry() const; - uint8_t GetAge() const; - void SetAge(uint8_t newAge); - void IncreaseAge(const CoordsXY& sceneryPos); - uint8_t GetSceneryQuadrant() const; - void SetSceneryQuadrant(uint8_t newQuadrant); - colour_t GetPrimaryColour() const; - void SetPrimaryColour(colour_t colour); - colour_t GetSecondaryColour() const; - void SetSecondaryColour(colour_t colour); - colour_t GetTertiaryColour() const; - void SetTertiaryColour(colour_t colour); - bool NeedsSupports() const; - void SetNeedsSupports(); - void UpdateAge(const CoordsXY& sceneryPos); -}; -static_assert(sizeof(SmallSceneryElement) == 16); - -struct LargeSceneryElement : TileElementBase -{ - static constexpr TileElementType ElementType = TileElementType::LargeScenery; - -private: - ObjectEntryIndex EntryIndex; - ::BannerIndex BannerIndex; - uint8_t SequenceIndex; - uint8_t Colour[3]; - uint8_t Flags2; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-private-field" - uint8_t pad[2]; -#pragma clang diagnostic pop - -public: - ObjectEntryIndex GetEntryIndex() const; - void SetEntryIndex(ObjectEntryIndex newIndex); - const LargeSceneryEntry* GetEntry() const; - const LargeSceneryObject* GetObject() const; - - uint8_t GetSequenceIndex() const; - void SetSequenceIndex(uint8_t newIndex); - - colour_t GetPrimaryColour() const; - void SetPrimaryColour(colour_t colour); - colour_t GetSecondaryColour() const; - void SetSecondaryColour(colour_t colour); - colour_t GetTertiaryColour() const; - void SetTertiaryColour(colour_t colour); - - Banner* GetBanner() const; - ::BannerIndex GetBannerIndex() const; - void SetBannerIndex(::BannerIndex newIndex); - - bool IsAccounted() const; - void SetIsAccounted(bool isAccounted); -}; -static_assert(sizeof(LargeSceneryElement) == 16); - -#pragma pack(pop) - -enum -{ - SURFACE_ELEMENT_HAS_TRACK_THAT_NEEDS_WATER = (1 << 6), -}; - -enum -{ - TILE_ELEMENT_DIRECTION_WEST, - TILE_ELEMENT_DIRECTION_NORTH, - TILE_ELEMENT_DIRECTION_EAST, - TILE_ELEMENT_DIRECTION_SOUTH -}; - -enum -{ - TILE_ELEMENT_FLAG_GHOST = (1 << 4), - TILE_ELEMENT_FLAG_INVISIBLE = (1 << 5), - TILE_ELEMENT_FLAG_LAST_TILE = (1 << 7) -}; - -enum -{ - ELEMENT_IS_ABOVE_GROUND = 1 << 0, - ELEMENT_IS_UNDERGROUND = 1 << 1, - ELEMENT_IS_UNDERWATER = 1 << 2, -}; - -enum -{ - MAP_ELEM_TRACK_SEQUENCE_GREEN_LIGHT = (1 << 7), -}; - -constexpr uint8_t kTileElementQuadrantMask = 0b11000000; -constexpr uint8_t kTileElementTypeMask = 0b00111100; -constexpr uint8_t kTileElementDirectionMask = 0b00000011; -constexpr uint8_t kTileElementOccupiedQuadrantsMask = 0b00001111; - -bool TileElementIsUnderground(TileElement* tileElement); diff --git a/src/openrct2/world/TileElementsView.h b/src/openrct2/world/TileElementsView.h index a8bef7a87a..edf1057e6c 100644 --- a/src/openrct2/world/TileElementsView.h +++ b/src/openrct2/world/TileElementsView.h @@ -11,7 +11,6 @@ #include "Location.hpp" #include "Map.h" -#include "TileElement.h" #include diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index 996461a6b4..97351eec7c 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -24,10 +24,13 @@ #include "MapAnimation.h" #include "Park.h" #include "Scenery.h" -#include "Surface.h" #include "tile_element/BannerElement.h" #include "tile_element/EntranceElement.h" +#include "tile_element/LargeSceneryElement.h" +#include "tile_element/PathElement.h" #include "tile_element/Slope.h" +#include "tile_element/SmallSceneryElement.h" +#include "tile_element/SurfaceElement.h" #include "tile_element/TrackElement.h" #include "tile_element/WallElement.h" @@ -429,7 +432,7 @@ namespace OpenRCT2::TileInspector { return GameActions::Result(GameActions::Status::TooLow, STR_CANT_LOWER_ELEMENT_HERE, STR_TOO_LOW); } - if (newBaseHeight > MAX_ELEMENT_HEIGHT) + if (newBaseHeight > kMaxTileElementHeight) { return GameActions::Result(GameActions::Status::TooHigh, STR_CANT_RAISE_ELEMENT_HERE, STR_TOO_HIGH); } @@ -437,7 +440,7 @@ namespace OpenRCT2::TileInspector { return GameActions::Result(GameActions::Status::NoClearance, STR_CANT_LOWER_ELEMENT_HERE, STR_NO_CLEARANCE); } - if (newClearanceHeight > MAX_ELEMENT_HEIGHT) + if (newClearanceHeight > kMaxTileElementHeight) { return GameActions::Result(GameActions::Status::NoClearance, STR_CANT_RAISE_ELEMENT_HERE, STR_NO_CLEARANCE); } diff --git a/src/openrct2/world/TileInspector.h b/src/openrct2/world/TileInspector.h index 777f03899a..d280ccb714 100644 --- a/src/openrct2/world/TileInspector.h +++ b/src/openrct2/world/TileInspector.h @@ -11,6 +11,8 @@ #include "Map.h" +struct Banner; + namespace OpenRCT2::GameActions { class Result; diff --git a/src/openrct2/world/Wall.cpp b/src/openrct2/world/Wall.cpp index 22e34cbcfe..484518bfe5 100644 --- a/src/openrct2/world/Wall.cpp +++ b/src/openrct2/world/Wall.cpp @@ -10,6 +10,7 @@ #include "Wall.h" #include "Map.h" +#include "tile_element/TileElement.h" #include "tile_element/WallElement.h" /** diff --git a/src/openrct2/world/tile_element/BannerElement.h b/src/openrct2/world/tile_element/BannerElement.h index a0bfe2d01b..929c46da70 100644 --- a/src/openrct2/world/tile_element/BannerElement.h +++ b/src/openrct2/world/tile_element/BannerElement.h @@ -9,7 +9,8 @@ #pragma once -#include "../TileElement.h" +#include "../Banner.h" +#include "TileElementBase.h" struct BannerSceneryEntry; diff --git a/src/openrct2/world/tile_element/EntranceElement.h b/src/openrct2/world/tile_element/EntranceElement.h index abeb9f43bd..c57c97722b 100644 --- a/src/openrct2/world/tile_element/EntranceElement.h +++ b/src/openrct2/world/tile_element/EntranceElement.h @@ -10,7 +10,11 @@ #pragma once #include "../../Identifiers.h" -#include "../TileElement.h" +#include "../../object/FootpathObject.h" +#include "../../object/FootpathRailingsObject.h" +#include "../../object/FootpathSurfaceObject.h" +#include "../../object/ObjectTypes.h" +#include "TileElementBase.h" #include @@ -21,6 +25,18 @@ enum ENTRANCE_TYPE_PARK_ENTRANCE }; +enum +{ + ENTRANCE_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY = (1 << 0), +}; + +namespace OpenRCT2::EntranceSequence +{ + constexpr uint8_t Centre = 0; + constexpr uint8_t Left = 1; + constexpr uint8_t Right = 2; +}; // namespace OpenRCT2::EntranceSequence + #pragma pack(push, 1) struct EntranceElement; diff --git a/src/openrct2/world/LargeScenery.cpp b/src/openrct2/world/tile_element/LargeSceneryElement.cpp similarity index 91% rename from src/openrct2/world/LargeScenery.cpp rename to src/openrct2/world/tile_element/LargeSceneryElement.cpp index f53c595fd7..2292c4ec98 100644 --- a/src/openrct2/world/LargeScenery.cpp +++ b/src/openrct2/world/tile_element/LargeSceneryElement.cpp @@ -7,14 +7,12 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ -#include "LargeScenery.h" +#include "LargeSceneryElement.h" -#include "../Context.h" -#include "../object/LargeSceneryObject.h" -#include "../object/ObjectEntryManager.h" -#include "../object/ObjectManager.h" -#include "../world/Banner.h" -#include "TileElement.h" +#include "../../object/LargeSceneryObject.h" +#include "../../object/ObjectEntryManager.h" +#include "../../object/ObjectManager.h" +#include "../Banner.h" #include diff --git a/src/openrct2/world/tile_element/LargeSceneryElement.h b/src/openrct2/world/tile_element/LargeSceneryElement.h new file mode 100644 index 0000000000..437e207337 --- /dev/null +++ b/src/openrct2/world/tile_element/LargeSceneryElement.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../Identifiers.h" +#include "../../object/LargeSceneryEntry.h" +#include "../../object/LargeSceneryObject.h" +#include "TileElementBase.h" + +struct Banner; + +enum +{ + LARGE_SCENERY_ELEMENT_FLAGS2_ACCOUNTED = 1 << 0, +}; + +#pragma pack(push, 1) +struct LargeSceneryElement : TileElementBase +{ + static constexpr TileElementType ElementType = TileElementType::LargeScenery; + +private: + ObjectEntryIndex EntryIndex; + ::BannerIndex BannerIndex; + uint8_t SequenceIndex; + uint8_t Colour[3]; + uint8_t Flags2; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" + uint8_t pad[2]; +#pragma clang diagnostic pop + +public: + ObjectEntryIndex GetEntryIndex() const; + void SetEntryIndex(ObjectEntryIndex newIndex); + const LargeSceneryEntry* GetEntry() const; + const LargeSceneryObject* GetObject() const; + + uint8_t GetSequenceIndex() const; + void SetSequenceIndex(uint8_t newIndex); + + colour_t GetPrimaryColour() const; + void SetPrimaryColour(colour_t colour); + colour_t GetSecondaryColour() const; + void SetSecondaryColour(colour_t colour); + colour_t GetTertiaryColour() const; + void SetTertiaryColour(colour_t colour); + + Banner* GetBanner() const; + ::BannerIndex GetBannerIndex() const; + void SetBannerIndex(::BannerIndex newIndex); + + bool IsAccounted() const; + void SetIsAccounted(bool isAccounted); +}; +static_assert(sizeof(LargeSceneryElement) == kTileElementSize); +#pragma pack(pop) diff --git a/src/openrct2/world/tile_element/PathElement.cpp b/src/openrct2/world/tile_element/PathElement.cpp new file mode 100644 index 0000000000..36ba91b305 --- /dev/null +++ b/src/openrct2/world/tile_element/PathElement.cpp @@ -0,0 +1,306 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "PathElement.h" + +#include "../../Context.h" +#include "../../Diagnostic.h" +#include "../../object/FootpathObject.h" +#include "../../object/FootpathRailingsObject.h" +#include "../../object/FootpathSurfaceObject.h" +#include "../../object/ObjectEntryManager.h" +#include "../../object/ObjectManager.h" +#include "../../object/PathAdditionEntry.h" +#include "../Footpath.h" + +bool PathElement::IsSloped() const +{ + return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED) != 0; +} + +void PathElement::SetSloped(bool isSloped) +{ + Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED; + if (isSloped) + Flags2 |= FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED; +} + +bool PathElement::HasJunctionRailings() const +{ + return Flags2 & FOOTPATH_ELEMENT_FLAGS2_HAS_JUNCTION_RAILINGS; +} + +void PathElement::SetJunctionRailings(bool hasJunctionRailings) +{ + Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_HAS_JUNCTION_RAILINGS; + if (hasJunctionRailings) + Flags2 |= FOOTPATH_ELEMENT_FLAGS2_HAS_JUNCTION_RAILINGS; +} + +Direction PathElement::GetSlopeDirection() const +{ + return SlopeDirection; +} + +void PathElement::SetSlopeDirection(Direction newSlope) +{ + SlopeDirection = newSlope; +} + +bool PathElement::IsQueue() const +{ + return (Type & FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE) != 0; +} + +void PathElement::SetIsQueue(bool isQueue) +{ + Type &= ~FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE; + if (isQueue) + Type |= FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE; +} + +bool PathElement::HasQueueBanner() const +{ + return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER) != 0; +} + +void PathElement::SetHasQueueBanner(bool hasQueueBanner) +{ + Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER; + if (hasQueueBanner) + Flags2 |= FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER; +} + +bool PathElement::IsBroken() const +{ + return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN) != 0; +} + +void PathElement::SetIsBroken(bool isBroken) +{ + if (isBroken) + { + Flags2 |= FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN; + } + else + { + Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN; + } +} + +bool PathElement::IsBlockedByVehicle() const +{ + return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE) != 0; +} + +void PathElement::SetIsBlockedByVehicle(bool isBlocked) +{ + if (isBlocked) + { + Flags2 |= FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE; + } + else + { + Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE; + } +} + +::StationIndex PathElement::GetStationIndex() const +{ + return StationIndex; +} + +void PathElement::SetStationIndex(::StationIndex newStationIndex) +{ + StationIndex = newStationIndex; +} + +bool PathElement::IsWide() const +{ + return (Type & FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE) != 0; +} + +void PathElement::SetWide(bool isWide) +{ + Type &= ~FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE; + if (isWide) + Type |= FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE; +} + +bool PathElement::HasAddition() const +{ + return Additions != 0; +} + +uint8_t PathElement::GetAddition() const +{ + return Additions; +} + +ObjectEntryIndex PathElement::GetAdditionEntryIndex() const +{ + // `Additions` is set to 0 when there is no addition, so the value 1 corresponds with path addition slot 0, etc. + return GetAddition() - 1; +} + +const PathAdditionEntry* PathElement::GetAdditionEntry() const +{ + if (!HasAddition()) + return nullptr; + return OpenRCT2::ObjectManager::GetObjectEntry(GetAdditionEntryIndex()); +} + +void PathElement::SetAddition(uint8_t newAddition) +{ + Additions = newAddition; +} + +void PathElement::SetAdditionEntryIndex(ObjectEntryIndex entryIndex) +{ + // `Additions` is set to 0 when there is no addition, so the value 1 corresponds with path addition slot 0, etc. + Additions = entryIndex + 1; +} + +bool PathElement::AdditionIsGhost() const +{ + return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST) != 0; +} + +void PathElement::SetAdditionIsGhost(bool isGhost) +{ + Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST; + if (isGhost) + Flags2 |= FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST; +} + +ObjectEntryIndex PathElement::GetLegacyPathEntryIndex() const +{ + if (Flags2 & FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY) + return SurfaceIndex; + + return OBJECT_ENTRY_INDEX_NULL; +} + +const FootpathObject* PathElement::GetLegacyPathEntry() const +{ + return GetLegacyFootpathEntry(GetLegacyPathEntryIndex()); +} + +void PathElement::SetLegacyPathEntryIndex(ObjectEntryIndex newIndex) +{ + SurfaceIndex = newIndex; + RailingsIndex = OBJECT_ENTRY_INDEX_NULL; + Flags2 |= FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY; +} + +bool PathElement::HasLegacyPathEntry() const +{ + return (Flags2 & FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY) != 0; +} + +const PathSurfaceDescriptor* PathElement::GetSurfaceDescriptor() const +{ + if (HasLegacyPathEntry()) + { + const auto* legacyPathEntry = GetLegacyPathEntry(); + if (legacyPathEntry == nullptr) + return nullptr; + + if (IsQueue()) + return &legacyPathEntry->GetQueueSurfaceDescriptor(); + + return &legacyPathEntry->GetPathSurfaceDescriptor(); + } + + const auto* surfaceEntry = GetSurfaceEntry(); + if (surfaceEntry == nullptr) + return nullptr; + + return &surfaceEntry->GetDescriptor(); +} + +const PathRailingsDescriptor* PathElement::GetRailingsDescriptor() const +{ + if (HasLegacyPathEntry()) + { + const auto* legacyPathEntry = GetLegacyPathEntry(); + if (legacyPathEntry == nullptr) + return nullptr; + + return &legacyPathEntry->GetPathRailingsDescriptor(); + } + + const auto* railingsEntry = GetRailingsEntry(); + if (railingsEntry == nullptr) + return nullptr; + + return &railingsEntry->GetDescriptor(); +} + +ObjectEntryIndex PathElement::GetSurfaceEntryIndex() const +{ + if (Flags2 & FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY) + return OBJECT_ENTRY_INDEX_NULL; + + return SurfaceIndex; +} + +const FootpathSurfaceObject* PathElement::GetSurfaceEntry() const +{ + auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); + return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathSurface, GetSurfaceEntryIndex())); +} + +void PathElement::SetSurfaceEntryIndex(ObjectEntryIndex newIndex) +{ + SurfaceIndex = newIndex; + Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY; +} + +ObjectEntryIndex PathElement::GetRailingsEntryIndex() const +{ + if (Flags2 & FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY) + return OBJECT_ENTRY_INDEX_NULL; + + return RailingsIndex; +} + +const FootpathRailingsObject* PathElement::GetRailingsEntry() const +{ + auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); + return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathRailings, GetRailingsEntryIndex())); +} + +void PathElement::SetRailingsEntryIndex(ObjectEntryIndex newEntryIndex) +{ + RailingsIndex = newEntryIndex; + Flags2 &= ~FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY; +} + +uint8_t PathElement::GetQueueBannerDirection() const +{ + return ((Type & FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK) >> 6); +} + +void PathElement::SetQueueBannerDirection(uint8_t direction) +{ + Type &= ~FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK; + Type |= (direction << 6); +} + +bool PathElement::ShouldDrawPathOverSupports() const +{ + // TODO: make this an actual decision of the tile element. + return (GetRailingsDescriptor()->Flags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS); +} + +void PathElement::SetShouldDrawPathOverSupports(bool on) +{ + LOG_VERBOSE("Setting 'draw path over supports' to %d", static_cast(on)); +} diff --git a/src/openrct2/world/tile_element/PathElement.h b/src/openrct2/world/tile_element/PathElement.h new file mode 100644 index 0000000000..bb3c759f13 --- /dev/null +++ b/src/openrct2/world/tile_element/PathElement.h @@ -0,0 +1,153 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../Identifiers.h" +#include "TileElementBase.h" + +class FootpathObject; +class FootpathRailingsObject; +class FootpathSurfaceObject; +struct PathAdditionEntry; +struct PathRailingsDescriptor; +struct PathSurfaceDescriptor; + +using ObjectEntryIndex = uint16_t; + +// Masks for values stored in TileElement.type +enum +{ + FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE = (1 << 0), + FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE = (1 << 1), + FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK = (1 << 6) | (1 << 7), +}; + +// Masks and flags for values stored in TileElement.properties.path.type +enum +{ + FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK = (1 << 0) | (1 << 1), + FOOTPATH_PROPERTIES_FLAG_IS_SLOPED = (1 << 2), + FOOTPATH_PROPERTIES_FLAG_HAS_QUEUE_BANNER = (1 << 3), + FOOTPATH_PROPERTIES_TYPE_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7), +}; + +// Masks and flags for values stored in TileElement.properties.path.edges +enum +{ + FOOTPATH_PROPERTIES_EDGES_EDGES_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3), + FOOTPATH_PROPERTIES_EDGES_CORNERS_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7), +}; + +enum +{ + FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED = 1 << 0, + FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER = (1 << 1), + FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST = (1 << 2), + FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE = (1 << 3), + FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN = (1 << 4), + FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY = (1 << 5), + FOOTPATH_ELEMENT_FLAGS2_HAS_JUNCTION_RAILINGS = (1 << 6), +}; + +#pragma pack(push, 1) +struct PathElement : TileElementBase +{ + static constexpr TileElementType ElementType = TileElementType::Path; + +private: + ObjectEntryIndex SurfaceIndex; // 5 + ObjectEntryIndex RailingsIndex; // 7 + uint8_t Additions; // 9 (0 means no addition) + uint8_t EdgesAndCorners; // 10 (edges in lower 4 bits, corners in upper 4) + uint8_t Flags2; // 11 + uint8_t SlopeDirection; // 12 + union + { + uint8_t AdditionStatus; // 13, only used for litter bins + RideId rideIndex; // 13 + }; + ::StationIndex StationIndex; // 15 + +public: + ObjectEntryIndex GetLegacyPathEntryIndex() const; + const FootpathObject* GetLegacyPathEntry() const; + void SetLegacyPathEntryIndex(ObjectEntryIndex newIndex); + bool HasLegacyPathEntry() const; + + ObjectEntryIndex GetSurfaceEntryIndex() const; + const FootpathSurfaceObject* GetSurfaceEntry() const; + void SetSurfaceEntryIndex(ObjectEntryIndex newIndex); + + ObjectEntryIndex GetRailingsEntryIndex() const; + const FootpathRailingsObject* GetRailingsEntry() const; + void SetRailingsEntryIndex(ObjectEntryIndex newIndex); + + const PathSurfaceDescriptor* GetSurfaceDescriptor() const; + const PathRailingsDescriptor* GetRailingsDescriptor() const; + + uint8_t GetQueueBannerDirection() const; + void SetQueueBannerDirection(uint8_t direction); + + bool IsSloped() const; + void SetSloped(bool isSloped); + + bool HasJunctionRailings() const; + void SetJunctionRailings(bool hasJunctionRailings); + + Direction GetSlopeDirection() const; + void SetSlopeDirection(Direction newSlope); + + RideId GetRideIndex() const; + void SetRideIndex(RideId newRideIndex); + + ::StationIndex GetStationIndex() const; + void SetStationIndex(::StationIndex newStationIndex); + + bool IsWide() const; + void SetWide(bool isWide); + + bool IsQueue() const; + void SetIsQueue(bool isQueue); + bool HasQueueBanner() const; + void SetHasQueueBanner(bool hasQueueBanner); + + bool IsBroken() const; + void SetIsBroken(bool isBroken); + + bool IsBlockedByVehicle() const; + void SetIsBlockedByVehicle(bool isBlocked); + + uint8_t GetEdges() const; + void SetEdges(uint8_t newEdges); + uint8_t GetCorners() const; + void SetCorners(uint8_t newCorners); + uint8_t GetEdgesAndCorners() const; + void SetEdgesAndCorners(uint8_t newEdgesAndCorners); + + bool HasAddition() const; + uint8_t GetAddition() const; + ObjectEntryIndex GetAdditionEntryIndex() const; + const PathAdditionEntry* GetAdditionEntry() const; + void SetAddition(uint8_t newAddition); + void SetAdditionEntryIndex(ObjectEntryIndex entryIndex); + + bool AdditionIsGhost() const; + void SetAdditionIsGhost(bool isGhost); + + uint8_t GetAdditionStatus() const; + void SetAdditionStatus(uint8_t newStatus); + + bool ShouldDrawPathOverSupports() const; + void SetShouldDrawPathOverSupports(bool on); + + bool IsLevelCrossing(const CoordsXY& coords) const; +}; +static_assert(sizeof(PathElement) == kTileElementSize); +#pragma pack(pop) diff --git a/src/openrct2/world/SmallScenery.cpp b/src/openrct2/world/tile_element/SmallSceneryElement.cpp similarity index 84% rename from src/openrct2/world/SmallScenery.cpp rename to src/openrct2/world/tile_element/SmallSceneryElement.cpp index ffef941662..4109953518 100644 --- a/src/openrct2/world/SmallScenery.cpp +++ b/src/openrct2/world/tile_element/SmallSceneryElement.cpp @@ -7,24 +7,23 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ -#include "SmallScenery.h" +#include "SmallSceneryElement.h" -#include "../Cheats.h" -#include "../Context.h" -#include "../Game.h" -#include "../OpenRCT2.h" -#include "../management/Finance.h" -#include "../network/network.h" -#include "../object/ObjectEntryManager.h" -#include "../object/ObjectManager.h" -#include "../object/SmallSceneryEntry.h" -#include "../ride/TrackDesign.h" -#include "Footpath.h" -#include "Map.h" -#include "MapAnimation.h" -#include "Park.h" -#include "Scenery.h" -#include "Surface.h" +#include "../../Cheats.h" +#include "../../Context.h" +#include "../../Game.h" +#include "../../OpenRCT2.h" +#include "../../management/Finance.h" +#include "../../network/network.h" +#include "../../object/ObjectEntryManager.h" +#include "../../object/ObjectManager.h" +#include "../../object/SmallSceneryEntry.h" +#include "../../ride/TrackDesign.h" +#include "../Footpath.h" +#include "../Map.h" +#include "../MapAnimation.h" +#include "../Park.h" +#include "../Scenery.h" #include diff --git a/src/openrct2/world/tile_element/SmallSceneryElement.h b/src/openrct2/world/tile_element/SmallSceneryElement.h new file mode 100644 index 0000000000..a025314025 --- /dev/null +++ b/src/openrct2/world/tile_element/SmallSceneryElement.h @@ -0,0 +1,57 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../interface/Colour.h" +#include "../../object/ObjectTypes.h" +#include "../../object/SmallSceneryEntry.h" +#include "TileElementBase.h" + +enum +{ + MAP_ELEM_SMALL_SCENERY_FLAGS2_NEEDS_SUPPORTS = (1 << 0), +}; + +#pragma pack(push, 1) +struct SmallSceneryElement : TileElementBase +{ + static constexpr TileElementType ElementType = TileElementType::SmallScenery; + +private: + ObjectEntryIndex entryIndex; // 5 + uint8_t age; // 7 + uint8_t Colour[3]; // 8 + uint8_t Flags2; // B +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" + uint8_t Pad0B[4]; +#pragma clang diagnostic pop + +public: + ObjectEntryIndex GetEntryIndex() const; + void SetEntryIndex(ObjectEntryIndex newIndex); + const SmallSceneryEntry* GetEntry() const; + uint8_t GetAge() const; + void SetAge(uint8_t newAge); + void IncreaseAge(const CoordsXY& sceneryPos); + uint8_t GetSceneryQuadrant() const; + void SetSceneryQuadrant(uint8_t newQuadrant); + colour_t GetPrimaryColour() const; + void SetPrimaryColour(colour_t colour); + colour_t GetSecondaryColour() const; + void SetSecondaryColour(colour_t colour); + colour_t GetTertiaryColour() const; + void SetTertiaryColour(colour_t colour); + bool NeedsSupports() const; + void SetNeedsSupports(); + void UpdateAge(const CoordsXY& sceneryPos); +}; +static_assert(sizeof(SmallSceneryElement) == kTileElementSize); +#pragma pack(pop) diff --git a/src/openrct2/world/Surface.cpp b/src/openrct2/world/tile_element/SurfaceElement.cpp similarity index 94% rename from src/openrct2/world/Surface.cpp rename to src/openrct2/world/tile_element/SurfaceElement.cpp index 61cb6bde17..aba3d12553 100644 --- a/src/openrct2/world/Surface.cpp +++ b/src/openrct2/world/tile_element/SurfaceElement.cpp @@ -7,16 +7,16 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ -#include "Surface.h" +#include "SurfaceElement.h" -#include "../Context.h" -#include "../object/ObjectManager.h" -#include "../object/TerrainEdgeObject.h" -#include "../object/TerrainSurfaceObject.h" -#include "../scenario/Scenario.h" -#include "Location.hpp" -#include "Map.h" -#include "tile_element/Slope.h" +#include "../../Context.h" +#include "../../object/ObjectManager.h" +#include "../../object/TerrainEdgeObject.h" +#include "../../object/TerrainSurfaceObject.h" +#include "../../scenario/Scenario.h" +#include "../Map.h" +#include "Slope.h" +#include "TileElement.h" ObjectEntryIndex SurfaceElement::GetSurfaceObjectIndex() const { @@ -67,7 +67,7 @@ bool SurfaceElement::CanGrassGrow() const auto obj = objMgr.GetLoadedObject(ObjectType::TerrainSurface, surfaceStyle); if (obj != nullptr) { - auto surfaceObject = static_cast(obj); + const auto* surfaceObject = static_cast(obj); if (surfaceObject->Flags & TERRAIN_SURFACE_FLAGS::CAN_GROW) { return true; diff --git a/src/openrct2/world/tile_element/SurfaceElement.h b/src/openrct2/world/tile_element/SurfaceElement.h new file mode 100644 index 0000000000..4d4c3c63a9 --- /dev/null +++ b/src/openrct2/world/tile_element/SurfaceElement.h @@ -0,0 +1,92 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../object/TerrainEdgeObject.h" +#include "../../object/TerrainSurfaceObject.h" +#include "TileElementBase.h" + +enum +{ + SURFACE_ELEMENT_HAS_TRACK_THAT_NEEDS_WATER = (1 << 6), +}; + +enum GrassLength : uint8_t +{ + GRASS_LENGTH_MOWED, + GRASS_LENGTH_CLEAR_0, + GRASS_LENGTH_CLEAR_1, + GRASS_LENGTH_CLEAR_2, + GRASS_LENGTH_CLUMPS_0, + GRASS_LENGTH_CLUMPS_1, + GRASS_LENGTH_CLUMPS_2, +}; + +enum +{ + OWNERSHIP_UNOWNED = 0, + OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED = (1 << 4), + OWNERSHIP_OWNED = (1 << 5), + OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE = (1 << 6), + OWNERSHIP_AVAILABLE = (1 << 7) +}; + +constexpr uint8_t kTileElementSurfaceOwnershipMask = 0xF0; +constexpr uint8_t kTileElementSurfaceParkFenceMask = 0x0F; + +#pragma pack(push, 1) +struct SurfaceElement : TileElementBase +{ + static constexpr TileElementType ElementType = TileElementType::Surface; + +private: + uint8_t Slope; + uint8_t WaterHeight; + uint8_t GrassLength; + uint8_t Ownership; + uint8_t SurfaceStyle; + uint8_t EdgeObjectIndex; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" + uint8_t Pad0B[5]; +#pragma clang diagnostic pop + +public: + uint8_t GetSlope() const; + void SetSlope(uint8_t newSlope); + + ObjectEntryIndex GetSurfaceObjectIndex() const; + TerrainSurfaceObject* GetSurfaceObject() const; + void SetSurfaceObjectIndex(ObjectEntryIndex newStyle); + + ObjectEntryIndex GetEdgeObjectIndex() const; + TerrainEdgeObject* GetEdgeObject() const; + void SetEdgeObjectIndex(ObjectEntryIndex newStyle); + + bool CanGrassGrow() const; + uint8_t GetGrassLength() const; + void SetGrassLength(uint8_t newLength); + void SetGrassLengthAndInvalidate(uint8_t newLength, const CoordsXY& coords); + void UpdateGrassLength(const CoordsXY& coords); + + uint8_t GetOwnership() const; + void SetOwnership(uint8_t newOwnership); + + int32_t GetWaterHeight() const; + void SetWaterHeight(int32_t newWaterHeight); + + uint8_t GetParkFences() const; + void SetParkFences(uint8_t newParkFences); + + bool HasTrackThatNeedsWater() const; + void SetHasTrackThatNeedsWater(bool on); +}; +static_assert(sizeof(SurfaceElement) == kTileElementSize); +#pragma pack(pop) diff --git a/src/openrct2/world/TileElement.cpp b/src/openrct2/world/tile_element/TileElement.cpp similarity index 87% rename from src/openrct2/world/TileElement.cpp rename to src/openrct2/world/tile_element/TileElement.cpp index c5c98518de..bf730e0e2b 100644 --- a/src/openrct2/world/TileElement.cpp +++ b/src/openrct2/world/tile_element/TileElement.cpp @@ -9,34 +9,20 @@ #include "TileElement.h" -#include "../Diagnostic.h" -#include "../core/Guard.hpp" -#include "../interface/Window.h" -#include "../object/LargeSceneryEntry.h" -#include "../object/WallSceneryEntry.h" -#include "../ride/Track.h" -#include "Banner.h" -#include "Location.hpp" -#include "Scenery.h" -#include "tile_element/BannerElement.h" -#include "tile_element/EntranceElement.h" -#include "tile_element/Slope.h" -#include "tile_element/TrackElement.h" -#include "tile_element/WallElement.h" +#include "../../Diagnostic.h" +#include "../../core/Guard.hpp" +#include "../../interface/Window.h" +#include "../../interface/WindowClasses.h" +#include "../Map.h" +#include "BannerElement.h" +#include "EntranceElement.h" +#include "LargeSceneryElement.h" +#include "PathElement.h" +#include "TrackElement.h" +#include "WallElement.h" using namespace OpenRCT2; -bool TileElementIsUnderground(TileElement* tileElement) -{ - do - { - tileElement++; - if ((tileElement - 1)->IsLastForTile()) - return false; - } while (tileElement->GetType() != TileElementType::Surface); - return true; -} - BannerIndex TileElement::GetBannerIndex() const { switch (GetType()) @@ -120,3 +106,14 @@ void TileElement::ClearAs(TileElementType newType) std::fill_n(Pad05, sizeof(Pad05), 0x00); std::fill_n(Pad08, sizeof(Pad08), 0x00); } + +bool TileElementIsUnderground(TileElement* tileElement) +{ + do + { + tileElement++; + if ((tileElement - 1)->IsLastForTile()) + return false; + } while (tileElement->GetType() != TileElementType::Surface); + return true; +} diff --git a/src/openrct2/world/tile_element/TileElement.h b/src/openrct2/world/tile_element/TileElement.h new file mode 100644 index 0000000000..6d1bdce5e9 --- /dev/null +++ b/src/openrct2/world/tile_element/TileElement.h @@ -0,0 +1,38 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../Identifiers.h" +#include "../Banner.h" +#include "TileElementBase.h" + +#pragma pack(push, 1) +/** + * Map element structure + * size: 0x10 + */ +struct TileElement : public TileElementBase +{ + uint8_t Pad05[3]; + uint8_t Pad08[8]; + + void ClearAs(TileElementType newType); + + RideId GetRideIndex() const; + + void SetBannerIndex(BannerIndex newIndex); + void RemoveBannerEntry(); + BannerIndex GetBannerIndex() const; +}; +static_assert(sizeof(TileElement) == kTileElementSize); + +bool TileElementIsUnderground(TileElement* tileElement); + +#pragma pack(pop) diff --git a/src/openrct2/world/tile_element/TileElementBase.cpp b/src/openrct2/world/tile_element/TileElementBase.cpp index 9e8a1215cb..48e2578113 100644 --- a/src/openrct2/world/tile_element/TileElementBase.cpp +++ b/src/openrct2/world/tile_element/TileElementBase.cpp @@ -7,10 +7,17 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ +#include "TileElementBase.h" + +#include "../../util/Util.h" #include "../Map.h" -#include "../TileElement.h" #include "BannerElement.h" #include "EntranceElement.h" +#include "LargeSceneryElement.h" +#include "PathElement.h" +#include "SmallSceneryElement.h" +#include "SurfaceElement.h" +#include "TileElement.h" #include "TrackElement.h" #include "WallElement.h" @@ -122,13 +129,13 @@ void TileElementBase::SetClearanceZ(int32_t newZ) uint8_t TileElementBase::GetOwner() const { - return Owner & OWNER_MASK; + return Owner & kTileElementOwnerMask; } void TileElementBase::SetOwner(uint8_t newOwner) { - Owner &= ~OWNER_MASK; - Owner |= (newOwner & OWNER_MASK); + Owner &= ~kTileElementOwnerMask; + Owner |= (newOwner & kTileElementOwnerMask); } const SurfaceElement* TileElementBase::AsSurface() const diff --git a/src/openrct2/world/tile_element/TileElementBase.h b/src/openrct2/world/tile_element/TileElementBase.h new file mode 100644 index 0000000000..a57a45de00 --- /dev/null +++ b/src/openrct2/world/tile_element/TileElementBase.h @@ -0,0 +1,120 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../Location.hpp" +#include "TileElementType.h" + +#include + +constexpr uint8_t kTileElementSize = 16; +constexpr uint8_t kMaxTileElementHeight = 255; +constexpr uint8_t kTileElementOwnerMask = 0b00001111; +constexpr uint8_t kTileElementQuadrantMask = 0b11000000; +constexpr uint8_t kTileElementTypeMask = 0b00111100; +constexpr uint8_t kTileElementDirectionMask = 0b00000011; +constexpr uint8_t kTileElementOccupiedQuadrantsMask = 0b00001111; + +enum +{ + TILE_ELEMENT_DIRECTION_WEST, + TILE_ELEMENT_DIRECTION_NORTH, + TILE_ELEMENT_DIRECTION_EAST, + TILE_ELEMENT_DIRECTION_SOUTH +}; + +enum +{ + TILE_ELEMENT_FLAG_GHOST = (1 << 4), + TILE_ELEMENT_FLAG_INVISIBLE = (1 << 5), + TILE_ELEMENT_FLAG_LAST_TILE = (1 << 7) +}; + +struct TileElement; +struct SurfaceElement; +struct PathElement; +struct TrackElement; +struct SmallSceneryElement; +struct LargeSceneryElement; +struct WallElement; +struct EntranceElement; +struct BannerElement; + +#pragma pack(push, 1) +struct TileElementBase +{ + uint8_t Type; // 0 + uint8_t Flags; // 1. Upper nibble: flags. Lower nibble: occupied quadrants (one bit per quadrant). + uint8_t BaseHeight; // 2 + uint8_t ClearanceHeight; // 3 + uint8_t Owner; // 4 + + void Remove(); + + TileElementType GetType() const; + void SetType(TileElementType newType); + + Direction GetDirection() const; + void SetDirection(Direction direction); + Direction GetDirectionWithOffset(uint8_t offset) const; + + bool IsLastForTile() const; + void SetLastForTile(bool on); + bool IsGhost() const; + void SetGhost(bool isGhost); + bool IsInvisible() const; + void SetInvisible(bool on); + + uint8_t GetOccupiedQuadrants() const; + void SetOccupiedQuadrants(uint8_t quadrants); + + int32_t GetBaseZ() const; + void SetBaseZ(int32_t newZ); + + int32_t GetClearanceZ() const; + void SetClearanceZ(int32_t newZ); + + uint8_t GetOwner() const; + void SetOwner(uint8_t newOwner); + + template const TType* as() const + { + if constexpr (std::is_same_v) + return reinterpret_cast(this); + else + return GetType() == TType::ElementType ? reinterpret_cast(this) : nullptr; + } + + template TType* as() + { + if constexpr (std::is_same_v) + return reinterpret_cast(this); + else + return GetType() == TType::ElementType ? reinterpret_cast(this) : nullptr; + } + + const SurfaceElement* AsSurface() const; + SurfaceElement* AsSurface(); + const PathElement* AsPath() const; + PathElement* AsPath(); + const TrackElement* AsTrack() const; + TrackElement* AsTrack(); + const SmallSceneryElement* AsSmallScenery() const; + SmallSceneryElement* AsSmallScenery(); + const LargeSceneryElement* AsLargeScenery() const; + LargeSceneryElement* AsLargeScenery(); + const WallElement* AsWall() const; + WallElement* AsWall(); + const EntranceElement* AsEntrance() const; + EntranceElement* AsEntrance(); + const BannerElement* AsBanner() const; + BannerElement* AsBanner(); +}; +#pragma pack(pop) diff --git a/src/openrct2/world/tile_element/TrackElement.h b/src/openrct2/world/tile_element/TrackElement.h index 460190be10..bec0b0c443 100644 --- a/src/openrct2/world/tile_element/TrackElement.h +++ b/src/openrct2/world/tile_element/TrackElement.h @@ -9,7 +9,16 @@ #pragma once -#include "../TileElement.h" +#include "../../Identifiers.h" +#include "TileElementBase.h" + +using ride_type_t = uint16_t; +enum class RideColourScheme : uint8_t; + +namespace OpenRCT2 +{ + enum class TrackElemType : uint16_t; +} enum { diff --git a/src/openrct2/world/tile_element/WallElement.h b/src/openrct2/world/tile_element/WallElement.h index bb179b4425..453acac36f 100644 --- a/src/openrct2/world/tile_element/WallElement.h +++ b/src/openrct2/world/tile_element/WallElement.h @@ -10,7 +10,11 @@ #pragma once #include "../../Identifiers.h" -#include "../TileElement.h" +#include "../../interface/Colour.h" +#include "../../object/ObjectTypes.h" +#include "../../object/WallSceneryEntry.h" +#include "../Banner.h" +#include "TileElementBase.h" #include diff --git a/test/tests/Pathfinding.cpp b/test/tests/Pathfinding.cpp index a9d84a5407..7e08f5422d 100644 --- a/test/tests/Pathfinding.cpp +++ b/test/tests/Pathfinding.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/test/tests/TileElements.cpp b/test/tests/TileElements.cpp index 41c18c4501..de1b1cf156 100644 --- a/test/tests/TileElements.cpp +++ b/test/tests/TileElements.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include using namespace OpenRCT2; diff --git a/test/tests/TileElementsView.cpp b/test/tests/TileElementsView.cpp index fb880e1f5f..ffcc93bdd8 100644 --- a/test/tests/TileElementsView.cpp +++ b/test/tests/TileElementsView.cpp @@ -20,6 +20,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include From 9eb6ee2417a830c52a91aa79011c6047004b3356 Mon Sep 17 00:00:00 2001 From: mrmbernardi Date: Wed, 16 Oct 2024 07:03:38 +1100 Subject: [PATCH 34/97] Fix UB from unaligned load of RLE line offsets --- src/openrct2/drawing/Drawing.Sprite.RLE.cpp | 7 ++++--- src/openrct2/interface/Viewport.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/openrct2/drawing/Drawing.Sprite.RLE.cpp b/src/openrct2/drawing/Drawing.Sprite.RLE.cpp index 1e4d675535..defed692ee 100644 --- a/src/openrct2/drawing/Drawing.Sprite.RLE.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.RLE.cpp @@ -15,8 +15,7 @@ template static void FASTCALL DrawRLESpriteMagnify(DrawPixelInfo& dpi, const DrawSpriteArgs& args) { auto& paletteMap = args.PalMap; - auto lineOffsets = reinterpret_cast(args.SourceImage.offset); - auto src0 = args.SourceImage.offset; + auto imgData = args.SourceImage.offset; auto dst = args.DestinationBits; auto srcX = args.SrcX; auto srcY = args.SrcY; @@ -29,7 +28,9 @@ template static void FASTCALL DrawRLESpriteMagnify(DrawPix { uint8_t* nextDst = dst + dstLineWidth; const int32_t rowNum = zoom.ApplyTo(srcY + y); - const uint8_t* data8 = src0 + lineOffsets[rowNum]; + uint16_t lineOffset; + std::memcpy(&lineOffset, &imgData[rowNum * sizeof(uint16_t)], sizeof(uint16_t)); + const uint8_t* data8 = imgData + lineOffset; bool lastDataForLine = false; int32_t numPixels = 0; diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 64c5b6b4d0..ef05f4f5a6 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -1552,11 +1552,11 @@ static bool IsPixelPresentBMP( /** * rct2: 0x0067933B, 0x00679788, 0x00679C4A, 0x0067A117 */ -static bool IsPixelPresentRLE(const void* data, const int32_t x, const int32_t y) +static bool IsPixelPresentRLE(const uint8_t* imgData, const int32_t x, const int32_t y) { - const uint16_t* data16 = static_cast(data); - uint16_t startOffset = data16[y]; - const uint8_t* data8 = static_cast(data) + startOffset; + uint16_t lineOffset; + std::memcpy(&lineOffset, &imgData[y * sizeof(uint16_t)], sizeof(uint16_t)); + const uint8_t* data8 = imgData + lineOffset; bool lastDataLine = false; while (!lastDataLine) From 5934dc63800776a35c3a3fb95368b9ef540f2baf Mon Sep 17 00:00:00 2001 From: Duncan Date: Wed, 16 Oct 2024 09:50:38 +0100 Subject: [PATCH 35/97] Remove void* obj from RideEntry --- .../windows/EditorObjectSelection.cpp | 10 ++-- src/openrct2-ui/windows/NewRide.cpp | 45 +++++++++-------- src/openrct2/object/ObjectManager.cpp | 6 +-- src/openrct2/object/RideObject.cpp | 2 - src/openrct2/object/RideObject.h | 4 ++ src/openrct2/rct2/T6Importer.cpp | 9 ++-- src/openrct2/ride/RideEntry.h | 1 - .../scripting/bindings/object/ScObject.hpp | 48 +++++++++---------- 8 files changed, 60 insertions(+), 65 deletions(-) diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index 5a46c4b015..fea0a1c252 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -1275,19 +1275,19 @@ namespace OpenRCT2::Ui::Windows if (GetSelectedObjectType() == ObjectType::Ride) { auto* rideObject = reinterpret_cast(_loadedObject.get()); - const auto* rideEntry = reinterpret_cast(rideObject->GetLegacyData()); - if (rideEntry->shop_item[0] != ShopItem::None) + const auto& rideEntry = rideObject->GetEntry(); + if (rideEntry.shop_item[0] != ShopItem::None) { std::string sells = ""; - for (size_t i = 0; i < std::size(rideEntry->shop_item); i++) + for (size_t i = 0; i < std::size(rideEntry.shop_item); i++) { - if (rideEntry->shop_item[i] == ShopItem::None) + if (rideEntry.shop_item[i] == ShopItem::None) continue; if (!sells.empty()) sells += ", "; - sells += LanguageGetString(GetShopItemDescriptor(rideEntry->shop_item[i]).Naming.Plural); + sells += LanguageGetString(GetShopItemDescriptor(rideEntry.shop_item[i]).Naming.Plural); } auto ft = Formatter(); ft.Add(sells.c_str()); diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index 5ef6e9acff..490f2efba3 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -682,22 +682,23 @@ namespace OpenRCT2::Ui::Windows continue; // Ride entries - const auto* rideEntry = GetRideEntryByIndex(rideEntryIndex); + auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); + auto rideObj = static_cast(objMgr.GetLoadedObject(ObjectType::Ride, rideEntryIndex)); // Skip if the vehicle isn't the preferred vehicle for this generic track type if (!Config::Get().interface.ListRideVehiclesSeparately && !GetRideTypeDescriptor(rideType).HasFlag(RtdFlag::listVehiclesSeparately) - && highestVehiclePriority > rideEntry->BuildMenuPriority) + && highestVehiclePriority > rideObj->GetEntry().BuildMenuPriority) { continue; } - if (!IsFiltered(*rideEntry)) + if (!IsFiltered(*rideObj)) { continue; } - highestVehiclePriority = rideEntry->BuildMenuPriority; + highestVehiclePriority = rideObj->GetEntry().BuildMenuPriority; // Determines how and where to draw a button for this ride type/vehicle. if (Config::Get().interface.ListRideVehiclesSeparately @@ -729,7 +730,7 @@ namespace OpenRCT2::Ui::Windows else if (allowDrawingOverLastButton) { // Non-separate, draw over previous - if (rideType == rideEntry->ride_type[0]) + if (rideType == rideObj->GetEntry().ride_type[0]) { nextListItem--; nextListItem->Type = rideType; @@ -742,13 +743,13 @@ namespace OpenRCT2::Ui::Windows return nextListItem; } - bool IsFiltered(const RideObjectEntry& rideEntry) + bool IsFiltered(const RideObject& rideObject) { if (_filter.empty()) return true; - return IsFilterInRideType(rideEntry) || IsFilterInRideName(rideEntry) || IsFilterInIdentifier(rideEntry) - || IsFilterInAuthors(rideEntry) || IsFilterInFilename(rideEntry); + return IsFilterInRideType(rideObject.GetEntry()) || IsFilterInRideName(rideObject.GetEntry()) + || IsFilterInIdentifier(rideObject) || IsFilterInAuthors(rideObject) || IsFilterInFilename(rideObject); } bool IsFilterInRideType(const RideObjectEntry& rideEntry) @@ -763,30 +764,27 @@ namespace OpenRCT2::Ui::Windows return String::Contains(u8string_view(LanguageGetString(rideName)), _filter, true); } - bool IsFilterInAuthors(const RideObjectEntry& rideEntry) + bool IsFilterInAuthors(const RideObject& rideObject) { - auto rideObject = static_cast(rideEntry.obj); - auto authors = rideObject->GetAuthors(); + auto& authors = rideObject.GetAuthors(); - for (auto author : authors) + for (auto& author : authors) if (String::Contains(author, _filter, true)) return true; return false; } - bool IsFilterInIdentifier(const RideObjectEntry& rideEntry) + bool IsFilterInIdentifier(const RideObject& rideObject) { - auto rideObject = static_cast(rideEntry.obj); - auto objectName = rideObject->GetObjectEntry().GetName(); + auto objectName = rideObject.GetObjectEntry().GetName(); return String::Contains(objectName, _filter, true); } - bool IsFilterInFilename(const RideObjectEntry& rideEntry) + bool IsFilterInFilename(const RideObject& rideObject) { - auto rideObject = static_cast(rideEntry.obj); - auto repoItem = ObjectRepositoryFindObjectByEntry(&(rideObject->GetObjectEntry())); + auto repoItem = ObjectRepositoryFindObjectByEntry(&(rideObject.GetObjectEntry())); return String::Contains(repoItem->Path, _filter, true); } @@ -919,8 +917,10 @@ namespace OpenRCT2::Ui::Windows void DrawRideInformation(DrawPixelInfo& dpi, RideSelection item, const ScreenCoordsXY& screenPos, int32_t textWidth) { - const auto* rideEntry = GetRideEntryByIndex(item.EntryIndex); - RideNaming rideNaming = GetRideNaming(item.Type, *rideEntry); + auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); + auto rideObj = static_cast(objMgr.GetLoadedObject(ObjectType::Ride, item.EntryIndex)); + const auto& rideEntry = rideObj->GetEntry(); + RideNaming rideNaming = GetRideNaming(item.Type, rideEntry); auto ft = Formatter(); UpdateVehicleAvailability(item.Type); @@ -935,7 +935,7 @@ namespace OpenRCT2::Ui::Windows if (Config::Get().interface.ListRideVehiclesSeparately) { ft = Formatter(); - ft.Add(rideEntry->naming.Name); + ft.Add(rideEntry.naming.Name); DrawTextEllipsised( dpi, screenPos + ScreenCoordsXY{ 0, 39 }, WindowWidth - 2, STR_NEW_RIDE_VEHICLE_NAME, ft); } @@ -976,8 +976,7 @@ namespace OpenRCT2::Ui::Windows // Draw object author(s) if debugging tools are active if (Config::Get().general.DebuggingTools) { - auto rideObject = static_cast(rideEntry->obj); - auto repoItem = ObjectRepositoryFindObjectByEntry(&(rideObject->GetObjectEntry())); + auto repoItem = ObjectRepositoryFindObjectByEntry(&(rideObj->GetObjectEntry())); StringId authorStringId = repoItem->Authors.size() > 1 ? STR_AUTHORS_STRING : STR_AUTHOR_STRING; diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index 7c7e836be0..64cf37bf76 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -740,11 +740,9 @@ private: if (rideObject == nullptr) continue; - const auto* entry = static_cast(rideObject->GetLegacyData()); - if (entry == nullptr) - continue; + const auto& entry = rideObject->GetEntry(); - for (auto rideType : entry->ride_type) + for (auto rideType : entry.ride_type) { if (rideType < _rideTypeToObjectMap.size()) { diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index c6d02fdb26..5a96645fd8 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -265,8 +265,6 @@ void RideObject::ReadLegacy(IReadObjectContext* context, IStream* stream) void RideObject::Load() { - _legacyType.obj = this; - GetStringTable().Sort(); _legacyType.naming.Name = LanguageAllocateObjectString(GetName()); _legacyType.naming.Description = LanguageAllocateObjectString(GetDescription()); diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index aa8b0afbd4..bd3cea4dad 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -30,6 +30,10 @@ public: { return &_legacyType; } + const RideObjectEntry& GetEntry() const + { + return _legacyType; + } void ReadJson(IReadObjectContext* context, json_t& root) override; void ReadLegacy(IReadObjectContext* context, OpenRCT2::IStream* stream) override; diff --git a/src/openrct2/rct2/T6Importer.cpp b/src/openrct2/rct2/T6Importer.cpp index 913e8e3923..5bc7ffa78e 100644 --- a/src/openrct2/rct2/T6Importer.cpp +++ b/src/openrct2/rct2/T6Importer.cpp @@ -218,12 +218,9 @@ namespace OpenRCT2::RCT2 auto rawObject = ObjectRepositoryLoadObject(&td->trackAndVehicle.vehicleObject.Entry); if (rawObject != nullptr) { - const auto* rideEntry = static_cast( - static_cast(rawObject.get())->GetLegacyData()); - if (rideEntry != nullptr) - { - td->trackAndVehicle.rtdIndex = RCT2RideTypeToOpenRCT2RideType(td->trackAndVehicle.rtdIndex, *rideEntry); - } + const auto& rideEntry = static_cast(rawObject.get())->GetEntry(); + + td->trackAndVehicle.rtdIndex = RCT2RideTypeToOpenRCT2RideType(td->trackAndVehicle.rtdIndex, rideEntry); rawObject->Unload(); } } diff --git a/src/openrct2/ride/RideEntry.h b/src/openrct2/ride/RideEntry.h index 4e442365ce..250714e74a 100644 --- a/src/openrct2/ride/RideEntry.h +++ b/src/openrct2/ride/RideEntry.h @@ -72,7 +72,6 @@ struct RideObjectEntry uint8_t max_height; ShopItem shop_item[OpenRCT2::RCT2::ObjectLimits::MaxShopItemsPerRideEntry]; StringId capacity; - void* obj; uint8_t Clearance; const CarEntry* GetCar(size_t id) const diff --git a/src/openrct2/scripting/bindings/object/ScObject.hpp b/src/openrct2/scripting/bindings/object/ScObject.hpp index 59d37a957d..a7e09d08e5 100644 --- a/src/openrct2/scripting/bindings/object/ScObject.hpp +++ b/src/openrct2/scripting/bindings/object/ScObject.hpp @@ -488,7 +488,7 @@ namespace OpenRCT2::Scripting return 0; } - Object* GetObject() const + const RideObject* GetObject() const { auto& objManager = GetContext()->GetObjectManager(); return static_cast(objManager.GetLoadedObject(_objectType, _objectIndex)); @@ -499,7 +499,7 @@ namespace OpenRCT2::Scripting auto obj = GetObject(); if (obj != nullptr) { - auto rideEntry = static_cast(obj->GetLegacyData()); + auto rideEntry = &obj->GetEntry(); if (rideEntry != nullptr && _vehicleIndex < std::size(rideEntry->Cars)) { return rideEntry->GetCar(_vehicleIndex); @@ -567,7 +567,7 @@ namespace OpenRCT2::Scripting uint32_t firstImageId_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->images_offset; @@ -577,7 +577,7 @@ namespace OpenRCT2::Scripting uint32_t flags_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->flags; @@ -588,7 +588,7 @@ namespace OpenRCT2::Scripting std::vector rideType_get() const { std::vector result; - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { for (auto rideType : entry->ride_type) @@ -601,7 +601,7 @@ namespace OpenRCT2::Scripting uint8_t minCarsInTrain_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->min_cars_in_train; @@ -611,7 +611,7 @@ namespace OpenRCT2::Scripting uint8_t maxCarsInTrain_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->max_cars_in_train; @@ -621,7 +621,7 @@ namespace OpenRCT2::Scripting uint8_t carsPerFlatRide_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->cars_per_flat_ride; @@ -631,7 +631,7 @@ namespace OpenRCT2::Scripting uint8_t zeroCars_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->zero_cars; @@ -641,7 +641,7 @@ namespace OpenRCT2::Scripting uint8_t tabVehicle_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->TabCar; @@ -651,7 +651,7 @@ namespace OpenRCT2::Scripting uint8_t defaultVehicle_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->DefaultCar; @@ -661,7 +661,7 @@ namespace OpenRCT2::Scripting uint8_t frontVehicle_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->FrontCar; @@ -671,7 +671,7 @@ namespace OpenRCT2::Scripting uint8_t secondVehicle_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->SecondCar; @@ -681,7 +681,7 @@ namespace OpenRCT2::Scripting uint8_t rearVehicle_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->RearCar; @@ -691,7 +691,7 @@ namespace OpenRCT2::Scripting uint8_t thirdVehicle_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->ThirdCar; @@ -702,7 +702,7 @@ namespace OpenRCT2::Scripting std::vector> vehicles_get() const { std::vector> result; - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { for (size_t i = 0; i < std::size(entry->Cars); i++) @@ -715,7 +715,7 @@ namespace OpenRCT2::Scripting int8_t excitementMultiplier_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->excitement_multiplier; @@ -725,7 +725,7 @@ namespace OpenRCT2::Scripting int8_t intensityMultiplier_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->intensity_multiplier; @@ -735,7 +735,7 @@ namespace OpenRCT2::Scripting int8_t nauseaMultiplier_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->nausea_multiplier; @@ -745,7 +745,7 @@ namespace OpenRCT2::Scripting uint8_t maxHeight_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return entry->max_height; @@ -755,7 +755,7 @@ namespace OpenRCT2::Scripting uint8_t shopItem_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return EnumValue(entry->shop_item[0]); @@ -765,7 +765,7 @@ namespace OpenRCT2::Scripting uint8_t shopItemSecondary_get() const { - auto entry = GetLegacyData(); + auto entry = GetEntry(); if (entry != nullptr) { return EnumValue(entry->shop_item[1]); @@ -779,12 +779,12 @@ namespace OpenRCT2::Scripting return static_cast(ScObject::GetObject()); } - const RideObjectEntry* GetLegacyData() const + const RideObjectEntry* GetEntry() const { auto obj = GetObject(); if (obj != nullptr) { - return static_cast(obj->GetLegacyData()); + return &obj->GetEntry(); } return nullptr; } From 8063c5caa76bcb2d1db5559ba1df8e1e46c9c62e Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:12:25 +0200 Subject: [PATCH 36/97] Reduce casting for objects --- src/openrct2-ui/interface/LandTool.cpp | 8 ++++---- src/openrct2-ui/windows/EditorParkEntrance.cpp | 2 +- src/openrct2-ui/windows/Footpath.cpp | 2 +- src/openrct2-ui/windows/NewRide.cpp | 6 +++--- src/openrct2-ui/windows/Ride.cpp | 8 ++++---- src/openrct2/actions/SurfaceSetStyleAction.cpp | 2 +- src/openrct2/localisation/Formatting.cpp | 2 +- src/openrct2/object/AudioObject.h | 2 ++ src/openrct2/object/BannerObject.h | 2 ++ src/openrct2/object/EntranceObject.h | 2 ++ src/openrct2/object/FootpathObject.h | 2 ++ src/openrct2/object/FootpathRailingsObject.h | 2 ++ src/openrct2/object/FootpathSurfaceObject.h | 2 ++ src/openrct2/object/LargeSceneryObject.h | 2 ++ src/openrct2/object/MusicObject.h | 2 ++ src/openrct2/object/ObjectManager.h | 4 ++++ src/openrct2/object/PathAdditionObject.h | 2 ++ src/openrct2/object/PeepNamesObject.h | 2 ++ src/openrct2/object/RideObject.h | 2 ++ src/openrct2/object/SceneryGroupObject.h | 2 ++ src/openrct2/object/SmallSceneryObject.h | 2 ++ src/openrct2/object/StationObject.h | 2 ++ src/openrct2/object/TerrainEdgeObject.h | 2 ++ src/openrct2/object/TerrainSurfaceObject.h | 2 ++ src/openrct2/object/WallObject.h | 2 ++ src/openrct2/object/WaterObject.h | 2 ++ src/openrct2/ride/Ride.cpp | 6 +++--- src/openrct2/ride/RideAudio.cpp | 4 ++-- src/openrct2/scripting/bindings/object/ScObject.hpp | 10 ++++------ src/openrct2/world/Footpath.cpp | 2 +- src/openrct2/world/tile_element/EntranceElement.cpp | 4 ++-- src/openrct2/world/tile_element/PathElement.cpp | 4 ++-- src/openrct2/world/tile_element/SurfaceElement.cpp | 4 ++-- 33 files changed, 71 insertions(+), 33 deletions(-) diff --git a/src/openrct2-ui/interface/LandTool.cpp b/src/openrct2-ui/interface/LandTool.cpp index a52541b77b..aceeedf02d 100644 --- a/src/openrct2-ui/interface/LandTool.cpp +++ b/src/openrct2-ui/interface/LandTool.cpp @@ -60,7 +60,7 @@ void LandTool::ShowSurfaceStyleDropdown(WindowBase* w, Widget* widget, ObjectEnt auto itemIndex = 0; for (size_t i = 0; i < kMaxTerrainSurfaceObjects; i++) { - const auto surfaceObj = static_cast(objManager.GetLoadedObject(ObjectType::TerrainSurface, i)); + const auto surfaceObj = objManager.GetLoadedObject(i); // If fallback images are loaded, the RCT1 styles will just look like copies of already existing styles, so hide them. if (surfaceObj != nullptr && !surfaceObj->UsesFallbackImages()) { @@ -92,7 +92,7 @@ ObjectEntryIndex LandTool::GetSurfaceStyleFromDropdownIndex(size_t index) auto itemIndex = 0U; for (size_t i = 0; i < kMaxTerrainSurfaceObjects; i++) { - const auto surfaceObj = static_cast(objManager.GetLoadedObject(ObjectType::TerrainSurface, i)); + const auto surfaceObj = objManager.GetLoadedObject(i); // If fallback images are loaded, the RCT1 styles will just look like copies of already existing styles, so hide them. if (surfaceObj != nullptr && !surfaceObj->UsesFallbackImages()) { @@ -114,7 +114,7 @@ void LandTool::ShowEdgeStyleDropdown(WindowBase* w, Widget* widget, ObjectEntryI auto itemIndex = 0; for (size_t i = 0; i < kMaxTerrainEdgeObjects; i++) { - const auto edgeObj = static_cast(objManager.GetLoadedObject(ObjectType::TerrainEdge, i)); + const auto edgeObj = objManager.GetLoadedObject(i); // If fallback images are loaded, the RCT1 styles will just look like copies of already existing styles, so hide them. if (edgeObj != nullptr && !edgeObj->UsesFallbackImages()) { @@ -143,7 +143,7 @@ ObjectEntryIndex LandTool::GetEdgeStyleFromDropdownIndex(size_t index) auto itemIndex = 0U; for (size_t i = 0; i < kMaxTerrainEdgeObjects; i++) { - const auto edgeObj = static_cast(objManager.GetLoadedObject(ObjectType::TerrainEdge, i)); + const auto edgeObj = objManager.GetLoadedObject(i); // If fallback images are loaded, the RCT1 styles will just look like copies of already existing styles, so hide them. if (edgeObj != nullptr && !edgeObj->UsesFallbackImages()) { diff --git a/src/openrct2-ui/windows/EditorParkEntrance.cpp b/src/openrct2-ui/windows/EditorParkEntrance.cpp index fcaa1fdd42..05108e445e 100644 --- a/src/openrct2-ui/windows/EditorParkEntrance.cpp +++ b/src/openrct2-ui/windows/EditorParkEntrance.cpp @@ -79,7 +79,7 @@ namespace OpenRCT2::Ui::Windows for (ObjectEntryIndex objectIndex = 0; objectIndex < kMaxParkEntranceObjects; objectIndex++) { auto& objManager = GetContext()->GetObjectManager(); - auto* object = static_cast(objManager.GetLoadedObject(ObjectType::ParkEntrance, objectIndex)); + auto* object = objManager.GetLoadedObject(objectIndex); if (object != nullptr) { const auto* legacyData = reinterpret_cast(object->GetLegacyData()); diff --git a/src/openrct2-ui/windows/Footpath.cpp b/src/openrct2-ui/windows/Footpath.cpp index 2cefec0636..b6f0a551b6 100644 --- a/src/openrct2-ui/windows/Footpath.cpp +++ b/src/openrct2-ui/windows/Footpath.cpp @@ -715,7 +715,7 @@ namespace OpenRCT2::Ui::Windows for (ObjectEntryIndex i = 0; i < kMaxPathObjects; i++) { - auto* pathObj = static_cast(objManager.GetLoadedObject(ObjectType::Paths, i)); + auto* pathObj = objManager.GetLoadedObject(i); if (pathObj == nullptr) { continue; diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index 490f2efba3..ef4043e3d9 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -638,7 +638,7 @@ namespace OpenRCT2::Ui::Windows ImageIndex GetRideImage(RideSelection rideSelection) { auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - auto obj = static_cast(objMgr.GetLoadedObject(ObjectType::Ride, rideSelection.EntryIndex)); + auto obj = objMgr.GetLoadedObject(rideSelection.EntryIndex); return obj == nullptr ? ImageIndexUndefined : obj->GetPreviewImage(rideSelection.Type); } @@ -683,7 +683,7 @@ namespace OpenRCT2::Ui::Windows // Ride entries auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - auto rideObj = static_cast(objMgr.GetLoadedObject(ObjectType::Ride, rideEntryIndex)); + auto* rideObj = objMgr.GetLoadedObject(rideEntryIndex); // Skip if the vehicle isn't the preferred vehicle for this generic track type if (!Config::Get().interface.ListRideVehiclesSeparately @@ -918,7 +918,7 @@ namespace OpenRCT2::Ui::Windows void DrawRideInformation(DrawPixelInfo& dpi, RideSelection item, const ScreenCoordsXY& screenPos, int32_t textWidth) { auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - auto rideObj = static_cast(objMgr.GetLoadedObject(ObjectType::Ride, item.EntryIndex)); + const auto* rideObj = objMgr.GetLoadedObject(item.EntryIndex); const auto& rideEntry = rideObj->GetEntry(); RideNaming rideNaming = GetRideNaming(item.Type, rideEntry); auto ft = Formatter(); diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index a8d1b8363c..90038c6eed 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -2113,7 +2113,7 @@ namespace OpenRCT2::Ui::Windows for (ObjectEntryIndex i = 0; i < kMaxStationObjects; i++) { - auto stationObj = static_cast(objManager.GetLoadedObject(ObjectType::Station, i)); + auto stationObj = objManager.GetLoadedObject(i); if (stationObj != nullptr) { auto name = stationObj->NameStringId; @@ -5055,7 +5055,7 @@ namespace OpenRCT2::Ui::Windows static std::string GetMusicString(ObjectEntryIndex musicObjectIndex) { auto& objManager = GetContext()->GetObjectManager(); - auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, musicObjectIndex)); + auto musicObj = objManager.GetLoadedObject(musicObjectIndex); return LanguageGetString(musicObj->NameStringId); } @@ -5080,7 +5080,7 @@ namespace OpenRCT2::Ui::Windows auto& objManager = GetContext()->GetObjectManager(); for (ObjectEntryIndex i = 0; i < kMaxMusicObjects; i++) { - auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, i)); + auto musicObj = objManager.GetLoadedObject(i); if (musicObj != nullptr) { // Hide custom music if the WAV file does not exist @@ -5119,7 +5119,7 @@ namespace OpenRCT2::Ui::Windows auto numItems = musicOrder.size(); for (size_t i = 0; i < numItems; i++) { - auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, musicOrder[i])); + auto musicObj = objManager.GetLoadedObject(musicOrder[i]); gDropdownItems[i].Format = STR_DROPDOWN_MENU_LABEL; gDropdownItems[i].Args = musicObj->NameStringId; } diff --git a/src/openrct2/actions/SurfaceSetStyleAction.cpp b/src/openrct2/actions/SurfaceSetStyleAction.cpp index ac39d49afa..950f291521 100644 --- a/src/openrct2/actions/SurfaceSetStyleAction.cpp +++ b/src/openrct2/actions/SurfaceSetStyleAction.cpp @@ -67,7 +67,7 @@ GameActions::Result SurfaceSetStyleAction::Query() const if (_edgeStyle != OBJECT_ENTRY_INDEX_NULL) { - const auto edgeObj = static_cast(objManager.GetLoadedObject(ObjectType::TerrainEdge, _edgeStyle)); + const auto edgeObj = objManager.GetLoadedObject(_edgeStyle); if (edgeObj == nullptr) { diff --git a/src/openrct2/localisation/Formatting.cpp b/src/openrct2/localisation/Formatting.cpp index fd66a30c8d..24df9fe32f 100644 --- a/src/openrct2/localisation/Formatting.cpp +++ b/src/openrct2/localisation/Formatting.cpp @@ -292,7 +292,7 @@ namespace OpenRCT2 if (IsRealNameStringId(id)) { auto& objManager = GetContext()->GetObjectManager(); - auto* peepNamesObj = static_cast(objManager.GetLoadedObject(ObjectType::PeepNames, 0)); + auto* peepNamesObj = objManager.GetLoadedObject(0); if (peepNamesObj != nullptr) { auto realNameIndex = id - kRealNameStart; diff --git a/src/openrct2/object/AudioObject.h b/src/openrct2/object/AudioObject.h index edd9dcee36..32c7aef5ec 100644 --- a/src/openrct2/object/AudioObject.h +++ b/src/openrct2/object/AudioObject.h @@ -23,6 +23,8 @@ private: AudioSampleTable _loadedSampleTable; public: + static constexpr ObjectType objectType = ObjectType::Audio; + void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; void Unload() override; diff --git a/src/openrct2/object/BannerObject.h b/src/openrct2/object/BannerObject.h index 08df37497f..18c077a987 100644 --- a/src/openrct2/object/BannerObject.h +++ b/src/openrct2/object/BannerObject.h @@ -19,6 +19,8 @@ private: BannerSceneryEntry _legacyType = {}; public: + static constexpr ObjectType objectType = ObjectType::Banners; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/EntranceObject.h b/src/openrct2/object/EntranceObject.h index 0abce30b8f..ce5fb15f28 100644 --- a/src/openrct2/object/EntranceObject.h +++ b/src/openrct2/object/EntranceObject.h @@ -20,6 +20,8 @@ private: EntranceEntry _legacyType = {}; public: + static constexpr ObjectType objectType = ObjectType::ParkEntrance; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/FootpathObject.h b/src/openrct2/object/FootpathObject.h index b6aba5f698..cce65563fd 100644 --- a/src/openrct2/object/FootpathObject.h +++ b/src/openrct2/object/FootpathObject.h @@ -22,6 +22,8 @@ private: PathRailingsDescriptor _pathRailingsDescriptor = {}; public: + static constexpr ObjectType objectType = ObjectType::Paths; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/FootpathRailingsObject.h b/src/openrct2/object/FootpathRailingsObject.h index 961d07c90e..028534f404 100644 --- a/src/openrct2/object/FootpathRailingsObject.h +++ b/src/openrct2/object/FootpathRailingsObject.h @@ -26,6 +26,8 @@ public: PathRailingsDescriptor _descriptor = {}; public: + static constexpr ObjectType objectType = ObjectType::FootpathRailings; + void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; void Unload() override; diff --git a/src/openrct2/object/FootpathSurfaceObject.h b/src/openrct2/object/FootpathSurfaceObject.h index 782b930d23..08aea17fb6 100644 --- a/src/openrct2/object/FootpathSurfaceObject.h +++ b/src/openrct2/object/FootpathSurfaceObject.h @@ -22,6 +22,8 @@ public: PathSurfaceDescriptor _descriptor = {}; public: + static constexpr ObjectType objectType = ObjectType::FootpathSurface; + void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; void Unload() override; diff --git a/src/openrct2/object/LargeSceneryObject.h b/src/openrct2/object/LargeSceneryObject.h index bba6e815de..f7174fc1ac 100644 --- a/src/openrct2/object/LargeSceneryObject.h +++ b/src/openrct2/object/LargeSceneryObject.h @@ -24,6 +24,8 @@ private: std::unique_ptr _3dFont; public: + static constexpr ObjectType objectType = ObjectType::LargeScenery; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/MusicObject.h b/src/openrct2/object/MusicObject.h index e71a81600e..274353736c 100644 --- a/src/openrct2/object/MusicObject.h +++ b/src/openrct2/object/MusicObject.h @@ -53,6 +53,8 @@ private: uint32_t _previewImageId{}; public: + static constexpr ObjectType objectType = ObjectType::Music; + StringId NameStringId{}; void ReadJson(IReadObjectContext* context, json_t& root) override; diff --git a/src/openrct2/object/ObjectManager.h b/src/openrct2/object/ObjectManager.h index 64c2eda918..98e0fb301e 100644 --- a/src/openrct2/object/ObjectManager.h +++ b/src/openrct2/object/ObjectManager.h @@ -26,6 +26,10 @@ struct IObjectManager } virtual Object* GetLoadedObject(ObjectType objectType, size_t index) = 0; + template TClass* GetLoadedObject(size_t index) + { + return static_cast(GetLoadedObject(TClass::objectType, index)); + } virtual Object* GetLoadedObject(const ObjectEntryDescriptor& entry) = 0; virtual ObjectEntryIndex GetLoadedObjectEntryIndex(std::string_view identifier) = 0; virtual ObjectEntryIndex GetLoadedObjectEntryIndex(const ObjectEntryDescriptor& descriptor) = 0; diff --git a/src/openrct2/object/PathAdditionObject.h b/src/openrct2/object/PathAdditionObject.h index bb24cf25ec..505cdc08f8 100644 --- a/src/openrct2/object/PathAdditionObject.h +++ b/src/openrct2/object/PathAdditionObject.h @@ -18,6 +18,8 @@ private: PathAdditionEntry _legacyType = {}; public: + static constexpr ObjectType objectType = ObjectType::PathAdditions; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/PeepNamesObject.h b/src/openrct2/object/PeepNamesObject.h index fc3fa120b1..919708c113 100644 --- a/src/openrct2/object/PeepNamesObject.h +++ b/src/openrct2/object/PeepNamesObject.h @@ -22,6 +22,8 @@ private: std::vector _surnames; public: + static constexpr ObjectType objectType = ObjectType::PeepNames; + void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; void Unload() override; diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index bd3cea4dad..110dc3fb07 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -26,6 +26,8 @@ private: std::vector> _peepLoadingWaypoints[OpenRCT2::RCT2::ObjectLimits::MaxCarTypesPerRideEntry]; public: + static constexpr ObjectType objectType = ObjectType::Ride; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/SceneryGroupObject.h b/src/openrct2/object/SceneryGroupObject.h index a07c86c9be..91c270043e 100644 --- a/src/openrct2/object/SceneryGroupObject.h +++ b/src/openrct2/object/SceneryGroupObject.h @@ -25,6 +25,8 @@ private: std::vector _items; public: + static constexpr ObjectType objectType = ObjectType::SceneryGroup; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/SmallSceneryObject.h b/src/openrct2/object/SmallSceneryObject.h index fe2051bd18..906fa776a1 100644 --- a/src/openrct2/object/SmallSceneryObject.h +++ b/src/openrct2/object/SmallSceneryObject.h @@ -22,6 +22,8 @@ private: std::vector _frameOffsets; public: + static constexpr ObjectType objectType = ObjectType::SmallScenery; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/StationObject.h b/src/openrct2/object/StationObject.h index 372204e18d..ed119fd05f 100644 --- a/src/openrct2/object/StationObject.h +++ b/src/openrct2/object/StationObject.h @@ -24,6 +24,8 @@ namespace OpenRCT2::STATION_OBJECT_FLAGS class StationObject final : public Object { public: + static constexpr ObjectType objectType = ObjectType::Station; + StringId NameStringId{}; ImageIndex BaseImageId = ImageIndexUndefined; ImageIndex ShelterImageId = ImageIndexUndefined; diff --git a/src/openrct2/object/TerrainEdgeObject.h b/src/openrct2/object/TerrainEdgeObject.h index 1eab9695f6..113b3464b2 100644 --- a/src/openrct2/object/TerrainEdgeObject.h +++ b/src/openrct2/object/TerrainEdgeObject.h @@ -15,6 +15,8 @@ class TerrainEdgeObject final : public Object { private: public: + static constexpr ObjectType objectType = ObjectType::TerrainEdge; + StringId NameStringId{}; uint32_t IconImageId{}; uint32_t BaseImageId{}; diff --git a/src/openrct2/object/TerrainSurfaceObject.h b/src/openrct2/object/TerrainSurfaceObject.h index 18d78e1d8f..aebf3f9692 100644 --- a/src/openrct2/object/TerrainSurfaceObject.h +++ b/src/openrct2/object/TerrainSurfaceObject.h @@ -35,6 +35,8 @@ private: static constexpr auto kNumImagesInEntry = 19; public: + static constexpr ObjectType objectType = ObjectType::TerrainSurface; + static constexpr uint8_t kNoValue = 0xFF; StringId NameStringId{}; uint32_t IconImageId{}; diff --git a/src/openrct2/object/WallObject.h b/src/openrct2/object/WallObject.h index 6f90f14ad4..8b85548427 100644 --- a/src/openrct2/object/WallObject.h +++ b/src/openrct2/object/WallObject.h @@ -18,6 +18,8 @@ private: WallSceneryEntry _legacyType = {}; public: + static constexpr ObjectType objectType = ObjectType::Walls; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/object/WaterObject.h b/src/openrct2/object/WaterObject.h index ff7be845bd..096261f9d2 100644 --- a/src/openrct2/object/WaterObject.h +++ b/src/openrct2/object/WaterObject.h @@ -20,6 +20,8 @@ private: WaterObjectEntry _legacyType = {}; public: + static constexpr ObjectType objectType = ObjectType::Water; + void* GetLegacyData() override { return &_legacyType; diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 1275005c85..a239f4b4c2 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -1981,7 +1981,7 @@ void DefaultMusicUpdate(Ride& ride) if (ride.music_tune_id == TUNE_ID_NULL) { auto& objManager = GetContext()->GetObjectManager(); - auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, ride.music)); + auto musicObj = objManager.GetLoadedObject(ride.music); if (musicObj != nullptr) { auto numTracks = musicObj->GetTrackCount(); @@ -5543,13 +5543,13 @@ int32_t RideGetEntryIndex(int32_t rideType, int32_t rideSubType) const StationObject* Ride::GetStationObject() const { auto& objManager = GetContext()->GetObjectManager(); - return static_cast(objManager.GetLoadedObject(ObjectType::Station, entrance_style)); + return objManager.GetLoadedObject(entrance_style); } const MusicObject* Ride::GetMusicObject() const { auto& objManager = GetContext()->GetObjectManager(); - return static_cast(objManager.GetLoadedObject(ObjectType::Music, music)); + return objManager.GetLoadedObject(music); } // Normally, a station has at most one entrance and one exit, which are at the same height diff --git a/src/openrct2/ride/RideAudio.cpp b/src/openrct2/ride/RideAudio.cpp index e07610a1f2..a8f73ef962 100644 --- a/src/openrct2/ride/RideAudio.cpp +++ b/src/openrct2/ride/RideAudio.cpp @@ -170,7 +170,7 @@ namespace OpenRCT2::RideAudio { auto& objManager = GetContext()->GetObjectManager(); auto ride = GetRide(instance.RideId); - auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, ride->music)); + auto musicObj = objManager.GetLoadedObject(ride->music); if (musicObj != nullptr) { auto shouldLoop = musicObj->GetTrackCount() == 1; @@ -276,7 +276,7 @@ namespace OpenRCT2::RideAudio std::pair RideMusicGetTrackOffsetLength_Default(const Ride& ride) { auto& objManager = GetContext()->GetObjectManager(); - auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, ride.music)); + auto musicObj = objManager.GetLoadedObject(ride.music); if (musicObj != nullptr) { auto numTracks = musicObj->GetTrackCount(); diff --git a/src/openrct2/scripting/bindings/object/ScObject.hpp b/src/openrct2/scripting/bindings/object/ScObject.hpp index a7e09d08e5..cf403a0b92 100644 --- a/src/openrct2/scripting/bindings/object/ScObject.hpp +++ b/src/openrct2/scripting/bindings/object/ScObject.hpp @@ -158,14 +158,12 @@ namespace OpenRCT2::Scripting class ScRideObjectVehicle { private: - ObjectType _objectType{}; ObjectEntryIndex _objectIndex{}; size_t _vehicleIndex{}; public: - ScRideObjectVehicle(ObjectType objectType, ObjectEntryIndex objectIndex, size_t vehicleIndex) - : _objectType(objectType) - , _objectIndex(objectIndex) + ScRideObjectVehicle(ObjectEntryIndex objectIndex, size_t vehicleIndex) + : _objectIndex(objectIndex) , _vehicleIndex(vehicleIndex) { } @@ -491,7 +489,7 @@ namespace OpenRCT2::Scripting const RideObject* GetObject() const { auto& objManager = GetContext()->GetObjectManager(); - return static_cast(objManager.GetLoadedObject(_objectType, _objectIndex)); + return objManager.GetLoadedObject(_objectIndex); } const CarEntry* GetEntry() const @@ -707,7 +705,7 @@ namespace OpenRCT2::Scripting { for (size_t i = 0; i < std::size(entry->Cars); i++) { - result.push_back(std::make_shared(static_cast(_type), _index, i)); + result.push_back(std::make_shared(_index, i)); } } return result; diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 771050cb80..aca0df9433 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -1862,7 +1862,7 @@ static bool FootpathIsLegacyPathEntryOkay(ObjectEntryIndex index) { bool showEditorPaths = ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || GetGameState().Cheats.SandboxMode); auto& objManager = OpenRCT2::GetContext()->GetObjectManager(); - auto footpathObj = static_cast(objManager.GetLoadedObject(ObjectType::Paths, index)); + auto footpathObj = objManager.GetLoadedObject(index); if (footpathObj != nullptr) { auto pathEntry = reinterpret_cast(footpathObj->GetLegacyData()); diff --git a/src/openrct2/world/tile_element/EntranceElement.cpp b/src/openrct2/world/tile_element/EntranceElement.cpp index 385b26f0a4..60ffecc6c7 100644 --- a/src/openrct2/world/tile_element/EntranceElement.cpp +++ b/src/openrct2/world/tile_element/EntranceElement.cpp @@ -80,7 +80,7 @@ ObjectEntryIndex EntranceElement::GetLegacyPathEntryIndex() const const FootpathObject* EntranceElement::GetLegacyPathEntry() const { auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objMgr.GetLoadedObject(ObjectType::Paths, GetLegacyPathEntryIndex())); + return objMgr.GetLoadedObject(GetLegacyPathEntryIndex()); } void EntranceElement::SetLegacyPathEntryIndex(ObjectEntryIndex newPathType) @@ -100,7 +100,7 @@ ObjectEntryIndex EntranceElement::GetSurfaceEntryIndex() const const FootpathSurfaceObject* EntranceElement::GetSurfaceEntry() const { auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathSurface, GetSurfaceEntryIndex())); + return objMgr.GetLoadedObject(GetSurfaceEntryIndex()); } void EntranceElement::SetSurfaceEntryIndex(ObjectEntryIndex newIndex) diff --git a/src/openrct2/world/tile_element/PathElement.cpp b/src/openrct2/world/tile_element/PathElement.cpp index 36ba91b305..1c8b058b00 100644 --- a/src/openrct2/world/tile_element/PathElement.cpp +++ b/src/openrct2/world/tile_element/PathElement.cpp @@ -254,7 +254,7 @@ ObjectEntryIndex PathElement::GetSurfaceEntryIndex() const const FootpathSurfaceObject* PathElement::GetSurfaceEntry() const { auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathSurface, GetSurfaceEntryIndex())); + return objMgr.GetLoadedObject(GetSurfaceEntryIndex()); } void PathElement::SetSurfaceEntryIndex(ObjectEntryIndex newIndex) @@ -274,7 +274,7 @@ ObjectEntryIndex PathElement::GetRailingsEntryIndex() const const FootpathRailingsObject* PathElement::GetRailingsEntry() const { auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objMgr.GetLoadedObject(ObjectType::FootpathRailings, GetRailingsEntryIndex())); + return objMgr.GetLoadedObject(GetRailingsEntryIndex()); } void PathElement::SetRailingsEntryIndex(ObjectEntryIndex newEntryIndex) diff --git a/src/openrct2/world/tile_element/SurfaceElement.cpp b/src/openrct2/world/tile_element/SurfaceElement.cpp index aba3d12553..1d5711ff5a 100644 --- a/src/openrct2/world/tile_element/SurfaceElement.cpp +++ b/src/openrct2/world/tile_element/SurfaceElement.cpp @@ -26,7 +26,7 @@ ObjectEntryIndex SurfaceElement::GetSurfaceObjectIndex() const TerrainSurfaceObject* SurfaceElement::GetSurfaceObject() const { auto& objManager = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objManager.GetLoadedObject(ObjectType::TerrainSurface, GetSurfaceObjectIndex())); + return objManager.GetLoadedObject(GetSurfaceObjectIndex()); } ObjectEntryIndex SurfaceElement::GetEdgeObjectIndex() const @@ -37,7 +37,7 @@ ObjectEntryIndex SurfaceElement::GetEdgeObjectIndex() const TerrainEdgeObject* SurfaceElement::GetEdgeObject() const { auto& objManager = OpenRCT2::GetContext()->GetObjectManager(); - return static_cast(objManager.GetLoadedObject(ObjectType::TerrainEdge, GetEdgeObjectIndex())); + return objManager.GetLoadedObject(GetEdgeObjectIndex()); } void SurfaceElement::SetSurfaceObjectIndex(ObjectEntryIndex newStyle) From f6582647f5d8b9078692efcbf878bfe42bb8bd2b Mon Sep 17 00:00:00 2001 From: Duncan Date: Wed, 16 Oct 2024 22:35:29 +0100 Subject: [PATCH 37/97] Large scenery tiles 2 (#22888) * Use std::span for tiles * Add an index helper parameter * Use coordsxyz * Split up corners and walls * Use bools for the two flags * Apply coding style * Refer only to LargeSceneryObject where required * Address comments --- src/openrct2-ui/windows/Scenery.cpp | 9 ++- .../actions/LargeSceneryPlaceAction.cpp | 52 ++++++-------- .../actions/LargeSceneryPlaceAction.h | 5 +- .../actions/LargeSceneryRemoveAction.cpp | 28 +++----- .../actions/LargeScenerySetColourAction.cpp | 13 ++-- src/openrct2/actions/WallPlaceAction.cpp | 4 +- src/openrct2/object/LargeSceneryEntry.h | 22 +++--- src/openrct2/object/LargeSceneryObject.cpp | 67 +++++++++---------- src/openrct2/object/LargeSceneryObject.h | 1 - .../paint/tile_element/Paint.LargeScenery.cpp | 34 +++++----- src/openrct2/ride/TrackDesign.cpp | 18 ++--- src/openrct2/ride/TrackDesignSave.cpp | 38 ++++------- .../scripting/bindings/object/ScObject.hpp | 16 ++--- .../bindings/world/ScTileElement.cpp | 15 ++--- src/openrct2/world/Map.cpp | 19 ++---- src/openrct2/world/TileInspector.cpp | 15 ++--- .../tile_element/LargeSceneryElement.cpp | 7 +- 17 files changed, 151 insertions(+), 212 deletions(-) diff --git a/src/openrct2-ui/windows/Scenery.cpp b/src/openrct2-ui/windows/Scenery.cpp index 1a38918b49..e8b2c53275 100644 --- a/src/openrct2-ui/windows/Scenery.cpp +++ b/src/openrct2-ui/windows/Scenery.cpp @@ -1965,10 +1965,9 @@ namespace OpenRCT2::Ui::Windows auto* sceneryEntry = OpenRCT2::ObjectManager::GetObjectEntry(selection.EntryIndex); gMapSelectionTiles.clear(); - for (auto* tile = sceneryEntry->tiles; - tile->x_offset != static_cast(static_cast(0xFFFF)); tile++) + for (auto& tile : sceneryEntry->tiles) { - CoordsXY tileLocation = { tile->x_offset, tile->y_offset }; + CoordsXY tileLocation = { tile.offset }; auto rotatedTileCoords = tileLocation.Rotate(direction); rotatedTileCoords.x += mapTile.x; @@ -2775,9 +2774,9 @@ namespace OpenRCT2::Ui::Windows if (sceneryEntry) { int16_t maxClearZ = 0; - for (int32_t i = 0; sceneryEntry->tiles[i].x_offset != -1; ++i) + for (auto& tile : sceneryEntry->tiles) { - maxClearZ = std::max(maxClearZ, sceneryEntry->tiles[i].z_clearance); + maxClearZ = std::max(maxClearZ, tile.zClearance); } maxPossibleHeight = std::max(0, maxPossibleHeight - maxClearZ); } diff --git a/src/openrct2/actions/LargeSceneryPlaceAction.cpp b/src/openrct2/actions/LargeSceneryPlaceAction.cpp index 36888238db..53f8097c78 100644 --- a/src/openrct2/actions/LargeSceneryPlaceAction.cpp +++ b/src/openrct2/actions/LargeSceneryPlaceAction.cpp @@ -108,7 +108,7 @@ GameActions::Result LargeSceneryPlaceAction::Query() const GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_UNKNOWN_OBJECT_TYPE); } - uint32_t totalNumTiles = GetTotalNumTiles(sceneryEntry->tiles); + const auto totalNumTiles = sceneryEntry->tiles.size(); int16_t maxHeight = GetMaxSurfaceHeight(sceneryEntry->tiles); if (_loc.z != 0) @@ -128,18 +128,17 @@ GameActions::Result LargeSceneryPlaceAction::Query() const } } - uint8_t tileNum = 0; - for (LargeSceneryTile* tile = sceneryEntry->tiles; tile->x_offset != -1; tile++, tileNum++) + for (auto& tile : sceneryEntry->tiles) { - auto curTile = CoordsXY{ tile->x_offset, tile->y_offset }.Rotate(_loc.direction); + auto curTile = CoordsXY{ tile.offset }.Rotate(_loc.direction); curTile.x += _loc.x; curTile.y += _loc.y; - int32_t zLow = tile->z_offset + maxHeight; - int32_t zHigh = tile->z_clearance + zLow; + int32_t zLow = tile.offset.z + maxHeight; + int32_t zHigh = tile.zClearance + zLow; - QuarterTile quarterTile = QuarterTile{ static_cast(tile->flags >> 12), 0 }.Rotate(_loc.direction); + QuarterTile quarterTile = QuarterTile{ tile.corners, 0 }.Rotate(_loc.direction); const auto isTree = (sceneryEntry->flags & LARGE_SCENERY_FLAG_IS_TREE) != 0; auto canBuild = MapCanConstructWithClearAt( { curTile, zLow, zHigh }, &MapPlaceSceneryClearFunc, quarterTile, GetFlags(), CreateCrossingMode::none, isTree); @@ -222,7 +221,7 @@ GameActions::Result LargeSceneryPlaceAction::Execute() const GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_UNKNOWN_OBJECT_TYPE); } - if (sceneryEntry->tiles == nullptr) + if (sceneryEntry->tiles.empty()) { LOG_ERROR("Invalid large scenery object, sceneryType = %u", _sceneryType); return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE, STR_NONE); @@ -266,18 +265,17 @@ GameActions::Result LargeSceneryPlaceAction::Execute() const resultData.bannerId = banner->id; } - uint8_t tileNum = 0; - for (LargeSceneryTile* tile = sceneryEntry->tiles; tile->x_offset != -1; tile++, tileNum++) + for (auto& tile : sceneryEntry->tiles) { - auto curTile = CoordsXY{ tile->x_offset, tile->y_offset }.Rotate(_loc.direction); + auto curTile = CoordsXY{ tile.offset }.Rotate(_loc.direction); curTile.x += _loc.x; curTile.y += _loc.y; - int32_t zLow = tile->z_offset + maxHeight; - int32_t zHigh = tile->z_clearance + zLow; + int32_t zLow = tile.offset.z + maxHeight; + int32_t zHigh = tile.zClearance + zLow; - QuarterTile quarterTile = QuarterTile{ static_cast(tile->flags >> 12), 0 }.Rotate(_loc.direction); + QuarterTile quarterTile = QuarterTile{ tile.corners, 0 }.Rotate(_loc.direction); const auto isTree = (sceneryEntry->flags & LARGE_SCENERY_FLAG_IS_TREE) != 0; auto canBuild = MapCanConstructWithClearAt( { curTile, zLow, zHigh }, &MapPlaceSceneryClearFunc, quarterTile, GetFlags(), CreateCrossingMode::none, isTree); @@ -310,7 +308,7 @@ GameActions::Result LargeSceneryPlaceAction::Execute() const Guard::Assert(newSceneryElement != nullptr); newSceneryElement->SetClearanceZ(zHigh); - SetNewLargeSceneryElement(*newSceneryElement, tileNum); + SetNewLargeSceneryElement(*newSceneryElement, tile.index); if (banner != nullptr) { newSceneryElement->SetBannerIndex(banner->id); @@ -319,7 +317,7 @@ GameActions::Result LargeSceneryPlaceAction::Execute() const MapAnimationCreate(MAP_ANIMATION_TYPE_LARGE_SCENERY, { curTile, zLow }); MapInvalidateTileFull(curTile); - if (tileNum == 0) + if (tile.index == 0) { resultData.firstTileHeight = zLow; } @@ -334,21 +332,11 @@ GameActions::Result LargeSceneryPlaceAction::Execute() const return res; } -int16_t LargeSceneryPlaceAction::GetTotalNumTiles(LargeSceneryTile* tiles) const +bool LargeSceneryPlaceAction::CheckMapCapacity(std::span tiles, size_t numTiles) const { - uint32_t totalNumTiles = 0; - for (LargeSceneryTile* tile = tiles; tile->x_offset != -1; tile++) + for (auto& tile : tiles) { - totalNumTiles++; - } - return totalNumTiles; -} - -bool LargeSceneryPlaceAction::CheckMapCapacity(LargeSceneryTile* tiles, int16_t numTiles) const -{ - for (LargeSceneryTile* tile = tiles; tile->x_offset != -1; tile++) - { - auto curTile = CoordsXY{ tile->x_offset, tile->y_offset }.Rotate(_loc.direction); + auto curTile = CoordsXY{ tile.offset }.Rotate(_loc.direction); curTile.x += _loc.x; curTile.y += _loc.y; @@ -360,12 +348,12 @@ bool LargeSceneryPlaceAction::CheckMapCapacity(LargeSceneryTile* tiles, int16_t return true; } -int16_t LargeSceneryPlaceAction::GetMaxSurfaceHeight(LargeSceneryTile* tiles) const +int16_t LargeSceneryPlaceAction::GetMaxSurfaceHeight(std::span tiles) const { int16_t maxHeight = -1; - for (LargeSceneryTile* tile = tiles; tile->x_offset != -1; tile++) + for (auto& tile : tiles) { - auto curTile = CoordsXY{ tile->x_offset, tile->y_offset }.Rotate(_loc.direction); + auto curTile = CoordsXY{ tile.offset }.Rotate(_loc.direction); curTile.x += _loc.x; curTile.y += _loc.y; diff --git a/src/openrct2/actions/LargeSceneryPlaceAction.h b/src/openrct2/actions/LargeSceneryPlaceAction.h index dc5f59aadf..4667da4d5b 100644 --- a/src/openrct2/actions/LargeSceneryPlaceAction.h +++ b/src/openrct2/actions/LargeSceneryPlaceAction.h @@ -46,8 +46,7 @@ public: OpenRCT2::GameActions::Result Execute() const override; private: - int16_t GetTotalNumTiles(LargeSceneryTile* tiles) const; - bool CheckMapCapacity(LargeSceneryTile* tiles, int16_t numTiles) const; - int16_t GetMaxSurfaceHeight(LargeSceneryTile* tiles) const; + bool CheckMapCapacity(std::span tiles, size_t numTiles) const; + int16_t GetMaxSurfaceHeight(std::span tiles) const; void SetNewLargeSceneryElement(LargeSceneryElement& sceneryElement, uint8_t tileNum) const; }; diff --git a/src/openrct2/actions/LargeSceneryRemoveAction.cpp b/src/openrct2/actions/LargeSceneryRemoveAction.cpp index 998b5f470e..ad6f412f90 100644 --- a/src/openrct2/actions/LargeSceneryRemoveAction.cpp +++ b/src/openrct2/actions/LargeSceneryRemoveAction.cpp @@ -77,20 +77,15 @@ GameActions::Result LargeSceneryRemoveAction::Query() const return GameActions::Result(GameActions::Status::Unknown, STR_CANT_REMOVE_THIS, STR_UNKNOWN_OBJECT_TYPE); } - auto rotatedOffsets = CoordsXYZ{ - CoordsXY{ sceneryEntry->tiles[_tileIndex].x_offset, sceneryEntry->tiles[_tileIndex].y_offset }.Rotate(_loc.direction), - sceneryEntry->tiles[_tileIndex].z_offset - }; + auto rotatedOffsets = CoordsXYZ{ CoordsXY{ sceneryEntry->tiles[_tileIndex].offset }.Rotate(_loc.direction), + sceneryEntry->tiles[_tileIndex].offset.z }; auto firstTile = CoordsXYZ{ _loc.x, _loc.y, _loc.z } - rotatedOffsets; bool calculate_cost = true; - for (int32_t i = 0; sceneryEntry->tiles[i].x_offset != -1; i++) + for (auto& tile : sceneryEntry->tiles) { - auto currentTileRotatedOffset = CoordsXYZ{ - CoordsXY{ sceneryEntry->tiles[i].x_offset, sceneryEntry->tiles[i].y_offset }.Rotate(_loc.direction), - sceneryEntry->tiles[i].z_offset - }; + auto currentTileRotatedOffset = CoordsXYZ{ CoordsXY{ tile.offset }.Rotate(_loc.direction), tile.offset.z }; auto currentTile = CoordsXYZ{ firstTile.x, firstTile.y, firstTile.z } + currentTileRotatedOffset; @@ -163,19 +158,14 @@ GameActions::Result LargeSceneryRemoveAction::Execute() const tileElement->RemoveBannerEntry(); - auto rotatedFirstTile = CoordsXYZ{ - CoordsXY{ sceneryEntry->tiles[_tileIndex].x_offset, sceneryEntry->tiles[_tileIndex].y_offset }.Rotate(_loc.direction), - sceneryEntry->tiles[_tileIndex].z_offset - }; + auto rotatedFirstTile = CoordsXYZ{ CoordsXY{ sceneryEntry->tiles[_tileIndex].offset }.Rotate(_loc.direction), + sceneryEntry->tiles[_tileIndex].offset.z }; auto firstTile = CoordsXYZ{ _loc.x, _loc.y, _loc.z } - rotatedFirstTile; - for (int32_t i = 0; sceneryEntry->tiles[i].x_offset != -1; i++) + for (auto& tile : sceneryEntry->tiles) { - auto rotatedCurrentTile = CoordsXYZ{ - CoordsXY{ sceneryEntry->tiles[i].x_offset, sceneryEntry->tiles[i].y_offset }.Rotate(_loc.direction), - sceneryEntry->tiles[i].z_offset - }; + auto rotatedCurrentTile = CoordsXYZ{ CoordsXY{ tile.offset }.Rotate(_loc.direction), tile.offset.z }; auto currentTile = CoordsXYZ{ firstTile.x, firstTile.y, firstTile.z } + rotatedCurrentTile; @@ -187,7 +177,7 @@ GameActions::Result LargeSceneryRemoveAction::Execute() const } } - auto* sceneryElement = FindLargeSceneryElement(currentTile, i); + auto* sceneryElement = FindLargeSceneryElement(currentTile, tile.index); if (sceneryElement == nullptr) { LOG_ERROR("Tile not found when trying to remove element!"); diff --git a/src/openrct2/actions/LargeScenerySetColourAction.cpp b/src/openrct2/actions/LargeScenerySetColourAction.cpp index e7f73fdca3..b5c179fa3c 100644 --- a/src/openrct2/actions/LargeScenerySetColourAction.cpp +++ b/src/openrct2/actions/LargeScenerySetColourAction.cpp @@ -116,18 +116,15 @@ GameActions::Result LargeScenerySetColourAction::QueryExecute(bool isExecuting) return GameActions::Result(GameActions::Status::Unknown, STR_CANT_REPAINT_THIS, STR_NONE); } // Work out the base tile coordinates (Tile with index 0) - auto rotatedBaseCoordsOffset = CoordsXYZ{ - CoordsXY{ sceneryEntry->tiles[_tileIndex].x_offset, sceneryEntry->tiles[_tileIndex].y_offset }.Rotate(_loc.direction), - sceneryEntry->tiles[_tileIndex].z_offset - }; + auto rotatedBaseCoordsOffset = CoordsXYZ{ CoordsXY{ sceneryEntry->tiles[_tileIndex].offset }.Rotate(_loc.direction), + sceneryEntry->tiles[_tileIndex].offset.z }; auto baseTile = CoordsXYZ{ _loc.x, _loc.y, _loc.z } - rotatedBaseCoordsOffset; - auto i = 0; - for (auto tile = sceneryEntry->tiles; tile->x_offset != -1; ++tile, ++i) + for (auto& tile : sceneryEntry->tiles) { // Work out the current tile coordinates - auto rotatedTileCoords = CoordsXYZ{ CoordsXY{ tile->x_offset, tile->y_offset }.Rotate(_loc.direction), tile->z_offset }; + auto rotatedTileCoords = CoordsXYZ{ CoordsXY{ tile.offset }.Rotate(_loc.direction), tile.offset.z }; auto currentTile = CoordsXYZ{ baseTile.x, baseTile.y, baseTile.z } + rotatedTileCoords; if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !GetGameState().Cheats.SandboxMode) @@ -143,7 +140,7 @@ GameActions::Result LargeScenerySetColourAction::QueryExecute(bool isExecuting) return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_OFF_EDGE_OF_MAP); } - auto tileElement = MapGetLargeScenerySegment({ currentTile.x, currentTile.y, _loc.z, _loc.direction }, i); + auto tileElement = MapGetLargeScenerySegment({ currentTile.x, currentTile.y, _loc.z, _loc.direction }, tile.index); if (tileElement == nullptr) { diff --git a/src/openrct2/actions/WallPlaceAction.cpp b/src/openrct2/actions/WallPlaceAction.cpp index 852a506d1a..13918ca308 100644 --- a/src/openrct2/actions/WallPlaceAction.cpp +++ b/src/openrct2/actions/WallPlaceAction.cpp @@ -569,8 +569,8 @@ GameActions::Result WallPlaceAction::WallCheckObstruction( auto sequence = largeSceneryElement->GetSequenceIndex(); const LargeSceneryTile& tile = sceneryEntry->tiles[sequence]; - int32_t direction = ((_edge - tileElement->GetDirection()) & kTileElementDirectionMask) + 8; - if (!(tile.flags & (1 << direction))) + int32_t direction = ((_edge - tileElement->GetDirection()) & kTileElementDirectionMask); + if (!(tile.walls & (1 << direction))) { MapGetObstructionErrorText(tileElement, res); return res; diff --git a/src/openrct2/object/LargeSceneryEntry.h b/src/openrct2/object/LargeSceneryEntry.h index 3afee6fecb..0e489ead61 100644 --- a/src/openrct2/object/LargeSceneryEntry.h +++ b/src/openrct2/object/LargeSceneryEntry.h @@ -14,6 +14,7 @@ #include "../world/Location.hpp" #include "ObjectTypes.h" +#include #include enum class CursorID : uint8_t; @@ -22,18 +23,13 @@ struct LargeSceneryText; struct LargeSceneryTile { - int16_t x_offset; - int16_t y_offset; - int16_t z_offset; - uint8_t z_clearance; - // CCCC WWWW 0SS0 0000 - uint16_t flags; -}; - -enum -{ - LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS = 0x20, - LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE = 0x40, + CoordsXYZ offset; + int32_t zClearance; // BigZ + bool hasSupports; + bool allowSupportsAbove; + uint8_t corners; // occupied corners of the tile + uint8_t walls; // sides that walls can be placed on + uint8_t index; // Purely to save having to look this up all the time }; struct LargeSceneryTextGlyph @@ -74,7 +70,7 @@ struct LargeSceneryEntry uint16_t flags; money64 price; money64 removal_price; - LargeSceneryTile* tiles; + std::span tiles; ObjectEntryIndex scenery_tab_id; uint8_t scrolling_mode; LargeSceneryText* text; diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index b0d24dc5f4..46a7819100 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -117,7 +117,7 @@ void LargeSceneryObject::Load() _baseImageId = LoadImages(); _legacyType.image = _baseImageId; - _legacyType.tiles = _tiles.data(); + _legacyType.tiles = _tiles; if (_legacyType.flags & LARGE_SCENERY_FLAG_3D_TEXT) { @@ -158,17 +158,27 @@ void LargeSceneryObject::DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t GfxDrawSprite(dpi, image, screenCoords); } +enum +{ + LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS = 0x20, + LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE = 0x40, +}; + std::vector LargeSceneryObject::ReadTiles(OpenRCT2::IStream* stream) { auto tiles = std::vector(); auto ReadLegacyTile = [&stream]() { LargeSceneryTile tile{}; - tile.x_offset = stream->ReadValue(); - tile.y_offset = stream->ReadValue(); - tile.z_offset = stream->ReadValue(); - tile.z_clearance = stream->ReadValue(); - tile.flags = stream->ReadValue(); + tile.offset.x = stream->ReadValue(); + tile.offset.y = stream->ReadValue(); + tile.offset.z = stream->ReadValue(); + tile.zClearance = stream->ReadValue(); + uint16_t flags = stream->ReadValue(); + tile.walls = (flags >> 8) & 0xF; + tile.corners = (flags >> 12) & 0xF; + tile.allowSupportsAbove = flags & LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE; + tile.hasSupports = !(flags & LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS); return tile; }; @@ -177,7 +187,11 @@ std::vector LargeSceneryObject::ReadTiles(OpenRCT2::IStream* s stream->Seek(-2, OpenRCT2::STREAM_SEEK_CURRENT); tiles.push_back(ReadLegacyTile()); } - tiles.push_back({ -1, -1, -1, 255, 0xFFFF }); + uint8_t index = 0; + for (auto& tile : tiles) + { + tile.index = index++; + } return tiles; } @@ -231,41 +245,30 @@ void LargeSceneryObject::ReadJson(IReadObjectContext* context, json_t& root) std::vector LargeSceneryObject::ReadJsonTiles(json_t& jTiles) { std::vector tiles; - for (auto& jTile : jTiles) { if (jTile.is_object()) { LargeSceneryTile tile = {}; - tile.x_offset = Json::GetNumber(jTile["x"]); - tile.y_offset = Json::GetNumber(jTile["y"]); - tile.z_offset = Json::GetNumber(jTile["z"]); - tile.z_clearance = Json::GetNumber(jTile["clearance"]); + tile.offset.x = Json::GetNumber(jTile["x"]); + tile.offset.y = Json::GetNumber(jTile["y"]); + tile.offset.z = Json::GetNumber(jTile["z"]); + tile.zClearance = Json::GetNumber(jTile["clearance"]); - // clang-format off - tile.flags = Json::GetFlags( - jTile, - { - {"hasSupports", LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS, Json::FlagType::Inverted}, - {"allowSupportsAbove", LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE, Json::FlagType::Normal} - }); - // clang-format on + tile.hasSupports = Json::GetBoolean(jTile["hasSupports"], true); + tile.allowSupportsAbove = Json::GetBoolean(jTile["allowSupportsAbove"]); // All corners are by default occupied - uint16_t corners = Json::GetNumber(jTile["corners"], 0xF); - tile.flags |= (corners & 0xFF) << 12; + tile.corners = Json::GetNumber(jTile["corners"], 0xF); - auto walls = Json::GetNumber(jTile["walls"]); - tile.flags |= (walls & 0xFF) << 8; + tile.walls = Json::GetNumber(jTile["walls"]); + + tile.index = static_cast(tiles.size()); tiles.push_back(std::move(tile)); } } - // HACK Add end of tiles marker - // We should remove this later by improving the code base to use tiles array length - tiles.push_back({ -1, -1, -1, 0xFF, 0xFFFF }); - return tiles; } @@ -336,11 +339,3 @@ std::vector LargeSceneryObject::ReadJsonGlyphs(json_t& jG } return glyphs; } - -const LargeSceneryTile* LargeSceneryObject::GetTileForSequence(uint8_t SequenceIndex) const -{ - if (SequenceIndex >= _tiles.size()) - return nullptr; - - return &_tiles[SequenceIndex]; -} diff --git a/src/openrct2/object/LargeSceneryObject.h b/src/openrct2/object/LargeSceneryObject.h index f7174fc1ac..8572d8baf7 100644 --- a/src/openrct2/object/LargeSceneryObject.h +++ b/src/openrct2/object/LargeSceneryObject.h @@ -37,7 +37,6 @@ public: void Unload() override; void DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const override; - const LargeSceneryTile* GetTileForSequence(uint8_t SequenceIndex) const; private: [[nodiscard]] static std::vector ReadTiles(OpenRCT2::IStream* stream); diff --git a/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp b/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp index 7cdc0ca7ad..1e03888826 100644 --- a/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp +++ b/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp @@ -18,7 +18,7 @@ #include "../../interface/Viewport.h" #include "../../localisation/Formatting.h" #include "../../localisation/StringIds.h" -#include "../../object/LargeSceneryObject.h" +#include "../../object/LargeSceneryEntry.h" #include "../../profiling/Profiling.h" #include "../../ride/Ride.h" #include "../../ride/TrackDesign.h" @@ -63,7 +63,7 @@ static void PaintLargeScenerySupports( { PROFILED_FUNCTION(); - if (tile.flags & LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS) + if (!tile.hasSupports) return; auto transitionType = WoodenSupportTransitionType::None; @@ -78,7 +78,7 @@ static void PaintLargeScenerySupports( session, WoodenSupportType::Truss, WoodenSupportSubType::NeSw, direction, supportHeight, imageTemplate, transitionType); int32_t clearanceHeight = Ceil2(tileElement.GetClearanceZ() + 15, 16); - if (tile.flags & LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE) + if (tile.allowSupportsAbove) { PaintUtilSetSegmentSupportHeight(session, kSegmentsAll, clearanceHeight, 0x20); } @@ -192,7 +192,7 @@ static void PaintLargeScenery3DText( { PROFILED_FUNCTION(); - if (sceneryEntry.tiles[1].x_offset != -1) + if (sceneryEntry.tiles.size() != 1) { auto sequenceDirection = (tileElement.GetSequenceIndex() - 1) & 3; if (sequenceDirection != direction) @@ -341,18 +341,16 @@ void PaintLargeScenery(PaintSession& session, uint8_t direction, uint16_t height return; auto sequenceNum = tileElement.GetSequenceIndex(); - const auto* object = tileElement.GetObject(); - if (object == nullptr) - return; const auto* sceneryEntry = tileElement.GetEntry(); if (sceneryEntry == nullptr) return; - const auto* tile = object->GetTileForSequence(sequenceNum); - if (tile == nullptr) + if (sequenceNum >= sceneryEntry->tiles.size()) return; + auto& tile = sceneryEntry->tiles[sequenceNum]; + session.InteractionType = ViewportInteractionItem::LargeScenery; auto isGhost = false; @@ -389,14 +387,16 @@ void PaintLargeScenery(PaintSession& session, uint8_t direction, uint16_t height } } - auto boxlengthZ = std::min(tile->z_clearance, 128) - 3; - auto flags = tile->flags; + auto boxlengthZ = std::min(tile.zClearance, 128) - 3; auto bbIndex = 16; - if (flags & 0xF00) + // This matches vanilla but its odd that its a branch on walls + // and then operates on corners. I guess its because if you + // have no walls then you must be occupying the whole tile + // and all the connecting tiles so using an even bigger boundbox + // makes sense. + if (tile.walls) { - flags &= 0xF000; - flags = Numerics::rol16(flags, direction); - bbIndex = (flags & 0xF) | (flags >> 12); + bbIndex = Numerics::rol4(tile.corners, direction); } const CoordsXYZ& bbOffset = { LargeSceneryBoundBoxes[bbIndex].offset, height }; const CoordsXYZ& bbLength = { LargeSceneryBoundBoxes[bbIndex].length, boxlengthZ }; @@ -408,7 +408,7 @@ void PaintLargeScenery(PaintSession& session, uint8_t direction, uint16_t height { if (sceneryEntry->flags & LARGE_SCENERY_FLAG_3D_TEXT) { - PaintLargeScenery3DText(session, *sceneryEntry, *tile, tileElement, direction, height, isGhost); + PaintLargeScenery3DText(session, *sceneryEntry, tile, tileElement, direction, height, isGhost); } else if (session.DPI.zoom_level <= ZoomLevel{ 0 }) { @@ -420,5 +420,5 @@ void PaintLargeScenery(PaintSession& session, uint8_t direction, uint16_t height } } PaintLargeScenerySupports( - session, direction, height, tileElement, isGhost ? imageTemplate : ImageId(0, COLOUR_BLACK), *tile); + session, direction, height, tileElement, isGhost ? imageTemplate : ImageId(0, COLOUR_BLACK), tile); } diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 86a702b2dd..29f0832e5a 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -760,23 +760,23 @@ static void TrackDesignMirrorScenery(TrackDesign& td) { auto* sceneryEntry = reinterpret_cast(obj->GetLegacyData()); int16_t x1 = 0, x2 = 0, y1 = 0, y2 = 0; - for (LargeSceneryTile* tile = sceneryEntry->tiles; tile->x_offset != -1; tile++) + for (auto& tile : sceneryEntry->tiles) { - if (x1 > tile->x_offset) + if (x1 > tile.offset.x) { - x1 = tile->x_offset; + x1 = tile.offset.x; } - if (x2 < tile->x_offset) + if (x2 < tile.offset.x) { - x2 = tile->x_offset; + x2 = tile.offset.x; } - if (y1 > tile->y_offset) + if (y1 > tile.offset.y) { - y1 = tile->y_offset; + y1 = tile.offset.y; } - if (y2 < tile->y_offset) + if (y2 < tile.offset.y) { - y2 = tile->y_offset; + y2 = tile.offset.y; } } diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 469e514a07..e793fc579e 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -148,11 +148,8 @@ bool TrackDesignSaveContainsTileElement(const TileElement* tileElement) return false; } -static int32_t TrackDesignSaveGetTotalElementCount(TileElement* tileElement) +static size_t TrackDesignSaveGetTotalElementCount(TileElement* tileElement) { - int32_t elementCount; - LargeSceneryTile* tile; - switch (tileElement->GetType()) { case TileElementType::Path: @@ -163,14 +160,7 @@ static int32_t TrackDesignSaveGetTotalElementCount(TileElement* tileElement) case TileElementType::LargeScenery: { auto* sceneryEntry = tileElement->AsLargeScenery()->GetEntry(); - tile = sceneryEntry->tiles; - elementCount = 0; - do - { - tile++; - elementCount++; - } while (tile->x_offset != static_cast(static_cast(0xFFFF))); - return elementCount; + return sceneryEntry->tiles.size(); } default: return 0; @@ -287,7 +277,7 @@ static TrackDesignAddStatus TrackDesignSaveAddLargeScenery(const CoordsXY& loc, if (obj != nullptr && TrackDesignSaveIsSupportedObject(obj)) { auto sceneryEntry = reinterpret_cast(obj->GetLegacyData()); - auto sceneryTiles = sceneryEntry->tiles; + auto& sceneryTiles = sceneryEntry->tiles; int32_t z = tileElement->BaseHeight; auto direction = tileElement->GetDirection(); @@ -301,18 +291,17 @@ static TrackDesignAddStatus TrackDesignSaveAddLargeScenery(const CoordsXY& loc, } // Iterate through each tile of the large scenery element - sequence = 0; - for (auto tile = sceneryTiles; tile->x_offset != -1; tile++, sequence++) + for (auto& tile : sceneryTiles) { - CoordsXY offsetPos{ tile->x_offset, tile->y_offset }; + CoordsXY offsetPos{ tile.offset }; auto rotatedOffsetPos = offsetPos.Rotate(direction); CoordsXYZ tileLoc = { sceneryOrigin->x + rotatedOffsetPos.x, sceneryOrigin->y + rotatedOffsetPos.y, - sceneryOrigin->z + tile->z_offset }; - auto largeElement = MapGetLargeScenerySegment({ tileLoc, static_cast(direction) }, sequence); + sceneryOrigin->z + tile.offset.z }; + auto largeElement = MapGetLargeScenerySegment({ tileLoc, static_cast(direction) }, tile.index); if (largeElement != nullptr) { - if (sequence == 0) + if (tile.index == 0) { auto item = TrackDesignSaveCreateLargeSceneryDesc(*obj, tileLoc, *largeElement); _trackSavedTileElementsDesc.push_back(std::move(item)); @@ -518,18 +507,17 @@ static void TrackDesignSaveRemoveLargeScenery(const CoordsXY& loc, LargeSceneryE } // Iterate through each tile of the large scenery element - sequence = 0; - for (auto tile = sceneryTiles; tile->x_offset != -1; tile++, sequence++) + for (auto& tile : sceneryTiles) { - CoordsXY offsetPos{ tile->x_offset, tile->y_offset }; + CoordsXY offsetPos{ tile.offset }; auto rotatedOffsetPos = offsetPos.Rotate(direction); CoordsXYZ tileLoc = { sceneryOrigin->x + rotatedOffsetPos.x, sceneryOrigin->y + rotatedOffsetPos.y, - sceneryOrigin->z + tile->z_offset }; - auto largeElement = MapGetLargeScenerySegment({ tileLoc, static_cast(direction) }, sequence); + sceneryOrigin->z + tile.offset.z }; + auto largeElement = MapGetLargeScenerySegment({ tileLoc, static_cast(direction) }, tile.index); if (largeElement != nullptr) { - if (sequence == 0) + if (tile.index == 0) { auto item = TrackDesignSaveCreateLargeSceneryDesc(*obj, tileLoc, *largeElement); TrackDesignSavePopTileElementDesc(item); diff --git a/src/openrct2/scripting/bindings/object/ScObject.hpp b/src/openrct2/scripting/bindings/object/ScObject.hpp index cf403a0b92..0f41cbc1b9 100644 --- a/src/openrct2/scripting/bindings/object/ScObject.hpp +++ b/src/openrct2/scripting/bindings/object/ScObject.hpp @@ -925,33 +925,33 @@ namespace OpenRCT2::Scripting { auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto start = CoordsXYZ(_tile.x_offset, _tile.y_offset, _tile.z_offset); + auto start = _tile.offset; return ToDuk(ctx, start); } int32_t zClearance_get() const { - return _tile.z_clearance; + return _tile.zClearance; } bool hasSupports_get() const { - return !(_tile.flags & LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS); + return _tile.hasSupports; } bool allowSupportsAbove_get() const { - return _tile.flags & LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE; + return _tile.allowSupportsAbove; } uint8_t corners_get() const { - return (_tile.flags >> 12) & 0xF; + return _tile.corners; } uint8_t walls_get() const { - return (_tile.flags >> 8) & 0xF; + return _tile.walls; } }; @@ -977,9 +977,9 @@ namespace OpenRCT2::Scripting auto entry = GetEntry(); if (entry != nullptr) { - for (auto* tile = entry->tiles; tile->x_offset != -1; ++tile) + for (auto& tile : entry->tiles) { - result.push_back(std::make_shared(*tile)); + result.push_back(std::make_shared(tile)); } } return result; diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.cpp b/src/openrct2/scripting/bindings/world/ScTileElement.cpp index 027a73a76b..7ec82c4171 100644 --- a/src/openrct2/scripting/bindings/world/ScTileElement.cpp +++ b/src/openrct2/scripting/bindings/world/ScTileElement.cpp @@ -2161,18 +2161,17 @@ namespace OpenRCT2::Scripting const auto* const largeEntry = largeScenery->GetEntry(); const auto direction = largeScenery->GetDirection(); const auto sequenceIndex = largeScenery->GetSequenceIndex(); - const auto* tiles = largeEntry->tiles; - const auto& tile = tiles[sequenceIndex]; + const auto& tiles = largeEntry->tiles; + const auto& initialTile = tiles[sequenceIndex]; const auto rotatedFirstTile = CoordsXYZ{ - CoordsXY{ tile.x_offset, tile.y_offset }.Rotate(direction), - tile.z_offset, + CoordsXY{ initialTile.offset }.Rotate(direction), + initialTile.offset.z, }; const auto firstTile = CoordsXYZ{ loc, largeScenery->GetBaseZ() } - rotatedFirstTile; - for (int32_t i = 0; tiles[i].x_offset != -1; i++) + for (auto& tile : tiles) { - const auto rotatedCurrentTile = CoordsXYZ{ CoordsXY{ tiles[i].x_offset, tiles[i].y_offset }.Rotate(direction), - tiles[i].z_offset }; + const auto rotatedCurrentTile = CoordsXYZ{ CoordsXY{ tile.offset }.Rotate(direction), tile.offset.z }; const auto currentTile = firstTile + rotatedCurrentTile; @@ -2192,7 +2191,7 @@ namespace OpenRCT2::Scripting continue; if (tileElement->AsLargeScenery()->GetEntryIndex() != largeScenery->GetEntryIndex()) continue; - if (tileElement->AsLargeScenery()->GetSequenceIndex() != i) + if (tileElement->AsLargeScenery()->GetSequenceIndex() != tile.index) continue; return tileElement->AsLargeScenery(); diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 5c033abfc1..3e69e19bdc 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1678,20 +1678,18 @@ SmallSceneryElement* MapGetSmallSceneryElementAt(const CoordsXYZ& sceneryCoords, std::optional MapLargeSceneryGetOrigin( const CoordsXYZD& sceneryPos, int32_t sequence, LargeSceneryElement** outElement) { - LargeSceneryTile* tile; - auto tileElement = MapGetLargeScenerySegment(sceneryPos, sequence); if (tileElement == nullptr) return std::nullopt; auto* sceneryEntry = tileElement->GetEntry(); - tile = &sceneryEntry->tiles[sequence]; + auto& tile = sceneryEntry->tiles[sequence]; - CoordsXY offsetPos{ tile->x_offset, tile->y_offset }; + CoordsXY offsetPos{ tile.offset }; auto rotatedOffsetPos = offsetPos.Rotate(sceneryPos.direction); auto origin = CoordsXYZ{ sceneryPos.x - rotatedOffsetPos.x, sceneryPos.y - rotatedOffsetPos.y, - sceneryPos.z - tile->z_offset }; + sceneryPos.z - tile.offset.z }; if (outElement != nullptr) *outElement = tileElement; return origin; @@ -1704,7 +1702,6 @@ std::optional MapLargeSceneryGetOrigin( bool MapLargeScenerySignSetColour(const CoordsXYZD& signPos, int32_t sequence, uint8_t mainColour, uint8_t textColour) { LargeSceneryElement* tileElement; - LargeSceneryTile *sceneryTiles, *tile; auto sceneryOrigin = MapLargeSceneryGetOrigin(signPos, sequence, &tileElement); if (!sceneryOrigin) @@ -1713,18 +1710,16 @@ bool MapLargeScenerySignSetColour(const CoordsXYZD& signPos, int32_t sequence, u } auto* sceneryEntry = tileElement->GetEntry(); - sceneryTiles = sceneryEntry->tiles; // Iterate through each tile of the large scenery element - sequence = 0; - for (tile = sceneryTiles; tile->x_offset != -1; tile++, sequence++) + for (auto& tile : sceneryEntry->tiles) { - CoordsXY offsetPos{ tile->x_offset, tile->y_offset }; + CoordsXY offsetPos{ tile.offset }; auto rotatedOffsetPos = offsetPos.Rotate(signPos.direction); auto tmpSignPos = CoordsXYZD{ sceneryOrigin->x + rotatedOffsetPos.x, sceneryOrigin->y + rotatedOffsetPos.y, - sceneryOrigin->z + tile->z_offset, signPos.direction }; - tileElement = MapGetLargeScenerySegment(tmpSignPos, sequence); + sceneryOrigin->z + tile.offset.z, signPos.direction }; + tileElement = MapGetLargeScenerySegment(tmpSignPos, tile.index); if (tileElement != nullptr) { tileElement->SetPrimaryColour(mainColour); diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index 97351eec7c..63211571bd 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -93,19 +93,18 @@ namespace OpenRCT2::TileInspector const auto* const largeEntry = largeScenery->GetEntry(); const auto direction = largeScenery->GetDirection(); const auto sequenceIndex = largeScenery->GetSequenceIndex(); - const auto* tiles = largeEntry->tiles; - const auto& tile = tiles[sequenceIndex]; + const auto& tiles = largeEntry->tiles; + const auto& initialTile = tiles[sequenceIndex]; const auto rotatedFirstTile = CoordsXYZ{ - CoordsXY{ tile.x_offset, tile.y_offset }.Rotate(direction), - tile.z_offset, + CoordsXY{ initialTile.offset }.Rotate(direction), + initialTile.offset.z, }; const auto firstTile = CoordsXYZ{ loc, largeScenery->GetBaseZ() } - rotatedFirstTile; auto numFoundElements = 0; - for (int32_t i = 0; tiles[i].x_offset != -1; i++) + for (auto& tile : tiles) { - const auto rotatedCurrentTile = CoordsXYZ{ CoordsXY{ tiles[i].x_offset, tiles[i].y_offset }.Rotate(direction), - tiles[i].z_offset }; + const auto rotatedCurrentTile = CoordsXYZ{ CoordsXY{ tile.offset }.Rotate(direction), tile.offset.z }; const auto currentTile = firstTile + rotatedCurrentTile; @@ -120,7 +119,7 @@ namespace OpenRCT2::TileInspector if (tileElement->GetDirection() != direction) continue; - if (tileElement->AsLargeScenery()->GetSequenceIndex() != i) + if (tileElement->AsLargeScenery()->GetSequenceIndex() != tile.index) continue; if (tileElement->GetBaseZ() != currentTile.z) diff --git a/src/openrct2/world/tile_element/LargeSceneryElement.cpp b/src/openrct2/world/tile_element/LargeSceneryElement.cpp index 2292c4ec98..def95e30d3 100644 --- a/src/openrct2/world/tile_element/LargeSceneryElement.cpp +++ b/src/openrct2/world/tile_element/LargeSceneryElement.cpp @@ -9,7 +9,7 @@ #include "LargeSceneryElement.h" -#include "../../object/LargeSceneryObject.h" +#include "../../object/LargeSceneryEntry.h" #include "../../object/ObjectEntryManager.h" #include "../../object/ObjectManager.h" #include "../Banner.h" @@ -91,11 +91,6 @@ const LargeSceneryEntry* LargeSceneryElement::GetEntry() const return OpenRCT2::ObjectManager::GetObjectEntry(GetEntryIndex()); } -const LargeSceneryObject* LargeSceneryElement::GetObject() const -{ - return static_cast(ObjectEntryGetObject(ObjectType::LargeScenery, GetEntryIndex())); -} - uint8_t LargeSceneryElement::GetSequenceIndex() const { return SequenceIndex; From 5ec1b5bf9da9307b25cdd39c31bc77471a3e722a Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:41:20 +0200 Subject: [PATCH 38/97] Compile AppImage with Ubuntu 22.04 + Clang 15 --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26afde2dc5..0c36637b1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -379,7 +379,7 @@ jobs: name: Ubuntu Linux (AppImage, x86_64) runs-on: ubuntu-latest needs: [check-code-formatting, get_artifact_name] - container: openrct2/openrct2-build:16-noble + container: openrct2/openrct2-build:14-jammy steps: - name: Checkout uses: actions/checkout@v4 @@ -387,11 +387,13 @@ jobs: uses: hendrikmuhs/ccache-action@v1.2.13 with: key: linux-appimage + - name: Install Clang 15 + run: apt update && apt install -y clang-15 - name: Get pre-reqs run: . scripts/setenv -q && get-discord-rpc - name: Build OpenRCT2 run: | - . scripts/setenv -q && build -DCMAKE_BUILD_TYPE=Release -DAPPIMAGE=ON -DOPENRCT2_USE_CCACHE=on + . scripts/setenv -q && build -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -DCMAKE_BUILD_TYPE=Release -DAPPIMAGE=ON -DOPENRCT2_USE_CCACHE=on strip bin/install/usr/bin/openrct2 - name: Build AppImage env: From 2c7c9a5e05294856c15fd16712dee123355daee5 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:17:10 +0200 Subject: [PATCH 39/97] Add #23010 to changelog [ci skip] --- distribution/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 1765da97a3..3b595d68bc 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.4.16 (in development) ------------------------------------------------------------------------ +- Improved: [#23010] Make AppImage compatible with Ubuntu 22.04 and Debian Bookworm again. - Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. - Fix: [#22633] Crash when drawing loading screen with an outdated g2.dat. - Fix: [#22918] Zooming with keyboard moves the view off centre. From 0c842d795e247f7e57c09f9fadd95e9aaa8c09ed Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Thu, 17 Oct 2024 21:27:25 +0200 Subject: [PATCH 40/97] Fix .sea files not being listed in scenario index (#23013) --- distribution/changelog.txt | 1 + src/openrct2/scenario/ScenarioRepository.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 3b595d68bc..c0ffacf556 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -6,6 +6,7 @@ - Fix: [#22918] Zooming with keyboard moves the view off centre. - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. - Fix: [#22962] Fuzzy horizontal-to-vertical line transitions in charts. +- Fix: [#23009] Scenarios from RCT Classic (.sea files) are not included in the scenario index. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2/scenario/ScenarioRepository.cpp b/src/openrct2/scenario/ScenarioRepository.cpp index e2b91456d4..4ec3ba2e25 100644 --- a/src/openrct2/scenario/ScenarioRepository.cpp +++ b/src/openrct2/scenario/ScenarioRepository.cpp @@ -209,15 +209,24 @@ private: std::string extension = Path::GetExtension(path); if (String::IEquals(extension, ".park")) + { importer = ParkImporter::CreateParkFile(objRepository); + importer->LoadScenario(path, true); + } else if (String::IEquals(extension, ".sc4")) + { importer = ParkImporter::CreateS4(); + importer->LoadScenario(path, true); + } else + { importer = ParkImporter::CreateS6(objRepository); + auto stream = GetStreamFromRCT2Scenario(path); + importer->LoadFromStream(stream.get(), true); + } if (importer) { - importer->LoadScenario(path, true); if (importer->GetDetails(entry)) { entry->Path = path; From 236f4afbd7d735ee3f3bbb26f8416323ea5bef73 Mon Sep 17 00:00:00 2001 From: Duncan Date: Thu, 17 Oct 2024 21:19:06 +0100 Subject: [PATCH 41/97] Fix default supports for large scenery (#23014) --- src/openrct2/object/LargeSceneryObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index 46a7819100..d96679b08f 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -255,7 +255,7 @@ std::vector LargeSceneryObject::ReadJsonTiles(json_t& jTiles) tile.offset.z = Json::GetNumber(jTile["z"]); tile.zClearance = Json::GetNumber(jTile["clearance"]); - tile.hasSupports = Json::GetBoolean(jTile["hasSupports"], true); + tile.hasSupports = Json::GetBoolean(jTile["hasSupports"]); tile.allowSupportsAbove = Json::GetBoolean(jTile["allowSupportsAbove"]); // All corners are by default occupied From 0d6ed8efc5dc835e9e31ecb94ff74279b974f338 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Fri, 18 Oct 2024 09:14:50 +0200 Subject: [PATCH 42/97] Close windows before loading another save --- distribution/changelog.txt | 1 + src/openrct2-ui/windows/LoadSave.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index c0ffacf556..c2653a3a21 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -7,6 +7,7 @@ - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. - Fix: [#22962] Fuzzy horizontal-to-vertical line transitions in charts. - Fix: [#23009] Scenarios from RCT Classic (.sea files) are not included in the scenario index. +- Fix: [#23015] Crash when loading a save game when the construction window is still open. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 58b7ec134c..c15424d652 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -267,6 +267,11 @@ namespace OpenRCT2::Ui::Windows char pathBuffer[MAX_PATH]; SafeStrCpy(pathBuffer, path, sizeof(pathBuffer)); + // Closing this will cause a Ride window to pop up, so we have to do this to ensure that + // no windows are open (besides the toolbars and LoadSave window). + WindowCloseByClass(WindowClass::RideConstruction); + WindowCloseAllExceptClass(WindowClass::Loadsave); + auto& gameState = GetGameState(); switch (_type & 0x0F) From 34720ff33f9c54b5292c5ae5a5cc85e1e1db1ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Mon, 7 Oct 2024 21:13:37 +0200 Subject: [PATCH 43/97] Checkout changelog.txt --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c36637b1f..84f5c09c59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -538,6 +538,11 @@ jobs: needs: [get_artifact_name, linux-portable, android, linux-appimage, macos-universal, windows] if: startsWith(github.ref, 'refs/tags/v') steps: + - name: Checkout + uses: actions/checkout@v4 + with: + sparse-checkout: | + distribution/changelog.txt - name: Download artifacts uses: actions/download-artifact@v4 with: From b24990080eb2484ff823c8ffb5a453a82af9e0a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Mon, 7 Oct 2024 19:46:43 +0200 Subject: [PATCH 44/97] Do releases in binaries repo --- .github/workflows/ci.yml | 128 +++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84f5c09c59..25e875daf3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ concurrency: cancel-in-progress: true jobs: - get_artifact_name: + build_variables: name: Get version info runs-on: ubuntu-latest outputs: @@ -39,12 +39,21 @@ jobs: short-sha: ${{ steps.ghd.outputs.short-sha }} distance: ${{ steps.ghd.outputs.distance }} tag: ${{ steps.ghd.outputs.tag }} + push: ${{ steps.setenv.outputs.push }} steps: + # We need to fetch entire repo to get the tags and correctly run `describe` - name: Check out code uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Git describe id: ghd uses: proudust/gh-describe@v2 + - name: Set env + id: setenv + run: | + . scripts/setenv -q + echo "push=$OPENRCT2_PUSH" >> $GITHUB_OUTPUT lint-commit: name: Lint Commit Message if: github.event_name == 'pull_request' @@ -86,7 +95,7 @@ jobs: g2dat: name: g2.dat runs-on: ubuntu-latest - needs: get_artifact_name + needs: build_variables steps: - name: Checkout OpenRCT2 uses: actions/checkout@v4 @@ -104,12 +113,12 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: g2-${{ needs.get_artifact_name.outputs.name }}.dat + name: g2-${{ needs.build_variables.outputs.name }}.dat path: g2.dat windows: name: Windows runs-on: windows-latest - needs: [check-code-formatting, get_artifact_name] + needs: [check-code-formatting, build_variables] strategy: fail-fast: false matrix: @@ -139,26 +148,26 @@ jobs: build-installer -i - name: Rename artifacts run: | - mv artifacts/openrct2-portable-*.zip artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-portable-$PLATFORM.zip - mv artifacts/openrct2-installer-*.exe artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-installer-$PLATFORM.exe - mv artifacts/openrct2-symbols-*.zip artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-symbols-$PLATFORM.zip + mv artifacts/openrct2-portable-*.zip artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-portable-$PLATFORM.zip + mv artifacts/openrct2-installer-*.exe artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-installer-$PLATFORM.exe + mv artifacts/openrct2-symbols-*.zip artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-symbols-$PLATFORM.zip - name: Upload portable artifact (CI) uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-${{ runner.os }}-portable-${{ matrix.platform }} - path: artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-portable-${{ matrix.platform }}.zip + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-portable-${{ matrix.platform }} + path: artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-portable-${{ matrix.platform }}.zip if-no-files-found: error - name: Upload installer artifact (CI) uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-${{ runner.os }}-installer-${{ matrix.platform }} - path: artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-installer-${{ matrix.platform }}.exe + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-installer-${{ matrix.platform }} + path: artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-installer-${{ matrix.platform }}.exe if-no-files-found: error - name: Upload symbols artifact (CI) uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-${{ runner.os }}-symbols-${{ matrix.platform }} - path: artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-symbols-${{ matrix.platform }}.zip + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-symbols-${{ matrix.platform }} + path: artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-symbols-${{ matrix.platform }}.zip if-no-files-found: error - name: Run Tests if: matrix.platform != 'arm64' @@ -172,17 +181,17 @@ jobs: run: | . scripts/setenv if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-portable-$PLATFORM.zip "windows-portable-$PLATFORM.zip" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - upload-build artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-installer-$PLATFORM.exe "windows-installer-$PLATFORM.exe" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - upload-build artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-symbols-$PLATFORM.zip "windows-symbols-$PLATFORM.zip" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - upload-backtrace-symbols artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-windows-symbols-*.zip + upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-portable-$PLATFORM.zip "windows-portable-$PLATFORM.zip" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH + upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-installer-$PLATFORM.exe "windows-installer-$PLATFORM.exe" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH + upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-symbols-$PLATFORM.zip "windows-symbols-$PLATFORM.zip" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH + upload-backtrace-symbols artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-symbols-*.zip else echo 'Not going to push build' fi windows-mingw: name: Windows (${{ matrix.platform_name }}) using mingw runs-on: ubuntu-latest - needs: [check-code-formatting, get_artifact_name] + needs: [check-code-formatting, build_variables] container: openrct2/openrct2-build:14-mingw strategy: fail-fast: false @@ -212,7 +221,7 @@ jobs: if: matrix.platform == 'NT5.1' uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-Windows-mingw-${{ matrix.platform }} + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-Windows-mingw-${{ matrix.platform }} path: bin/openrct2.exe if-no-files-found: error macos-cmake: @@ -278,7 +287,7 @@ jobs: macos-universal: name: macOS universal app bundle runs-on: macos-14 - needs: [macos-cmake, get_artifact_name] + needs: [macos-cmake, build_variables] steps: - name: Checkout uses: actions/checkout@v4 @@ -306,25 +315,25 @@ jobs: mv macos_universal/OpenRCT2-universal.app artifacts/OpenRCT2.app echo -e "\033[0;36mCompressing OpenRCT2.app...\033[0m" cd artifacts - zip -rqy OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-macos-universal.zip OpenRCT2.app + zip -rqy OpenRCT2-${{ needs.build_variables.outputs.name }}-macos-universal.zip OpenRCT2.app - name: Upload artifacts (CI) uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-${{ runner.os }}-universal - path: artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-macos-universal.zip + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-universal + path: artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-macos-universal.zip if-no-files-found: error - name: Upload artifacts (openrct2.org) run: | . scripts/setenv if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-macos-universal.zip macos-universal.zip $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH + upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-macos-universal.zip macos-universal.zip $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH else echo 'Not going to push build' fi linux-portable: name: ${{ matrix.distro }} Linux (${{ matrix.release }}, ${{ matrix.platform }}, portable) runs-on: ubuntu-latest - needs: [check-code-formatting, get_artifact_name] + needs: [check-code-formatting, build_variables] container: ${{ matrix.image }} strategy: fail-fast: false @@ -357,11 +366,11 @@ jobs: . scripts/setenv -q && build -DWITH_TESTS=on -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DPORTABLE=ON ${{ matrix.build_flags }} strip bin/install/usr/bin/libopenrct2.so - name: Build artifacts - run: . scripts/setenv -q && build-portable artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-${{ runner.os }}-${{ matrix.release }}-${{ matrix.platform }}.tar.gz bin/install/usr + run: . scripts/setenv -q && build-portable artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-${{ matrix.release }}-${{ matrix.platform }}.tar.gz bin/install/usr - name: Upload artifacts (CI) uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-${{ runner.os }}-${{ matrix.release }}-${{ matrix.platform }} + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-${{ matrix.release }}-${{ matrix.platform }} path: artifacts if-no-files-found: error - name: Run Tests @@ -371,14 +380,14 @@ jobs: # Build identification code: https://github.com/Limetric/OpenRCT2.org/blob/e5b738f3dadcc5a3b78e8dfd434756ff31eaa1d3/src/misc/releaseAsset.js#L94-L116 . scripts/setenv -q if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-${{ runner.os }}-${{ matrix.release }}-${{ matrix.platform }}.tar.gz linux-${{ matrix.platform }}-${{ matrix.distro }}.tar.gz $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH + upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-${{ matrix.release }}-${{ matrix.platform }}.tar.gz linux-${{ matrix.platform }}-${{ matrix.distro }}.tar.gz $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH else echo 'Not going to push build' fi linux-appimage: name: Ubuntu Linux (AppImage, x86_64) runs-on: ubuntu-latest - needs: [check-code-formatting, get_artifact_name] + needs: [check-code-formatting, build_variables] container: openrct2/openrct2-build:14-jammy steps: - name: Checkout @@ -397,12 +406,12 @@ jobs: strip bin/install/usr/bin/openrct2 - name: Build AppImage env: - APPIMAGE_FILE_NAME: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-linux-x86_64.AppImage + APPIMAGE_FILE_NAME: OpenRCT2-${{ needs.build_variables.outputs.name }}-linux-x86_64.AppImage run: . scripts/setenv -q && build-appimage - name: Upload artifacts (CI) uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-AppImage + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-AppImage path: artifacts if-no-files-found: error - name: Upload artifacts (openrct2.org) @@ -410,7 +419,7 @@ jobs: # Build identification code: https://github.com/Limetric/OpenRCT2.org/blob/e5b738f3dadcc5a3b78e8dfd434756ff31eaa1d3/src/misc/releaseAsset.js#L94-L116 . scripts/setenv -q if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-linux-x86_64.AppImage linux.AppImage $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH + upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-linux-x86_64.AppImage linux.AppImage $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH else echo 'Not going to push build' fi @@ -458,7 +467,7 @@ jobs: linux-clang-tests: name: Ubuntu Linux (debug) using clang, coverage enabled runs-on: ubuntu-latest - needs: [check-code-formatting, get_artifact_name] + needs: [check-code-formatting, build_variables] container: openrct2/openrct2-build:16-noble steps: - name: Checkout @@ -490,7 +499,7 @@ jobs: - name: Upload artifacts (CI) uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-${{ runner.os }}-coverage + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-coverage path: | bin/*profdata* bin/coverage.json* @@ -499,7 +508,7 @@ jobs: android: name: Android runs-on: ubuntu-latest - needs: [check-code-formatting, get_artifact_name] + needs: [check-code-formatting, build_variables] container: openrct2/openrct2-build:14-android steps: - name: Checkout @@ -517,26 +526,25 @@ jobs: ./gradlew app:assembleRelease popd mkdir -p artifacts - mv src/openrct2-android/app/build/outputs/apk/release/app-release.apk artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-android-arm.apk + mv src/openrct2-android/app/build/outputs/apk/release/app-release.apk artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-android-arm.apk - name: Upload artifacts (CI) uses: actions/upload-artifact@v4 with: - name: OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-Android + name: OpenRCT2-${{ needs.build_variables.outputs.name }}-Android path: artifacts if-no-files-found: error - name: Upload artifacts (openrct2.org) run: | . scripts/setenv -q if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-android-arm.apk android-arm.apk $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH + upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-android-arm.apk android-arm.apk $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH else echo 'Not going to push build' fi release: name: Release runs-on: ubuntu-latest - needs: [get_artifact_name, linux-portable, android, linux-appimage, macos-universal, windows] - if: startsWith(github.ref, 'refs/tags/v') + needs: [build_variables, linux-portable, android, linux-appimage, macos-universal, windows] steps: - name: Checkout uses: actions/checkout@v4 @@ -551,21 +559,49 @@ jobs: run: | ls -lR pushd ${{ github.workspace }} - sha1sum OpenRCT2-* > openrct2-${{ needs.get_artifact_name.outputs.name }}-sha1sums.txt + sha1sum OpenRCT2-* > OpenRCT2-${{ needs.build_variables.outputs.name }}-sha1sums.txt popd - name: Create release notes run: | + # Print all the lines until an empty line + sed -n '1,/^$/p' distribution/changelog.txt >> release_notes.txt + echo "" >> release_notes.txt + echo "SHA1 checksums:" >> release_notes.txt echo "\`\`\`" >> release_notes.txt - cat openrct2-${{ needs.get_artifact_name.outputs.name }}-sha1sums.txt >> release_notes.txt + cat OpenRCT2-${{ needs.build_variables.outputs.name }}-sha1sums.txt >> release_notes.txt echo "\`\`\`" >> release_notes.txt echo "" >> release_notes.txt - - name: Create release + # Only upload tagged releases, mark them as draft for manual verification + - name: Create tagged release uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/v') with: draft: true files: | - openrct2-${{ needs.get_artifact_name.outputs.name }}-sha1sums.txt - OpenRCT2-${{ needs.get_artifact_name.outputs.name }}-* + OpenRCT2-${{ needs.build_variables.outputs.name }}-sha1sums.txt + OpenRCT2-${{ needs.build_variables.outputs.name }}-* body_path: release_notes.txt - tag_name: ${{ needs.get_artifact_name.outputs.tag }} + tag_name: ${{ needs.build_variables.outputs.tag }} + # The upload to binaries repository is done from develop only + - name: Create tag for binaries repository + uses: actions/github-script@v5 + if: ${{ needs.build_variables.outputs.push }} + with: + github-token: ${{ secrets.OPENRCT2_BINARIES_CI_UPLOAD }} + script: | + github.rest.git.createRef({ + owner: 'OpenRCT2', + repo: 'OpenRCT2-binaries', + ref: 'refs/tags/${{ needs.build_variables.outputs.name }}', + sha: '2032e1601f3b35d07f088758d34bedbb84868616' + }) + - name: Create release in binaries repo + uses: softprops/action-gh-release@v2 + if: ${{ needs.build_variables.outputs.push }} + with: + files: | + openrct2-${{ needs.build_variables.outputs.name }}-sha1sums.txt + OpenRCT2-${{ needs.build_variables.outputs.name }}-* + body_path: release_notes.txt + tag_name: ${{ needs.build_variables.outputs.name }} From 1ae9bf2c26986cd27ec9091f6ff1b7cca1eba997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 8 Oct 2024 11:41:50 +0200 Subject: [PATCH 45/97] Update artifact name --- .github/workflows/ci.yml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25e875daf3..e6ace01085 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,8 @@ jobs: name: Get version info runs-on: ubuntu-latest outputs: - name: ${{ steps.ghd.outputs.describe }} + name: ${{ steps.artifact-name.outputs.name }} + describe: ${{ steps.ghd.outputs.describe }} short-sha: ${{ steps.ghd.outputs.short-sha }} distance: ${{ steps.ghd.outputs.distance }} tag: ${{ steps.ghd.outputs.tag }} @@ -46,14 +47,32 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + # We cannot use proudust/gh-describe, as it reports incorrect (too short) short-sha - name: Git describe id: ghd - uses: proudust/gh-describe@v2 + run: | + TAG=$(git describe --abbrev=0 --tags) + DESCRIBE=$(git describe --tags) + SHORT_SHA=$(git rev-parse --short HEAD) + DISTANCE=$(git rev-list --count $TAG..HEAD) + echo "tag=$TAG" >> $GITHUB_OUTPUT + echo "describe=$DESCRIBE" >> $GITHUB_OUTPUT + echo "short-sha=$SHORT_SHA" >> $GITHUB_OUTPUT + echo "distance=$DISTANCE" >> $GITHUB_OUTPUT - name: Set env id: setenv run: | . scripts/setenv -q echo "push=$OPENRCT2_PUSH" >> $GITHUB_OUTPUT + # Name is very similar to "describe", but skips the "v" prefix + - name: Get artifact name + id: artifact-name + run: | + if [ ${{ steps.ghd.outputs.distance }} -eq 0 ]; then + echo "name=${{ env.OPENRCT2_VERSION }}" >> $GITHUB_OUTPUT + else + echo "name=${{ env.OPENRCT2_VERSION }}-${{ steps.ghd.outputs.distance }}-${{ steps.ghd.outputs.short-sha }}" >> $GITHUB_OUTPUT + fi lint-commit: name: Lint Commit Message if: github.event_name == 'pull_request' From ad0f703ca828c60add6dcecabbbb9a7ed8d1a980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Thu, 10 Oct 2024 23:33:33 +0200 Subject: [PATCH 46/97] Remove old upload code to prevent uploading twice As we now upload in dedicated job to our own repo without any intermediary, there's no need to keep the upload-build script nor the steps executing it --- .github/workflows/ci.yml | 41 ++--------------------------------- scripts/upload-build | 47 ---------------------------------------- 2 files changed, 2 insertions(+), 86 deletions(-) delete mode 100755 scripts/upload-build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6ace01085..f27f3ec26e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,16 +196,13 @@ jobs: with: paths: "artifacts/test-**.xml" if: matrix.platform != 'arm64' - - name: Upload artifacts (openrct2.org) + - name: Upload symbols (backtrace.io) run: | . scripts/setenv if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-portable-$PLATFORM.zip "windows-portable-$PLATFORM.zip" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-installer-$PLATFORM.exe "windows-installer-$PLATFORM.exe" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-symbols-$PLATFORM.zip "windows-symbols-$PLATFORM.zip" $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH upload-backtrace-symbols artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-windows-symbols-*.zip else - echo 'Not going to push build' + echo 'Not going to push build' fi windows-mingw: name: Windows (${{ matrix.platform_name }}) using mingw @@ -341,14 +338,6 @@ jobs: name: OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-universal path: artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-macos-universal.zip if-no-files-found: error - - name: Upload artifacts (openrct2.org) - run: | - . scripts/setenv - if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-macos-universal.zip macos-universal.zip $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - else - echo 'Not going to push build' - fi linux-portable: name: ${{ matrix.distro }} Linux (${{ matrix.release }}, ${{ matrix.platform }}, portable) runs-on: ubuntu-latest @@ -394,15 +383,6 @@ jobs: if-no-files-found: error - name: Run Tests run: . scripts/setenv -q && run-tests - - name: Upload artifacts (openrct2.org) - run: | - # Build identification code: https://github.com/Limetric/OpenRCT2.org/blob/e5b738f3dadcc5a3b78e8dfd434756ff31eaa1d3/src/misc/releaseAsset.js#L94-L116 - . scripts/setenv -q - if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-${{ runner.os }}-${{ matrix.release }}-${{ matrix.platform }}.tar.gz linux-${{ matrix.platform }}-${{ matrix.distro }}.tar.gz $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - else - echo 'Not going to push build' - fi linux-appimage: name: Ubuntu Linux (AppImage, x86_64) runs-on: ubuntu-latest @@ -433,15 +413,6 @@ jobs: name: OpenRCT2-${{ needs.build_variables.outputs.name }}-AppImage path: artifacts if-no-files-found: error - - name: Upload artifacts (openrct2.org) - run: | - # Build identification code: https://github.com/Limetric/OpenRCT2.org/blob/e5b738f3dadcc5a3b78e8dfd434756ff31eaa1d3/src/misc/releaseAsset.js#L94-L116 - . scripts/setenv -q - if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-linux-x86_64.AppImage linux.AppImage $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - else - echo 'Not going to push build' - fi linux-docker: name: Ubuntu Linux (Docker) needs: check-code-formatting @@ -552,14 +523,6 @@ jobs: name: OpenRCT2-${{ needs.build_variables.outputs.name }}-Android path: artifacts if-no-files-found: error - - name: Upload artifacts (openrct2.org) - run: | - . scripts/setenv -q - if [[ "$OPENRCT2_PUSH" == "true" ]]; then - upload-build artifacts/OpenRCT2-${{ needs.build_variables.outputs.name }}-android-arm.apk android-arm.apk $OPENRCT2_VERSION $OPENRCT2_SHA1 $OPENRCT2_BRANCH - else - echo 'Not going to push build' - fi release: name: Release runs-on: ubuntu-latest diff --git a/scripts/upload-build b/scripts/upload-build deleted file mode 100755 index 5dbb4dc37c..0000000000 --- a/scripts/upload-build +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if [[ "$#" -ne 4 && "$#" -ne 5 ]]; then - echo 'Upload an OpenRCT2 build to openrct2.org.' - echo '' - echo 'Usage: upload-build []' - echo 'Flavours: windows-portable-x86, windows-portable-x64' - echo ' windows-installer-x86, windows-installer-x64' - echo ' windows-symbols-x86, windows-symbols-x64' - echo ' macos' - echo ' linux-i686, linux-x86_64' - echo ' android-arm, android-x86' - echo '' - echo 'Environment variable ''OPENRCT2_ORG_TOKEN'' must be set.' - exit 1 -fi - -path=$1 -flavour=$2 -version=$3 -sha1=$4 -branch=$5 - -if [ -n "$branch" ]; then - versionextra=-$branch-${sha1::10} -fi -filename=OpenRCT2-$version$versionextra-$flavour - -echo -e "\033[0;36mUploading to openrct2.org as '$filename'..." -if [ -z "$OPENRCT2_ORG_TOKEN" ]; then - echo -e "\033[0;31mOPENRCT2_ORG_TOKEN not set" - exit 1 -fi -# Use HTTP1.1 as a workaround for curl bug: -# https://github.com/actions/runner-images/issues/7329 -# https://github.com/curl/curl/issues/10591 -curl --include -m 300 --connect-timeout 5 -o - \ - --http1.1 \ - --form "key=$OPENRCT2_ORG_TOKEN" \ - --form "fileName=$filename" \ - --form "version=$version" \ - --form "gitHash=$sha1" \ - --form "gitBranch=$branch" \ - --form "file=@$path" \ - "https://openrct2.org/altapi/?command=push-build" From 836b8f0e1d60267ddc413fa12262a8a41396cfba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Fri, 18 Oct 2024 23:07:16 +0200 Subject: [PATCH 47/97] Fix upload target of develop CI builds (#23021) --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f27f3ec26e..2cdbab306f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -582,6 +582,8 @@ jobs: uses: softprops/action-gh-release@v2 if: ${{ needs.build_variables.outputs.push }} with: + repository: OpenRCT2/OpenRCT2-binaries + token: ${{ secrets.OPENRCT2_BINARIES_CI_UPLOAD }} files: | openrct2-${{ needs.build_variables.outputs.name }}-sha1sums.txt OpenRCT2-${{ needs.build_variables.outputs.name }}-* From f0c353254f515624e5e636c5271d8f12316f438f Mon Sep 17 00:00:00 2001 From: OpenRCT2 git bot Date: Sat, 19 Oct 2024 04:02:06 +0000 Subject: [PATCH 48/97] Merge Localisation/master into OpenRCT2/develop --- data/language/ja-JP.txt | 1049 ++++++++++++++++++++++++++------------- 1 file changed, 702 insertions(+), 347 deletions(-) diff --git a/data/language/ja-JP.txt b/data/language/ja-JP.txt index 8f69fe273b..4caa76ef28 100644 --- a/data/language/ja-JP.txt +++ b/data/language/ja-JP.txt @@ -94,15 +94,20 @@ STR_0089 :ミニジェットコースター STR_0090 :鉱山ライド STR_0091 :Unknown Ride (59) STR_0092 :リニアモーターコースター -STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops. -STR_0513 :A looping roller coaster where the riders ride in a standing position +STR_0093 :ハイブリッドコースター +STR_0094 :シングルレール・ジェットコースター +STR_0095 :アルパインコースター +STR_0096 :クラシック木製ジェットコースター +STR_0097 :クラシック・スタンドアップ・ジェットコースター +STR_0512 :スパイラルリフトヒルと滑らかで曲がりくねった落下を持つコンパクトなジェットコースター +STR_0513 :ライダーが立った状態で乗るループ型ジェットコースター STR_0514 :コースターのコースにぶら下がった車両は、コーナーにさしかかるとコースサイドに振り出されま -STR_0515 :A steel roller coaster with trains that are held beneath the track, with many complex and twisting track elements +STR_0515 :トラックの下に支えられた車両を持つスチール製ジェットコースターで、多くの複雑で曲がりくねったトラック要素があります STR_0516 :まだ大きなライドに挑戦する勇気がない人々のための、穏やかなローラーコースターです。 STR_0517 :狭い軌間の線路に沿って移動するミニチュア電車に乗客を乗せる。 STR_0518 :モノレールトラックを移動する電車。 STR_0519 :乗客はう特別にデザインされた車両に乗り、コーナーで制限なく振られる。 -STR_0520 :A dock platform where guests can drive/row personal watercraft on a body of water +STR_0520 :ゲストが水上バイクを運転または漕ぐことができるドックプラットフォーム STR_0521 :小さなネズミ型の車両がヘアピンコーナーと急な落下を横断して不安定に身を乗り出す。強烈度が高いはずです。 STR_0522 :単線のコースタートラックに沿って走る、馬の形をした車両に乗客を乗せる。 STR_0523 :乗客は、軌道の付いたルートを動力付きの車両でゆっくりと移動します @@ -114,14 +119,14 @@ STR_0528 :ねじれた半円(あるいは完全に覆われた)パイプ STR_0529 :古い鉄道を模して作られた金属のコースタートラックを鉱山電車テーマのローラーコースターが疾走する。 STR_0530 :車両は鋼のケーブルに吊られてライドの端からもう一方の端まで行き、そして戻ってくる。 STR_0531 :コークスクリューやループを伴う金属製トラックの小型ローラーコースター。 -STR_0532 :Maze is constructed from 6-foot tall hedges or walls, and guests wander around the maze leaving only when they find the exit +STR_0532 :迷路は6フィートの高さの生け垣や壁で構成されており、ゲストは出口を見つけるまで迷路の中を歩き回ります STR_0533 :内部に階段を、外部に螺旋滑り台とマットを有する木造の建築物。 STR_0534 :乗客が自分で運転するガソリンエンジンのゴーカート。 STR_0535 :丸太の形のボードが溝に沿って移動し、急斜面で乗客を水浸しにする。 STR_0536 :滝の水しぶきや急流部分を通る広い溝に沿って流れる円形のボート。 -STR_0537 :Self-drive electric dodgem cars -STR_0538 :Large swinging pirate ship -STR_0539 :Ship is attached to an arm with a counterweight at the opposite end, and swings through a complete 360 degrees +STR_0537 :自動運転の電動ドッジカー +STR_0538 :大きな振り子式海賊船 +STR_0539 :船は反対側にカウンターウェイトのあるアームに取り付けられており、360度完全に振り子のように揺れます STR_0540 :食べ物を売ります店です。 STR_0542 :飲み物を売ります店です。 STR_0544 :お土産を売ります店です。 @@ -134,11 +139,11 @@ STR_0551 :ジオデシック・ドームの中で3D映画が放映されて STR_0552 :星の形を形成して回転するゴンドラにさらに回転アームが接続。 STR_0553 :同心上の旋回リングが乗客をあらゆる方向に振り回す。 STR_0554 :リニア誘導モーターで加速された車両が垂直トラックを上昇し、それから乗り場まで自由落下する -STR_0555 :Guests ride in a lift up or down a vertical tower to get from one level to another +STR_0555 :ゲストは垂直のタワーのリフトに乗って、ある階から別の階へ移動します STR_0556 :究極の自由落下体験のために、完全な垂直軌道を降下するとても広幅の車両を持つコースターです。 STR_0557 :お金が無くなったゲストが使うキャッシュ機です。 -STR_0558 :Riders ride in pairs of seats rotating around the ends of three long rotating arms -STR_0559 :Large themed building containing scary corridors and spooky rooms +STR_0558 :ライダーは、3本の長い回転アームの端を回るペアの座席に乗ります +STR_0559 :怖い廊下や不気味な部屋がある大きなテーマビル STR_0560 :気分が悪くなったピープや怪我をしたピープを救護するための施設。 STR_0561 :サーカステントの中でサーカス用動物とピエロがショーを行う。 STR_0562 :特別なエフェクトと景観を有する多段トラックを移動するエンジン付き車両。 @@ -160,24 +165,30 @@ STR_0580 :300フィート以上のリフトアップとドロップが可能 STR_0581 :座席のリングが穏やかに回転しながら塔の最上部まで持ち上げられ、それから自由落下し、磁器ブレーキにより最下部でゆっくり停止する。 STR_0582 :自分で運転するホバークラフトです。 STR_0583 :その家の中は通路も部屋も曲がりくねっており、訪れた人々の方向感覚を狂わせる。 -STR_0584 :Special bicycles run on a steel monorail track, propelled by the pedalling of the riders +STR_0584 :特別な自転車がスチールのモノレールトラックの上を走り、ライダーのペダル漕ぎによって推進されます STR_0585 :トラックに吊り下げられた席に座り、乗客は休む間もなくループやツイストを体験する。 STR_0586 :ボート型の車両がねじれたカーブや急降下を含むトラックを滑走し、穏やかな川のセクションに着水する。 STR_0587 :車両は空圧により勢いよく発車して垂直トラックを駆け上がり、トップに達して別方向を垂直落下して乗り場に帰還する。 STR_0588 :連結していない個々の車両が、ヘアピンターンと急降下のあるジグザグのトラックを滑走する。 STR_0589 :4本のアームにより周期的に上下する、空飛ぶじゅうたんをテーマにした車。 STR_0590 :ミニ潜水艦に乗って水中のコースを走る。 -STR_0591 :Raft-shaped boats gently meander around a river track +STR_0591 :いかだの形をしたボートが川のコースを穏やかに漂います STR_0593 :ポッドを吊した回転ホイールが、回転を始めた後に支持アームによって上に傾けられる。 STR_0598 :乗り場から一気に加速される車両が、トラックを垂直に上昇して、もう一方の垂直トラックを戻る。 STR_0599 :コンパクトなローラーコースターで個別の車両を持ち、スムーズなひねり急降下があります STR_0600 :動力を持つ鉱山の列車が、スムースなツイスト・トラック・レイアウトに沿って走る。 STR_0602 :ローラーコースター車両はリニア誘導モーター(LIM)で加速され、ツイストや回転のあるコースを疾走する。 +STR_0603 :スチールトラックを持つ木製スタイルのジェットコースターで、急な落下や反転が可能です。 +STR_0604 :ライダーは狭いモノレールトラックに1列に並んで乗り、急な反転や方向転換をしながらレースします +STR_0605 :ライダーは曲がりくねったスチールトラックをトボガンで滑り降り、ブレーキを使ってスピードを調整します +STR_0606 :古いスタイルの木製ジェットコースターで、速くて揺れる乗り心地が特徴で、たくさんのエアタイムや横Gを感じられ、「制御を失った」ようなデザインになっています +STR_0607 :激しい古いスタイルのスチール製ループ型ジェットコースターで、ライダーは立った状態で乗ります STR_0767 :来客{INT32} STR_0768 :清掃員{INT32} STR_0769 :整備士{INT32} STR_0770 :警備員{INT32} STR_0771 :エンターテイナー{INT32} +STR_0777 :名前のない公園 STR_0778 :バナー STR_0779 :1日 STR_0780 :2日 @@ -237,7 +248,6 @@ STR_0833 :ゲームをポーズする STR_0834 :ディスクとゲームオプション STR_0839 :{UINT16} x {UINT16} STR_0840 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{UINT16} x {UINT16} -# The following six strings were used for display resolutions, but have been replaced. STR_0847 :OpenRCT2について STR_0850 :{WINDOW_COLOUR_2}Copyright © 2002 Chris Sawyer, all rights reserved STR_0851 :{WINDOW_COLOUR_2}Designed and programmed by Chris Sawyer @@ -1878,7 +1888,7 @@ STR_2568 :Execute STR_2569 :Snapshot STR_2570 :Insert STR_2571 :Delete -STR_2572 :ヘルプ +STR_2572 :Help STR_2618 :Menu STR_2621 :NumPad 0 STR_2622 :NumPad 1 @@ -1897,20 +1907,20 @@ STR_2635 :NumPad . STR_2636 :NumPad / STR_2669 :NumLock STR_2670 :Scroll -STR_2680 :All research complete -STR_2684 :Large group of guests arrive -STR_2685 :Simplex Noise Parameters -STR_2686 :Low: -STR_2687 :High: -STR_2688 :Base Frequency: -STR_2689 :Octaves: -STR_2690 :Map Generation +STR_2680 :すべての研究の完了 +STR_2684 :大量のゲストが到着する +STR_2685 :シンプルノイズのパラメータ +STR_2686 :最小土地高さ: +STR_2687 :最大土地高さ: +STR_2688 :基準周波数: +STR_2689 :オクターブ: +STR_2690 :マップジェネレーション STR_2691 :ベースの高さ: -STR_2692 :Water level: -STR_2693 :Terrain: -STR_2694 :Generate -STR_2695 :Random terrain -STR_2696 :Place trees +STR_2692 :水高さ: +STR_2693 :地形: +STR_2694 :生成する +STR_2695 :地形をランダム化する +STR_2696 :木を配置する STR_2700 :自動セーブ頻度: STR_2701 :毎1分 STR_2702 :毎5分 @@ -2072,20 +2082,20 @@ STR_2992 :バナーのテキト STR_2993 :テキトを入力してください: STR_2994 :看板の文字を変更 STR_2995 :この看板を除去する -STR_2996 :{BLACK}ABC -STR_2997 :{GREY}ABC -STR_2998 :{WHITE}ABC -STR_2999 :{RED}ABC -STR_3000 :{GREEN}ABC -STR_3001 :{YELLOW}ABC -STR_3002 :{TOPAZ}ABC -STR_3003 :{CELADON}ABC -STR_3004 :{BABYBLUE}ABC -STR_3005 :{PALELAVENDER}ABC -STR_3006 :{PALEGOLD}ABC -STR_3007 :{LIGHTPINK}ABC -STR_3008 :{PEARLAQUA}ABC -STR_3009 :{PALESILVER}ABC +STR_2996 :{BLACK}あいう +STR_2997 :{GREY}あいう +STR_2998 :{WHITE}あいう +STR_2999 :{RED}あいう +STR_3000 :{GREEN}あいう +STR_3001 :{YELLOW}あいう +STR_3002 :{TOPAZ}あいう +STR_3003 :{CELADON}あいう +STR_3004 :{BABYBLUE}あいう +STR_3005 :{PALELAVENDER}あいう +STR_3006 :{PALEGOLD}あいう +STR_3007 :{LIGHTPINK}あいう +STR_3008 :{PEARLAQUA}あいう +STR_3009 :{PALESILVER}あいう STR_3010 :ファイルをロードすることができません… STR_3011 :ファイルには無効なデータが含まれています STR_3045 :音楽のスタイルの選定 @@ -2109,7 +2119,7 @@ STR_3066 :名手のパーク STR_3067 :現実のパーク STR_3068 :外のパーク STR_3069 :トップの部分 -STR_3070 :Slope to Level +STR_3070 :傾斜から水平 STR_3071 :{WINDOW_COLOUR_2}パーク中で同一価格 STR_3072 :この価格を園内全体に使用するかどうかを選択 STR_3073 :{RED}警告:遊園地のランクが700以下に下がりました!{NEWLINE} 4週間以内にランクを上げることができなかった場合、遊園地は閉鎖されてしまいます @@ -2171,7 +2181,7 @@ STR_3141 :ケーブルリフトヒルでは各乗物の複数周回路は不 STR_3142 :{WINDOW_COLOUR_2}収容能力: {BLACK}{STRINGID} STR_3143 :マップ上の人々を表示 STR_3144 :マップ上の乗物と売店を表示 -STR_3160 :Select the number of circuits per ride +STR_3160 :乗り物ごとの周回数を選択する STR_3162 :充分なメモリーを割り当てられません STR_3163 :新規データをインストール中: STR_3164 :{BLACK}{COMMA16} 選択(最高{COMMA16}) @@ -2399,7 +2409,7 @@ STR_5122 :RCT1のようにライドタイプ選定 STR_5123 :ライドを新品にする STR_5125 :全て解体できる STR_5126 :ランダムのタイトル音楽 -STR_5127 :While dragging, paint landscape instead of changing elevation +STR_5127 :ドラッグ中に、標高を変更するのではなく風景を塗る STR_5128 :選択範囲 STR_5129 :{COMMA16}と{COMMA16}の間に選択範囲を入力して下さい。 STR_5130 :マップサイズ @@ -2409,11 +2419,11 @@ STR_5133 :パーク敷地のもっと小量の調整 STR_5134 :パーク敷地のもっと大量の調整 STR_5135 :パーク敷地や土地利用権を購入する STR_5136 :パーク敷地 -STR_5137 :Unlock operating limits +STR_5137 :運営制限を解除する STR_5138 :{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} -STR_5140 :Disable brakes failure -STR_5141 :Disable all breakdowns +STR_5140 :ブレーキの故障を無効にする +STR_5141 :すべての故障を無効にする STR_5142 :通常スピード STR_5143 :クイックスピード STR_5144 :高速スピード @@ -2427,8 +2437,8 @@ STR_5151 :, STR_5152 :. STR_5153 :テーマを変更する STR_5154 :ハードウェア表示 -STR_5155 :Allow testing of unfinished tracks -STR_5156 :Allows testing of most ride types even when the track is unfinished, does not apply to block sectioned modes +STR_5155 :未完成のトラックのテストを許可する +STR_5156 :トラックが未完成でもほとんどの乗り物タイプのテストを許可し、ブロックセクションモードには適用されません STR_5158 :メニューに戻る STR_5159 :OpenRCT2終了 STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID} {POP16}{COMMA16}年 @@ -2521,7 +2531,7 @@ STR_5261 :フィルター STR_5262 :ワッキーワールド STR_5263 :タイムツイスター STR_5264 :カスタム -STR_5265 :Select which content sources are visible +STR_5265 :どのコンテンツソースを表示するか選択する STR_5266 :表示 STR_5267 :文化と単位 STR_5268 :音楽 @@ -2535,15 +2545,15 @@ STR_5276 :オブジェクトの名を入力して下さい。 STR_5277 :クリア STR_5278 :サンドボックスモード STR_5279 :サンドボックスモードを切る -STR_5280 :Allow editing land ownership settings through the Map window and other options that are normally restricted to the Scenario Editor -STR_5281 :Features +STR_5280 :マップウィンドウを通じて土地所有設定の編集を許可し、通常はシナリオエディターに制限される他のオプションも許可する +STR_5281 :機能 STR_5282 :RCT1のライド「稼動/閉鎖」信号機 STR_5283 :RCT1のパーク「稼動/閉鎖」信号機 STR_5284 :RCT1ののシナリオ選定フォント -STR_5287 :Ride is already broken down -STR_5288 :Ride is closed -STR_5289 :No breakdowns available for this ride -STR_5290 :Fix ride +STR_5287 :乗り物はすでに故障しています +STR_5288 :乗り物は閉鎖されています +STR_5289 :この乗り物には故障が発生しません +STR_5290 :乗り物を修理する STR_5291 :故障を強制できません STR_5292 :故障を強制する STR_5293 :ライド/アトラクションの閉鎖 @@ -2553,10 +2563,10 @@ STR_5296 :遊園地を閉める STR_5297 :遊園地を開ける STR_5298 :{RED}{STRINGID} STR_5299 :{LIGHTPINK}{STRINGID} -STR_5300 :Quick fire staff -STR_5301 :Clear your loan +STR_5300 :スタッフを即座に解雇する +STR_5301 :ローンを削除する STR_5302 :借入額をクリアする -STR_5303 :Allow building in pause mode +STR_5303 :ポーズ中の建設を許可する STR_5304 :タイトル順序: STR_5305 :RollerCoaster Tycoon 1 STR_5306 :RollerCoaster Tycoon 1 (AA) @@ -2571,7 +2581,7 @@ STR_5314 :タイルインスペクター STR_5335 :ライド入口 STR_5336 :ライド出口 STR_5337 :パーク入口 -STR_5338 :Element type +STR_5338 :要素タイプ STR_5339 :ベースの高さ STR_5340 :クリアランス高さ STR_5343 :自動的にスタッフを配置する @@ -2599,16 +2609,16 @@ STR_5364 :15以下 STR_5365 :{BLACK}スタッフのスピード: STR_5366 :普通 STR_5367 :速い -STR_5368 :Reset crash status +STR_5368 :クラッシュ状態をリセットする STR_5371 :オブジェクト選定 -STR_5372 :Invert right mouse dragging +STR_5372 :右マウスドラッグを反転する STR_5373 :名前 {STRINGID} STR_5374 :日時 {STRINGID} STR_5375 :▲ STR_5376 :▼ -STR_5404 :Name already exists +STR_5404 :名前はすでに存在します STR_5440 :フォーカス損失時に全画面を最小化 -STR_5442 :Force park rating: +STR_5442 :パーク評価を設定する: STR_5447 :タイプ {STRINGID} STR_5448 :ライド/乗り物 {STRINGID} STR_5449 :ゲームのスピードを下げる @@ -2623,10 +2633,10 @@ STR_5457 :サポート制限を無効にする STR_5458 :右へ回転する STR_5459 :左へ回転する STR_5460 :ビュウを左へ回転する -STR_5461 :Set guests’ parameters +STR_5461 :すべてのゲストのパラメータ STR_5462 :{CURRENCY} STR_5463 :楽しむの目的 -STR_5464 :General +STR_5464 :一般設定 STR_5465 :天気 STR_5466 :スタッフ STR_5467 :ALT + @@ -2650,7 +2660,7 @@ STR_5484 :{BLACK}(残り{COMMA16}週間) STR_5485 :{STRING} STR_5486 :{BLACK}{COMMA16} STR_5487 :最近のメッセージの表示 -STR_5489 :Show only tracked guests +STR_5489 :トラッキングされたゲストのみ表示する STR_5490 :フォーカス損失時に音を切る STR_5491 :発明品リスト STR_5492 :シナリオ設定 @@ -2666,7 +2676,7 @@ STR_5502 :マルチプレイ STR_5503 :ホスト名またはIPアドレスを入力してください: STR_5504 :マルチプレイのステイタスの表示 STR_5505 :サーバに接続できない -STR_5506 :Guests ignore intensities +STR_5506 :ゲストは強度を無視する STR_5510 :デフォルトのサウンドデバイス STR_5511 :(未知) STR_5512 :名前を保存 @@ -2711,24 +2721,24 @@ STR_5550 :{POP16}{POP16}{COMMA16}年 {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16} STR_5551 :年日月 STR_5552 :{POP16}{POP16}{COMMA16}年 {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH} STR_5553 :Steamオーバーレイが開いている時に一時停止する -STR_5554 :Enable mountain tool -STR_5555 :Show vehicles from other track types +STR_5554 :マウンテンツールを切り替える +STR_5555 :他のトラックタイプの乗り物を表示する STR_5556 :プレイヤーを蹴る STR_5557 :非同期化後に接続を維持する(マルチプレイ) -STR_5558 :A restart is required for this setting to take effect -STR_5559 :10 min. inspections -STR_5560 :Sets the inspection time to ‘Every 10 minutes’ on all rides -STR_5561 :Failed to load language +STR_5558 :この設定を適用するには再起動が必要です +STR_5559 :10分ごとの点検 +STR_5560 :すべての乗り物の点検時間を「10分ごと」に設定する。 +STR_5561 :言語の読み込みに失敗しました STR_5562 :ご注意! -STR_5563 :This feature is currently unstable, take extra caution. +STR_5563 :この機能は現在不安定ですので、十分に注意してください STR_5566 :パスワード: STR_5567 :発表する STR_5568 :パスワードが必要 STR_5569 :このサーバはパスワードが必要 STR_5570 :リストを更新する -STR_5571 :Join Game -STR_5572 :Add To Favourites -STR_5573 :Remove From Favourites +STR_5571 :ゲームに参加する +STR_5572 :お気に入りに追加す +STR_5573 :お気に入りから削除する STR_5574 :サーバの名前: STR_5575 :プレイヤーの制限: STR_5576 :ポート: @@ -2737,12 +2747,12 @@ STR_5578 :ロシア・ルーブル (₽) STR_5579 :ウインドウのスケール: STR_5580 :チェコ・コルナ (Kč) STR_5581 :FPSを表示する -STR_5582 :Trap mouse cursor in window +STR_5582 :ウィンドウ内でマウスカーソルを制限する STR_5583 :{COMMA1DP16}m/s STR_5584 :SI -STR_5585 :Unlocks ride operation limits, allowing for things like {VELOCITY} lift hills -STR_5586 :Automatically open shops and stalls -STR_5587 :Shops and stalls will be automatically opened after building them +STR_5585 :乗り物の運営制限を解除し、{VELOCITY} のリフトヒルなどを可能にします +STR_5586 :ショップと屋台を自動的に開く +STR_5587 :ショップと屋台は建設後に自動的に開かれます STR_5588 :他のプレイヤーと一緒にゲームする STR_5589 :知らせ設定 STR_5590 :パークの賞罰 @@ -2761,16 +2771,16 @@ STR_5603 :ゲストがライドを出る STR_5604 :ゲストが売り物を買った STR_5605 :ゲストが設備を使った STR_5606 :ゲストが死んだ -STR_5607 :Forcefully remove selected map element. -STR_5608 :BH -STR_5609 :CH -STR_5610 :Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution. +STR_5607 :選択したマップ要素を強制的に削除する +STR_5608 :ベ高 +STR_5609 :ク高 +STR_5610 :現在選択されているマップ要素を削除します。これは強制的に削除されるため、現金は使用されず、得られることもありません。使用には注意してください。 STR_5611 :化 STR_5612 :お化けを示すフラグ STR_5613 :壊 STR_5614 :破損を示すフラグ -STR_5615 :L -STR_5616 :Last element for tile flag +STR_5615 :最後 +STR_5616 :タイルフラグの最後の要素 STR_5617 :選択された要素を上に移動する STR_5618 :選択された要素を下に移動する STR_5619 :ローラーコースタータイクーン @@ -2789,24 +2799,24 @@ STR_5631 :オリジナルDLCパーク STR_5632 :自分だけのビルド… STR_5633 :CMD + STR_5634 :OPTION + -STR_5635 :{WINDOW_COLOUR_2}Money spent: {BLACK}{CURRENCY2DP} -STR_5636 :{WINDOW_COLOUR_2}Commands ran: {BLACK}{COMMA16} +STR_5635 :{WINDOW_COLOUR_2}支出金額:{BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}実行されたコマンド:{BLACK}{COMMA16} STR_5637 :それはできません… STR_5638 :アクセス拒否 -STR_5639 :Show list of players -STR_5640 :Manage groups +STR_5639 :プレイヤーのリストを表示する +STR_5640 :グループを管理する STR_5641 :デファルトのグループ: STR_5642 :グループ STR_5643 :新しいグループ STR_5644 :グループを退ける STR_5645 :チャット STR_5646 :テラフォーム -STR_5647 :Toggle Pause -STR_5648 :Set Water Level -STR_5649 :Create Ride -STR_5650 :Remove Ride -STR_5651 :Build Ride -STR_5652 :Ride Properties +STR_5647 :ポーズを切り替える +STR_5648 :水位を設定する +STR_5649 :乗り物を作成する +STR_5650 :乗り物を削除する +STR_5651 :乗り物を建設する +STR_5652 :乗り物の設定 STR_5653 :景色物 STR_5654 :歩道 STR_5655 :ゲスト @@ -2817,22 +2827,22 @@ STR_5659 :プレイヤーを蹴る STR_5660 :グループを変更する STR_5661 :プレイヤーのグループに設定する STR_5662 :N/A -STR_5663 :Clear Landscape +STR_5663 :景色をクリアする STR_5664 :カンニング -STR_5665 :Toggle Scenery Cluster -STR_5666 :Passwordless Login +STR_5665 :景観クラスタを切り替える +STR_5666 :パスワードなしログイン STR_5701 :{WINDOW_COLOUR_2}最後のアクション: {BLACK}{STRINGID} STR_5702 :プレイヤーの最後のアクションをに移動 STR_5703 :ホストを蹴られません STR_5704 :最後のアクション -STR_5705 :Can’t set to this group -STR_5706 :Can’t remove group that players belong to -STR_5707 :This group cannot be modified -STR_5708 :Can’t change the group that the host belongs to +STR_5705 :このグループに設定できません +STR_5706 :プレイヤーが所属しているグループは削除できません +STR_5707 :このグループは変更できません +STR_5708 :ホストが所属するグループは変更できません STR_5709 :グループ名を変える STR_5710 :グループ名 STR_5711 :グループ名を入力してください。 -STR_5712 :Can’t modify permission that you do not have yourself +STR_5712 :自分が持っていない権限を変更することはできません STR_5713 :プレイヤーを蹴る STR_5714 :設定ウィンドウの表示 STR_5715 :新しいゲーム @@ -2869,9 +2879,9 @@ STR_5750 :接続が切断されました。 STR_5751 :データなし STR_5752 :{OUTLINE}{RED}{STRING}が切断されました STR_5753 :{OUTLINE}{RED}{STRING}が切断されました ({STRING}) -STR_5754 :Bad Player Name +STR_5754 :無効なプレイヤー名 STR_5755 :不適切なソフトウェアバージョン(サーバは{STRING}を使用しています) -STR_5756 :Bad Password +STR_5756 :無効なパスワード STR_5757 :サーバがいっぱいです STR_5758 :{OUTLINE}{GREEN}{STRING}がゲームに参加しました。 STR_5759 :地図をダウンロード中… @@ -2879,8 +2889,8 @@ STR_5760 :香港ドル (HK$) STR_5761 :ニュー台湾ドル (NT$) STR_5762 :人民元 (CN¥) STR_5763 :全てのファイル -STR_5764 :Invalid ride type -STR_5765 :Cannot edit rides of invalid type +STR_5764 :無効な乗り物タイプ +STR_5765 :無効なタイプの乗り物は編集できません STR_5766 :ハンガリーのフォリント(Ft) STR_5767 :収入 STR_5768 :顧客総数 @@ -2901,93 +2911,93 @@ STR_5782 :今から接続中です。「{STRING}」でチャットできま STR_5783 :{WINDOW_COLOUR_2}シナリオがロック中 STR_5784 :{BLACK}このシナリオのロックを解除するために前のシナリオを完了して下さい。 STR_5785 :グループの名を変えません。 -STR_5786 :Invalid group name -STR_5787 :{COMMA32} players online -STR_5788 :Default inspection interval: +STR_5786 :無効なグループ名 +STR_5787 :{COMMA32}人のプレイヤーがオンライン +STR_5788 :デフォルトの点検間隔: STR_5789 :電光効果を無効にする -STR_5790 :Toggles RCT1-style pricing{NEWLINE}(e.g. both ride price and entrance price) -STR_5791 :Sets the reliability of all rides to 100%{NEWLINE}and resets their built date to “this year” -STR_5792 :Fixes all broken down rides -STR_5793 :Resets the crash history of a ride,{NEWLINE}so guests will not complain that its unsafe -STR_5794 :Some scenarios disable editing of some{NEWLINE}of the rides already in the park.{NEWLINE}This cheat lifts the restriction -STR_5795 :Guests ride every attraction in the park{NEWLINE}even if the intensity is extremely high -STR_5796 :Forces the park to close or open -STR_5797 :Disables weather changes and{NEWLINE}freezes the selected weather -STR_5798 :Allows building actions in pause mode -STR_5799 :Disables ride breakdowns and crashes due to brake failure -STR_5800 :Prevents rides from breaking down -STR_5801 :Disable littering -STR_5802 :Stops guests from littering and vomiting -STR_5803 :Rotate selected map element +STR_5790 :RCT1スタイルの料金を切り替える{NEWLINE}(例:乗り物の料金と入場料の両方) +STR_5791 :すべての乗り物の信頼性を100%に設定し{NEWLINE}その建設日を「今年」にリセットする +STR_5792 :故障した乗り物をすべて修理する +STR_5793 :乗り物のクラッシュ履歴をリセットし、ゲストが安全ではないと不満を言わないようにする +STR_5794 :一部のシナリオでは、公園内の{NEWLINE}すでに存在する乗り物の編集が無効になります{NEWLINE}このチートはその制限を解除します +STR_5795 :ゲストは公園内のすべてのアトラクションに乗ります{NEWLINE}たとえ強度が非常に高くても +STR_5796 :パークを強制的に閉鎖または開放する +STR_5797 :天候の変化を無効にし、選択した天候を固定する +STR_5798 :ポーズモードでの建設行動を許可する +STR_5799 :ブレーキの故障による乗り物の故障とクラッシュを無効にする +STR_5800 :乗り物の故障を防ぐ +STR_5801 :ごみを散らかさないようにする +STR_5802 :ゲストがごみを捨てたり嘔吐したりするのを止める +STR_5803 :選択したマップ要素を回転させる STR_5804 :音をミュートする -STR_5805 :If checked, your server will be added to the{NEWLINE}public server list so everyone can find it -STR_5806 :Toggle windowed mode +STR_5805 :チェックされている場合、あなたのサーバーは{NEWLINE}公共サーバーリストに追加され、誰でも見つけられるようになります。 +STR_5806 :ウィンドウモードを切り替える STR_5807 :{WINDOW_COLOUR_2}ライドの数: {BLACK}{COMMA16} STR_5808 :{WINDOW_COLOUR_2}ショップの数: {BLACK}{COMMA16} STR_5809 :{WINDOW_COLOUR_2}インフォメーションキオスクと設備などの数: {BLACK}{COMMA16} -STR_5810 :Disable vehicle limits -STR_5811 :If checked, you can have up to{NEWLINE}255 cars per train and 31{NEWLINE}trains per ride -STR_5812 :Show multiplayer window +STR_5810 :乗り物の制限を無効にする +STR_5811 :チェックされている場合、1編成あたり最大255台の車両と、1つの乗り物に対して31編成を持つことができます。 +STR_5812 :マルチプレイヤーのウィンドウを表示する STR_5813 :「{STRING}」 STR_5814 :{WINDOW_COLOUR_1}「{STRING}」 #tooltips -STR_5815 :Display FPS counter in-game -STR_5816 :Sets ratio to scale the game by.{NEWLINE}Most useful when playing in{NEWLINE}high resolutions -STR_5819 :[Requires hardware display]{NEWLINE}Pause the game if Steam{NEWLINE}in-game overlay is opened -STR_5820 :Minimise the game if focus is{NEWLINE}lost while in fullscreen mode -STR_5822 :Cycle between day and night.{NEWLINE}Full cycle takes one in-game month -STR_5823 :Display banners in uppercase (RCT1 behaviour) +STR_5815 :ゲーム内でFPSカウンターを表示する +STR_5816 :ゲームのスケール比率を設定する。{NEWLINE}高解像度でプレイする際に最も便利 +STR_5819 :[ハードウェアディスプレイが必要]{NEWLINE}Steamのゲーム内オーバーレイが開かれるとゲームを一時停止する +STR_5820 :フルスクリーンモードでフォーカスを失った場合、ゲームを最小化する +STR_5822 :昼と夜をサイクルする。{NEWLINE}フルサイクルはゲーム内の1か月を要する +STR_5823 :バナーを大文字で表示する(RCT1の動作) STR_5824 :雷雨時に電光効果を無効にする -STR_5825 :Keep the mouse cursor in the window -STR_5826 :Invert right mouse dragging of the viewport -STR_5827 :Sets the colour scheme used for the GUI -STR_5828 :Changes what measurement format is used for distances, speed, etc. -STR_5829 :Changes what currency format is used. Purely visual, there is no exact exchange rate implementation -STR_5830 :Changes what language is used -STR_5831 :Changes what format the{NEWLINE}temperature is displayed in -STR_5832 :Show height as generic units instead of measurement format set under “Distance and Speed” -STR_5833 :Changes what date format is used -STR_5834 :Select which audio device OpenRCT2 will use -STR_5835 :Mute the game if the window loses focus -STR_5836 :Select music to use on the main menu.{NEWLINE}Selecting RCT1 theme requires that you copy ‘data/css17.dat’ from your RCT1 game folder to ‘data/css50.dat’ in your RCT2 folder, or set the path to RCT1 in the Miscellaneous tab. -STR_5837 :Create and manage custom UI themes +STR_5825 :マウスカーソルをウィンドウ内に留める +STR_5826 :ビューポートの右マウスドラッグを反転する +STR_5827 :GUIに使用するカラースキームを設定する +STR_5828 :距離、速度などに使用する測定形式を変更する +STR_5829 :使用する通貨形式を変更する。純粋に視覚的なもので、正確な為替レートの実装はありません +STR_5830 :使用する言語を変更する +STR_5831 :温度の表示形式を変更する +STR_5832 :高さを「距離と速度」の下で設定した測定形式ではなく一般的な単位で表示する +STR_5833 :使用する日付形式を変更する +STR_5834 :OpenRCT2が使用するオーディオデバイスを選択する +STR_5835 :ウィンドウのフォーカスを失った場合、ゲームをミュートにする +STR_5836 :メインメニューで使用する音楽を選択する。{NEWLINE}RCT1のテーマを選択するには、RCT1ゲームフォルダーから「data/css17.dat」をコピーして、RCT2フォルダーの「data/css50.dat」に貼り付けるか、雑多タブでRCT1のパスを設定する必要があります。 +STR_5837 :カスタムUIテーマを作成し、管理する STR_5838 :ツールバーで財務表のボタンを表示する STR_5839 :ツールバーで研究設定のボタンを表示する STR_5840 :ツールバーでカンニングのボタンを表示する STR_5841 :ツールバーで最近のメッセージのボタンを表示する -STR_5842 :Sort scenarios into tabs by their difficulty (RCT2 behaviour) or their source game (RCT1 behaviour) -STR_5843 :Enable scenario unlocking (RCT1 behaviour) -STR_5844 :Stay connected to a multiplayer server{NEWLINE}even if a desync or error occurs -STR_5845 :Adds a button for{NEWLINE}debugging tools to the toolbar.{NEWLINE}Enables keyboard shortcut for developer console -STR_5846 :Set often OpenRCT2 automatically saves -STR_5847 :Select park sequence used on the title screen.{NEWLINE}Title sequences from RCT1/2 require imported scenarios to function -STR_5849 :Automatically place{NEWLINE}newly hired staff members -STR_5851 :Sets the default inspection interval{NEWLINE}on newly built rides -STR_5853 :Toggle sound effects on/off -STR_5854 :Toggle ride music on/off -STR_5855 :Set regular fullscreen, borderless fullscreen{NEWLINE}or windowed display -STR_5856 :Set game resolution when in fullscreen mode +STR_5842 :シナリオを難易度(RCT2の動作)または出典ゲーム(RCT1の動作)によってタブに分ける +STR_5843 :シナリオの段階的なアンロックを有効にする(RCT1の動作) +STR_5844 :デシンクやエラーが発生しても、マルチプレイヤーサーバーに接続を維持する +STR_5845 :ツールバーにデバッグツールのボタンを追加する。{NEWLINE}開発者コンソールのキーボードショートカットを有効にする +STR_5846 :OpenRCT2が自動的に保存する頻度を設定する +STR_5847 :タイトル画面で使用される公園のシーケンスを選択する。{NEWLINE}RCT1と2のタイトルシーケンスは、機能するためにインポートされたシナリオが必要です +STR_5849 :新しく雇ったスタッフメンバーを自動的に配置する +STR_5851 :新しく建設した乗り物のデフォルトの点検間隔を設定する +STR_5853 :効果音のオン/オフを切り替える +STR_5854 :乗り物の音楽のオン/オフを切り替える +STR_5855 :通常のフルスクリーン、ボーダレスフルスクリーン、{NEWLINE}またはウィンドウ表示を設定する +STR_5856 :フルスクリーンモードのゲーム解像度を設定する STR_5857 :ゲーム設定 -STR_5858 :Use GPU for displaying instead of CPU. Improves compatibility with screen capture software. May slightly decrease performance. -STR_5859 :Enables frame tweening for visually{NEWLINE}smoother gameplay. When disabled,{NEWLINE}the game will run at 40 FPS. -STR_5860 :Toggle original/decompiled track drawing -STR_5861 :Key verification failure. -STR_5862 :Block unknown players. -STR_5863 :Only allow players with known keys to join. -STR_5864 :This server only allows whitelisted players to connect. -STR_5865 :Log chat history -STR_5866 :Logs all chat history to files in your user directory. -STR_5867 :{WINDOW_COLOUR_2}プロバイダ名: {BLACK}{STRING} -STR_5868 :{WINDOW_COLOUR_2}プロバイダのメール: {BLACK}{STRING} -STR_5869 :{WINDOW_COLOUR_2}プロバイダのウェブサイト: {BLACK}{STRING} +STR_5858 :表示にCPUではなくGPUを使用する。画面キャプチャソフトウェアとの互換性を改善します。パフォーマンスがわずかに低下する可能があります +STR_5859 :視覚的に滑らかなゲームプレイのためにフレームツイーニングを有効にする。無効にすると、{NEWLINE}ゲームは40fpsで実行されます +STR_5860 :オリジナル/デコンパイルされたトラック描画を切り替える +STR_5861 :キーの確認に失敗しました。 +STR_5862 :不明なプレイヤーをブロックする。 +STR_5863 :知られたキーを持つプレイヤーのみ参加を許可する。 +STR_5864 :このサーバーはホワイトリストに登録されたプレイヤーのみ接続を許可します +STR_5865 :チャット履歴を記録する +STR_5866 :すべてのチャット履歴をユーザーディレクトリのファイルに記録する +STR_5867 :{WINDOW_COLOUR_2}プロバイダ名:{BLACK}{STRING} +STR_5868 :{WINDOW_COLOUR_2}プロバイダのメール:{BLACK}{STRING} +STR_5869 :{WINDOW_COLOUR_2}プロバイダのウェブサイト:{BLACK}{STRING} STR_5870 :サーバ報知の表示 -STR_5871 :Plants don’t age -STR_5872 :Disable plant ageing such that they don’t wilt. -STR_5873 :Allow chain lifts on all track pieces -STR_5874 :Allows any piece of track to be made into a chain lift +STR_5871 :植物の成長を無効にする +STR_5872 :植物が枯れないように成長を無効にする +STR_5873 :すべてのトラック部分でチェーンリフトを許可する +STR_5874 :任意のトラック部分をチェーンリフトにすることを許可する STR_5875 :レンダリングエンジン: -STR_5876 :ゲームのレンダリングに使用するエンジン。 +STR_5876 :ゲームのレンダリングに使用するエンジン STR_5877 :ソフトウェア STR_5878 :ソフトウェア(ハードウェア表示) STR_5879 :OpenGL(試験的) @@ -2996,35 +3006,35 @@ STR_5881 :選定ないだけ STR_5882 :カスタム通貨記号 STR_5883 :カスタム通貨記号設定 STR_5884 :{WINDOW_COLOUR_2}円相場: -STR_5885 :{WINDOW_COLOUR_2}は{COMMA32}GBP(£)と等価です。 +STR_5885 :{WINDOW_COLOUR_2}は{COMMA32}GBP(£)と等価です STR_5886 :{WINDOW_COLOUR_2}通貨記号: STR_5887 :接頭辞 STR_5888 :接尾辞 STR_5889 :カスタム通貨記号 -STR_5890 :通貨記号を入力して下さい。 +STR_5890 :通貨記号を入力して下さい STR_5891 :デフォルト STR_5892 :デフォルト・ディレクトリに移動 STR_5893 :円相場 -STR_5894 :円相場を入力して下さい。 +STR_5894 :円相場を入力して下さい STR_5895 :トラックをセーブする -STR_5896 :Track save failed! -STR_5898 :{BLACK}Can’t load the track, the file might be {newline}corrupted, broken or missing! -STR_5899 :Toggle paint debug window -STR_5900 :Use original drawing code -STR_5901 :Show segment heights -STR_5902 :Show bounding boxes -STR_5903 :Show paint debug window -STR_5904 :Reset date -STR_5905 :A map generation tool that automatically creates a custom landscape +STR_5896 :トラックの保存に失敗しました! +STR_5898 :{BLACK}トラックを読み込めません。ファイルが破損しているか、壊れているか、存在しない可能性があります! +STR_5899 :塗装デバッグウィンドウを切り替える +STR_5900 :オリジナルの描画コードを使用する +STR_5901 :セグメントの高さを表示する +STR_5902 :バウンディングボックスを表示する +STR_5903 :塗装デバッグウィンドウを表示する +STR_5904 :日付をリセットする +STR_5905 :カスタムランドスケープを自動的に作成するマップ生成ツール STR_5906 :マウスカーソルにズームする -STR_5907 :このオプションを有効にすると、ズームがマウスカーソルに中央します。 -STR_5908 :Allow arbitrary ride type changes -STR_5909 :Allows changing ride type freely. May cause crashes. -STR_5910 :Apply +STR_5907 :このオプションを有効にすると、ズームがマウスカーソルに中央します +STR_5908 :任意の乗り物タイプの変更を許可する +STR_5909 :乗り物タイプを自由に変更できる。クラッシュの原因になる可能性があります +STR_5910 :設定する STR_5911 :歩道透明度の切り替え STR_5912 :歩道透明度の切り替え STR_5913 :チャット -STR_5914 :Unknown ride +STR_5914 :不明なライド STR_5915 :プレイヤー STR_5916 :{COMMA16}プレイヤー STR_5917 :{COMMA16}プレイヤー @@ -3032,8 +3042,8 @@ STR_5918 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COM STR_5919 :{COMMA16} STR_5920 :天気効果をレンダリングする STR_5921 :このオプションを有効にすると、暴風雨ある時に雨と湿っぽい色でレンダリングします。 -STR_5922 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}Max {STRINGID} -STR_5923 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}Max {COMMA16} {STRINGID} per train +STR_5922 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}最大{STRINGID} +STR_5923 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}列車ごとに最大{COMMA16}{STRINGID}の車両 STR_5924 :面ディテール STR_5925 :歩道ディテール STR_5926 :トラック・ディテール @@ -3043,68 +3053,68 @@ STR_5929 :壁ディテール STR_5930 :大景色物ディテール STR_5931 :バナー・ディテール STR_5932 :破損要素ディテール -STR_5933 :Properties -STR_5934 :Terrain texture: {BLACK}{STRINGID} -STR_5935 :Terrain edge: {BLACK}{STRINGID} -STR_5936 :Land ownership: {BLACK}{STRINGID} -STR_5937 :Not owned and not for sale -STR_5938 :Water level: {BLACK}{COMMA16} -STR_5939 :Remove park fences -STR_5940 :Restore park fences -STR_5941 :Base height: -STR_5942 :Path name: {BLACK}{STRINGID} -STR_5943 :Additions: {BLACK}{STRINGID} -STR_5944 :Additions: {BLACK}None -STR_5945 :Connected edges: -STR_5946 :Ride type: {BLACK}{STRINGID} -STR_5947 :Ride ID: {BLACK}{COMMA16} -STR_5948 :Ride name: {BLACK}{STRINGID} -STR_5949 :Chain lift -STR_5950 :Apply changes to entire track piece -STR_5951 :Track piece ID: {BLACK}{COMMA16} -STR_5952 :Sequence number: {BLACK}{COMMA16} -STR_5953 :Sort the map elements on the current tile based on their base height. -STR_5954 :Scenery age: {BLACK}{COMMA16} -STR_5955 :Quadrant placement: {BLACK}{STRINGID} +STR_5933 :プロパティ +STR_5934 :地形テクスチャ:{BLACK}{STRINGID} +STR_5935 :地形エッジ:{BLACK}{STRINGID} +STR_5936 :土地所有権:{BLACK}{STRINGID} +STR_5937 :所有されておらず、販売されていません +STR_5938 :水位:{BLACK}{COMMA16} +STR_5939 :パークフェンスを削除 +STR_5940 :パークフェンスを復元 +STR_5941 :基本高さ: +STR_5942 :パス名:{BLACK}{STRINGID} +STR_5943 :追加:{BLACK}{STRINGID} +STR_5944 :追加:{BLACK}なし +STR_5945 :接続エッジ: +STR_5946 :ライドタイプ:{BLACK}{STRINGID} +STR_5947 :ライドID:{BLACK}{COMMA16} +STR_5948 :ライド名:{BLACK}{STRINGID} +STR_5949 :チェーンリフト +STR_5950 :変更を全トラックピースに適用 +STR_5951 :トラックピースID:{BLACK}{COMMA16} +STR_5952 :シーケンス番号:{BLACK}{COMMA16} +STR_5953 :現在のタイル上の地面の高さに基づいてマップ要素をソートします +STR_5954 :景観の年齢:{BLACK}{COMMA16} +STR_5955 :四分円配置:{BLACK}{STRINGID} STR_5956 :南西 STR_5957 :北西 STR_5958 :北東 STR_5959 :南東 -STR_5960 :Quadrant placement: -STR_5961 :Entry index: {BLACK}{COMMA16} -STR_5962 :Collision detection: -STR_5963 :Raised Corners: -STR_5964 :Diagonal -STR_5965 :Entrance type: {BLACK}{STRINGID} -STR_5966 :Park entrance part: {BLACK}{STRINGID} +STR_5960 :四分円配置: +STR_5961 :エントリーのインデックス:{BLACK}{COMMA16} +STR_5962 :衝突検出: +STR_5963 :角の持ち上げ: +STR_5964 :対角線 +STR_5965 :入口タイプ:{BLACK}{STRINGID} +STR_5966 :パーク入口パート:{BLACK}{STRINGID} STR_5967 :中 STR_5968 :左 STR_5969 :右 -STR_5970 :入口のID: {BLACK}{COMMA16} -STR_5971 :出口のID: {BLACK}{COMMA16} -STR_5972 :ライドのID: {BLACK}{COMMA16} -STR_5973 :Clamp to next -STR_5974 :Changes the base- and clearance height so that it’s at the same as the next element on the current tile. Doing this makes it easier to build on this tile. -STR_5975 :Slope: -STR_5976 :Flat -STR_5977 :Right side up -STR_5978 :Left side up -STR_5979 :Wall type: {BLACK}{COMMA16} -STR_5980 :Banner text: {BLACK}{STRINGID} +STR_5970 :入口のID:{BLACK}{COMMA16} +STR_5971 :出口のID:{BLACK}{COMMA16} +STR_5972 :ライドのID:{BLACK}{COMMA16} +STR_5973 :次にクランプ +STR_5974 :基本高さとクリアランス高さを、現在のタイルの次の要素と同じに変更します。これにより、このタイル上での建設が容易になります +STR_5975 :傾斜: +STR_5976 :平坦 +STR_5977 :右側上 +STR_5978 :左側上 +STR_5979 :壁の種類: {BLACK}{COMMA16} +STR_5980 :バナーテキスト:{BLACK}{STRINGID} STR_5981 :バナーではありません -STR_5982 :Large scenery type: {BLACK}{COMMA16} -STR_5983 :Large scenery piece ID: {BLACK}{COMMA16} -STR_5984 :Blocked paths: +STR_5982 :大型景観タイプ:{BLACK}{COMMA16} +STR_5983 :大型景観ピースID:{BLACK}{COMMA16} +STR_5984 :ブロックされたパス: STR_5985 :新しいフォルダ STR_5986 :新しいフォルダの名を入力して下さい。 STR_5987 :フォルダを作成できません -STR_5988 :No remaining land rights for sale -STR_5989 :No remaining construction rights for sale -STR_5990 :No remaining land rights or construction rights for sale -STR_5991 :Can’t paste element… -STR_5992 :The map elements limit has been reached -STR_5993 :Copy selected element -STR_5994 :Paste copied element +STR_5988 :売りに出ている土地権利はありません +STR_5989 :売りに出ている建設権利はありません +STR_5990 :売りに出ている土地権利または建設権利はありません +STR_5991 :要素を貼り付けることができません… +STR_5992 :マップ要素の制限に達しました +STR_5993 :選択した要素をコピー +STR_5994 :コピーした要素を貼り付け STR_5995 :ブースター STR_5996 :ブースターのスピード STR_5997 :資金を追加/設定 @@ -3116,18 +3126,18 @@ STR_6002 :ランプと乗り物は夜にライトアップされます。{NEW STR_6003 :切り欠きビュー STR_6004 :切り欠きビュー STR_6005 :切り欠きビューを使う -STR_6006 :Cut-away view only displays map elements at or below the cut height (vertical clipping) and in the selected area (horizontal clipping). +STR_6006 :切り取りビューは、切り高さ(垂直クリッピング)以下のマップ要素と選択されたエリア(水平クリッピング)のみを表示します STR_6007 :切り高さ -STR_6008 :Click to toggle raw value<->value in measurement units +STR_6008 :クリックして生の値<->測定単位の値を切り替え STR_6009 :切り高さに選定 STR_6010 :{COMMA2DP32}m STR_6011 :{COMMA1DP16}ft STR_6012 :{COMMA1DP16} -STR_6013 :Guests will only pay the ticket to enter the park and services.{NEWLINE}Ride entry is free. -STR_6014 :Guests will only pay entrance tickets for rides and services.{NEWLINE}They won’t pay anything to enter the park. +STR_6013 :ゲストはパークに入るためのチケットとサービスのみを支払います。{NEWLINE}ライドの入場は無料です +STR_6014 :ゲストはライドとサービスの入場チケットのみを支払います。{NEWLINE}パークに入るためには何も支払う必要はありません STR_6015 :斜面 -STR_6016 :Modify Tile -STR_6017 :ゆっくりして下さい。 +STR_6016 :タイルを変更 +STR_6017 :ゆっくりして下さい STR_6018 :ライドの建設 - 左折 STR_6019 :ライドの建設 - 右折 STR_6020 :ライドの建設 - 直進 @@ -3140,30 +3150,30 @@ STR_6026 :ライドの建設 - 前のトラック STR_6027 :ライドの建設 - 次のトラック STR_6028 :ライドの建設 - 現在のアイテムを建てる STR_6029 :ライドの建設 - 削除 -STR_6030 :Scenery picker. Click any scenery on the map to select the same piece for construction. +STR_6030 :景観ピッカー。マップ上の任意の景観をクリックすると、同じピースを建設用に選択できます STR_6031 :サーバの説明: STR_6032 :サーバの挨拶: STR_6033 :RCT1インストールのパス: STR_6034 :{BLACK}{STRING} STR_6035 :RCT1のダイレクトリーを選定します。 STR_6036 :クリア -STR_6037 :Please select a valid RCT1 directory -STR_6038 :If you have RCT1 installed, set this option to its directory to load scenarios, music, etc. -STR_6039 :Quick demolish ride +STR_6037 :有効なRCT1ディレクトリを選択してください +STR_6038 :RCT1がインストールされている場合、このオプションをそのディレクトリに設定してシナリオ、音楽などを読み込むことができます。 +STR_6039 :ライドを迅速に解体 STR_6040 :シナリオ設定 -STR_6041 :{BLACK}No mechanics are hired! -STR_6042 :ハイトマップをロード -STR_6043 :ハイトマップを選ぶ -STR_6044 :地形の滑らか -STR_6045 :Strength -STR_6046 :Normalise height map -STR_6047 :Smooth tiles -STR_6048 :Height map error -STR_6049 :Error reading PNG -STR_6050 :Error reading bitmap -STR_6052 :The heightmap is too big, and will be cut off -STR_6053 :The heightmap cannot be normalised -STR_6054 :Only 24-bit bitmaps are supported +STR_6041 :{BLACK}メカニックが雇われていません! +STR_6042 :ハイトマップを読み込む +STR_6043 :ハイトマップを選択 +STR_6044 :ハイトマップを平滑化 +STR_6045 :強度: +STR_6046 :ハイトマップを正規化 +STR_6047 :タイルのエッジを平滑化 +STR_6048 :ハイトマップエラー +STR_6049 :PNGの読み取りエラー +STR_6050 :ビットマップの読み取りエラー +STR_6052 :ハイトマップが大きすぎて、切り取られます +STR_6053 :ハイトマップを正規化できません +STR_6054 :24ビットビットマップのみがサポートされています STR_6055 :OpenRCT2ハイトマップファイル STR_6056 :ミュート STR_6057 :ツールバーでミュートのボタンを表示する @@ -3173,82 +3183,82 @@ STR_6060 :来客の購入をアニメーションで表示する STR_6061 :来客の購入時、金額をアニメーションで表示する STR_6062 :{OUTLINE}{GREEN}+ {CURRENCY2DP} STR_6063 :{OUTLINE}{RED}- {CURRENCY2DP} -STR_6064 :Own all land -STR_6065 :Log user actions -STR_6066 :Logs all user actions to files in your user directory. -STR_6067 :Server started. -STR_6068 :Server shutdown. -STR_6069 :{STRING} was kicked from the server by {STRING}. -STR_6070 :{STRING} was set to group ‘{STRING}’ by {STRING}. -STR_6071 :{STRING} created new player group ‘{STRING}’. -STR_6072 :{STRING} deleted player group ‘{STRING}’. -STR_6073 :{STRING} edited permissions for player group ‘{STRING}’. -STR_6074 :{STRING} changed player group name from ‘{STRING}’ to ‘{STRING}’. -STR_6075 :{STRING} changed the default player group to ‘{STRING}’. -STR_6076 :{STRING} used/toggled cheat ‘{STRING}’. +STR_6064 :すべての土地を所有 +STR_6065 :ユーザーアクションをログに記録 +STR_6066 :ユーザーアクションをすべてユーザーディレクトリのファイルに記録します +STR_6067 :サーバーが起動しました +STR_6068 :サーバーがシャットダウンしました +STR_6069 :{STRING}は{STRING} によってサーバーからキックされました。 +STR_6070 :{STRING}は{STRING} によってグループ「{STRING}」に設定されました。 +STR_6071 :{STRING}が新しいプレイヤーグループ「{STRING}」を作成しました。 +STR_6072 :{STRING}がプレイヤーグループ「{STRING}」を削除しました。 +STR_6073 :{STRING}がプレイヤーグループ「{STRING}」の権限を編集しました。 +STR_6074 :{STRING}がプレイヤーグループ名を「{STRING}」から「{STRING}」に変更しました。 +STR_6075 :{STRING}がデフォルトのプレイヤーグループを「{STRING}」に変更しました。 +STR_6076 :{STRING}がチート「{STRING}」を使用/切り替えました。 STR_6077 :資金を追加 -STR_6078 :{STRING} created ride ‘{STRING}’. -STR_6079 :{STRING} demolished ride ‘{STRING}’. -STR_6080 :{STRING} changed the appearance of ride ‘{STRING}’. -STR_6081 :{STRING} changed the status of ride ‘{STRING}’ to closed. -STR_6082 :{STRING} changed the status of ride ‘{STRING}’ to open. -STR_6083 :{STRING} changed the status of ride ‘{STRING}’ to testing. -STR_6084 :{STRING} changed the vehicle settings of ride ‘{STRING}’. -STR_6085 :{STRING} changed the ride settings of ride ‘{STRING}’. -STR_6086 :{STRING} renamed the ride ‘{STRING}’ to ‘{STRING}’. -STR_6087 :{STRING} changed the price of ride ‘{STRING}’ to {STRING} -STR_6088 :{STRING} changed the secondary price of ride ‘{STRING}’ to {STRING} -STR_6089 :{STRING} renamed the park from ‘{STRING}’ to ‘{STRING}’. -STR_6090 :{STRING} opened the park. -STR_6091 :{STRING} closed the park. -STR_6092 :{STRING} changed the park entrance fee to {STRING} -STR_6093 :{STRING} placed new scenery. -STR_6094 :{STRING} removed scenery. -STR_6095 :{STRING} edited scenery. -STR_6096 :{STRING} set sign name to ‘{STRING}’. -STR_6097 :{STRING} placed a track of ride ‘{STRING}’. -STR_6098 :{STRING} removed a track of ride. -STR_6099 :You connected to the server. -STR_6100 :You disconnected from the server. -STR_6101 :Rides don’t decrease in value over time -STR_6102 :The value of a ride won’t decrease over time, so guests will not suddenly think that a ride is too expensive. -STR_6103 :This option is disabled during network play. +STR_6078 :{STRING}がライド「{STRING}」を作成しました。 +STR_6079 :{STRING}がライド「{STRING}」を解体しました。 +STR_6080 :{STRING}がライド「{STRING}」の外観を変更しました。 +STR_6081 :{STRING}がライド「{STRING}」の状態を閉鎖に変更しました。 +STR_6082 :{STRING}がライド「{STRING}」の状態を開放に変更しました。 +STR_6083 :{STRING}がライド「{STRING}」の状態をテスト中に変更しました。 +STR_6084 :{STRING}がライド「{STRING}」の車両設定を変更しました。 +STR_6085 :{STRING}がライド「{STRING}」の設定を変更しました。 +STR_6086 :{STRING}がライド「{STRING}」の名前を「{STRING}」に変更しました。 +STR_6087 :{STRING}がライド「{STRING}」の価格を {STRING} に変更しました。 +STR_6088 :{STRING}がライド「{STRING}」の追加価格を {STRING} に変更しました。 +STR_6089 :{STRING}がパークの名前を「{STRING}」から「{STRING}」に変更しました。 +STR_6090 :{STRING}がパークを開放しました。 +STR_6091 :{STRING}がパークを閉鎖しました。 +STR_6092 :{STRING}がパークの入場料を {STRING} に変更しました。 +STR_6093 :{STRING}が新しい景観を配置しました。 +STR_6094 :{STRING}が景観を削除しました。 +STR_6095 :{STRING}が景観を編集しました。 +STR_6096 :{STRING}が看板の名前を「{STRING}」に設定しました。 +STR_6097 :{STRING}がライド「{STRING}」のトラックを配置しました。 +STR_6098 :{STRING}がライドのトラックを削除しました。 +STR_6099 :サーバーに接続しました +STR_6100 :サーバーから切断されました +STR_6101 :ライドの価値は時間とともに減少しませ +STR_6102 :ライドの価値は時間とともに減少しないため、ゲストが突然ライドが高すぎると感じることはありません +STR_6103 :このオプションはネットワークプレイ中は無効です STR_6105 :ハイパーコースター STR_6107 :モンスタートラック STR_6109 :ハイパー・ツイスター STR_6111 :クラシック・ミニ・ジェットコースター -STR_6113 :A tall non-inverting roller coaster with large drops, high speed, and comfortable trains with only lap bar restraints -STR_6115 :Powered giant 4 x 4 trucks which can climb steep slopes -STR_6116 :Wide roller coaster trains glide along smooth steel track, travelling through a variety of inversions -STR_6119 :A cheap and easy to build roller coaster, but with a limited height -STR_6120 :{BABYBLUE}{STRINGID}に新しい車両:{NEWLINE}{STRINGID} -STR_6121 :Extends the park’s land rights all the way to the edges of the map -STR_6122 :There are not enough roller coasters in this scenario! -STR_6123 :Error loading objects for park +STR_6113 :大型の落下や高速を持つ、背の高い非反転ローラーコースターで、ラップバーだけの快適な車両を備えています +STR_6115 :急な坂を登れる電動巨大4x4トラック +STR_6116 :幅広のローラーコースターの列車が滑らかな鋼鉄のトラックの上を滑り、さまざまな逆さまの動きを通過します +STR_6119 :安価で簡単に建設できるローラーコースターですが、高さに制限があります +STR_6120 :{BABYBLUE}{STRINGID}に新しい車両: {NEWLINE}{STRINGID} +STR_6121 :パークの土地権を地図の端まで拡張します +STR_6122 :このシナリオにはローラーコースターが足りません! +STR_6123 :パークのオブジェクトの読み込みエラー STR_6124 :オブジェクトの名 STR_6125 :オブジェクトのタイプ STR_6126 :タイプ未知 STR_6127 :ファイル: {STRING} -STR_6128 :The file could not be loaded as some of the objects referenced in it are missing or corrupt. A list of these objects is given below. +STR_6128 :ファイルを読み込むことができませんでした。参照されているオブジェクトの一部が欠損または破損しています。オブジェクトのリストは以下に示されています。 STR_6129 :このアイテムをクリップボードにコッピーする STR_6130 :全てをクリップボードにコッピーする STR_6131 :オブジェクト源 STR_6132 :研究のステータスを無視する -STR_6133 :Access rides and scenery that have not yet been invented +STR_6133 :まだ発明されていないアトラクションやシーナリーにアクセス STR_6134 :景色物をクリアする -STR_6135 :Client sent invalid request -STR_6136 :Server sent invalid request -STR_6137 :OpenRCT2, a free and open source clone of Roller Coaster Tycoon 2. -STR_6138 :OpenRCT2 is the work of many authors, a full list can be found in “contributors.md”. For more information, visit http://github.com/OpenRCT2/OpenRCT2 -STR_6139 :All product and company names belong to their respective holders. Use of them does not imply any affiliation with or endorsement by them. +STR_6135 :クライアントが無効なリクエストを送信しました +STR_6136 :サーバーが無効なリクエストを送信しました +STR_6137 :OpenRCT2は、RollerCoaster Tycoon 2の無料かつオープンソースのクローンです。 +STR_6138 :OpenRCT2は多くの著者の作品であり、完全なリストは「contributors.md」にあります。詳細については、https://github.com/OpenRCT2/OpenRCT2 を訪れてください。 +STR_6139 :すべての製品名および会社名はそれぞれの権利者に属します。これらの使用は、いかなる提携や承認を示すものではありません。 STR_6140 :変更履歴… STR_6141 :RCT1の下のツールバー STR_6142 :{WINDOW_COLOUR_2}トラックの名: {BLACK}{STRING} STR_6143 :{WINDOW_COLOUR_2}ラウドの名: {BLACK}{STRINGID} STR_6144 :汚いビジュアルを表示する -STR_6145 :Set speed limit for boosters -STR_6146 :Enable all drawable track pieces -STR_6147 :Enables all track pieces the ride type is capable of in the construction window, regardless of whether the vehicle supports them. +STR_6145 :ブースターの速度制限を設定 +STR_6146 :描画可能なすべてのトラックパーツを有効にする +STR_6147 :車両がサポートしているかどうかに関わらず、建設ウィンドウでライドタイプが対応可能なすべてのトラックパーツを有効にします STR_6148 :マスターサーバに接続中… STR_6149 :マスターサーバに接続が失敗しました。 STR_6150 :マスターサーバから無効な返事をいただきました。(JSON整数がありません) @@ -3361,29 +3371,29 @@ STR_6296 :GiB STR_6297 :TiB STR_6298 :1秒あたり{STRING} STR_6299 :全部のダウンロード -STR_6300 :Download all missing objects if available online. -STR_6301 :Copy the selected object name to the clipboard. -STR_6302 :Copy the entire list of missing objects to the clipboard. +STR_6300 :オンラインで利用可能なら、すべての欠損オブジェクトをダウンロード +STR_6301 :選択したオブジェクト名をクリップボードにコピー +STR_6302 :欠損オブジェクトの全リストをクリップボードにコピー STR_6303 :オブジェクトのダウンロード中 ({COMMA16} / {COMMA16}): [{STRING}] -STR_6304 :Open scenery picker +STR_6304 :シーナリーピッカーを開く STR_6305 :マルチスレッド -STR_6306 :Experimental option to use multiple threads to render, may cause instability. -STR_6307 :配色: {BLACK}{STRINGID} +STR_6306 :複数のスレッドを使用してレンダリングする実験的オプションです(安定性に影響を与える可能性があります) +STR_6307 :配色:{BLACK}{STRINGID} STR_6308 :{TOPAZ}「{STRINGID}{OUTLINE}{TOPAZ}」{NEWLINE}{STRINGID} STR_6309 :再接続 -STR_6310 :{WINDOW_COLOUR_2}拠点: {BLACK}{INT32} {INT32} {INT32} -STR_6311 :{WINDOW_COLOUR_2}次: {BLACK}{INT32} {INT32} {INT32} -STR_6312 :(surface) -STR_6313 :(slope {INT32}) +STR_6310 :{WINDOW_COLOUR_2}拠点:{BLACK}{INT32} {INT32} {INT32} +STR_6311 :{WINDOW_COLOUR_2}次:{BLACK}{INT32} {INT32} {INT32} +STR_6312 :(サーフェス) +STR_6313 :(傾斜:{INT32}) STR_6314 :{WINDOW_COLOUR_2}目的地: {BLACK}{INT32}, {INT32} 寛大 {INT32} STR_6315 :{WINDOW_COLOUR_2}経路探索の目標: {BLACK}{INT32}, {INT32}, {INT32} 方 {INT32} STR_6316 :{WINDOW_COLOUR_2}経路探索の歴史: STR_6317 :{BLACK}{INT32}, {INT32}, {INT32} 方 {INT32} -STR_6318 :Network desync detected.{NEWLINE}Log file: {STRING} -STR_6319 :Block Brake Closed -STR_6320 :Indestructible -STR_6321 :Addition is broken -STR_6322 :{WINDOW_COLOUR_2}Sprite Id: {BLACK}{INT32} +STR_6318 :ネットワークの非同期が検出されました。{NEWLINE}ログファイル:{STRING} +STR_6319 :ブロックブレーキ閉鎖 +STR_6320 :壊れない +STR_6321 :追加が壊れています +STR_6322 :{WINDOW_COLOUR_2}スプライトID:{BLACK}{INT32} STR_6323 :シミュレーション中 STR_6324 :シミュレーション STR_6325 :ライドやアトラクションをシミュレーションする @@ -3391,7 +3401,7 @@ STR_6326 :{STRINGID}をシミュレートできません… STR_6327 :拡大スクリーンショットに透明な背景を使用 STR_6328 :このオプションでは、拡大スクリーンショットの際にデフォルトの黒背景ではなく透明な背景を使用 STR_6329 :{STRING}{STRINGID} -STR_6330 :{POP16}{POP16}{POP16}{POP16}{STRING}から [{PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{STRING}]をダウンロード中 ({COMMA16} / {COMMA16}) +STR_6330 :{POP16}{POP16}{POP16}{POP16}{STRING}から [{PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{STRING}]をダウンロード中({COMMA16}/{COMMA16}) STR_6331 :カモを投入する STR_6332 :カモを取り除く STR_6333 :ウインドウのスケール係数を上げる @@ -3423,7 +3433,352 @@ STR_6359 :{POP16}{POP16}{UINT16}ページ目 STR_6361 :乗り物のライトの効果を表示にする(試験的) STR_6362 :有効になっている場合、追跡された乗り物の車両は夜間にライトアップされます。 STR_6363 :テキストをクリップボードにコピーしました。 +STR_6364 :{RED}{COMMA16} 人が {STRINGID} で事故で死亡しました +STR_6365 :アトラクションの死傷者 +STR_6366 :動かないまたは停止した車両 +STR_6367 :アニメーションフレーム: +STR_6368 :互換性の理由から、WineでOpenRCT2を実行することは推奨されません。OpenRCT2はmacOS、Linux、FreeBSD、OpenBSDをネイティブでサポートしています。 +STR_6369 :無効な高さでのトラックの建設を許可 +STR_6370 :どの高さの間隔でもトラックパーツを配置できるようにします +STR_6371 :指定されたパスにはRollerCoaster Tycoon 1のインストールがありますが、「csg1i.dat」ファイルが欠けています。このファイルはLoopy LandscapesまたはRCT DeluxeのCDからハードドライブ上のRollerCoaster Tycoon 1インストールの「Data」フォルダーにコピーする必要があります。 +STR_6372 :指定されたパスにはRollerCoaster Tycoon 1のインストールがありますが、このバージョンは適切ではありません。OpenRCT2はRollerCoaster Tycoon 1のアセットを使用するためにLoopy LandscapesまたはRCT Deluxeのインストールが必要です。 +STR_6373 :クリアランスチェックを切り替え +STR_6374 :C +STR_6375 :不明なアトラクション +STR_6376 :{WINDOW_COLOUR_2}アトラクション車両:{NEWLINE}{BLACK}{STRINGID}の{STRINGID} +STR_6377 :{WINDOW_COLOUR_2}タイプ:{BLACK}{STRINGID}の{STRINGID} +STR_6378 :オブジェクトリストを受信中… +STR_6379 :無効なデータを受信しました +STR_6380 :アップデートが利用可能です! +STR_6381 :OpenRCT2 Discordに参加! +STR_6382 :より新しいOpenRCT2のリリースが利用可能です: {STRING}! +STR_6383 :ダウンロードページを開く +STR_6384 :雪 +STR_6385 :大雪 +STR_6386 :吹雪 +STR_6387 :ここで要素を下げることはできません… +STR_6388 :ここで要素を上げることはできません… +STR_6389 :無効なクリアランス +STR_6390 :OpenRCT2は、動作するために元のRollerCoaster Tycoon 2またはRollerCoaster Tycoon Classicのファイルが必要です。RollerCoaster Tycoon 2またはRollerCoaster Tycoon Classicをインストールしたフォルダーを選択してください。 +STR_6391 :RCT2またはRCTCのフォルダーを選択してください +STR_6392 :このパスで{STRING}が見つかりませんでした。 +STR_6393 :目標選択 +STR_6394 :目標 +STR_6395 :メンテナンス +STR_6396 :スクリーンセーバーとモニターの省電力を無効にする +STR_6397 :チェックされている場合、OpenRCT2が実行中はスクリーンセーバーやその他のモニター省電力機能が無効になります。 +STR_6398 :ファイルにはサポートされていないアトラクションタイプが含まれています。新しいバージョンのOpenRCT2にアップデートしてください。 +STR_6399 :OpenRCT2は、動作するために元のRollerCoaster Tycoon 2またはRollerCoaster Tycoon Classicのファイルが必要です。「config.ini」の「game_path」変数を、RollerCoaster Tycoon 2またはRollerCoaster Tycoon Classicをインストールしたフォルダーに設定し、OpenRCT2を再起動してください。 +STR_6400 :RollerCoaster Tycoon 2のGOGオフラインインストーラーをダウンロードしましたが、インストールされていません。 +STR_6401 :すでにRollerCoaster Tycoon 2またはRollerCoaster Tycoon Classicがインストールされています。 +STR_6402 :OpenRCT2データセットアップ +STR_6403 :最も適したものを選択してください +STR_6404 :GOGのRollerCoaster Tycoon 2インストーラーを選択してください。 +STR_6405 :GOGインストーラーを選択 +STR_6406 :GOG RollerCoaster Tycoon 2インストーラー +STR_6407 :これには数分かかる場合があります。 +STR_6408 :GOGインストーラーを抽出するために「innoextract」をインストールしてください。その後、OpenRCT2を再起動してください。 +STR_6409 :選択したファイルは、RollerCoaster Tycoon 2のオフラインGOGインストーラーではありません。GOG Galaxyダウンローダースタブをダウンロードしたか、間違ったファイルを選択した可能性があります。 +STR_6410 :ズームイン/アウト +STR_6411 :ツールバーにズームインおよびズームアウトのボタンを表示 +STR_6412 :NumPad Enter +STR_6413 :Shift +STR_6414 :L Shift +STR_6415 :R Shift +STR_6416 :Ctrl +STR_6417 :L Ctrl +STR_6418 :R Ctrl +STR_6419 :Alt +STR_6420 :L Alt +STR_6421 :R Alt +STR_6422 :Cmd +STR_6423 :L Cmd +STR_6424 :R Cmd +STR_6425 :Joy Left +STR_6426 :Joy Right +STR_6427 :Joy Up +STR_6428 :Joy Down +STR_6429 :Joy {INT32} +STR_6430 :LMB +STR_6431 :RMB +STR_6432 :Mouse {INT32} +STR_6433 :削除 +STR_6434 :このショートカットのすべてのバインディングを削除します +STR_6435 :{WINDOW_COLOUR_2}バンダルが停止しました:{BLACK}{COMMA32} +STR_6436 :不可視状態の切り替え +STR_6437 :可視 +STR_6438 :{MOVE_X}{2}👁 +STR_6439 :タイルインスペクター:不可視状態の切り替え STR_6440 :透明な水 +STR_6441 :少なくとも1つの非キュー歩道表面オブジェクトを選択する必要があります +STR_6442 :少なくとも1つのキュー歩道表面オブジェクトを選択する必要があります +STR_6443 :少なくとも1つの歩道手すりオブジェクトを選択する必要があります +STR_6444 :歩道表面 +STR_6445 :歩道手すり +STR_6446 :{WINDOW_COLOUR_2}表面名:{BLACK}{STRINGID} +STR_6447 :{WINDOW_COLOUR_2}手すり名:{BLACK}{STRINGID} +STR_6448 :サポートされていないオブジェクト形式 +STR_6449 :{WINDOW_COLOUR_2}トラック: +STR_6450 :{BLACK}「{STRING}」 +STR_6451 :{BLACK}「{STRING}」・{STRING} +STR_6452 :{WINDOW_COLOUR_2}販売: {BLACK}{STRING} +STR_6453 :バージョン情報をコピー +STR_6454 :バナーの名前を変更できません… +STR_6455 :サインの名前を変更できません… +STR_6456 :巨大スクリーンショット +STR_6457 :GitHubでバグを報告 +STR_6458 :メインビューでこれをフォロー +STR_6460 :方 +STR_6461 :方向 +STR_6462 :エキサイトメント +STR_6463 :エキサイトメント:{COMMA2DP32} +STR_6464 :強度 +STR_6465 :強度:{COMMA2DP32} +STR_6466 :吐き気 +STR_6467 :吐き気:{COMMA2DP32} +STR_6468 :まだ知られていません +STR_6469 :パトロールエリアの小さい部分を調整 +STR_6470 :パトロールエリアの大きい部分を調整 +STR_6471 :透過性のある植生 +STR_6472 :透過性のある車両 +STR_6473 :透過性のある支持物 +STR_6474 :不可視のゲスト +STR_6475 :不可視のスタッフ +STR_6476 :不可視の植生 +STR_6477 :不可視の風景 +STR_6478 :不可視の道 +STR_6479 :不可視のアトラクション +STR_6480 :不可視の車両 +STR_6481 :透明度オプション +STR_6482 :透明度オプション +STR_6483 :透明度オプションを開く +STR_6484 :透過性のある植生の切り替え +STR_6485 :透過性のある車両の切り替え +STR_6486 :ゲストを非表示にする切り替え +STR_6487 :スタッフを非表示にする切り替え +STR_6488 :{RED}ゲストがあなたのパークの行列の長さについて不満を言っています。{NEWLINE}問題のある行列を短くするか、ライドの処理能力を上げることを検討してください。 +STR_6489 :エラー:互換性のないパークバージョン +STR_6490 :警告:準互換性のあるパークバージョン +STR_6491 :このパークは新しいバージョンのOpenRCT2で保存されました。パークはv{INT32}で保存されており、少なくともv{INT32}が必要です。現在のバージョンはv{INT32}です。 +STR_6492 :このパークは古いバージョンのOpenRCT2で保存されており、このバージョンのOpenRCT2では開くことができません。パークはv{INT32}です。 +STR_6493 :このパークは新しいバージョンのOpenRCT2で保存されましたが、一部のデータが失われる可能性があります。パークはv{INT32}で保存されました。現在のバージョンはv{INT32}です。 +STR_6494 :ライドタイプでグループ化 +STR_6495 :各車両を別々に表示するのではなく、ライドタイプでライドをグループ化します。 +STR_6496 :{WINDOW_COLOUR_2}{STRINGID} +STR_6497 :タイルをクリックすると、そのタイル要素が表示されます。{NEWLINE}Ctrl + クリックでタイル要素を直接選択できます。 +STR_6498 :正方形のマップ形状を維持するために有効にします。 +STR_6499 :トラックデザインフォーマットでサポートされていない車両タイプ +STR_6500 :トラックデザインフォーマットでサポートされていないトラック要素 +STR_6501 :ランダムカラー +STR_6502 :{COMMA16}と{COMMA16}の間の値を入力してください +STR_6503 :少なくとも1つのステーションオブジェクトを選択する必要があります +STR_6504 :少なくとも1つの地形表面を選択する必要があります +STR_6505 :少なくとも1つの地形エッジを選択する必要があります +STR_6506 :大型ハーフコークスクリュー(左) +STR_6507 :大型ハーフコークスクリュー(右) +STR_6508 :中型ハーフループ(左) +STR_6509 :中型ハーフループ(右) +STR_6510 :ゼロGロール(左) +STR_6511 :ゼロGロール(右) +STR_6512 :大型ゼロGロール(左) +STR_6513 :大型ゼロGロール(右) +STR_6514 :無効な高さ! +STR_6515 :{BLACK}RollerCoaster Tycoon 1がリンクされていません - フォールバック画像が使用されます。 +STR_6516 :追加された1つまたは複数のオブジェクトには、正しい表示のためにRollerCoaster Tycoon 1がリンクされている必要があります。フォールバック画像が使用されます。 +STR_6517 :このパークの1つまたは複数のオブジェクトには、正しい表示のためにRollerCoaster Tycoon 1がリンクされている必要があります。フォールバック画像が使用されます。 +STR_6518 :{BLACK}シナリオにマウスを乗せると、その説明と目的が表示されます。クリックするとプレイが開始されます。 +STR_6519 :追加要素 +STR_6520 :アセットパック +STR_6521 :低優先度 +STR_6522 :高優先度 +STR_6523 :選択したアセットパックの優先度を下げます。 +STR_6524 :選択したアセットパックの優先度を上げます。 +STR_6525 :有効なアセットパックでゲーム内のすべてのアセットを再読み込みします。 +STR_6526 :(基本グラフィックス、音楽、音響効果) +STR_6527 :コンペティション +STR_6528 :無効なトラックパラメータ! +STR_6529 :無効なカラースキームパラメータ! +STR_6530 :ユーザー作成の拡張セット +STR_6531 :ザ・タイム・マシン +STR_6532 :ケイティーのドリームワールド +STR_6533 :{WINDOW_COLOUR_2}エキサイトメントファクター:{BLACK}-{COMMA16}% +STR_6534 :{WINDOW_COLOUR_2}強度ファクター:{BLACK}-{COMMA16}% +STR_6535 :{WINDOW_COLOUR_2}吐き気ファクター:{BLACK}-{COMMA16}% +STR_6536 :このパークはOpenRCT2の後のバージョンで保存されました。パークはv{INT32}で保存され、現在のバージョンはv{INT32}です。 +STR_6537 :通常の道をキューとして使用することを許可 +STR_6538 :フットパスウィンドウのキューのドロップダウンに通常の道を表示します。 +STR_6539 :ブレーキが閉じました +STR_6540 :{WINDOW_COLOUR_2}以下の企業に肖像権を許可していただき、特別な感謝を申し上げます +STR_6541 :{WINDOW_COLOUR_2}Rocky Mountain Construction Group, Josef Wiegand GmbH & Co. KG +STR_6542 :貢献者 +STR_6543 :貢献者… +STR_6544 :ローンは負の値にできません! +STR_6545 :RCT1の利息計算を使用 +STR_6546 :RollerCoaster Tycoon 1の利息計算アルゴリズムを使用します。これは約1.33%の固定パーセンテージを使用しました。 +STR_6547 :すべての風景 +STR_6548 :交差点で手すりを表示 +STR_6549 :互換性のあるオブジェクトは選択できません! +STR_6550 : このエントリーは古いまたは破損したオブジェクトとの後方互換性のために含まれています。選択できず、非選択にすることのみ可能です。 + +STR_6551 :アーミーグリーン色 +STR_6552 :ハニーデュー色 +STR_6553 :タン色 +STR_6554 :マルーン色 +STR_6555 :コーラルピンク色 +STR_6556 :フォレストグリーン色 +STR_6557 :シャルトリューズ色 +STR_6558 :ハンターグリーン色 +STR_6559 :セラドン色 +STR_6560 :ライムグリーン色 +STR_6561 :セピア色 +STR_6562 :ピーチ色 +STR_6563 :ペリウィンクル色 +STR_6564 :ヴィリディアン色 +STR_6565 :シーフォームグリーン色 +STR_6566 :バイオレット色 +STR_6567 :ラベンダー色 +STR_6568 :パステルオレンジ色 +STR_6569 :ディープウォーター色 +STR_6570 :パステルピンク色 +STR_6571 :アンバー色 +STR_6572 :ベージュ色 +STR_6573 :インビジブル色 +STR_6574 :ヴォイド色 +STR_6575 :特殊なカラースキームを許可 +STR_6576 :カラードロップダウンに特殊な色を追加 +STR_6577 :ブロックブレーキ速度 +STR_6578 :ブロックブレーキの速度制限を設定します。ブロックセクションモードでは、隣接するブレーキが遅い速度のものとリンクされます。 +STR_6579 :トラックデザインとして保存すると、ブロックブレーキはデフォルトの速度に設定されます。 +STR_6580 :リセット +STR_6581 :このタブのすべてのショートカットキーをリセットしてもよろしいですか? +STR_6582 :キーボードショートカットウィンドウを開く +STR_6583 :{WINDOW_COLOUR_2}逆転列車 +STR_6584 :列車を逆方向に運行するために選択 +STR_6585 :変更を加えることができません… +STR_6586 :OpenRCT2 +STR_6587 :OpenRCT2のタイトルテーマはAllister Brimbleの作品{NEWLINE}CC BY-SA 4.0のライセンスがあります +STR_6588 :35er Voigtの録音を許可してくれたHerman Ridderingに感謝します +STR_6589 :ウィンドウボタンを左側に表示 +STR_6590 :ウィンドウボタン(例: ウィンドウを閉じるためのボタン)をタイトルバーの右側ではなく左側に表示します。 +STR_6591 :スタッフメンバーは現在アトラクションを修理中で、解雇できません。 +STR_6592 :スタッフメンバーは現在アトラクションを検査中で、解雇できません。 +STR_6593 :パークのフェンスを削除 +STR_6594 :タイルインスペクタ:壁の傾斜を切り替え +STR_6595 :{WINDOW_COLOUR_2}作者:{BLACK}{STRING} +STR_6596 :{WINDOW_COLOUR_2}作者:{BLACK}{STRING} +STR_6597 :無効なパラメーター +STR_6598 :値が範囲外です +STR_6599 :ゴースト要素が見つかりません +STR_6600 :バルーンが見つかりません +STR_6601 :スタッフが見つかりません +STR_6602 :アトラクションが見つかりません +STR_6603 :アトラクションオブジェクトのエントリーが見つかりません +STR_6604 :プレイヤーが見つかりません +STR_6605 :入口要素が見つかりません +STR_6606 :サーフェス要素が見つかりません +STR_6607 :タイル要素が見つかりません +STR_6608 :トラック要素が見つかりません +STR_6609 :トラックブロックが見つかりません +STR_6610 :パス要素が見つかりません +STR_6611 :壁要素が見つかりません +STR_6612 :バナー要素が見つかりません +STR_6613 :オブジェクトを再読み込み +STR_6614 :パークの入場料を変更できません +STR_6615 :このタイルのトラックには水が必要です +STR_6616 :そのスタッフタイプには無効なアクションです +STR_6617 :タイル要素を自分自身と入れ替えることはできません +STR_6618 :オブジェクトの制限または解除ができません… +STR_6619 :オブジェクトタイプは制限できません! +STR_6620 :オブジェクトが見つかりません! +STR_6621 :制限 +STR_6622 :オブジェクトをシナリオエディタとサンドボックスモードに制限します +STR_6623 :利用可能なコマンドの一覧を表示するには「help」と入力してください。コンソールを隠すには「hide」と入力してください。 +STR_6624 :タイルインスペクタ: 要素を並べ替え +STR_6625 :無効な色 +STR_6626 :アニメーションが逆になっています +STR_6627 :トラックの速度が高すぎます! +STR_6628 :パスの端にのみ配置できます! +STR_6629 :ツールバーボタンを水平方向に中央揃え +STR_6630 :この設定により、ツールバーボタンが画面の中央に水平に揃えられます。従来の方法では、左端と右端に揃えられます。 +STR_6631 :読み込み中… +STR_6632 :オブジェクトのチェック中… +STR_6633 :シナリオのチェック中… +STR_6634 :トラックデザインのチェック中… +STR_6635 :アセットパックのチェック中… +STR_6636 :タイトルシーケンスのチェック中… +STR_6637 :タイトルシーケンスの読み込み中… +STR_6638 :UIの拡大 +STR_6639 :タッチ操作に適したインターフェースに変更します +STR_6640 :アセットパックを編集… +STR_6641 :読み込み/進行状況ウィンドウ +STR_6642 :{STRING}({COMMA32}/{COMMA32}) +STR_6643 :{STRING}({COMMA32}/{COMMA32} KiB) +STR_6644 :タッチ強化 +STR_6645 :一部のUI要素を大きくして、クリックやタップしやすくします +STR_6646 :作者:{STRING} +STR_6647 :作者:{STRING} +STR_6648 :プラグインエンジンを読み込み中… +STR_6649 :シナリオを読み込み中… +STR_6650 :セーブデータを読み込み中… +STR_6651 :{STRING}({COMMA32}%) +STR_6652 :エラーメッセージウィンドウ +STR_6653 :すべてのソースを表示 +STR_6654 :{POP16}{UINT16} のソースを表示中 +STR_6655 :「{POP16}{STRINGID}」のみ +STR_6656 :パークからすべてのフェンスを削除 +STR_6657 :所有していない土地 +STR_6658 :土地をパークの所有ではなく、購入可能にも設定しない +STR_6659 :ゲストが価格を無視 +STR_6660 :ゲストはアトラクションやスタンドの価格を無視します。 +STR_6661 :すべてをランダム化 +STR_6662 :すべての列車や車両の色をランダム化します。 +STR_6663 :日付チート +STR_6664 :日付チートを表示 +STR_6665 :自然/天候チート +STR_6666 :自然/天候チートを表示 +STR_6667 :動物 +STR_6668 :スタッフチート +STR_6669 :スタッフチートを表示 +STR_6670 :ゲストの行動 +STR_6671 :スタッフの「実名」を表示 +STR_6672 :スタッフの「実名」とスタッフ番号の表示を切り替え +STR_6673 :透明 +STR_6674 :{MONTH}、{COMMA16}年 +STR_6675 :ピープの名 +STR_6676 :少なくとも1つのピープ名オブジェクトを選択する必要があります +STR_6677 :水域の周りにビーチを追加 +STR_6678 :ハイトマップソース: +STR_6679 :平地 +STR_6680 :シンプレックスノイズ +STR_6681 :ハイトマップファイル +STR_6682 :マップジェネレーター・ジェネレーター +STR_6683 :マップジェネレーター・地形の設定 +STR_6684 :マップジェネレーター・水の設定 +STR_6685 :マップジェネレーター・森の設定 +STR_6686 :木と土地の比率: +STR_6687 :最小木の高度: +STR_6688 :最大木の高度: +STR_6689 :{UINT16}% +STR_6690 :最低土地高さ +STR_6691 :{COMMA16}と{COMMA16}の間で最小土地高さを入力してください +STR_6692 :最高土地高さ +STR_6693 :{COMMA16}と{COMMA16}の間で最大土地高さを入力してください +STR_6694 :最小木の高度 +STR_6695 :{COMMA16}と{COMMA16}の間で最小木の高度を入力してください +STR_6696 :最大木の高度 +STR_6697 :{COMMA16}と{COMMA16}の間で最大木の高度を入力してください +STR_6698 :木と土地の比率 +STR_6699 :{COMMA16}と{COMMA16}の間で木と土地の比率を入力してください +STR_6700 :シンプレックスベース周波数 +STR_6701 :{COMMA2DP32}と{COMMA2DP32}の間でベース周波数を入力してください +STR_6702 :シンプレックスオクターブ +STR_6703 :{COMMA16}と{COMMA16}の間でオクターブを入力してください +STR_6704 :{COMMA2DP32} +STR_6705 :ブラウズ... +STR_6706 :{WINDOW_COLOUR_2}現在の画像ファイル:{BLACK}{STRING} +STR_6707 :(選択されていません) +STR_6708 :スムース強度 +STR_6709 :{COMMA16}と{COMMA16}の間でスムース強度を入力してください ############# # Scenarios # From 8fe2d7de1f4be43728f10dce64df69a553bda579 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Sun, 20 Oct 2024 08:10:55 +0200 Subject: [PATCH 49/97] Rename Object and TileElement type constant (#23030) * Rename Object::objectType to Object::kObjectType * Rename TileElement::ElementType to TileElement::kElementType --- src/openrct2/object/AudioObject.h | 2 +- src/openrct2/object/BannerObject.h | 2 +- src/openrct2/object/EntranceObject.h | 2 +- src/openrct2/object/FootpathObject.h | 2 +- src/openrct2/object/FootpathRailingsObject.h | 2 +- src/openrct2/object/FootpathSurfaceObject.h | 2 +- src/openrct2/object/LargeSceneryObject.h | 2 +- src/openrct2/object/MusicObject.h | 2 +- src/openrct2/object/ObjectManager.h | 2 +- src/openrct2/object/PathAdditionObject.h | 2 +- src/openrct2/object/PeepNamesObject.h | 2 +- src/openrct2/object/RideObject.h | 2 +- src/openrct2/object/SceneryGroupObject.h | 2 +- src/openrct2/object/SmallSceneryObject.h | 2 +- src/openrct2/object/StationObject.h | 2 +- src/openrct2/object/TerrainEdgeObject.h | 2 +- src/openrct2/object/TerrainSurfaceObject.h | 2 +- src/openrct2/object/WallObject.h | 2 +- src/openrct2/object/WaterObject.h | 2 +- src/openrct2/world/Map.h | 4 ++-- src/openrct2/world/tile_element/BannerElement.h | 2 +- src/openrct2/world/tile_element/EntranceElement.h | 2 +- src/openrct2/world/tile_element/LargeSceneryElement.h | 2 +- src/openrct2/world/tile_element/PathElement.h | 2 +- src/openrct2/world/tile_element/SmallSceneryElement.h | 2 +- src/openrct2/world/tile_element/SurfaceElement.h | 2 +- src/openrct2/world/tile_element/TileElementBase.h | 4 ++-- src/openrct2/world/tile_element/TrackElement.h | 2 +- src/openrct2/world/tile_element/WallElement.h | 2 +- 29 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/openrct2/object/AudioObject.h b/src/openrct2/object/AudioObject.h index 32c7aef5ec..0fdcadf545 100644 --- a/src/openrct2/object/AudioObject.h +++ b/src/openrct2/object/AudioObject.h @@ -23,7 +23,7 @@ private: AudioSampleTable _loadedSampleTable; public: - static constexpr ObjectType objectType = ObjectType::Audio; + static constexpr ObjectType kObjectType = ObjectType::Audio; void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; diff --git a/src/openrct2/object/BannerObject.h b/src/openrct2/object/BannerObject.h index 18c077a987..177f2127a0 100644 --- a/src/openrct2/object/BannerObject.h +++ b/src/openrct2/object/BannerObject.h @@ -19,7 +19,7 @@ private: BannerSceneryEntry _legacyType = {}; public: - static constexpr ObjectType objectType = ObjectType::Banners; + static constexpr ObjectType kObjectType = ObjectType::Banners; void* GetLegacyData() override { diff --git a/src/openrct2/object/EntranceObject.h b/src/openrct2/object/EntranceObject.h index ce5fb15f28..bdcd157338 100644 --- a/src/openrct2/object/EntranceObject.h +++ b/src/openrct2/object/EntranceObject.h @@ -20,7 +20,7 @@ private: EntranceEntry _legacyType = {}; public: - static constexpr ObjectType objectType = ObjectType::ParkEntrance; + static constexpr ObjectType kObjectType = ObjectType::ParkEntrance; void* GetLegacyData() override { diff --git a/src/openrct2/object/FootpathObject.h b/src/openrct2/object/FootpathObject.h index cce65563fd..119391ef06 100644 --- a/src/openrct2/object/FootpathObject.h +++ b/src/openrct2/object/FootpathObject.h @@ -22,7 +22,7 @@ private: PathRailingsDescriptor _pathRailingsDescriptor = {}; public: - static constexpr ObjectType objectType = ObjectType::Paths; + static constexpr ObjectType kObjectType = ObjectType::Paths; void* GetLegacyData() override { diff --git a/src/openrct2/object/FootpathRailingsObject.h b/src/openrct2/object/FootpathRailingsObject.h index 028534f404..e1ec306ca8 100644 --- a/src/openrct2/object/FootpathRailingsObject.h +++ b/src/openrct2/object/FootpathRailingsObject.h @@ -26,7 +26,7 @@ public: PathRailingsDescriptor _descriptor = {}; public: - static constexpr ObjectType objectType = ObjectType::FootpathRailings; + static constexpr ObjectType kObjectType = ObjectType::FootpathRailings; void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; diff --git a/src/openrct2/object/FootpathSurfaceObject.h b/src/openrct2/object/FootpathSurfaceObject.h index 08aea17fb6..84a6aca363 100644 --- a/src/openrct2/object/FootpathSurfaceObject.h +++ b/src/openrct2/object/FootpathSurfaceObject.h @@ -22,7 +22,7 @@ public: PathSurfaceDescriptor _descriptor = {}; public: - static constexpr ObjectType objectType = ObjectType::FootpathSurface; + static constexpr ObjectType kObjectType = ObjectType::FootpathSurface; void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; diff --git a/src/openrct2/object/LargeSceneryObject.h b/src/openrct2/object/LargeSceneryObject.h index 8572d8baf7..ab0bc1baa9 100644 --- a/src/openrct2/object/LargeSceneryObject.h +++ b/src/openrct2/object/LargeSceneryObject.h @@ -24,7 +24,7 @@ private: std::unique_ptr _3dFont; public: - static constexpr ObjectType objectType = ObjectType::LargeScenery; + static constexpr ObjectType kObjectType = ObjectType::LargeScenery; void* GetLegacyData() override { diff --git a/src/openrct2/object/MusicObject.h b/src/openrct2/object/MusicObject.h index 274353736c..2495980f5f 100644 --- a/src/openrct2/object/MusicObject.h +++ b/src/openrct2/object/MusicObject.h @@ -53,7 +53,7 @@ private: uint32_t _previewImageId{}; public: - static constexpr ObjectType objectType = ObjectType::Music; + static constexpr ObjectType kObjectType = ObjectType::Music; StringId NameStringId{}; diff --git a/src/openrct2/object/ObjectManager.h b/src/openrct2/object/ObjectManager.h index 98e0fb301e..eee1357f8e 100644 --- a/src/openrct2/object/ObjectManager.h +++ b/src/openrct2/object/ObjectManager.h @@ -28,7 +28,7 @@ struct IObjectManager virtual Object* GetLoadedObject(ObjectType objectType, size_t index) = 0; template TClass* GetLoadedObject(size_t index) { - return static_cast(GetLoadedObject(TClass::objectType, index)); + return static_cast(GetLoadedObject(TClass::kObjectType, index)); } virtual Object* GetLoadedObject(const ObjectEntryDescriptor& entry) = 0; virtual ObjectEntryIndex GetLoadedObjectEntryIndex(std::string_view identifier) = 0; diff --git a/src/openrct2/object/PathAdditionObject.h b/src/openrct2/object/PathAdditionObject.h index 505cdc08f8..a51f3132d7 100644 --- a/src/openrct2/object/PathAdditionObject.h +++ b/src/openrct2/object/PathAdditionObject.h @@ -18,7 +18,7 @@ private: PathAdditionEntry _legacyType = {}; public: - static constexpr ObjectType objectType = ObjectType::PathAdditions; + static constexpr ObjectType kObjectType = ObjectType::PathAdditions; void* GetLegacyData() override { diff --git a/src/openrct2/object/PeepNamesObject.h b/src/openrct2/object/PeepNamesObject.h index 919708c113..abdc834a0b 100644 --- a/src/openrct2/object/PeepNamesObject.h +++ b/src/openrct2/object/PeepNamesObject.h @@ -22,7 +22,7 @@ private: std::vector _surnames; public: - static constexpr ObjectType objectType = ObjectType::PeepNames; + static constexpr ObjectType kObjectType = ObjectType::PeepNames; void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index 110dc3fb07..d41bf85829 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -26,7 +26,7 @@ private: std::vector> _peepLoadingWaypoints[OpenRCT2::RCT2::ObjectLimits::MaxCarTypesPerRideEntry]; public: - static constexpr ObjectType objectType = ObjectType::Ride; + static constexpr ObjectType kObjectType = ObjectType::Ride; void* GetLegacyData() override { diff --git a/src/openrct2/object/SceneryGroupObject.h b/src/openrct2/object/SceneryGroupObject.h index 91c270043e..c99846d117 100644 --- a/src/openrct2/object/SceneryGroupObject.h +++ b/src/openrct2/object/SceneryGroupObject.h @@ -25,7 +25,7 @@ private: std::vector _items; public: - static constexpr ObjectType objectType = ObjectType::SceneryGroup; + static constexpr ObjectType kObjectType = ObjectType::SceneryGroup; void* GetLegacyData() override { diff --git a/src/openrct2/object/SmallSceneryObject.h b/src/openrct2/object/SmallSceneryObject.h index 906fa776a1..c9406863ee 100644 --- a/src/openrct2/object/SmallSceneryObject.h +++ b/src/openrct2/object/SmallSceneryObject.h @@ -22,7 +22,7 @@ private: std::vector _frameOffsets; public: - static constexpr ObjectType objectType = ObjectType::SmallScenery; + static constexpr ObjectType kObjectType = ObjectType::SmallScenery; void* GetLegacyData() override { diff --git a/src/openrct2/object/StationObject.h b/src/openrct2/object/StationObject.h index ed119fd05f..7874e21d4f 100644 --- a/src/openrct2/object/StationObject.h +++ b/src/openrct2/object/StationObject.h @@ -24,7 +24,7 @@ namespace OpenRCT2::STATION_OBJECT_FLAGS class StationObject final : public Object { public: - static constexpr ObjectType objectType = ObjectType::Station; + static constexpr ObjectType kObjectType = ObjectType::Station; StringId NameStringId{}; ImageIndex BaseImageId = ImageIndexUndefined; diff --git a/src/openrct2/object/TerrainEdgeObject.h b/src/openrct2/object/TerrainEdgeObject.h index 113b3464b2..ea77f40656 100644 --- a/src/openrct2/object/TerrainEdgeObject.h +++ b/src/openrct2/object/TerrainEdgeObject.h @@ -15,7 +15,7 @@ class TerrainEdgeObject final : public Object { private: public: - static constexpr ObjectType objectType = ObjectType::TerrainEdge; + static constexpr ObjectType kObjectType = ObjectType::TerrainEdge; StringId NameStringId{}; uint32_t IconImageId{}; diff --git a/src/openrct2/object/TerrainSurfaceObject.h b/src/openrct2/object/TerrainSurfaceObject.h index aebf3f9692..9b06c21855 100644 --- a/src/openrct2/object/TerrainSurfaceObject.h +++ b/src/openrct2/object/TerrainSurfaceObject.h @@ -35,7 +35,7 @@ private: static constexpr auto kNumImagesInEntry = 19; public: - static constexpr ObjectType objectType = ObjectType::TerrainSurface; + static constexpr ObjectType kObjectType = ObjectType::TerrainSurface; static constexpr uint8_t kNoValue = 0xFF; StringId NameStringId{}; diff --git a/src/openrct2/object/WallObject.h b/src/openrct2/object/WallObject.h index 8b85548427..7be5bc2a5d 100644 --- a/src/openrct2/object/WallObject.h +++ b/src/openrct2/object/WallObject.h @@ -18,7 +18,7 @@ private: WallSceneryEntry _legacyType = {}; public: - static constexpr ObjectType objectType = ObjectType::Walls; + static constexpr ObjectType kObjectType = ObjectType::Walls; void* GetLegacyData() override { diff --git a/src/openrct2/object/WaterObject.h b/src/openrct2/object/WaterObject.h index 096261f9d2..30408bc493 100644 --- a/src/openrct2/object/WaterObject.h +++ b/src/openrct2/object/WaterObject.h @@ -20,7 +20,7 @@ private: WaterObjectEntry _legacyType = {}; public: - static constexpr ObjectType objectType = ObjectType::Water; + static constexpr ObjectType kObjectType = ObjectType::Water; void* GetLegacyData() override { diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 49f7da9cad..bfe64cab2e 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -183,13 +183,13 @@ TileElement* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants, template T* MapGetFirstTileElementWithBaseHeightBetween(const TileCoordsXYRangedZ& loc) { - auto* element = MapGetFirstTileElementWithBaseHeightBetween(loc, T::ElementType); + auto* element = MapGetFirstTileElementWithBaseHeightBetween(loc, T::kElementType); return element != nullptr ? element->template as() : nullptr; } template T* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants) { - auto* element = TileElementInsert(loc, occupiedQuadrants, T::ElementType); + auto* element = TileElementInsert(loc, occupiedQuadrants, T::kElementType); return (element != nullptr) ? element->template as() : nullptr; } diff --git a/src/openrct2/world/tile_element/BannerElement.h b/src/openrct2/world/tile_element/BannerElement.h index 929c46da70..6c127f5727 100644 --- a/src/openrct2/world/tile_element/BannerElement.h +++ b/src/openrct2/world/tile_element/BannerElement.h @@ -17,7 +17,7 @@ struct BannerSceneryEntry; #pragma pack(push, 1) struct BannerElement : TileElementBase { - static constexpr TileElementType ElementType = TileElementType::Banner; + static constexpr TileElementType kElementType = TileElementType::Banner; private: BannerIndex index; // 5 diff --git a/src/openrct2/world/tile_element/EntranceElement.h b/src/openrct2/world/tile_element/EntranceElement.h index c57c97722b..d6b4789e9c 100644 --- a/src/openrct2/world/tile_element/EntranceElement.h +++ b/src/openrct2/world/tile_element/EntranceElement.h @@ -42,7 +42,7 @@ struct EntranceElement; struct EntranceElement : TileElementBase { - static constexpr TileElementType ElementType = TileElementType::Entrance; + static constexpr TileElementType kElementType = TileElementType::Entrance; private: uint8_t entranceType; // 5 diff --git a/src/openrct2/world/tile_element/LargeSceneryElement.h b/src/openrct2/world/tile_element/LargeSceneryElement.h index 437e207337..9a45dfddb0 100644 --- a/src/openrct2/world/tile_element/LargeSceneryElement.h +++ b/src/openrct2/world/tile_element/LargeSceneryElement.h @@ -24,7 +24,7 @@ enum #pragma pack(push, 1) struct LargeSceneryElement : TileElementBase { - static constexpr TileElementType ElementType = TileElementType::LargeScenery; + static constexpr TileElementType kElementType = TileElementType::LargeScenery; private: ObjectEntryIndex EntryIndex; diff --git a/src/openrct2/world/tile_element/PathElement.h b/src/openrct2/world/tile_element/PathElement.h index bb3c759f13..75eb619871 100644 --- a/src/openrct2/world/tile_element/PathElement.h +++ b/src/openrct2/world/tile_element/PathElement.h @@ -59,7 +59,7 @@ enum #pragma pack(push, 1) struct PathElement : TileElementBase { - static constexpr TileElementType ElementType = TileElementType::Path; + static constexpr TileElementType kElementType = TileElementType::Path; private: ObjectEntryIndex SurfaceIndex; // 5 diff --git a/src/openrct2/world/tile_element/SmallSceneryElement.h b/src/openrct2/world/tile_element/SmallSceneryElement.h index a025314025..ec890822a9 100644 --- a/src/openrct2/world/tile_element/SmallSceneryElement.h +++ b/src/openrct2/world/tile_element/SmallSceneryElement.h @@ -22,7 +22,7 @@ enum #pragma pack(push, 1) struct SmallSceneryElement : TileElementBase { - static constexpr TileElementType ElementType = TileElementType::SmallScenery; + static constexpr TileElementType kElementType = TileElementType::SmallScenery; private: ObjectEntryIndex entryIndex; // 5 diff --git a/src/openrct2/world/tile_element/SurfaceElement.h b/src/openrct2/world/tile_element/SurfaceElement.h index 4d4c3c63a9..ca8c1900bc 100644 --- a/src/openrct2/world/tile_element/SurfaceElement.h +++ b/src/openrct2/world/tile_element/SurfaceElement.h @@ -44,7 +44,7 @@ constexpr uint8_t kTileElementSurfaceParkFenceMask = 0x0F; #pragma pack(push, 1) struct SurfaceElement : TileElementBase { - static constexpr TileElementType ElementType = TileElementType::Surface; + static constexpr TileElementType kElementType = TileElementType::Surface; private: uint8_t Slope; diff --git a/src/openrct2/world/tile_element/TileElementBase.h b/src/openrct2/world/tile_element/TileElementBase.h index a57a45de00..f4b5ba44a9 100644 --- a/src/openrct2/world/tile_element/TileElementBase.h +++ b/src/openrct2/world/tile_element/TileElementBase.h @@ -89,7 +89,7 @@ struct TileElementBase if constexpr (std::is_same_v) return reinterpret_cast(this); else - return GetType() == TType::ElementType ? reinterpret_cast(this) : nullptr; + return GetType() == TType::kElementType ? reinterpret_cast(this) : nullptr; } template TType* as() @@ -97,7 +97,7 @@ struct TileElementBase if constexpr (std::is_same_v) return reinterpret_cast(this); else - return GetType() == TType::ElementType ? reinterpret_cast(this) : nullptr; + return GetType() == TType::kElementType ? reinterpret_cast(this) : nullptr; } const SurfaceElement* AsSurface() const; diff --git a/src/openrct2/world/tile_element/TrackElement.h b/src/openrct2/world/tile_element/TrackElement.h index bec0b0c443..7ed7a55917 100644 --- a/src/openrct2/world/tile_element/TrackElement.h +++ b/src/openrct2/world/tile_element/TrackElement.h @@ -52,7 +52,7 @@ enum struct TrackElement : TileElementBase { - static constexpr TileElementType ElementType = TileElementType::Track; + static constexpr TileElementType kElementType = TileElementType::Track; private: OpenRCT2::TrackElemType TrackType; diff --git a/src/openrct2/world/tile_element/WallElement.h b/src/openrct2/world/tile_element/WallElement.h index 453acac36f..f032fabcfb 100644 --- a/src/openrct2/world/tile_element/WallElement.h +++ b/src/openrct2/world/tile_element/WallElement.h @@ -29,7 +29,7 @@ enum #pragma pack(push, 1) struct WallElement : TileElementBase { - static constexpr TileElementType ElementType = TileElementType::Wall; + static constexpr TileElementType kElementType = TileElementType::Wall; private: ObjectEntryIndex entryIndex; // 05 From 75d06c8b89024d45d95d8ab24221f529445045d4 Mon Sep 17 00:00:00 2001 From: Duncan Date: Mon, 21 Oct 2024 20:58:25 +0100 Subject: [PATCH 50/97] Fix #23023: Incorrect large scenery clearance calculation --- distribution/changelog.txt | 1 + src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/object/LargeSceneryObject.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index c2653a3a21..1f4cee7a3e 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -8,6 +8,7 @@ - Fix: [#22962] Fuzzy horizontal-to-vertical line transitions in charts. - Fix: [#23009] Scenarios from RCT Classic (.sea files) are not included in the scenario index. - Fix: [#23015] Crash when loading a save game when the construction window is still open. +- Fix: [#23023] Large scenery clearance height interpreted as negative when greater than 127. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index a1c1edf24d..d4cb290212 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -49,7 +49,7 @@ using namespace OpenRCT2; // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -constexpr uint8_t kNetworkStreamVersion = 7; +constexpr uint8_t kNetworkStreamVersion = 8; const std::string kNetworkStreamID = std::string(OPENRCT2_VERSION) + "-" + std::to_string(kNetworkStreamVersion); diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index d96679b08f..8d5d5bb975 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -253,7 +253,7 @@ std::vector LargeSceneryObject::ReadJsonTiles(json_t& jTiles) tile.offset.x = Json::GetNumber(jTile["x"]); tile.offset.y = Json::GetNumber(jTile["y"]); tile.offset.z = Json::GetNumber(jTile["z"]); - tile.zClearance = Json::GetNumber(jTile["clearance"]); + tile.zClearance = Json::GetNumber(jTile["clearance"]); tile.hasSupports = Json::GetBoolean(jTile["hasSupports"]); tile.allowSupportsAbove = Json::GetBoolean(jTile["allowSupportsAbove"]); From 4b0b32b2b77f1ba36a0a76e2deb2d732eb62e8d4 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:15:55 +0200 Subject: [PATCH 51/97] Fix #22920: Crash when sacking a staff member --- distribution/changelog.txt | 1 + src/openrct2-ui/windows/StaffFirePrompt.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 1f4cee7a3e..8ccca2f605 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -4,6 +4,7 @@ - Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. - Fix: [#22633] Crash when drawing loading screen with an outdated g2.dat. - Fix: [#22918] Zooming with keyboard moves the view off centre. +- Fix: [#22920] Crash when sacking a staff member. - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. - Fix: [#22962] Fuzzy horizontal-to-vertical line transitions in charts. - Fix: [#23009] Scenarios from RCT Classic (.sea files) are not included in the scenario index. diff --git a/src/openrct2-ui/windows/StaffFirePrompt.cpp b/src/openrct2-ui/windows/StaffFirePrompt.cpp index 02a1b67df6..28c4528ee7 100644 --- a/src/openrct2-ui/windows/StaffFirePrompt.cpp +++ b/src/openrct2-ui/windows/StaffFirePrompt.cpp @@ -78,6 +78,11 @@ namespace OpenRCT2::Ui::Windows DrawWidgets(dpi); Peep* peep = GetEntity(EntityId::FromUnderlying(number)); + // The staff member may have been fired in the meantime. + if (peep == nullptr) + { + return; + } auto ft = Formatter(); peep->FormatNameTo(ft); From 1ff192b8a085d8182f1929663a9f599c5e00ba0f Mon Sep 17 00:00:00 2001 From: Sjoerd de Bruin Date: Wed, 23 Oct 2024 11:24:14 +0200 Subject: [PATCH 52/97] Fix #23044: "remove_unused_objects" command causes blank peep names --- distribution/changelog.txt | 1 + src/openrct2/EditorObjectSelectionSession.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 8ccca2f605..04d58c3dcb 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -10,6 +10,7 @@ - Fix: [#23009] Scenarios from RCT Classic (.sea files) are not included in the scenario index. - Fix: [#23015] Crash when loading a save game when the construction window is still open. - Fix: [#23023] Large scenery clearance height interpreted as negative when greater than 127. +- Fix: [#23044] "remove_unused_objects" command causes blank peep names. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp index 292e2a5ed2..ad049d6efa 100644 --- a/src/openrct2/EditorObjectSelectionSession.cpp +++ b/src/openrct2/EditorObjectSelectionSession.cpp @@ -707,6 +707,10 @@ int32_t EditorRemoveUnusedObjects() if (objectType == ObjectType::Water) continue; + // Avoid the used peep names object being deleted as no in-use checks are performed. + if (objectType == ObjectType::PeepNames) + continue; + // It’s hard to determine exactly if a scenery group is used, so do not remove these automatically. if (objectType == ObjectType::SceneryGroup) continue; From f4d2dadfe7cd94e19097e6ad50dbc8c8b1810472 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:33:37 +0200 Subject: [PATCH 53/97] Close #23018: Close windows before loading new game --- distribution/changelog.txt | 1 + src/openrct2/Game.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 04d58c3dcb..acf3aad5b6 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -9,6 +9,7 @@ - Fix: [#22962] Fuzzy horizontal-to-vertical line transitions in charts. - Fix: [#23009] Scenarios from RCT Classic (.sea files) are not included in the scenario index. - Fix: [#23015] Crash when loading a save game when the construction window is still open. +- Fix: [#23018] Crash when loading a new game when the construction window is still open. - Fix: [#23023] Large scenery clearance height interpreted as negative when greater than 127. - Fix: [#23044] "remove_unused_objects" command causes blank peep names. diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 767e53ff75..b4de059728 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -622,7 +622,11 @@ static void GameLoadOrQuitNoSavePromptCallback(int32_t result, const utf8* path) static void NewGameWindowCallback(const utf8* path) { - WindowCloseByClass(WindowClass::EditorObjectSelection); + // Closing this will cause a Ride window to pop up, so we have to do this to ensure that + // no windows are open (besides the toolbars and LoadSave window). + WindowCloseByClass(WindowClass::RideConstruction); + WindowCloseAllExceptClass(WindowClass::Loadsave); + GameNotifyMapChange(); GetContext()->LoadParkFromFile(path, false, true); GameLoadScripts(); From abb387021277fe6a18c37b7b117faed36ec3d0e2 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Fri, 25 Oct 2024 08:23:38 +0200 Subject: [PATCH 54/97] Remove dead code from Viewport.cpp (#23049) --- src/openrct2/interface/Viewport.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index ef05f4f5a6..067b939d35 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -920,18 +920,7 @@ void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport) if (dpi.y >= viewport->pos.y + viewport->height) return; -#ifdef DEBUG_SHOW_DIRTY_BOX - const auto dirtyBoxTopLeft = topLeft; - const auto dirtyBoxTopRight = bottomRight - ScreenCoordsXY{ 1, 1 }; -#endif - ViewportPaint(viewport, dpi); - -#ifdef DEBUG_SHOW_DIRTY_BOX - // FIXME g_viewport_list doesn't exist anymore - if (viewport != g_viewport_list) - GfxFillRectInset(dpi, { dirtyBoxTopLeft, dirtyBoxTopRight }, 0x2, INSET_RECT_F_30); -#endif } static void ViewportFillColumn(PaintSession& session) From 1c61c24ec2803ae9b7da049de8cca8f24824236e Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Fri, 25 Oct 2024 19:34:26 +0200 Subject: [PATCH 55/97] Add clamp to map size text input (#23050) --- distribution/changelog.txt | 1 + src/openrct2-ui/windows/MapGen.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index acf3aad5b6..bc3c11b17d 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -12,6 +12,7 @@ - Fix: [#23018] Crash when loading a new game when the construction window is still open. - Fix: [#23023] Large scenery clearance height interpreted as negative when greater than 127. - Fix: [#23044] "remove_unused_objects" command causes blank peep names. +- Fix: [#23048] Map generator allows map sizes out of range through text input. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2-ui/windows/MapGen.cpp b/src/openrct2-ui/windows/MapGen.cpp index 086ea6c88e..bfc7dc89a7 100644 --- a/src/openrct2-ui/windows/MapGen.cpp +++ b/src/openrct2-ui/windows/MapGen.cpp @@ -499,11 +499,11 @@ namespace OpenRCT2::Ui::Windows case WIDX_MAP_SIZE_Y: case WIDX_MAP_SIZE_X: // The practical size is 2 lower than the technical size - value += 2; + auto technicalSize = std::clamp(value + 2, kMinimumMapSizeTechnical, kMaximumMapSizeTechnical); if (_resizeDirection == ResizeDirection::Y || _mapWidthAndHeightLinked) - _settings.mapSize.y = value; + _settings.mapSize.y = technicalSize; if (_resizeDirection == ResizeDirection::X || _mapWidthAndHeightLinked) - _settings.mapSize.x = value; + _settings.mapSize.x = technicalSize; break; } From 5931996edc0f71731375cb968b7b868ef168f5db Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 26 Oct 2024 23:30:17 +0200 Subject: [PATCH 56/97] [Plugin] Invalidate window after changing its colours --- distribution/changelog.txt | 1 + src/openrct2-ui/scripting/ScWindow.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index bc3c11b17d..cc76e6058c 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -13,6 +13,7 @@ - Fix: [#23023] Large scenery clearance height interpreted as negative when greater than 127. - Fix: [#23044] "remove_unused_objects" command causes blank peep names. - Fix: [#23048] Map generator allows map sizes out of range through text input. +- Fix: [#23058] [Plugin] Changing window colours doesn’t trigger the window to be fully redrawn. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2-ui/scripting/ScWindow.hpp b/src/openrct2-ui/scripting/ScWindow.hpp index af4d0f2307..6289386ad9 100644 --- a/src/openrct2-ui/scripting/ScWindow.hpp +++ b/src/openrct2-ui/scripting/ScWindow.hpp @@ -262,6 +262,7 @@ namespace OpenRCT2::Scripting } w->colours[i] = c; } + w->Invalidate(); } } From 2bcf24f3d32ac25f490d19f805b3a81a64a4194d Mon Sep 17 00:00:00 2001 From: mix <167040362+mixiate@users.noreply.github.com> Date: Sat, 26 Oct 2024 23:03:46 +0100 Subject: [PATCH 57/97] Add medium and large half loops to the Wooden Roller Coaster --- distribution/changelog.txt | 1 + resources/g2/sprites.json | 672 +++++++++++ .../track/wooden/large_half_loop_left_1_1.png | Bin 0 -> 5457 bytes .../track/wooden/large_half_loop_left_1_2.png | Bin 0 -> 5600 bytes .../track/wooden/large_half_loop_left_1_3.png | Bin 0 -> 5778 bytes .../track/wooden/large_half_loop_left_1_4.png | Bin 0 -> 5861 bytes .../track/wooden/large_half_loop_left_1_5.png | Bin 0 -> 1611 bytes .../track/wooden/large_half_loop_left_1_6.png | Bin 0 -> 1333 bytes .../wooden/large_half_loop_left_1_6_2.png | Bin 0 -> 5283 bytes .../track/wooden/large_half_loop_left_1_7.png | Bin 0 -> 5618 bytes .../track/wooden/large_half_loop_left_2_1.png | Bin 0 -> 1169 bytes .../track/wooden/large_half_loop_left_2_2.png | Bin 0 -> 1081 bytes .../track/wooden/large_half_loop_left_2_3.png | Bin 0 -> 1061 bytes .../wooden/large_half_loop_left_2_3_2.png | Bin 0 -> 5178 bytes .../track/wooden/large_half_loop_left_2_4.png | Bin 0 -> 1436 bytes .../track/wooden/large_half_loop_left_2_5.png | Bin 0 -> 1686 bytes .../track/wooden/large_half_loop_left_2_6.png | Bin 0 -> 1560 bytes .../track/wooden/large_half_loop_left_2_7.png | Bin 0 -> 1362 bytes .../track/wooden/large_half_loop_left_3_1.png | Bin 0 -> 1106 bytes .../track/wooden/large_half_loop_left_3_2.png | Bin 0 -> 1119 bytes .../wooden/large_half_loop_left_3_2_2.png | Bin 0 -> 5151 bytes .../track/wooden/large_half_loop_left_3_3.png | Bin 0 -> 5304 bytes .../track/wooden/large_half_loop_left_3_4.png | Bin 0 -> 5757 bytes .../track/wooden/large_half_loop_left_3_5.png | Bin 0 -> 1603 bytes .../track/wooden/large_half_loop_left_3_6.png | Bin 0 -> 1329 bytes .../track/wooden/large_half_loop_left_3_7.png | Bin 0 -> 1387 bytes .../track/wooden/large_half_loop_left_4_1.png | Bin 0 -> 1416 bytes .../track/wooden/large_half_loop_left_4_2.png | Bin 0 -> 1527 bytes .../track/wooden/large_half_loop_left_4_3.png | Bin 0 -> 1869 bytes .../track/wooden/large_half_loop_left_4_4.png | Bin 0 -> 2040 bytes .../track/wooden/large_half_loop_left_4_5.png | Bin 0 -> 1486 bytes .../track/wooden/large_half_loop_left_4_6.png | Bin 0 -> 1542 bytes .../wooden/large_half_loop_left_4_6_2.png | Bin 0 -> 5194 bytes .../track/wooden/large_half_loop_left_4_7.png | Bin 0 -> 5262 bytes .../wooden/large_half_loop_right_1_1.png | Bin 0 -> 1381 bytes .../wooden/large_half_loop_right_1_2.png | Bin 0 -> 1452 bytes .../wooden/large_half_loop_right_1_3.png | Bin 0 -> 1656 bytes .../wooden/large_half_loop_right_1_4.png | Bin 0 -> 1794 bytes .../wooden/large_half_loop_right_1_5.png | Bin 0 -> 1411 bytes .../wooden/large_half_loop_right_1_6.png | Bin 0 -> 1526 bytes .../wooden/large_half_loop_right_1_6_2.png | Bin 0 -> 5219 bytes .../wooden/large_half_loop_right_1_7.png | Bin 0 -> 5360 bytes .../wooden/large_half_loop_right_2_1.png | Bin 0 -> 1175 bytes .../wooden/large_half_loop_right_2_2.png | Bin 0 -> 1101 bytes .../wooden/large_half_loop_right_2_2_2.png | Bin 0 -> 5106 bytes .../wooden/large_half_loop_right_2_3.png | Bin 0 -> 5238 bytes .../wooden/large_half_loop_right_2_4.png | Bin 0 -> 5660 bytes .../wooden/large_half_loop_right_2_5.png | Bin 0 -> 1760 bytes .../wooden/large_half_loop_right_2_6.png | Bin 0 -> 1468 bytes .../wooden/large_half_loop_right_2_7.png | Bin 0 -> 1385 bytes .../wooden/large_half_loop_right_3_1.png | Bin 0 -> 1134 bytes .../wooden/large_half_loop_right_3_2.png | Bin 0 -> 1078 bytes .../wooden/large_half_loop_right_3_3.png | Bin 0 -> 1111 bytes .../wooden/large_half_loop_right_3_3_2.png | Bin 0 -> 5241 bytes .../wooden/large_half_loop_right_3_4.png | Bin 0 -> 1504 bytes .../wooden/large_half_loop_right_3_5.png | Bin 0 -> 1558 bytes .../wooden/large_half_loop_right_3_6.png | Bin 0 -> 1461 bytes .../wooden/large_half_loop_right_3_7.png | Bin 0 -> 1391 bytes .../wooden/large_half_loop_right_4_1.png | Bin 0 -> 5472 bytes .../wooden/large_half_loop_right_4_2.png | Bin 0 -> 5711 bytes .../wooden/large_half_loop_right_4_3.png | Bin 0 -> 5969 bytes .../wooden/large_half_loop_right_4_4.png | Bin 0 -> 6069 bytes .../wooden/large_half_loop_right_4_5.png | Bin 0 -> 1688 bytes .../wooden/large_half_loop_right_4_6.png | Bin 0 -> 1268 bytes .../wooden/large_half_loop_right_4_6_2.png | Bin 0 -> 5195 bytes .../wooden/large_half_loop_right_4_7.png | Bin 0 -> 5292 bytes .../wooden/medium_half_loop_left_1_1.png | Bin 0 -> 1592 bytes .../wooden/medium_half_loop_left_1_2.png | Bin 0 -> 1540 bytes .../wooden/medium_half_loop_left_1_3.png | Bin 0 -> 1890 bytes .../wooden/medium_half_loop_left_1_4.png | Bin 0 -> 1590 bytes .../wooden/medium_half_loop_left_1_4_2.png | Bin 0 -> 1183 bytes .../wooden/medium_half_loop_left_1_5.png | Bin 0 -> 1284 bytes .../wooden/medium_half_loop_left_2_1.png | Bin 0 -> 1142 bytes .../wooden/medium_half_loop_left_2_1_2.png | Bin 0 -> 1009 bytes .../wooden/medium_half_loop_left_2_2.png | Bin 0 -> 1062 bytes .../wooden/medium_half_loop_left_2_2_2.png | Bin 0 -> 1107 bytes .../wooden/medium_half_loop_left_2_3.png | Bin 0 -> 1462 bytes .../wooden/medium_half_loop_left_2_4.png | Bin 0 -> 2094 bytes .../wooden/medium_half_loop_left_2_5.png | Bin 0 -> 1328 bytes .../wooden/medium_half_loop_left_3_1.png | Bin 0 -> 1043 bytes .../wooden/medium_half_loop_left_3_1_2.png | Bin 0 -> 941 bytes .../wooden/medium_half_loop_left_3_2.png | Bin 0 -> 1031 bytes .../wooden/medium_half_loop_left_3_3.png | Bin 0 -> 1550 bytes .../wooden/medium_half_loop_left_3_4.png | Bin 0 -> 1686 bytes .../wooden/medium_half_loop_left_3_5.png | Bin 0 -> 1279 bytes .../wooden/medium_half_loop_left_4_1.png | Bin 0 -> 1451 bytes .../wooden/medium_half_loop_left_4_2.png | Bin 0 -> 1610 bytes .../wooden/medium_half_loop_left_4_3.png | Bin 0 -> 1894 bytes .../wooden/medium_half_loop_left_4_4.png | Bin 0 -> 1986 bytes .../wooden/medium_half_loop_left_4_5.png | Bin 0 -> 1196 bytes .../wooden/medium_half_loop_right_1_1.png | Bin 0 -> 1388 bytes .../wooden/medium_half_loop_right_1_2.png | Bin 0 -> 1450 bytes .../wooden/medium_half_loop_right_1_3.png | Bin 0 -> 1688 bytes .../wooden/medium_half_loop_right_1_4.png | Bin 0 -> 1863 bytes .../wooden/medium_half_loop_right_1_5.png | Bin 0 -> 12457 bytes .../wooden/medium_half_loop_right_2_1.png | Bin 0 -> 1084 bytes .../wooden/medium_half_loop_right_2_1_2.png | Bin 0 -> 930 bytes .../wooden/medium_half_loop_right_2_2.png | Bin 0 -> 1012 bytes .../wooden/medium_half_loop_right_2_3.png | Bin 0 -> 1520 bytes .../wooden/medium_half_loop_right_2_4.png | Bin 0 -> 1920 bytes .../wooden/medium_half_loop_right_2_5.png | Bin 0 -> 1221 bytes .../wooden/medium_half_loop_right_3_1.png | Bin 0 -> 1173 bytes .../wooden/medium_half_loop_right_3_1_2.png | Bin 0 -> 1070 bytes .../wooden/medium_half_loop_right_3_2.png | Bin 0 -> 1112 bytes .../wooden/medium_half_loop_right_3_2_2.png | Bin 0 -> 1162 bytes .../wooden/medium_half_loop_right_3_3.png | Bin 0 -> 10644 bytes .../wooden/medium_half_loop_right_3_4.png | Bin 0 -> 1872 bytes .../wooden/medium_half_loop_right_3_5.png | Bin 0 -> 1387 bytes .../wooden/medium_half_loop_right_4_1.png | Bin 0 -> 1680 bytes .../wooden/medium_half_loop_right_4_2.png | Bin 0 -> 1696 bytes .../wooden/medium_half_loop_right_4_3.png | Bin 0 -> 2106 bytes .../wooden/medium_half_loop_right_4_4.png | Bin 0 -> 1593 bytes .../wooden/medium_half_loop_right_4_4_2.png | Bin 0 -> 1127 bytes .../wooden/medium_half_loop_right_4_5.png | Bin 0 -> 1162 bytes .../track/coaster/WoodenRollerCoaster.cpp | 1027 +++++++++++++++++ src/openrct2/park/Legacy.cpp | 19 + src/openrct2/park/ParkFile.h | 3 +- .../rtd/coaster/ClassicWoodenRollerCoaster.h | 2 +- .../ride/rtd/coaster/WoodenRollerCoaster.h | 2 +- src/openrct2/sprites.h | 4 +- 120 files changed, 1726 insertions(+), 4 deletions(-) create mode 100644 resources/g2/track/wooden/large_half_loop_left_1_1.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_1_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_1_3.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_1_4.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_1_5.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_1_6.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_1_6_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_1_7.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_2_1.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_2_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_2_3.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_2_3_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_2_4.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_2_5.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_2_6.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_2_7.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_3_1.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_3_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_3_2_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_3_3.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_3_4.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_3_5.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_3_6.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_3_7.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_4_1.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_4_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_4_3.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_4_4.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_4_5.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_4_6.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_4_6_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_left_4_7.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_1_1.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_1_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_1_3.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_1_4.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_1_5.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_1_6.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_1_6_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_1_7.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_2_1.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_2_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_2_2_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_2_3.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_2_4.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_2_5.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_2_6.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_2_7.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_3_1.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_3_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_3_3.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_3_3_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_3_4.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_3_5.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_3_6.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_3_7.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_4_1.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_4_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_4_3.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_4_4.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_4_5.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_4_6.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_4_6_2.png create mode 100644 resources/g2/track/wooden/large_half_loop_right_4_7.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_1_1.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_1_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_1_3.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_1_4.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_1_4_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_1_5.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_2_1.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_2_1_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_2_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_2_2_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_2_3.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_2_4.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_2_5.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_3_1.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_3_1_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_3_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_3_3.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_3_4.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_3_5.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_4_1.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_4_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_4_3.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_4_4.png create mode 100644 resources/g2/track/wooden/medium_half_loop_left_4_5.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_1_1.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_1_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_1_3.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_1_4.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_1_5.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_2_1.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_2_1_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_2_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_2_3.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_2_4.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_2_5.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_3_1.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_3_1_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_3_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_3_2_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_3_3.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_3_4.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_3_5.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_4_1.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_4_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_4_3.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_4_4.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_4_4_2.png create mode 100644 resources/g2/track/wooden/medium_half_loop_right_4_5.png diff --git a/distribution/changelog.txt b/distribution/changelog.txt index cc76e6058c..7494e672a7 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.4.16 (in development) ------------------------------------------------------------------------ +- Improved: [#22967] Add medium and large half loops to the Wooden and Classic Wooden Roller Coasters. - Improved: [#23010] Make AppImage compatible with Ubuntu 22.04 and Debian Bookworm again. - Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. - Fix: [#22633] Crash when drawing loading screen with an outdated g2.dat. diff --git a/resources/g2/sprites.json b/resources/g2/sprites.json index 5cdb0b0d11..fa6b492fef 100644 --- a/resources/g2/sprites.json +++ b/resources/g2/sprites.json @@ -7188,6 +7188,678 @@ "y": -2, "palette": "keep" }, + { + "path": "track/wooden/medium_half_loop_left_1_1.png", + "x": -26, + "y": -35, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_1_2.png", + "x": -26, + "y": -57, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_1_3.png", + "x": -32, + "y": -103, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_1_4.png", + "x": -33, + "y": -128, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_1_5.png", + "x": -26, + "y": -37, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_2_1.png", + "x": -26, + "y": -13, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_2_2.png", + "x": 0, + "y": -36, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_2_3.png", + "x": -16, + "y": -86, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_2_4.png", + "x": -34, + "y": -151, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_2_5.png", + "x": -26, + "y": -47, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_3_1.png", + "x": -23, + "y": -8, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_3_2.png", + "x": 0, + "y": -14, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_3_3.png", + "x": -7, + "y": -75, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_3_4.png", + "x": -32, + "y": -155, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_3_5.png", + "x": -20, + "y": -47, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_4_1.png", + "x": -25, + "y": -21, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_4_2.png", + "x": -27, + "y": -29, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_4_3.png", + "x": -32, + "y": -32, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_4_4.png", + "x": -14, + "y": -128, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_4_5.png", + "x": -32, + "y": -40, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_1_1.png", + "x": -26, + "y": -21, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_1_2.png", + "x": -23, + "y": -29, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_1_3.png", + "x": -21, + "y": -32, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_1_4.png", + "x": -37, + "y": -128, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_1_5.png", + "x": -26, + "y": -40, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_2_1.png", + "x": -26, + "y": -8, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_2_2.png", + "x": -32, + "y": -15, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_2_3.png", + "x": -32, + "y": -74, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_2_4.png", + "x": -28, + "y": -155, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_2_5.png", + "x": -26, + "y": -47, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_3_1.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_3_2.png", + "x": -32, + "y": -36, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_3_3.png", + "x": -32, + "y": -86, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_3_4.png", + "x": -14, + "y": -151, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_3_5.png", + "x": -15, + "y": -47, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_4_1.png", + "x": -26, + "y": -36, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_4_2.png", + "x": -20, + "y": -57, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_4_3.png", + "x": -7, + "y": -103, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_4_4.png", + "x": -32, + "y": -128, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_4_5.png", + "x": -32, + "y": -37, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_2_1_2.png", + "x": -26, + "y": -13, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_2_2_2.png", + "x": -32, + "y": -36, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_3_1_2.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_3_2_2.png", + "x": -32, + "y": -36, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_1_4_2.png", + "x": -33, + "y": -128, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_left_3_1_2.png", + "x": 0, + "y": 3, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_2_1_2.png", + "x": -25, + "y": 3, + "palette": "keep" + }, + { + "path": "track/wooden/medium_half_loop_right_4_4_2.png", + "x": -32, + "y": -128, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_1_1.png", + "x": -26, + "y": -32, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_1_2.png", + "x": -32, + "y": -45, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_1_3.png", + "x": -32, + "y": -71, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_1_4.png", + "x": -32, + "y": -86, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_1_5.png", + "x": -21, + "y": -69, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_1_6.png", + "x": -10, + "y": -181, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_1_7.png", + "x": -25, + "y": -19, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_2_1.png", + "x": -26, + "y": -8, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_2_2.png", + "x": -6, + "y": -9, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_2_3.png", + "x": -10, + "y": -27, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_2_4.png", + "x": -9, + "y": -117, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_2_5.png", + "x": -32, + "y": -140, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_2_6.png", + "x": -29, + "y": -199, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_2_7.png", + "x": -27, + "y": -31, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_3_1.png", + "x": -25, + "y": -6, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_3_2.png", + "x": -32, + "y": -10, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_3_3.png", + "x": -29, + "y": -39, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_3_4.png", + "x": -10, + "y": -61, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_3_5.png", + "x": -11, + "y": -118, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_3_6.png", + "x": -27, + "y": -198, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_3_7.png", + "x": -31, + "y": -31, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_4_1.png", + "x": -26, + "y": -20, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_4_2.png", + "x": -32, + "y": -24, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_4_3.png", + "x": -32, + "y": -63, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_4_4.png", + "x": -32, + "y": -83, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_4_5.png", + "x": 14, + "y": -61, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_4_6.png", + "x": -17, + "y": -184, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_4_7.png", + "x": -24, + "y": -21, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_1_1.png", + "x": -26, + "y": -20, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_1_2.png", + "x": -22, + "y": -24, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_1_3.png", + "x": -16, + "y": -62, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_1_4.png", + "x": 0, + "y": -83, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_1_5.png", + "x": -32, + "y": -61, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_1_6.png", + "x": -22, + "y": -184, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_1_7.png", + "x": -28, + "y": -21, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_2_1.png", + "x": -26, + "y": -6, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_2_2.png", + "x": -13, + "y": -10, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_2_3.png", + "x": -16, + "y": -39, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_2_4.png", + "x": -32, + "y": -61, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_2_5.png", + "x": -28, + "y": -118, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_2_6.png", + "x": -21, + "y": -198, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_2_7.png", + "x": -25, + "y": -31, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_3_1.png", + "x": -26, + "y": -8, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_3_2.png", + "x": -29, + "y": -10, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_3_3.png", + "x": -29, + "y": -27, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_3_4.png", + "x": -32, + "y": -117, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_3_5.png", + "x": 12, + "y": -140, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_3_6.png", + "x": 0, + "y": -200, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_3_7.png", + "x": -20, + "y": -31, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_4_1.png", + "x": -26, + "y": -32, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_4_2.png", + "x": -28, + "y": -45, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_4_3.png", + "x": -25, + "y": -71, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_4_4.png", + "x": -8, + "y": -86, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_4_5.png", + "x": -9, + "y": -69, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_4_6.png", + "x": -31, + "y": -181, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_4_7.png", + "x": -32, + "y": -19, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_1_6_2.png", + "x": -10, + "y": -181, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_2_3_2.png", + "x": -32, + "y": -27, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_3_2_2.png", + "x": -32, + "y": -10, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_left_4_6_2.png", + "x": -17, + "y": -184, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_1_6_2.png", + "x": -22, + "y": -184, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_2_2_2.png", + "x": -13, + "y": -10, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_3_3_2.png", + "x": -29, + "y": -27, + "palette": "keep" + }, + { + "path": "track/wooden/large_half_loop_right_4_6_2.png", + "x": -31, + "y": -181, + "palette": "keep" + }, { "path": "track/bm_invert/booster_1.png", "x": -25, diff --git a/resources/g2/track/wooden/large_half_loop_left_1_1.png b/resources/g2/track/wooden/large_half_loop_left_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..6c1e9de13763a13ee504024fe05dac5dce07d9a0 GIT binary patch literal 5457 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_1_2.png b/resources/g2/track/wooden/large_half_loop_left_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..b0c70a3ee45cad0d44a6266b6af9d4b078a601f2 GIT binary patch literal 5600 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_1_3.png b/resources/g2/track/wooden/large_half_loop_left_1_3.png new file mode 100644 index 0000000000000000000000000000000000000000..0092b048461d899ee71b1ca6bf8ff1b5a73cf98c GIT binary patch literal 5778 zcmeHLYgAKL7QVb1AsCE$ zwYCT)n9B_)0WH(2A*k%@;_T#U0nbi3;(0A8*>C2~;ZnP(^6&1bSBlRcY@ic`O9S5= z@c7yNz6dRNCwE``?EDoU%ZR7HB)g9{kkf@dg)tc+e*02d`a5!3uy(g~BmUb@jEwq< zDXxVJY8>llE0!&qKj*hUESoH3b z7D$=%XW*-r(zEf$RGlYMiVnkPKUd37ITCkNv2X2JfzOY9Ybpf!ZPp5f*&?CvUN9hp z?HlS6)1BFouSlft=PaC7`t;f@**mVkM||`BnYF9m?VR~i3BCL$JWHFNQ!qDZU{kfA z_C;KjW@Su4Q1VUO@r&J}FH5;y zhQaUK&(CQ$NhXeEzaTqp+;M(Zeg2YQ?Ut=yE}j{mzoqY^Iweu)UK@_>8J0AN=jY9Q zeQwAe;VVDf?#3>S6`kq(qSF@nTEOqLgTFKU0!ufR_8)Xui@P@X-)`PW*>|nOUiF)# z&$g0k3=Ay}h#FX#IT#RUsj4HdWX?+)?VpkH+@;@N|Lj93bjZIu-lE%K+MWb)-}!1Z z%wU+ZtTDFY+u?5mj+(~pt*`^1wcofc^>d*=D7sQDD6ag>WjsV*9H&s}m1ta9u>n*a z1SJT{3<{(WH4~JmMypFCj&wPQ1g$EOm=~W(&ol_pHQMxbMpU{kD;HT;h;UUzK~iu+ z84myyqh2LB9RF83HSUfHe_brhu4|zvHh^1t51F`i~l>T+pMm9Mq&QF(PPcDXKG*9)?gM_w@}W#v)%hDujj>p~XPd1gtV1 zF_|XH%)YPTr9h)CHu$sv*^fw?wdx0CJ>r{p#~04SjsW%hxQ|HRi`^#-q%t#kDSD*D z>z*hjk?6J0Q|S?{is!p!bK!V3i?xW#P$(BsSujIM8Q9L5XxG zvqFcUUMK(_rv*3&TghNBxJoKh0V}917H1Ka%SK@;J)Q$|Q5ILljLsVq9o1$XLrYP?FxRWncq2ZgylZ&V0xsoq$u0O`~gD>Nw0 zpwsv^yoB?TvqgzSW*q&&N_LULtOg382edks-eP*Nm8&gArDlbfPX?RGVbhsRHl5C7 zFktwB&~nsh0=4KxWzgebj&H}C7#;`*P^<7(Dgf}UgJ^g{BdRd#jk$V#Q6kan6v3-` ze>)R2luBV%q$tcN0HrfoJO-V|VCK?UJTRDC3Z22DKP0bLY1QTbP1@T&goMeYr)y2X zez|XHvZtiz+R54Ev`Fh~CIZ3N7CZ$q8G=bsimH5m0<6g`WQ{_nLBaWPw_xwBYyU$r zD3lBqN3DXXEEO}J%8IAMR3#nMQ#_XgtJO?8ou&R4bdz3fwkV8fvIg)7xB><0z|jRxLfZYK z@Gf88L+AhaxtoXoqXhu{#K>du`-HA1bUhXWk0t!1x}MPWSPVRt@RRELpV1Zk;9&~Y zfqy_2@Tio&IXMD?0-)?=xvAiB%g@ix-`_tVARsU>FeoVKsi&U8;c!!?Oqn`$Y7~h? zf?=9aD3D6U2qH6?^wrhXO-;=m9d@U)-{l(dcwibN;6oB|h)fnySctb&&}wS=O*Tnu zhrG*S>glZ=8g3C%aC!U?y*R2e4{t@t%_jIjwb0R&*VCbQovd-YTE<44Y0;3J0$Bu* zRf=oX;~cf&1FaFBo@mTX!#r|q+=^jN5(G&gNRGql!^111qpf6e3!i^LA~~ti3{+NL zYi`CIj%YZ7B#5F(@O(KrO;5?Igb^#>WD{1mi5t44Ej@C(OM_=e)6z(MDMgI1WqP5$ zMpDx(Z?^00y_HT^L$AAaXv`5VfFh(&lm^0AKx8Y9-5izHL6$iL`rf?SAydnU)rlRD zP$Cd^v?YyFo5ycOgk2_SZ#6Q|WEyU(9&t2{^|oQd&hQ8}nUV*yH3FeUDy>Bjo5j*m zTkB|U?zP*8`uj&lMldK^50RU2aBH}*D_Yt^(F_S|hGi{oOV^0C-_zk99~i?zDB;uTG+5JGTad1<>fYWqx4RbuwxTr< zToEF$MoC)maywb?;#)^#Z5~V4SX0lqeFz&EAxA)LJT8qEE)(DjrErBtY^^M8X{hXK zYv^^hxm`}oGsG5)F*}60APfV!r~&3CM|5?CZFrb%YnmLUo*to0CM_&PDk}6at(r}1 z62NUj*deC%ODOI<5+=uEm1N8YV|D@7D+a~SriT3D?E!O6mK0ii`2u*g1^Fq(X(`Z_ zpqO+pnQBO10mupg9TO7a2fed>7FfiYMVYC%E5V@wfq&Rr)wc$8)AOQ~&!Mx}t%zjc$$$_hv6W>?;BwfKeGvXOPmvG~!QxoRh z{OAii-kh72#xosEirfC@&=Wh`t)F&>X|4*pD+b1XL0&Gnx%E1d5&LpJ9`T=Nqn!NU zSCRNm(CN}U_Tz&ECE_E=pNxi+=SI};X<)tFa3tf0)z1%}>pWhTwn0|^27?!U#N^pc zycSk}W9R8<#~tx!vkG4gU!PG|z!`0P4!p++{9tv{5o_eu%?mFs?wdiBzLYZhOXkMP z!gor7XI*^x^wYb?#}+=_pRhdra$`Z%#?{X`Z+*Bm;T*Z=Z-;L+?jrGnWa4F){t;So zDKR$x=7~A;Y`Hi8Uez+M_l@KY=X1XcVkN|GSr9MY8@V;C;}Z8y<5#l2KTAJ2q&nSM zKQ?%UnmqgS5YGGzTHeV^+?9QA9ebt<+Sw#Md-QMr&=Kn?1%Y?AW^_x9lp^DshqGfB z%(sQe7VJN$r1Q1qbw_?)_180 z<+@zawQcx7ks|NC>p{DpIX}9!^YfG$!x5XN4SpHS479wrSNd6ga^xR>OY+RD|1J#A znBLZ0|7=-F^DFY8^rT49ijYHp&+cjUE4b1c7^rUk z=*)QqaORoR^@F(bT{v0$;;uDLTg|VwncsX`LOkMXoZ45HT;fmh%nkp>FaOMW{?rtj zm^8gC;I%UL!h>f^$uWm@k*5|%-x|Fd{?V#uaza_-pB`ITQ4nSi>pd509*h~}ZQ57G z5`FgdjUU7OXU#rjo2bP95OI{_N4Tv#9sAXx<&NurT{d^%E=*)A9%vLH{z{@F_*cc39=2boFrNKtbFtC ziHbiqYy3*rofE62_)XJ8-o4yFZmdWddV6Ae*BOsn-uB6l{qFi1;+enRxp_sNEJ!Lj bJmI(fW5X)ehOjR{D?y^vtdx(ItlsobL*=Sq literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_1_4.png b/resources/g2/track/wooden/large_half_loop_left_1_4.png new file mode 100644 index 0000000000000000000000000000000000000000..89acb24f6c96758c7ca20d613bd07dc067d2dffe GIT binary patch literal 5861 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_1_5.png b/resources/g2/track/wooden/large_half_loop_left_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..95ae4fcee07b5798a32d54266aa3d4526baad71d GIT binary patch literal 1611 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 BS(g9+ literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_1_6_2.png b/resources/g2/track/wooden/large_half_loop_left_1_6_2.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd1f81f21c359d9e08950e330ab05c86e99a736 GIT binary patch literal 5283 zcmeHLeN+=y7Jm>h2r6r-jV;>5q&CnPCSQ;bz!bx0V+;}$6ghD+nZy*5iJ3r9YGX?+ zDs8h$D{ir(Wi7R6aq9=WC$(vfR=ZSVrApmYsj^+V)s|Ma(n{&^7apBdO z^RB);@r4aX={r`+7A77s9?0GIeA=$ub&`)OXHnOk?86armM_W8t}8tOK*Vzvm8!5n zrMejo3}V}wO_}-r!u!{0b-Riln^OIUmFo*%yZSo&rCrk+mhU_;ZE2NY)xVh%OMcO^ z8PPq@)+rkn(HZ9QnaiTHzM~&K|3SegIZwQcBp+D+{gJ*k+gyQ5hljz=Mc7;C8MNY) zBGE^G-HPnl_)JOE)Mo+n!`Y^K!R&FhwGqmq>{~p7eNB19{ znsYWuf5N-Re)002a}VtywZ9xGTv+yz4Q?9v4OL48;#4Q&+l6S59z9(jXG4jHDyTPR1$PZFo zw%5pQbAkNTv)3lu?J@JWB-dW(yFfck4tKVRear>>99wgasUl(7Ra;lZA`c84qE^Zt2^r9F^g4j2MDf;#Me1 zLaV|%Oy(763U6tIC@@>B_OKQt`wmH`#dMpjJA4c6gu@x{2vom?dx!MR*u%n5N~2L^ z6IfNqy@KpacF4ZMNMIJDBK(LMFu7bR7xCq|$i$Zzg>t@3l7{mQsi@F^i3GA#gJB$0 zfsJ&cHVh9zLGTm{#6i;xqSQ1@%EwGXDPJNr3HUMrj`A@dRu5Q?jT_;hERoql(Be1iBZ6CAhl?yQXxQC14g4zIdIfTIEo3PGLs#0iWSnl zwXJ~-Wkj85HtNJ7s6Zr92n7nEs8}FY2t14=ZCd>G>8C z+Fuo38to|^zH)RnI<2&Xn~B8=w}k@5MnfRcYTOw16Jm{SVJlFZ8HeY`Si#<0xBNyi zq`^>NmQwk+05$R@5}A-M7YT5_2^WhEA|ocp(y%+xNy6lGp$FN8m+T&((kK28vrG@hO z62%D|B?Hki)Aiguf>+`eW1e)fSyk7rZuII}yY!twGgF#~y*B@Mk~>ww2k?bq@WFlnMI zkJnI=-iE2Xq%Kg0^)!)v?R5jbrlCMP)#r~-kaBq?VyRiFa_Mvp7}o4^bu={iT3P~~ zoxR=N0|NsTNF)Hai7sx7S9ue4T|9HIs=lwRwcq6(@N^G$^bhw8QE|NZcqxOC$K>dE z2$r5ssg3de;)B;KeD1t#Xh^baB z)mcGx)l?${O$cgKQ-7Z zRja8^Km`Fs!CcfsbE6}%uC}?aPukoxI>@drRau#?q5`X}CB#Ub6lqe5+f`zp8tK;Z z`b#*Jo=Lg6RI`}sR8j#oEPg3J?)y*=IExnOz~le=4F0(VA`I%hY_L9hW?t(6Ho@znk{laGyP!k)=rvytCMG0FBs#W&?RF3*?ZkkeQ4m|-g1U^ zU}^fxRqyN^nXqW#j4Gy8`pd;Bw4CxOhuqKOwwDeGr%!z#Y39dC9wqJDrIJfk2JWV% zBP)4NUw?6X>2r%_e=3riIwDRKe0Olwdef1T9Ro9W?4CPg-BYjY55GEViiekYpjg_N zbeebi*mBzJmz%zN|C+NqL3;Ywvbr2jQsMlrbLP{WeTpZ&!7ryeuRqC|{Aq1N`8VIH zb3U8yKlHSG$KF{N&LY!>i>B@fa{C@%ylu&k3I*P1qC?^vfrM!{Mr8k9}dCe literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_1_7.png b/resources/g2/track/wooden/large_half_loop_left_1_7.png new file mode 100644 index 0000000000000000000000000000000000000000..24529103431d94dde4cee3440c9ed9b9c11d55b6 GIT binary patch literal 5618 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_2_3.png b/resources/g2/track/wooden/large_half_loop_left_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..a683b54ba7a2110043acaddf67ae63e086cbbc71 GIT binary patch literal 1061 zcmX9-acCQL6n<&iUc0PhBg{CXq!Q%N>&V6-Cp+Y-*Ba~1Uc0M{5aHI{SkQY`Pjs+Cw2kA#N4YhM+Xxh)a00V(7!(OnGN8Dg(FL|1M2a3hK7c`UhnYm@W{x> z=;$bhVPj)s?!qR827wpc7zt7fgX<+|NokBkCC1JC&qi9jk9 zPG_RIJY6jDm8xjjO2f&w+B!>MaoQ(yK{X!MB)qJU>si(=#v4`Ht>-$f-tX38ArJ{j zGoT4rMaJyBzgY?N8X?q)qMnF$G=ypq03JZZFxl@{Lm>^vb(&u1`Fb+hRMq?CGP3Ou z8Hg~!C?BRpJSG!ym6SAEDY03DD_DZw5KT83rb5wJgcb-+q7pJI=lEP%ESs|Fs5Q6X zbSkaB?Pnk$Krjj64B#3@m4mS=p0F9&iRW92-qmVoohJek6-vj5e4MUGtfdG}R%#ZN zwvp}H#lB;pcFiB4a3W4pNrp`eLSB+e>2x)px65V6G+SF+-EJ2_NCv!!krh8{g@gu? zY_Yj^Lhq!luC~>yc6OS52IGynsj4$#H`4ZyP~qaZ^^Zj;ABCZWK9 z83UIGBmk0wC{H4tM`j8&a>&);Vek}iEW~*%B?Z+qQP5%)U9zmK;~1Teg9cimB#;>& zqXl_AESk9N(pooR^wL(p*w`^!sM*B>K!veb)SqC&DS^x+IZaLJ1=TVNPR;1JHPmZS z9EVImE+90>A~%qGgitn9YPYFU@e!0pgH0raR7%QZWHOqiqD6)@SkmUATRhQ;N01ms zDvnAdG8yD>gX5+iRZ9gCG9=*gGJuc;3F0 zelJO#`0d8ok58Y&KiTlUb>ZF3J+C}t(Vx-*qq}{`cz^o%FF(^K?o54q_tg57@9O2n z|627orQOHAAKp2;?p9}0iyuWO>4UG9Z!FzhQ@^bJv-jRl*Pd@IKe_$m=gZ9`y|z+a znf>n4`Pb7+)v3v6pF8}lk&{|Blr$npRH literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_2_3_2.png b/resources/g2/track/wooden/large_half_loop_left_2_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..0a545bae4d3f48c7fd3f6884d7f4151a9a60154b GIT binary patch literal 5178 zcmeHLeQ;A%7Qg*6(1KkoShO(7q_PpS=}Yp`q)8~Tq$RDPO=+qrRyMr6yo5}eypWeR zg$^4bxJ7~+*}Ak^pvz{kV5`Lei8}!^m`ZVqX0bxWfK@A2RJKBOi`&JwH)(+~I|{mdRef{QjFo zJI{4L>M3M8a{l@dYyCi#y2x97;KS}p*Wq_(5?521d-uJO`GS&Vz0&r5*UmP@#3lUG z4%6dr&A(K*W#hb8wuJxiz{-bmo?X6h=H5TfX~|eT>m@~o`po5jZ#g!c{zHnlc<>{| z_^(g1$$I|! zOH7fawCbq^X@i@+3g6?5Z1d`cPo))o$LKwGyzF$zV@Hw2hqqpNdwAn6cl5Jk6JYP- z_$%kKQ>xz+3g3OR4e8#tNtZfjGhm)rWcvERw}yN7{7|piSnXc9=i-HN^Xx}TT9TIT zC^+GYus>n#i5+&mKhcXlv19J%)aQ%6d8Pk3S%2=L6`e(-#x z+pxd)Q16_QGY{)ehPoY}eBOQb!EQ?P)7zCRYu|P5K0E))YQt z0A>v(AJ2E&cT>BT0_jU=w8 zI0@~BifVj=6_*;>ilymG8f6f`Mz}Cmqpi+P$r=mU30xU`j!z?ORzk#OEo9e}SF)6( zlVFMRM0tE(Nu#Af$X=SxTH-XCWL3q>ry$^{kiFLBa>x+G?RMw6(LB;=Mg&r+6yXaI zp^yh9c+`5k3v1-rsoXfkBt|ho;ZBRgWg+dXI3{Kw>s^IxHe6@j@XzKbFTV+Ir>0nd zd?1aO0}jPFK?{uegpijnG?{oJF(2g>h;T74Ura~| zkw8=+FbJkWmDwp5X2*#*6a>$+KpZ|U6&p+vF|WWV5b;DJATYL=qF9C&CFn&yX(^@uUX6$!I|NXnuZv0?LTX zmXl5!2GeP=VP*nx*v*NBIN`FQ%CbVXFpqz0rm_xmnVU!Rzo>?tj=ZgMm^tg|GViN#8^g$%72>Atkqx5!kiZr?0n3E_n zLmnYlus{=Bu^ygE)#BUb-D`<>9w22r0iQRGGBz?5EE3-_ZbZ8T`57Ne5(3k<7^pWn z2e&S`6CyXa!YRJuo6fKJo65tlXaPdsHF8J%-lgj@XXl9G~=lao_YQc_b>)6&xJx#u1RgE3>q zjF~fMX6NSSq9~$NDzsWPj@MEY>GgVBTRVDsf|1BTEH*keh9W>A2O4!oZEcp-%5*m& z%|3Z+yQZ^89|}|bQQy#TK*?q3*>(8M_5PD2cPxxs%k_&(a06l|2W@dVFa{L@lKrTO|(e#@9Im`#A=XGl7-RXv>Au!4;0d_z=V)E}V_ zX}DRqB*(4d`gHP6Tp6OYQ7=B&N)2~;N5ie-(Jp#8l9?spaCNA}tWdhOS|5(LyWKrL zU$~#k)2d#8}GaUD3rX~_ayb`2Ufp#g;uo@ZA za7T2xw4Ots*=;5z+|Hb!Vzf^r~?E<_{ zepMoTzITWEfs+$8+~Rjmm(oWr9AF?XJh!p)xiz8RA3d*mb^Pqh^nT{yZ|^;^X7t)7 Q7#t`osVIJJ*_zG&1+q|@tpET3 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_2_4.png b/resources/g2/track/wooden/large_half_loop_left_2_4.png new file mode 100644 index 0000000000000000000000000000000000000000..d44a37534b2c39efeef8e5e511ae564199570582 GIT binary patch literal 1436 zcmXAoe^AnQ7{@;<`t?T+lNA-a$RVRf4ePtfHqx&S9T}^y^=(6?!lK1ITHiBtoUz6h zEh=U#xJAb9XyJ`3Ht{r%^Ken4W{eaI7ZoWrN>;6yapjuVeMZ;a>v^7g{(0Viyx-6M z+SQ``+=HHEayu}A*sjp zHkr*$x`SF@#2kz}qElWf251DJD*#giI7WnTql;V|sTU)I5<^sFPZ)i$7w6LCe1=-Y zHAn;wxzM8`f;xHFqKY|n39n@;=!7vJmB#0AB`9Bk3DpE)kjt%VwaZ}e+H66$I~ocl z5(x+xB;Z&O)Ik+`7({@phzj*FsXeatB#fb?D?S~bf_Ypjl~1ROm@IrkKmvdY03!fS z00sewApoYpg;1k{PCJZ*aSk9+V8(!31R^+q1b`$R8c=A*p<4+9dKj^T=f?AaSO_FI zqLkCMYOdKRa@ge_k1iN=#^XVl(qbq8s>#EQbllFAxjAG+U`$AzNwsIn5}0;JVK~8| z0X`EE@u*UasU%R1LTuD3?PjgVX%70F@rVy5qkOR#x&e#;2vc6@Q*tk0=rq|CqN#SruPY{+Iw>X>XY+}` zpEHwXss>8GWuZY-cqsGu`~`1~RE!qgK2|z&t){8?CgI(4uPm)|{7v30YF&@(Y|rv% zN3R!cKD+IuW9mMCw|aDC_o7nK##O`P zLx)1@Pe*pL+4{xo>H3VKEh|s6rOVlS)^(Kn%A4#bh*usT(wIK$c&YxBqGM`{cWjwz z$Av!gr7h#Hz0RgJ`hWZDpHrIAJE}K8P5ssb&BLC7{-(C+?&^L{^orXwRONhpCyEyI#+Y&rqhx2!#$b!iT}n1=3SPw|BbdCG#}nK z_oU^gxhEf9zH(UXZ+O(>Z;UtdN9&~i?FW&PC9@u|`R7}fjc#P@^Yz{6Gqw1~_JwA} zm!3A%#A>^AO9yFn{-KU<+UnKj_|^6syUM0o_jEnj{_{}(?a~2mU0}oI76i+$98h0E zf|_leO@_1Jzo71$w?5G{UOSWZ zu2+y4dFY)zBWuo#k~z6`9yPD{qmq|b70l`W4!x_3rWfXu_s-n%r6LAus#jNaz1O(= Ef3iY}umAu6 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_2_5.png b/resources/g2/track/wooden/large_half_loop_left_2_5.png new file mode 100644 index 0000000000000000000000000000000000000000..022f7849b0f2358af57e09686714a88ddd5711f6 GIT binary patch literal 1686 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_2_7.png b/resources/g2/track/wooden/large_half_loop_left_2_7.png new file mode 100644 index 0000000000000000000000000000000000000000..c4757d2834ba53dc9ffd9a7f11098cf3f28a96e5 GIT binary patch literal 1362 zcmXAoe{2$W7{I=WzF^>l2W4wp-%dabmc^R!pRh>8=HIb2W6GGd8B zh7OhKsjOngQo5mH#SXK&V#J9XX3Zp%%^GP%$1>)aHcBnESZn+aWAb_5H}601^T+eN z`<5+LOf0G>0su^GsIP6zPHDE@F38RHo*jL^1CR@rEorLDt{e_0CnqO2H#aXYFF!wj z!h{J3f)o@K6c!c=#9}dqNeMzu)1*eD((4(E#o}WPRip`2ZH)=#1>Du2^3M{T!s{wlpKrZi?#FYNIC8 zpvwh=K_SK$%LP(OgsUYA2349c4U6lYgvCqR1GGD=_Q$j$nNX?_<1|WYWGaSWtd!NI zcKI29#1x9zBS}v@6XeMOp9TUg5E+4lMPx34!Y5G$_1Hb~{1)vvz z1Oi|dihxEv^txdzN=X2N0lOUd6(B|dNCU_Spbdj=3i@?0Y=tp5cwxK@kOWXth)yFg z8BjZ`@VGUBfF%;~CX*4E)e>p}X5`9Q0p%8{{SqdIvniD~Z3tu>;cx`jwaBCnIp!s>ASvym(4#3pENF|LCwGY zn*qoH4YdoJ>i4y^EkA0hEUvo)ug^SX#;X=w9y>P8y!xlreQf*aMcomHd98mB?~<{k z`O*CINUOEBfErFXS8^6CtlsJX;@yh zqpRo1Hts`NO;PK-UkWc%Ayrjp%aI^H&gmfAx*D%;S}=Fj^Rdr2&@BxICjQuMR*$j2 zP0!nKqxH#23a&GAL9la<4z4-@qmezi^aQ$ch1NuT-B>(^b literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_3_1.png b/resources/g2/track/wooden/large_half_loop_left_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..b5dae12a6335c34a45598de1e5d460331a31c598 GIT binary patch literal 1106 zcmX9-Z;0D;7=CxXyWDo0omQzXu((xLFlvx6vl%3FxlwO%%XT@;%^*<&*KI|DMyWGM zw{=pya%QZ$ekj;UK6Dyq(fd$lWyOW_rk#s$VuhS5uCR{HS!b0)2L6l;p7+o5<$d6N z-uK--yAx|xty={EYsQ}$n+Pf$#C;>7ATP~q3P=d{JUh7~pet6a7#J7`g+haagF{0@ z!^6WEhK-DjtX#P=8jHnfn&Np*k_1gt3`5Umv&CY$TCKV6qVMqv_?_9h)aHnH|-IXhtS1EnYV0xh&r(%FU|oFXXzuz1(vXIH)9~ zIj|(GqGOGGxK)Ytn>gxHsIQ{i7D8?eKm<@ROb>@MIBvz`Hp|Y5;zBan%4BYo%c#-7 z=}3%=QX;{s@q|vw8CtVgqr_(&p-`9Xrdsop1cOtF7%P#2#wa?k=fqrDE!Xs#mvQ}q z*R8ad8(|J25=4_gm=L!xrW{RF<4S|mJvrYt?4ISKIgyNL44zJqd6}(feBF?|tkx$ub; zlWjiNQS5HI-m@0_)$Z-qG8!erVI~?)5HX3QG?q04F{cK@%xb={P^tQ^*Kc#63YZ~< zGb&-F$dbu9IjLSsE;yN1qttD={r(Na0muLbfCb$|Am zW&{D%0QrDW;6*Nwy8}FHmO34#RJ;SD+2j>PN~JW@)M+ZqP(_Y*c)B4_iz3;TV@M@X zCXPxps&U8@g5zf%9liDc54=9HTY_y@f1VC{7$19ja?9-OiM@9ndvGoP)WBOPcIK44 z@0}x!n->r7-1f^igY)wHCttdDEwt~#)}+~^X@#v1t($$kv*Fw;hYr0uKUug)Ij1`h zxYjp>;ENxdu)EJY=*Jp_iV*Odk>#peQxvo%nz0Ov#TGHzF1`&w|*R~ zk4&Ba;Ew}iGwRf?OW&Q&-Mx0^6mhwE;Z`Xo{eETtSZ6pkch%f@c4FxbY@W7Fg77IpmO_FyqEzGL^; JXWL&q`X5on;e-GH literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_3_2.png b/resources/g2/track/wooden/large_half_loop_left_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..40d2acd0be016959a489346b48f30075683950b2 GIT binary patch literal 1119 zcmX9-f5;Pc7=L{CzVE%dUia$2(Ys>SgiDW?>+PU3PB_=lx4P3UsZ0N#aFZFFAe4bzbJRkUc zp6A4l+2H7k@f83tIz6>zu3snm@#u)7pHGn?H-H0n%z64S-yO^$M5%36v=U{DDsjNRunmzOlGtBQpqsQx@~v5U5W&j0fBdh!|qtj z7f+C>G?UE<#ZshPQEFDY*(z`Z7Gj(-?@>cOO~UgEbuP(OvY}c@wyUYOUFdbppcf(p z#97cptSDoZw5w5ccWYkMCQ&znmNbM+KY#!b!7$n7QoUXc#|sQ|P7tcmXhT(R<@2ag z@ltL->mdan6TyQr5mG5hW0V}1)cH(VEYu=~9re*(GU#VSf|uy9%*iPsm5<~N*|1d8 z&RFeYvsZDk;1mz&0k5Jg8>E-s2`Ny^3JrF6QI&s&Dktk*l84g#+Xcow6IF0Skq zYeclkrCQ-aJ6`T+^=_%X)aW56;d0R)PtfNV2~uJhg%?th{<1_Vov9W}wrO>nEJS!r z5nXD;r^Sd|g4I)EITx+!YNL{CH_UGL7GeQH01AKxpaWC^S{R@{1P&z>q!*Cg5O9zw z$gp4p!4?3CfMgF!Q>Y*yBZg`zWEbFp@ig!pgaj-mdDJ+O(SpT-R4ykiOK-O=)aUX> zfl4@8%_9_i5d)WPM(c$2ZoJ&f)|QMWYIJZn&^|0ky27k4CQ^wguc@&@MlI_Z%hcPp ziMmai=aB)(288-vr22FZ;Y}uTtrnfjK7>-MapABSi%E%uOp!^N%(9fuQ5Bx73q(8Q zM-d-Vag?Kw!6J+AA3r_eyz}4(7UpI}*!=so`F=k-y(O?~<6G~Zx_;7J`^fRVfn!VZ z`r#|z?S6ale%F5D_~vUbUo^zdn$5B9JBqNWa>y`GwYKkUEfpE*o#9|@SZ@19<{ zs(xfntL)Pjo_y@;8@sKZb$7$%H|@pG$A7qdwEoUYeeBSe7xtXrLsMY?Rxcbqe{bXB?1?ou-q&wFH{1FN|9%eG4SVmr$lm*B zf8KTD^j`;E3)fz|@byz4t@wsNGrFpM{?H45PJVi6`}h>6UOd@ebv7_Haq7UoRP)T* z4-c-s!u`7DW_Gyo-nKJ$*7SJCq;uS=hDWL3)!%;k`RUhZUis?r=DL-p`t8R*PA~oE ZoDA%g?ziT5_Em!Et+QJ`dw$=s{{cf9>rnsz literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_3_2_2.png b/resources/g2/track/wooden/large_half_loop_left_3_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..a93b37a93e15ee5b0c382d65a4f2d8b009c9398f GIT binary patch literal 5151 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_3_5.png b/resources/g2/track/wooden/large_half_loop_left_3_5.png new file mode 100644 index 0000000000000000000000000000000000000000..594d06bae250d21e2d4ccb8af1e1f720c1bb9820 GIT binary patch literal 1603 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_3_7.png b/resources/g2/track/wooden/large_half_loop_left_3_7.png new file mode 100644 index 0000000000000000000000000000000000000000..16b5740dcfd1f35e9a0069e61c02e915d92b8e0a GIT binary patch literal 1387 zcmXAoacmQH6vuztI&NdmCUmjj4LYsTkaH{Z2Hj}j7#(!;*pBSb0%a5}P@zJHhpSq& z%Aw7yT381+)yYy_fgT`~LC$ zzV=m3>f-6oPX_=LH`LcPXJ>V`$_w(c{eo(Z0DwHOYUS$X*)=C8CpR}YFE39Z5aj3Q zPn$LkL6Cxig2KW=u~aI>ak)xG&@`#nYZ=DGvMk5B{r*5W9OLaLY9tQ5%+27vtSZE5B7PG;WJ~d$$#hta z0v!g-1aQ!Z*Mx-Z!njwIiJ&kghZ!B5azGfC0zd(vLlBctXhl(nOy*H4dnszjV2E3- zV{SJLg-~21CB$+{qSVRMCQM_+^$sQDQn5bL8KgZCU4S=86sTM+Rni!#S7=QtlZ~>u zb?$&E5VeMRXEfzaOooI65Ya$v01^w3IS_?gtoF;aA;J{Z*b|H=?FhqO3KQuSs9BBK zHA=5u6=dirtB-R`(#NJl++@@TlVPDqA;UDd!a%6ZG;P=GU1qc2ZV$QL(Lf*(i>1?P z2v8G{aR}}es)8sT!3+tNEvfaS%)zuHmhq>i;*+ol6ABe#v05UfF}Yr;WJt=U%O11% z?am>upASbf2?FRygrS92oy1|pTo%G-qk}HPkk1+qxl-|PCNl;J05kwF05|~f0WbtW z5&=V$_SR zX3XhOdp-JKkc~!tsZA4#g$AdT-;NbNJOR8 z(nh1+Vlm-zRw3sI+^51rq&!ApDUB5BB+x2@E*u637$vjeSCkh`Jo$lL%}q2|di&ZI z0CHzF)YY!8Z$I3*wu7DjOkF>`oV%f#96*~r2e)?|>KgoViE6`pzRg>^cXSp{TuKl> zbWKim2`k6_@v%8uKH0u^{NK;7#`^N?Z}u=1f^8=^CU1ma=gy8Sygs6zIC5)ExzNzN zZ+$&~#xzerl}&K_ete_Er5qi8uBBf3M>SG&s<39;-?vVnAJi~TzD(UX*S=fc@B+q( ze7D~&{!}x%zHgwmqV836T(q6Nvd+EJUUH`OCGnk5W!L@B&Wk$FoS#uN`c_kCL+i!% z0my50yOZIj)SECP4f6UrjOUX-BRb2~i%-Y{Puf6%tQFHgHoxi_g8=SN2 z#GDm9$4iF=@yC`O;{r?Rhnt*%^FIrZb&NfleSE=vmdrWy(?nT`W7UJ<#@Mg@@6}hwAo!`la+NN_e!u6T(03jrBy(BE!PQTe*FA%J+X?9g6*Ry{>z+oO$ipcdsQ2r!{Yar45ec&7yX(rbLZ$i-HobmUvLxG5BLT<^Z2%GVnD<4rn-~MHtzW! DvMY0I literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_4_1.png b/resources/g2/track/wooden/large_half_loop_left_4_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7cfb02da5aff8d0eb274a58cbcc24dea2b61410c GIT binary patch literal 1416 zcmX9-e{51`6#e?c(jRM?MWq`ybW+7i8q}vnL(?}0O1szgX&;p+v(&MbOx#FH9kcww z6dhKkNU`F?jaf2iWD`y8u(Iq`(N#w+Doz?-l{IX|=_2WvYqZ_IVNA}wCpWpd=Z|x4 z*TzOkVgBp+0D!`}T5(gFSEZ{mH!I!m8ZI0JAPa1)m#$Bb85tRwnVDHxS=rgybLPy+ z$;qM7Xt}w$d3kwE4u^vve31wx2u!JzYqc7q(P+0jeLjCM7@??SDuwU?Dg-!IAeS@L zYPL?#H<^WY2k!AH0;Dz+Hpk*F5sxMl7HBZ0LB_TyxlS$8ZxoSsS;(iMhD`~|HJuDf zSU|x8Iuuw4nnyz;&Ge{;kqWV3f)7&)IAeh@$N>NcKtZEv=yU^%W#MvNLSa9S535vB zgW<8$2}zQLFgPfakF$jeu0+F=84#sKsC9^pUd$FCTp@*@Qn3XrzJwzrc$iWk*N8MG z+~ia^{ThGR5TtD3geNvl(ow)508<6ndcd{N1Wu;J$CZ<)CM+|@w63Hj2>Wp!Ln&bC zBs{ZB=uwISS|V&zM(x_T*O(;j(_t@+2k8s}mnTC6DpaH+2(wb@(CK_;GwF1O{r*@a zl1wHcU}*r?PD4C&QGi8+c&eDl6qmaaxz~qtgXUri9HQczmT$sKs!T zB7IEnGuwteJ}MYa#ZaKYXj+19P_Qj(o(<8ul8Zq$3dxrc#d~3V;j%EdUk( zyZ{UX5T^l{1}=hnE%dq|6~(zgg8&-}{1QOn01^Odn9z(s7Y_Yu7&1Z11zs300GJ5K zaGF}lH0XFXi^Stn1_H)#*qca%VOoo&0*JloPTjA$wD4``O_oj4#X?tkKAA`{( zmjMK9nuJf6qii*S=vA1-pmx~|0k16_^d_hvOvMBk2K@k10K&8vrnKBku#9>~JT7q9 zUqTxSiR5xZtyb#w8ia2Y@a-t#6(J@X4fRCf~mv|aYaykl3liVM%* zTU~nY=&G>dZc!uaroFGJ{UrDK*{0SStlWL2u4e1qb(0geqLCH9cRvaSYphGRKCXQK zr+Jt6v_HI|_=LMjy{v5CacpvUTW_?jI<fttgEz$o2SNDsDpY5+C2lA>L=RSZ<{3WGJ(;B;L;L{rMW^(l&`(e7P z?cmNs1Ni+@Lyps&E7+aRj9rpR(JS_n7IR03;d$-Iz%FUe7*(bm%s(d{SScub?eh5k gJ8-#ld}@mQl=wWBzrFKDI!>T&eWUoyTdjNl2P4;d@Bjb+ literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_4_2.png b/resources/g2/track/wooden/large_half_loop_left_4_2.png new file mode 100644 index 0000000000000000000000000000000000000000..95f829ff0a798be409a7f516ea8d65c9f317da49 GIT binary patch literal 1527 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_4_4.png b/resources/g2/track/wooden/large_half_loop_left_4_4.png new file mode 100644 index 0000000000000000000000000000000000000000..45cecbced1ed84f7ee6ddda23dfd53efea7cd664 GIT binary patch literal 2040 zcmXApZB){E7RP`15SqEzprKNsk&=srNggyNX+%Sp^lxHeOD-B27Nb;9)?(r018Ztb zS)x&rky=vXrVSNa=#W{dLxgF@wp5g44}%l6mRA39&YbhP_n!OaeqVg=y_M-{4By$o zvjG6UDanZ$Gc{x;c6qtaWY1^#l>oSd^tG8uGc5vvaC38WcX#*j@bL8XoHc6}5{dNk z^78if#^CXIGMPlD(^xDfkH-;-gr%jW3WZ9m)ftTztJUdpkx76?1rXDR!$AuKxFQKj zRz+1Pp;j$dZxHpHs%&;Oorq*peS}Pml#P?~2r3b|vy^U7u=}+_YoE+vRZlvN3@qRh zK@kneS;$r)(olsOX+^vGv9N;#ySVVQ9EOc}03ZOkNTd*jl47xP0zplsc0y1epFbj% zzE-JVg8@rM<7pTYgrjl^3?Y#%CG+G|k&<4jVbVB@y%EwW#BnFt zK{6Frr4#B*Qlquj2x-W#p!gy04oFp1(Mu~qU*7&ej?vSm)SXLN0Htsx45*9>5)m;hloN^Fc=07&mxj| zRH}#x$+$DaB-*OlzE-W(XmZ(TfXhURSSTqMCl?Tv5}HQF(kuCW8tI5Z=@>D(T(4mo z0Bit60LTH*0MG}39SPtWAUZ4&!5TGe9f1fyNCveupkn|l1Yj0`g&4Ss467knCxH89 zuvHEIFrEUKbijs?0v<+MM68uFTGc$gzSLyWI2 zhIKU9#GF}v%2J=-{55{|ZZd1<9**7TNkMzouc1PRFCg(nQo1Sm=t^QkW?CO}c zc+}93OHzNTJWs0kxaPmlGUu~<`?Vt>N}oVGRCw_A*!JpzIai`9-^AXEf6$RI`)AR$E?%*dF@}eobN5=}k3zPC7!p1C9?21v+kD zO1Dj9H=JKyV{x-|TkpS>bIJkUgEPX|{B267Lt>{^^_d$eL<*x0%E?+Q-a z7nGY>$sG*=8Of86!bkVLX(?Y{kaC~ndubJBe4hVe+jZi_tqaWh`m0I4)0axmjc;W1 zbPNq{UifQRxnH}x<{o@2ET%iPkh=U$<2;AnCE1&_5zA~Bn9+lAJMs<3yXD5V@rJ?$yf`#D5uNg3_gQNl(j5JCKH4JPx>Zr=xkPxm4C`(icR zjM(_?y?9US!TIe;hAC`bWnD=HBV1Ek@NL=q&npUc#3J_krq3&E4_Vyu^5>x(k9Y6A zvdW&Epv1R_j#NergYTOW!4mtC^4KmPj%IJmy}32zJB_b=h*hbxTiIE6Fc&U9JbP~E zU|9ZB#6Ww|GfDUO6Yqv{LJzlL8B`RRKDHG9rdwgFUi<$O&e6q++PtU{T7$7 z=tl7;a6nO_n|QX{@5iZ|mVvx1+SHcDPa_7tDsj4~@dH|@KKm*vWa)|1_L8i`+bG0K z^w^Z2pXumFzY>f_x$3KCae%om+KwEXnqNZvATM#5aeGbvQpDTiIU3aIHtfv%0x3yp KiR}qF2Y&}??V)4< literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_4_5.png b/resources/g2/track/wooden/large_half_loop_left_4_5.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b1eeea022bca3e9a9b9cb31f7b47ab91f99457 GIT binary patch literal 1486 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 SA|Gu4>gyVof4HpapT7Z?R>R5w literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_4_6_2.png b/resources/g2/track/wooden/large_half_loop_left_4_6_2.png new file mode 100644 index 0000000000000000000000000000000000000000..8b6ae7a762b2c6dd0676210f9b526f011f56c53e GIT binary patch literal 5194 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 b*zFik`krNX6RTj=0Fa+sl=H^gt@Zx_A`6|+ literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_left_4_7.png b/resources/g2/track/wooden/large_half_loop_left_4_7.png new file mode 100644 index 0000000000000000000000000000000000000000..2885d1f267a1ffdd4ff980658ce2f6b8c815347f GIT binary patch literal 5262 zcmeHLeNa7}%1-F*1ahGBq zw$nwLt(64Zy~RneiE67Efa<^5OUfUJ`_0T7<8u|UovU)655HAJemuap)bV~viuT?b6OL$(VWUU>Y)LkUUGXFZ&^M0aA>9-9J7+;Ob8Z9xCgC$*Qp!@n?e zZR}p~jbhifdB1yS#ZN@OXz<|1UiE@cg+^CQ@Q*(R*am(GxwdF^hfh-IUNpf)PMyZP zJO?{a@dDJJ^4@Uam8@OoP5U>@-hcK@^P78K=6^ZVTKp&J*K60#^JQ&006@$xt4dW; zq*C1q2L^F?Tce^dSTc9FPXB7@;}29lxM^?6k!!DTo_}>-!-k_L=lyoGaLYF=iM6nF z-6IL1ops8FRSc$O{i1aVdH-Vc4xTCcq~Pgykc^Xizk7dp+hI@t-%n3~qpR@O2bpnY zABn~1-#&;Odv1pz{-K?K^}%BE)z_{WA87r4vu<0NXJzYGpO0H+KVHxjv#e3}fjh{# z%x(>zbYGb0#a1`Yy+U2ds1p?4_;B;!SJDeaeM0NQS+1AkHyvE_#Q2HNg2#*3;$Kd-%zZBICUWYgC?>vYN7cZo9L~S%O1xJt=C?T6L_{aa@UI=Q(qsL^Yr2`Zti>cH85)^_DrV7 zafCX&3}her^!jY4bLNVdGHN~_{ygq9H4$h>dsxLMTn7uzs$yZ;Ras$qt>LT=8i_7q> zHay$JQ7%i$t(HRoJK@II)%HpUC9hU+qPTMS91$ZNc2vb}Q*hR3OV}#XMX)6Ti9pCN zsJ2##Im?pRxh|7gUYh^Z6a*Y8I2+w=ryM~%9*@9-3P_g)5oKp*BSJAE7W1J7pW5PZ zW7T{Il^%hZ#K$5wx+S~9BYKjHO2U3kW5s^TM z*zL%43(8$k1wp13^otf$8SGM|l%UAXE}ST+A{_4Y=@2ITw!L$+t1=pn2}g)Z!VXm_ z=v8!=OLdX9&;e3fKi$KkpGI6$16ooS3@~23b9fRq#+A#}( zI31SgM1*j8UP+OHBNhnnNJ=U(w;3A19)9Vq!x=*Dg=niVKj1;i@@BZtBfQo6`TkJJ7Rfz zS_>P>gt@VN%uPU0p;#gp3FRVjnGlsrM37RRP$U;l(U0P#mC1dBqYq3F@wQi%$zwhF)@*uo}P}Ph)Si@ z>oquDPEllCU0rjtud_1{3=V|Dqhn(z0+cyGr%5g^Pqo=to*JaSA*Z=T*WOvt-9z>D zHw+E8sdx-SPBN)s)*4t|oa>{|t~ymuv!Sn(44vi?M3SWQ> z^w$Q%P5mS7L*qRuN|34tObcMu0IruI^)c0*-0~hJ*>7kVqS{8iLAp!FOU0#W9yPDQ zkkgK@aQq>Qaw~ctZN4*1Mog)*WaXOiok|Jd?)vR4MY+z1sWAF=omJfS?l37dDZQ0cz1VQf4_fZq@RYq(kuY2NmhE9x;9otfJ=sR zyrbp*F;Dk+bKgW@hz^Z%Q-PGlP$MbjN|sHJ)>t&&T3cIFZMVOvKjJYYd3q=?!o2Zn`BYq)#9s# zJAd*QRnIh>4m@gkWzX*quXyjE>d}WX5*3HM*I&)$?OHy%To+2hPRBJ~&N#+XU^B{^>q!}x_z5w$@iM(KjNz4{@I8(i=W-bT6JNa_}vpr11}uie>AVrdT2#( z`HgF-T?cnRyt_J{w|zrbn)Zp%k~7wQNN=%VG5X9)KQ3Gd7M$~~Wt_=Ao-Qz_I|bq! zF&+EH`>tesIOuW}*C!*K!L#S*Kez6)O>eI>y*>Ez{Dl`QLgS|vByr@b3rDCUZ#?lv sCcWDC;1AnCfpX$|MN7TW=l?fL*>Pq6(%2=JAc>%;pg8~dlN)ya2i&f%nE(I) literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_1_1.png b/resources/g2/track/wooden/large_half_loop_right_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e62273adf18c7ed939b2cb080d3157d57ca76aa7 GIT binary patch literal 1381 zcmXAoeQZ)^6vp3vP};H<9d1NXF(VTlp}5^zR&VsK(iS^vZ`-RwB^|cc6(?4rOj&~! z9nG-Ad7Cwg6CHD?)G{TpALvNRESb14cdb>KWd;{iYU_rI4rkSO7?a;QC+DB@{P8@e zqqas~kUt|I08mi1th_!wi_;~}%}V!crZZmwkOgY1S5&0ejEs!T%*?E;tnBP;27{54 zlfz^(b8~a^^76O>fdD}yG8sk?3X)Xm^*XcJY_mB$9&aEp5{V>|NkjrL6yOS$O2yG? z`39rJVnuCs+~raG{Q3}WjmDfZ5mSk>bPBFX$)`x6Lyz>DWqzA7}w6UfL9hbkT8FH05VwfI|ST2JnqQNHL`juG}M3`7s@>v_|#L1Qme2xQIhac?P-2 zszhC+%%>-4Ga0t&V{UW8Z%ff`7z?mDQlUtRNHv(uKoC}vv>OZ_tJUvt&|YtJWF(PD zK)}-hp^b^S*fJlF2#GXNnI)!j#tps%HInqiC&MYo60zA*E?3SM5F!bQqIv~xQKyd? zJ=U(E%M%IE$tVWY3Z|Z5o78+tE3z9gw}tT8H9@y2?6=3mfn;(5VgM)s&;vjL;07QF zK#U1s8e9gAdgyk-NEjCa9Rj*A;FW_24j=)bjti{_bmGvfg&_-!IKfNfr9dGAN}Q=B zxh8|Ci;}yXq|axjX?HwM!?YGp0}vw%qqw+}ul5Rc5tK@(+)0BkWeZJuqcEHha)6Z2 zluOtujISjSqeelQw9YP*&)r1_-0?^NCZke?0(t?A00`4wSkiK@;F*o~SWIfSy+R)f z$y6#rt0j#_9U?JHB{mFk%MiapGJ=cZN&!^!p-Bks2=ro*R;0r(6|)|^{DIHvYY6bc zoj;lZ$mCR&m#tXVv2UMt|InP*Dt%c)FKkB{KTT^ovTghj(pp<_LU6}%RdMs-vBE%n z%V11SZ{4=@{$f&mz;j@DSI5}%M{k&Or#ve@yXpL9{{6;-Lw{cUd_m=biPN`=Zryw9 zhq9)jPk(P+UC+(RIfH+Xm)Es5Rm$5N8D&e6>n6vv|jk%1eck z6GeG#!bVbbUQ@+Tj9n zb=mN7b3@;Q&Fg4pe)Zv!WAB%)TYlxqm7e3b$NNq!9IV?D9DVZ1lzzJY-9s}!9>C`$>j;&xTmWUGnm&wRl9+j!s3WzrGt9{II>D;nARvo@04>_Qprj%l!-U+LRLm zH+Fa*FKRDj7+bJ#i)zy3sR*PN%C0_8S3hQ6zd0x=Et_>dofS}3QB!_u>Dn*;2Of55 Ai~s-t literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_1_2.png b/resources/g2/track/wooden/large_half_loop_right_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..f42c3772b3bb7c081219d10784441c10bcffd8a8 GIT binary patch literal 1452 zcmXAoaZr+X7{`B#hGLCvSd{F>j2aeGY;ThqwwF)gv<92u*(vKua3F13E6>+bVB&prP<-#@s08l_>d38x*O-f2iPEMv!C@Co^si~<`rc9wy zscC6x>FMcA4u^vve6d)BzKRUT?A3TrRiI*B1`Q;&FrzL_&a}88R6|rDAKe ze1lPFv0@IF+~ZXTg2qVHF6L3C!VCgs>ZELwf@@PF7xZGUMH+AsVZVV4+s9%)2@A-1 zKqCSsoa!K`UL!r^V8jC~Nb+G^4kt_y`Zxe!0LZCSf=<`5SSBvlE)-tCFuzh6(&>h6 zHt6-T5C%uY%#D=KMPHH?cQ(xRgPK3r_29Hh`FqslI2j}q>LZKSP4D!S= zt;=ZkJ6vI3Fdh*BIZ9RIbe)`SQt_->k<);CtV+LA7xG%kkS`t|h9Ur@0H^^l0pJ9{ z4?vU(U;<1GwQA_J!*B@W0s;YM5pYXD7y}RokYGY10__-dt6;zY!*=k-cmY7gK#EaS z3Z_oOGn*t1yTaqq2ZK(M48nvKO9>EdhRDRk>}aFt4-)e;C_FW_55h*OMsQGOrBBc&WDXG0wqS`p|L!62FlzaTf`pEp0Sy{ZBS zOCAku03dl)X>noovIEDCuBqGm(bRo|Nn4>X>!o^L<<%Ew1S^&*X*0O=FO(hZ(#>br z&D?cu`>PQ9<|%s4H+CAkvTWa4qRKq2aGq*(&3xL93`*PMg3t0x%5&X0fv(g2i@B5K zmolA6Pn))NXS^P*{H^fil{@*Lto(_?&bc+~&UNqQf@kvX&Ze9t@3fYE9ybLKa^_OP zCkw0As}vX8^B<-y?yfExY|NWX?=vjx-*~J$v!(Xn-?OD@w|CiBe%tyfUR>X7muA()9@~h*1kGtde0fFa*g#G#qr=vat0>uQrf(kJjF( zEMH!GwXJ;C*D3AwHB;&FrMo8secTQ2|O`l>~|Ekirv@0|G6&C9&CJ~ZdgtlrIo7aKa!hK0jJMJKasJBW$i(LX%l zj*&_7!TFr!F@`xeFZvw!*ZlIVcJ0QLyOTdeqE8$%{R7P-xh=bA->Z|>R_E01@3_0u zPh?*HuxZQL*l^hqXW`@>4T}EWxGC>Y-P&+d?C415Dfu-^XZ8?!AN_An*8W&tx-RK8 XWh$qpNOC$6IZ#?sQGB*&?f3r!qb--4 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_1_3.png b/resources/g2/track/wooden/large_half_loop_right_1_3.png new file mode 100644 index 0000000000000000000000000000000000000000..5d79cd2ede9479d94a4a01c331c0b24dde50a907 GIT binary patch literal 1656 zcmXAoadcAm6~})N2*D(hhFW5nMGsoysKu06vXbSIyjY?nd7L~~Qc=<3z=YG{4z@&5 zNkb~NWMWGbmU24m$O*O27EM~IqC$&Jj?#!TN2yZ9ggM-@<(aV+Tdlv*({sM}-gE!C z-#@i|)e6d)Bq6m&Fv|6>vWVG3AZnrlO2u7n*$t0Q0ibVjC0!&e? zRVN)#bNTq$KkfD+m8xW#tBAC^{2Tlm1d;l;2Gz^B3#jTz8UrZBB>Uk2bNY0nyLWNeM zHljv5X7_5mL1Qp(jV4|3j6anNvk<_>0Y?vb79emkBwmg@AW(-9V_fA(nS7)(3db-Z zTPxw3er$n6CSr|6K+$Qu#sVRE>6I7l*N_^getK_kDz88cWAX9vpL{!guUK) zFqoQ}B1sYgt`P{_46&buhPZf4s86BxwAz<3he+pCHjsIc$iZSEizVT3M#9S?c*6NEJp_GA*#Y<3nR0H^>k z0pJ9H0AK=uGy}lAFcex$knq7|0uunE7`PA+l!GJ&AP%6B107=M!(h+=V|JMIfuDny z00jzE7{j3DSj|G0Q||X^Lm^u{PGmB1nD^r9f!I=vI60V)rwIy-NvV@m6IpX8=Z-xH zreJ~;uz`ffkc(JqglE9T7QMo0HTYcC5aEhPiA*vIvnh!}0fPW00fhN1?0LIi#I;#G z>9oY-{zax(3{|UfgF$Pt7{wx+MC3-q1S$?IL{peBqvAsi4_XD#BZff)#ufSJm#iwD z|CxbZ?QJ-a{ry{A9*n2fH8pJLc=H35x_5YK$$x33Cdggc`y~DJ2{Sy|2wv-F4aSGI zw-2me(U$o9?1}1g!B6O$43w)KN2<3S|9I85T^EDrx!fD&$8xRA@jZ(+?mE6jm^$1u z*!7Cn`2se7>-`bx#Y0YZNezDO{pn8X%vs~F%jy>0<&Ebq*Y?b(slKU$^HbCUusf;j zsleY@QBT`GU?11L75mTbGS(ljIu=_8@2sOtlrJA=$rdZnjWzp~lxI5DJo--1e{bm1 z^6yNM%bl7vhjL8tS=YlYud+ucOAH6@d!8x1t~(Gplio-D_ra$rHNN|X<{CCJ**@+y z$SSVf_;ACF<cofK7Dvbb)k%G9yd{Ew@e@1`J(rh z{SDm?(My|lVyo|tE(FBG=jzQxYcp(F@A>DqCR*C5r^>$`>%8^SXj5d8y1cBYW$EH~ z)AE7WCu^AL(y!M4LGA)2Rm1nM|7wYRTtdJobU^hp}sLW8*u6eQoO5 zzs+R|@9ZCc>@T#Tox7v!yBq2T-wySYU3HsZ<#roxK5_(qQ{XSXaqfz8@0{{XckRNS z9W&I{^FO8h{oAYS3$iH&bMxr%dUejSsqsp5=&#$}6*TX!cx$A)<-&zSwboDOHzz6~ ekDTN6S%a-lDpp=QXwTyV)~#)8`m}Lt@BaZg+1qFU literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_1_4.png b/resources/g2/track/wooden/large_half_loop_right_1_4.png new file mode 100644 index 0000000000000000000000000000000000000000..df7a76dde332139c90932f15f46b8171f6dba7ae GIT binary patch literal 1794 zcmX9-aa5A`8vY3giY6{KG*;-q!x|M8Eq2B=GDuWR)UOjZY^ZeNc4(&1>IfXXiZc`<(Zm_xa;_o}(qj z{3ZD1cmTkXf_z?Clry8Fj6+BF-Rn;+0H8rh(T;7=GbSbmg+igxXbc7u8ykzoVsSWJ zTwGjyd_0jtp)i>YE|&vA0;yE2R4Q~joylZzIGi5OnBO0cM3@Y~VFRHcK`c&@%gHJ= zLvLW4%tD((;&Lm!K0_dA<I z2PzJLA)HNta~lZbwv>pMgoGGKM1m~92;!jtAOt{y!zl;^4T%KPXjV46Unm@r$;LIB zCl(9hc9WPX6b_LgB(o(nzJe~&Fr_eCY3Aze0;3DEdL>T3jLaf2_!Kro7f4xR1y`XL z>MatBQ{nV!Jbt4uWDCr@2^^3D0iq0$)qn=$SQaARK@+<<3ZKXjP+G&V2k95mQ=}}C zicdF)*fuHGrG$Js>9|Q5wClod)4b1)1U-Zl7L6`qvSb{t3W5w$sad6R7z}QU#piSe z#>T?oFak&lKr`W(HUig0g1mHDfU6IRts#{w439+|p@s2zB!NyKu!uxHnF7%nQZ`#D z5b7n-XKIJRIAU}7J-$eQ10({R5+Z0MWLQo&t2uT(rryTL>5x*7u zVLS^6xIiSt$)!Y%if)AYHmlU-()oP$P{@ZwwMa6+R3~s?qR>i~IB5z$8xD)@5tVD+ z>TwkpN2|K%4;a0|beBp^wV_ z36f524hC6f)1Od!yNnTbs~+TY&r%d{`wExA1FHWh%< zo`qLeyNlc5EEhX*micq~&9%x;~J=1c=`<^HtTSXWctc{w1> ztRB2_P~AG5^Ql@`$=@(JbS?bvmAdt#(vhmVJ^yN!bfKChZzE{v6&gy#J5E);ynz|K zf4rQ0E50x3*8QO?;ZI_q(>K%7A@kJXjjQ@DuezwcQPi_4S;y;+rq+T zZd%`k((0v!8Peb;qL9aLb`9k1t1V9Zlq!>*sl@P${(Dsvm-fx#=V|$!hp-*`LBE7v zlHY*|zNs}W%Q^P-XbVb|`*&r}i)XUIy1wC0KKPJ?IXBdjTXCKHh?%OkusqwKx z3r}XK`EB?gK3BE$m)BAT8`s}@i0eRcIwGThu zdVI_)Y3RtX^7d`Mbc03Q{Z{#Ifj8!sa{G5rS9f?@jM7h(-yK%SN8$8?oid-OeCl5Mf|A1n)*(lV$-kGA6_qS+g834Tk0JBM`ArS zyT%Y`+}=)YRGlCm>rLi<*0}UhN3Ut~&3PJWVo!1*PJB4E7S1TU)_1j~Df5-hOQ~po zu@^htReF2{_DkxT>5QEF@9R2x_peLea&E~1-=n0KTu1GQdUDiYqUJ>E+aKJ`t!~Aa zK1}s>nQCrd!>)>rO}njlb8jEcadP9S<4eAp-MP~6pI*i#9CpN#)G%!7Og_?_yL1nF zDl>lvUDvZ=p!m$8_352PZAFFlEUN0C=d_^{LsFrl7gKZfZK?Wriol$CSWR>JSCr%w4F59w&*T$G1Pp%)2u0NV-doEq^LUo!lHe@Vd3%L$(kWH78#D56z&2f7DxQc+nz* Nf^EgT@3vMR{y$idAqfBg literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_1_5.png b/resources/g2/track/wooden/large_half_loop_right_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..92261ed1b77970ec0cf4f03e90e7e2e43c7311c3 GIT binary patch literal 1411 zcmXAoe^AnQ7{@<}ia%CVxL7j7B8T?9j@-AT8+P9na_EtMo!=a{*rZ~`l;*c0rA5UQ z3ymceEt;$-DQQtr*~DVS8e3X4*=9u>-MEuWwyd}v7O8EY(RKHFp68x_p7$T`_tREc zA)1_#odE!tTvl3Am6+2LwK9#8=*`S$9|J%EmCIKM6YHc&lai8>C=^O^a&k&aN@{8< zl}b%ZOG{5rXRz696y*v87(s~Ta;Zv1>U27@+3IwNkoe6t0&J7sQ<%I7zP!ZraymGCo3F+(e18RZKbXA`&esH}X{$fzBZ|xe1$3<_aoUJSJDf<`alm&XbY?QjhDc zGOLSp`L*7l$se(Y;vO0X=mcOW080ZnMk>$B5IH$g4@UYWhLFk@HF{w;j?m>irdos; zBz(JE;8qcSojhPxg&n%6#~k-NVAxBe^EikEk0^k6k z4}dTgzy!DeYE;l+gTVmK0VE1c7;uR|5C@O|kYqpu3T-%aDWOjfgEsKecpeZ7fCQ&1 zXHp`^QA@&J0WT~56j*S29v&-Vju zp5l=mM>WCwJ8sUXTpt`4YnX~&)Al=CcB=$?&Gp}1KSygZ=KfB+Y1@$by!qQZMN_8~ z$`0;HYZ$oOPrDeUrDUZREtKt@Ypy?&A4Vdvyivu(4yCZ;$hr^f`|n`Kks(da`K}Gs z3tHa)Z`V+F`;mvwzZyT&UK5`-dx&>glilHDTdv${nw4MtgtE1?V0_6){uhtm@Pr)g l*R4OLJmxMmGsds>V{HT3^R_6*MiWT_Wx|S*v&&XB{|^(^bxi;O literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_1_6.png b/resources/g2/track/wooden/large_half_loop_right_1_6.png new file mode 100644 index 0000000000000000000000000000000000000000..27775d47e22f21ec4cab297bd6485b0816b5ef0b GIT binary patch literal 1526 zcmXAoe^8Tk9LK+oA46bFBbz#M=+LK{I`TOkH0_ZF4SI~Hc+^#+MvdD%mp*b2HgwvQ zDT4;=bm+u+H_lnBrp=;j=+2hT6JqH^iis97)*BA>sCgXl7 z7bpZkivcsqbW%*8i5+t0CIVa-6T*Z7J~2b+=L0|hpkOj7He1i-ni0ey7IzawuUZ|_ z>u=lb(C6c#xqOTxBzR&4BBcZ}J*qT|X`960!Yy9X5m0!-YMzKIl=8)-09T6Sl!P)8 zM!Ul9p*%soKWqucoRLW%8w0r{;HUvl2M{w;WamiTh}?%!L76E+JK|

?Q=cN)cBp z6_{jVr&8jj$)G_QveHqPA?~wI23;`fXXlC#feaO?F^QHWO-iLrt96@9KD#~W@k9m( zmGzqf=Y_^EQk@EPYK&TXpX`C=B zlE-vzlcm?`4*P?N2nG~5lP1}E1<$Mz*mRi7NP2DRUY9=Pv&BOGMB+BY0FVJd17HTg z1wbzVQ6_*%2np2D(B**P5P<*+1r`i=q##THNCHT4pb3Qz0(vwsV1!`@_|JF|z$HLN zFf~e!UMsMerA~*^>oo*}u2?JxlUiIgKy_J|nL{{u3J*es#pbx&mC$-8t$`<=2n@xM zTp;2xr9!qG<7r4#r^d~Cjl-h%x-3DzD;D;{L_~z+&;wu?K$!Hxn3Ve;u0dyuMnyL3 z|ImSeL@p;a8l_H0p+bX5XvI*M1oh#o2t2ZyCD_hEkrdT_kUR=EV$Ct}zeDM6$0^Qg9 zx-4gN^(pknjSc&2*~eR_`X9I(8_s?|Sv_X_Wp3Y)b#WxPt|)7c==PPf4R^V!X%!QR znj^ zVNYGzmtEbfyRd=go9)h}MV)<@=1tGe9=(+F?8*F1GuuX1>WIQ!6X)i?wf@)bjc*<; zNZ%c(9e*k3>97f?$vL*zb)h5mou{UbE>3;a zI{)X5g?szt$7T+-w&i6amDgW=W+i^5b#L^1!E>GX(Dj*=df9u67F1krYAe}G&lp*A zr9OZC*)xM{@FN?HZ&sE?4|-Hp-wciCJk0+tZBaWpQLwQ@HC&Unv-Lq}qWF z8BV_Vx0%6@AKYKx_;Wh4Ju{`b&Yl$;_;NIJRy(ou&%=fl8Qlw&&a|e`k{haBr`{d8 zBOfd|JbXYkwx>l7`#)SI`n*onUX{K4tzvh2-JVWUOVT(yBnr{0-hXtfg2`W~)br&-lj@?@Nn5W;M(2 z70EEvv;ER*JFi*)QVw+77ksg^6I*}s;nwe`Zty1UV~k(uylu(wf{L=r(yv~rY5W&! CceKv{ literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_1_6_2.png b/resources/g2/track/wooden/large_half_loop_right_1_6_2.png new file mode 100644 index 0000000000000000000000000000000000000000..53a5f5857677b6ce72d65d77b8d11bbb360d3bf8 GIT binary patch literal 5219 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 JUAb=Ce*ndtWre= zYSfgn6)Or_TERk#t=4p!x~WE`7F(=rMH`h?YFW44r7hdimUZ9W1XP^u%#JhL|IECv zd+#~FbI$Lab0_aTm$gDUHGEDu0AOlHdTKVji{Qx!3xZd&=|D2Pc{b26JtmJ7y^TOU6-I)}yZPg$5c;C*byfnzzVZ3s(KAx>u%G%vG zTxSZsc%ZyJdu`02&(BYFg$C|Pk_4%nSkpM2KmVyXtS#oPWtGdG`$gC+58Yb2`=q_@ zy5ef?;d4C;3zyD5xJLOqCi<5%wU?^rhTiDfe)*L@D6i5wrpqtX;>OXzg3^kvBh>U; zhn62&KK~}T_C@NA9T(cF4}~1uw_k8s@*4Nc{-zbLi0`aiGv`t~wi|$e9R`IWD?_2U z7Y+>Kz?QnibWhgIYPIIo>_yYcrf;mxI{3}Y>^-l}vadgUV%FMH-ljWDks&>M-Q1AA z?NxI7DjGvy@YK4HU0pZx7I`bCiktqg4@$4y7JrP_gfu<5*z!{F#(jCeA31j2(^1rR_W0Q+(mq{S z_<^g#eDhYvl{p=x`rl`=R_0%@9K167g}jt-L+$gQESVLTS9|%5x+1n>a3h^+8&KD) zp3a@MYwqMWMfI0Iou)n?Df#H~#S@J)cLv=>PTu7Q1ea|q>pkgq7+qTee`?+q`})_N z&S!sCUv4bmSc0b*gBX1UnKy&DwrA_23k36(-}lZ~w&3%-yZ(F>Oz96i9cMEgBo8D3 z$^K8jpK3OTE#Dhcabw^{&?$1%*(!81R~)nKOFO3sgk@J|faR5!xm=17MlPx)ig0eZ z(G2SjfCPED8O4fmE2{|C8%&ApA(xxYGH4UoxpA4iOtS*tU`XF=!8My#cmqGv|Zbez;#u5`LEl*_oai#FtH;u4aei3VNB0DcLi=`keI7`G8ae17yazmMb zofOVWuxNGC?9`>>5O9>p-e9$wr3hlP*|;_#m$2v&zCXEbMK-iJ4l<19cvkaEi2OUlD-$aUl>YdW=c~DtkmaT zMrtD4XJ4u%FoRa=e=I7(&^VnSj>Fe!#T*f?#W)f{oRFgx#fxxUi0e>E(FCXr6KO?F z8193D;9LX5Dbk8~f_Mz&;CLLLBa#TkoOoQI<)8xX;vzm=f>;wE)D{D*O0;C6S3W2$ zgc9pSx_BXqbHsd!078l4I7M+n0Y?`vh|{5XoJ1r-{ZLv=x|FaOQJ7AH5!K^}*`)U` z_z0IKXJsU^1zg^PnXD4js)Gu!2Mi`HVIv!h6!BHz=$svf6M7GZ<$r4$~(V z2vE*q4AXH$0#wJ5V0b)7!joWPo(LC91j2{WNkV6}p%y$@4|#-K!2*dYb9uIJH4+p zVz@h!8bqk!LTc1OQJyFO)BqIHXat>J85!w_j&703j;qyOdVODI<=4&4l-nICjEIsm z5H(X)7_B5?b1Q|ILq;|#s@hfcE=@~!q0_5piX#zaluQ$=!o>N6f~Zl~G#55I31?5G z$6Mbs*xEnhrprNu1~Bx1SplLQG;uRS*%_VhmJ>a>_I|Qu$l;-mt79WDaimQdYtNOn zVhR_j>8Zl{8pwh6sv&p7NKZR8;Gsu|qhoW0V!d2p(`f7%)@ZYJ+U@S<<{qcBzqfa2 zXov!l1c+{+30vt3SEQypR^P9v8OU!Lw7G^Hy~CY@qkSXPOV z4CS{E+gu|J-J{Nas&6Pd0*IM3B|^`aGmACC3cbovS=>@z>1wa<@w5+mJ=Ac&Sf!$z zfbs&0g1M-H=Ejc5s*1*e0dZr)*g}V56)b)+XYzNx9GyyI*{vc(sQ$z54j}GAds%Z@TSr z%f+B{hb`37@!8r_a@Mv{K7HSjnh#&vckbLpQQ|7yN=`xP#YO*|+4lC9*HWf^U$A3W zo6%NUakOSv{m@yNY-9D3_gkEE3|r5=HP0vx1nXL81wSRd-?;GXS{uD6_?s&U_Vr=- z%Kc`9?Q{rTJ1JLt!R+}^&Y*m&f0)dDqX{$clK<6if) z{^XaMcXZ8oCh*vtx7QzKr7umn9&uz~VDFjrmkf#3c+=}2oXR*U5OCk$@|JbckM88d zM}}|D{AyFvrIjxx%-DZ~F>+_`>f@$5$Gg8&xjVXdU3lY*zZ>Vzk2!bgC@1awI}2o| zpLuuWYQHkf=DKVDHt!!xRPiYZm(@?3VqQP};p}A_r((#fw5+_SAJ3PCcheQ`(h5>) sSDfYDT{Aemz|?t%nc9`IZmX99?nQSvHmYk1OcTgRTao%k%KGj90g5c;kN^Mx literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_2_1.png b/resources/g2/track/wooden/large_half_loop_right_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..4801eeac5ac907830c5abd0ab4f3d16ffd7ba5a5 GIT binary patch literal 1175 zcmX9-Z)_8F7=E{IyOqfb6l`Lh6$;elz!LAn%@jP~Hp@K2ksaEEMi0Gcfqppci47@w zfvPvDaEXnpSfEN1YHXy0MK4;hAF4E@Bxg30q6cZDV^u*aDapb=e;y%u-hW@-CwZUe z{cy`>|NME6%maY=qnn1u%u1NCq}O8Riw9Pkg9WxczjeeMJ32Z#J3B2FOIKG{cXxMB zPY;G+y}i9wtJUFly9vTe(-g-sf)JD>F&>YnQkgllA!~S+)`i)nxfi1qC`EAs7u+FT1JyBZWl;r)Q=|uzMMc8B~FhE zwUpGz$6KY;oSsLGvdvC<@Bl%EC_2h<2|-9lqlHAGl*#CtR-c}3wORD!jQYR!Af(xq?yF+jRKyL}Z=0096AKn2JHQ~(+nAQLQ&ViL+{kx^qk zAQF(IK=Xsa0^$IP4wN8JmPJ|^RTX4p;lA)BFf;^MEG#(WD4taPxvWqu#&td4Z0gA5 za)yA2^--#W&ANEaBN{%n70kDz#ko}Vj#fvtmd6gH3-fzzLCO{8h**eG<#0AB7xPKI zoNpRs)UJ~ZgET+}AY^Kxm~;=|jK|WA2ANJhfK;v0!5|k73$d6;c;louMG<+LC^6n? z7HF>-z`dgONiQXU4amy~5mG{_YnS&bFVB1k=8U>;1PM7k;Pa&YWuASUa&)*|lm? znVOK#sK&RKXCtHM%R|SGtzDsZFT!$N3a>4GgFE>7Pe;cFA}6i4rp|3+-cffP-t*cI z&eKCfP5Hpk?M36iE_I#bmc20Y@THsm5AA#JlYQ227FY#+vGnLGC%7s9?(6?q2mW|7 z`OkF+{CFBZIFkOwd-ti#b5Cz8iH*mWeYJ4aGqYd*rbvS`H;+$LBD1UC9#9sq>pyId zbpE{K$oFH{(i?A`IMwsr?D)}tcP=?ld3CZ@SXY=ypIP`P#uYQ|y_Yh_Eze%vvvTX% hftlo$-Z2@$*HarlyLf5ua`U<{ITvMtneULmqL zgFPf_)PsfglrXY!c2Q0jW-GCTnaOF3#(B8nq8v1`utgXcW{@IPzh(?R?>#>MybpXn z@4dZeA~?`@UmpMrj6E~5w>5`bHPqA5>Zb!CH$VsM8Q(YBqHS$$?d|Oy9UYyWon2jB z-QC?7hV}IH^!E08{C+=423VF61WuB|iXyA3s_WT&zF=9aj?-v1$pA1k@LYd5?2bl# zv3MYvqV)`)%ZtU5Qnpjon!yrSi0+p;Pa@>gBs{B-3o2XEL*=~etR(A>vEHzPUJwb0 zF`x-pPR2?pS0(3emc6JRKur;CXb4$;03JZZFxllwc)c2q8#KMZ^DB`^C6Tz5&7xAt zOS=7xC&2q?5f92lC_zdZtz=l$%EV&%RH~HC+J!=Ob+yrGAn?k7>lm4Hu|=;? zCL&cfSqmHWSh1n4HuLq3$~x*NTrSGv3Htm35s+wF;rOK3S{Bcz(kr>VW7*9r10shh zf-52Vv?!5@GiFjKW+E$QqEgD#D^|043o!s800lq;FacHoY8apvcoxMKWE#k+@HogM zq!}m#!QlZ3fMgF!k;vdtA&SaLq<&8oWRT{V(C?6IKxWbGtDv-eeR{@ZtcV0!O_0K0Dfa->Bz#zvmnx8uFpt5ff*TQ_$fdi1x! z;wALvfpb$Q)hEB6+4Sq{A56orvFkupe1~7Ve0H;M^wjd?;Bj^T{h60b-)_4e{@ZzD z@ZJ-j%wAhuTgUn?{V`e@0)xD{1s-{gBj(@Lo_&z6eQJ589-2ElHY)}X{;>4$>|0Vt`|4qCWi1 z#`Dhf#P-8Su6_0KpU=_9UVUN2e0)+re`Wcn%JC0htXU_A7ZzT+JbTZ~(qrQhY3{Ma{!Y;AOu%JbfrE0`1c}ZTDRD-jL~ zvGGn3rzG0@+}pRj|Bnb#^6+(ApSW}EUejQeGWWLjp9~+Zb-j8wuJQb`@@Byco6mKR zf0|5k0{UI-pRRB$2xk4ZWBXz8+y<(G+OSml;mNl+Us6WF*?H3E*Hym4y8jgbvhH>2 zbf#*Z?tC^dhdo<&mRH413-2?UpRB!Ue#@1cc9|p+IM)-&zmKi|HhR& zt7`99k~g%yT^n4@;yBh{dq>`izq5{=ey#ew%G-X2EIYj8i=(4k_xKZkdUX=)TTMK3 znv+xawoLZsOS_N*4{WpKF4zvZZ(QH->Hc%J`FsD_Y}{JszkTl~XC@r;ZmR6eTE0{H zhA+U;lNAUx; zr;i;vwxII;8?7gz2Rt8-9Qfdx1GMqGqo&*I-}FBI!Qw~O-csP)@vHZ4UZhyNCN}f*sIk*XD4!h@gnNACHz@nm?t$eTOYmBSfYU-NN}*niJX!Ft(s`Y#8sy6yV2-#+;J z{b25J_G=2i`*C{Da-iD%{+IJSp8S=ME^9k8dM4*pdNR_B#<;7V^X{sAU6&2JuEhzv zYi-R+H9@(=xSg_*;#QXjwjBUv+Ex!vG?G4^jdVEO<@{7M#^*Wh<$Q~xMpEO^ksF*< zTfC%s%c?qJOCzDO^R>$h%39SBz(x9SUaPCgO{-hW`59a_yiSV|J};xK@rXA@Tx1y`Dy=ZJ4HC{>dd7?UP{`q(gqQM5x7W>N|hoUCuAZ8Dla8S zQb{x@u~|^nZrX>t2{H`@!NpF9gOQk2QHm->Hkl0-$)yrPgewU`B$p{jy9}2p>;ygw z!svCvuEd*WN0o-MLnuOND@8FCDw5c78-yxViBzPjRAiG%vC>kxREn0`Gf;LyeJka4 z;jo-e7w#YtkK2)1NE5DJVX7|Y%fylk5>pfIYk&rD2Apm?<)<$!)j3_H*@vh3lwvX^ zCXvWcl>}2rl=2HoYe+8*dohhFm55PgW+h!1HB1Lmi>Esk0%YVc8@0|$;y%h-M^R1X z{B%&fwB^il4IC&t?!zl^9|=JvGPznRQA=fY5>$;!)TmM@k*X!L^eMZuVe|jePLB_- zY^vy0P8#~(oDogUl$qQ#bvJd}HBL;WK;tds6vq&2YKho@yB#FlKc*Y@ zyxjQ%&48Cml&D=U5h;`^OeDA2Z6X^cmy1x9Qf9*x3YF6KJ#?CC@cD5sxxxW?gj~S} z&2YuLak^B?GOW!+i{VeNhP8Sl&Sd0bh1c#$2gyD8S-Czlw}lVZ86YpN(Q$s zxDz5XTj4Zc(D#q|nXbc+>4L|*?BtU8y-e3-x-N-m1 z@GwQX;Xfchd{o-H57&Yc?AQqMoLy_V)I!uI~Q+NIX86Os2-iQ3Pl;z-TC}uPe39)mR03N@xk7L`Xx2b?tqI&ZxO(z#2(9xL7fwFVUEV1_G<6bX142 zqubgYp(2SuJlUBT>m8nmv9+Mc3^)$JZ3BW33+v|S`vvteEtRkYhv}YFD9#)*3X2G= z*sm7`Et+0J7p2XKc4DZD9_?#S#kwXEeavW_U4#jQ78G-6b$+usNDyJazdsm^b$2Hs zk>SC?R4T=QVhRYlSZFU>7cDjq2pz+^j?wy_F@H1_8XWH*n;e>83WaPo#^LC>C1xQ) zXf(9J*kOfWZT-Q{|mZ7@0^T zGtj{#dqBGI7%=F7#mH(TI03(~Go38qV-MFF5l~4@ zC{^D#?vGA%4NOLcnW2=R2w+^69%0vOxs7JD&0z=y8hbhe(Z0?^yl*TSXU2yygMovcy+rp!xSh#EIpa%wY_4Ve)Mxw2aLXmb1>C&QoIy7cL293foO9^A; zG64Y-Mwy6~Nf==BW1_+@(lg+zU1bJ0|K&sYZVP1D4EhSNBk$TOcr(XSwGNV12;Ybm z7G;6mdlo|>%U4}f$@*)--0Y=-ij9AG5Q>7;6)WnL1HV2wu;2(UKi4!#iE1A@qWbPC z#Zmj2@$jNkSN_Iygnn<^Q;(D^VS5%XSRB0P>(@c=oPiZzXpuFn53FUUmz-L2ptV0S z+4hTrFF0P#SA71|oBI#$@;|e~)!#5Ae)NPkka}q3=!?lR-3^-E8wZ~ckDMB`oh&<{ q)-%4h{uQdapMGO+)9U3fXQj@)8+NnrUIfDe)s?F%p1tL+?f(HnRBtN) literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_2_3.png b/resources/g2/track/wooden/large_half_loop_right_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..0353a049de784712f695c8977e9a61b0e440ad44 GIT binary patch literal 5238 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 Y-AB%uKY!73NEax~UzvCK@uzqG2i|e5bN~PV literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_2_4.png b/resources/g2/track/wooden/large_half_loop_right_2_4.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e77254d5dc49bf3c8e49cc9e660c0ab98ccb43 GIT binary patch literal 5660 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_2_7.png b/resources/g2/track/wooden/large_half_loop_right_2_7.png new file mode 100644 index 0000000000000000000000000000000000000000..2f246ab7f5c08beefbe54c4378ab3845a3e1f8c3 GIT binary patch literal 1385 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_3_2.png b/resources/g2/track/wooden/large_half_loop_right_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..ff241f6db5b15fd12c0e12b7235ad1d4fc4df3cd GIT binary patch literal 1078 zcmX9-acCQL6n<^mUE5d#rV{9h*-Y_-Q^Gjp)SJ7`YnRq@xzej-BX+0UW~Kpe^D05J z5ixF=%f@x48n#U13=%P}nf8xEB4!v}pmE%=Vy35L5H;e^Q1VB_qCam8zV{yAKkwt? zd+&`Izi)VGbO->3r>7=nt?9Aq&H+9?5@9*EV zX%mKF0|NttgM%)Q$3szGj$=iUm*t?UD)D$coz51EdZn^vn(a=9@&e0%z}tgCXE^MR zM7@b5lgg7zUUg>mhAQm71paN(B1%N6*69Z&H;80XWg&Z>L0s#sI zDHe1em;xXXkm5o~3grZ(hfyto%pBYdo(7(SfPjT%S1dxNG+#a^mr8NND70Dzvb69J zP*FRpxrCfs(h0?6w05x2iIlqO+J@dh^)}%I+Ku_Vjv(s}i&QkkYq4-H6)P1|My1d) zE2z_;c^>J2OhCxWB4Nqh0v?ZMnoT;Bz6G^bdR3u&>|zfrVMW2;;w9d)6YqOi%2XyYKYTH}~BB`sUll|IMDf z^b?vo_UFCMi`NhD3Vs+qDV&l_Q&Y!6K z_}No|Ll3@OUA}8~eRA*mj^O0J^Y2{Sa_IMuKRFw^zGZuB`AXt({KbdA9WB3YO7AbM ly3i{>&psk_4x}hguk5M;gG=YBp$+q(=axY} z95aP5Zu96O%ZCVIo->Y!anyQZlv6XPCFqS7&E~m98Z~7_LX9JHMSo@tp7-CE_krhm z-xK3w{w;mm`T$_d=(8gSS`}}__MVPb{@~c03D5!K`zQ9b#2I&Ka2A=B=2Az?J zCmQo5R63RBv-wcLluMRcsp>3&1?YZ>b14CjCgK^HoR70+Dp1Nx_F|%D>&<%6?}iWo zQ3f;t%SxE3I?7pRqvS?4A8LfqriM__3%~<}Fidhd6t`Q$ah;~;d44e*E-T7Bn=kcJ)NLE0t$a-BXqIsThij+I*C)5C)71@F;SaGqO zlB>CR-ApyD9I6%_P6{UiBo$`Zs354Kn2tvCs%mC3mSI#@R_gUS0=EQs3L~=)w%`^@ zM7Y8xszJRLE!4G@M!vRLZlZp|;h_ZGH}VJwR$kuh!&cu(xy>CdR2>)*Kj18*J}6X2;oF2CODyGBR$PCR+))bi+=`1XPBN#CWb z%T4q2-0F@K-g+=bGWp6@$h#a{b#ff;*P&Q zTdMAmkHmH_?zz7I?S(-*vVQQ!nT46PM@El+y=~9YsRv2%QDN=kxl4Qc&u*-D99M@9 VADRAkxTOw^?i(BV`02^F{s+%u>+=8r literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_3_3_2.png b/resources/g2/track/wooden/large_half_loop_right_3_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..44306f5616cc3eafbe7f38d70b02e8d3daf8c828 GIT binary patch literal 5241 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 S|D1{`C@v~3Jhy7of&T$xkh%B( literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_3_5.png b/resources/g2/track/wooden/large_half_loop_right_3_5.png new file mode 100644 index 0000000000000000000000000000000000000000..aa1bf22a1e3e0b3e9dc71db42ecf86f5bfe714b5 GIT binary patch literal 1558 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_3_7.png b/resources/g2/track/wooden/large_half_loop_right_3_7.png new file mode 100644 index 0000000000000000000000000000000000000000..d5386f0551dbe108f5aad074bd0bf8cbf3f71318 GIT binary patch literal 1391 zcmXAoeN0nl6vkh^EFZe6W$8x6jy2oOQe0sdy>3M>dX<7#xa!r^tZK)KHm=5NtxM4| z%2q~YRU53>xQf*k>0C1#K-ZbZRP16yDl4C(?`lkb=bW5>&hy9f zoVE?Ml6koWxd4E9)m3XYrKTuVCD|FN{?ozm5C9oq!}`r@Q)^mUT6%hVMn*nn)&55x~WOBJ*T2 zj!MPX>O@A9*lMGkZn@W|35HCuQ3oMpNyT{#$<<5wW(8u`pnV3yXO#xsOf+DOM;%iM zzk~DTlLW2>k*8C;;Rv7Q<%ic|0?MIK<*UiV7%| z5xsuGZihY}59J7Ou887`<%on4O7*D1EY{cvgNw9yX-81*i7NRRPb3kDX(6e=WDLO= zDWhF(_b{H2-XFDu;?CHVkBtKk4Y*3c*8#-L!t7j$8(MX5Bn$~M}hIQ z5}`>db}9(3h7K7N5vyj@Wk~p}Qy~`|^|Lt`B9x+-5+}4YZBi&~TCLk;^4aYnk0%xm zClUz=cnmIiWFk8hNO)0 z)G?jgWC=LkQGX~I!-1S+X=t`y&Nr)sHXZIV(q5Y~;L=BYws^#!Oin-?04V?(0L%cm z00;mu$^tM2ML?Yfx*RYXp%B2Jz=8vh1VkwSX#g26G@;NzL5~UsjWFr}FOA0lNdPIu zQYpB4tj}(O|VO%PJaz4}}(1t<}4nt%r{MeGb$(KKHU{fs( zD#q{b0wBGxdd;fMRc#$7cK5p8nqT<`yt8oM-ETf%KRpE83j_zZci@v{GtY)L95PRZ?)>z9?E9A#Zy&p@-fIY?Q4IMvd*O4R*etJJ)u{6bEVp^AJLDgO3S;Pp^JQG0i3 z=av>~#jhi!jV*)Kvz4Eo*0i{-C3}uvcMR;AS@sw?TlcV6nw-Bf?5rFcoTznEk9YLf z-)x{3Eg=4N^7~dd7*D}{OP{{|Fvn<&ENm;g)IQdY(xTj3_0#y;!M_K88IN4{_k4Nl z+ST!&ldb2t<^R1F==iGa!|Q>)x4RUUglxy}W$)}Q--y1KP#3Mf;i(_#Y+PyyW81Pz z`1_Y<4y_x$y7$=r5&@qQ&V9gFZ_C|URTC*KYI2X?uPAH{7rP23|7?HsS%HzceEZmi z*udDA%yEKe4uQUj{j)~>m@ I`jfBz2b@EG$p8QV literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_4_1.png b/resources/g2/track/wooden/large_half_loop_right_4_1.png new file mode 100644 index 0000000000000000000000000000000000000000..5aa1da56c77b66d094ff555ffc39f5481d66fdc3 GIT binary patch literal 5472 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 CS0fz& literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_4_2.png b/resources/g2/track/wooden/large_half_loop_right_4_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fb5474c26f664476a2257327e7401fdb260ad864 GIT binary patch literal 5711 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_4_4.png b/resources/g2/track/wooden/large_half_loop_right_4_4.png new file mode 100644 index 0000000000000000000000000000000000000000..f09cb5c7b52e25cf2e511e045d39c286a5dd3790 GIT binary patch literal 6069 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/large_half_loop_right_4_6_2.png b/resources/g2/track/wooden/large_half_loop_right_4_6_2.png new file mode 100644 index 0000000000000000000000000000000000000000..978e7a0983099c645bd02a12f7c5e05e43ad8b8a GIT binary patch literal 5195 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_1_1.png b/resources/g2/track/wooden/medium_half_loop_left_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..d37dbce30d749b232461b119bca3f3867c5c31ec GIT binary patch literal 1592 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 H3!DB0t<=H* literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_1_3.png b/resources/g2/track/wooden/medium_half_loop_left_1_3.png new file mode 100644 index 0000000000000000000000000000000000000000..d1e5b4007bcbcf1e72c4e31672022566292c5798 GIT binary patch literal 1890 zcmXApe^}D@7RNvS#2*uul5o;}a&ob#N2&ijw|Ij45( z7G_FPdJ+I2W#fi*`H@PBL`6bOBv)B0w*wFZw!Xh@eWZdbi8vyWNTEOs2A#uU359%_Orlb$^m?P!YInK%{r*rmOo0HM2H31*K0i$? zCdd_#T0_$t*k-H1;gos2nn2LRAY-_+WC;tWLLQb20(zpNU&HX9lOf*^to9z~f zd`jiG(TF;ocuE?Pj)T|)nt;TVkhw~VP)m~;7%B@(=irz;0=r*CfbkHMNaK)MLYOaM zNYre#QDC%7>|UkIuk#}2z?2h92WcFD69Iw(khB=sh+|qwd?#Jv)rEMz!j9Ir~~)60SuRmiEI@>5a4L}eB&s*s@;6YBS|NkBpYIy$g3fu9Xf4nQS1R6{{cY}77BJ!;f% z0)H3}0~P~t*%+}9r<9X*TBg|~bU0LAuLVK8XhaJy0u)6uU5jIz2m(7v;-_gtd`npF zn9_S@>;cplBBcSCfMG&dKAj-uP!uATRw*{=ln#r|>#`tz7a9)0EEZ}9s2`wc#0zyq z?oaS4g&`P(4f;Qkc{~h0pCc9v6$%LjQo)d(PO&g3P8QV9CL>%TDj=Xr5^A8Jb~@^1 zMV24VN}l}V2Fmlda6sPZosR*CP2IR|%{JcQBRqbWW$~IP+|KjfaXIHJlcRxR)-S&jH^U{3y+Y7U~2YO1+2`d+hr|@l3 z7j?(*;EL_TpJtVuC`dV4(^|KnjPqsrsou7jcs{fKg6k9U3sX@`+hx}_(+TChtMjPA z;(6_HC2fn-XO0ACBq7BQuet?K7N57CXWJBb}GUzJKVH8<(-E!2TG2=9J2NhE@lPuuWc%w#`Z}I|N8ZGxR`$hdW

FA<$c z%ox-?s4677`8$yA>XJIqy(>4KjbsV=<<9h;hbdH=)C_{%A}rv&L|x?l$NWfJw5 z$~A!n_SF8>^+p2qcl`+O@R_w9QYhx3;$-RR_tt&zk*0LM;rnXEvEJ$?X@hDPx_C%% z=lLDT9CInE3mUFWdYGoj{dp|UNX)`KOu}SkHe|Y0S6YOoxD}Y@oj2aY`8qzOp6Y!U z=1!v7o+93_3jEl*Gtjc`I5SBc$_os)?Ma2l<_`Q+*8h3>A^sZKcrx`_bVZcqLO*vC zM&LSeb+Y17($KfLD_<;{T~XaoJ~%WO-p3y1ExA=WE6HM(E;(DA)ZX~^&Wj6YHy3_4 zlGriv7NKqBNM*@E(JwoSysg7U!}I0&s?FN*vEcNoIivM_bs6>4KzJ*$?>qayVBGrw zQ2}f&JhJsfVpGQ&<~!0=*{_CL9{BUPIW64Q;Iz!MJLjt{r*|ozmz8WkEau6-%9HLs z$-IiZ=$o%WY*nkyzP3EK#*tpQD8X^*mMydOws3h_Ia1KnU2v;rPx8hUqx$pqJ;A=W z-?;W@;xh|J-Zy zHC&_g7;p9_9On%xFpZ_s{c--u-{!Uxp>vPitd;3|SNn@|B_FoPkJijdN!$x(AKyGn zxPrVY=XKvLLH61=&)YJBsYE8DwrjJBQGfm7h>fdR`gPgOr}tmV(At4-+RkMowhgIw zSJQo=C2DCV{y+jPBmUH(iPLX&%;|jHzx*H8i7pB9#h3nK#e(>*nYziM3)$ro>Iz>E zu?iPFscSx?>C^->Y|?>zwD}2@wvwdUHc)e$ld7!bi4p)nSz|-p#{8_wmx^1M@21W>y8tKz&FeSS=huRQ0v3x^SXjtr zvx|y~=FFMH;c&QIZgFw3P$H3_s7$HENm8xXYbnZPv)SBkZ!j2&M#qxLY%Yh&04@iF zx>Tzb7>#1HMdonI-5#Pps0&A^IO9yE{Yr$Rk(Zj(LaRnh>!n@_9keMUZcRLBO2!EJ94VN?PD0f3IfG4Xg-k%*Q`{c`yr zLBtG(gw;CX^}Lb+H!&J#it=aaC>$gZ zfgTf?Rftm~@7F8C6v^212{)Av*s>A#G!ua7C{KV%5etGbz*3hLJtZV&8tZB{y>#%*TWx>5w`#7Pdj0CX|EWs;;_5uMe5kAZQS9)fLi=d6 zdd*DHYhUZ1N6&Y>lREkRg!RWqFDJW>d^i2+A7b4vn^)bE*mr#KV0xCnaM_OGf`u*H z4dWv(k$V>}SN4q~jMa*1fQ8QTcoY zciuz66|>Cx>ZQomSlebKQD1To*8P~wnm;Vy-rQfaU9~rOYeHkS-rm!8jehP%;Z)kN z^{KAknSK1)v&!0Ejvnruy!A1HV#%=LcERXh8~L_|vu{m(zPyL`)c9k2HXVEA zFn(=uckRILXU}g()>GZP3>fpz4@A*c7QggL3-EO`eQu0A9quR}efaK{hVF6tD$%p* z?az+3e_OxEao~E@v-aV^){3J2U0+xAQs+|qH~Gf%@BCX@e`@T?p#|9EZC$=Ii#kx% z-N~!I_Ezo&cV?%jy_&y_g&m!m^U50DrQ?+?bj_Fc`$Nc*ODFGCt-1JFwAjTRI*q*N z>HFyYd3SRQT8j7iUf&m7E7QgZ_TWlOWZ;73T+hXd<~19ZZcHx_o;>GwuT_t_qQ}aH zx2|sUm4CBg6Ytu`^l45}>&>ABJ+=pqJ-y{SPZ)+O4;H-fL~!)T*x&nl+BWjnmc2ME zVP5quavZ%r`u*gNuMV8!->DW0u+98myTk+R7kuwlI@vd#{G|MOB6wz`2c4O?*`PT2 zTQ2sbjsJdM^TToX;v*ME8g_nsXr`oYMN9Ds^A^^limKc=X6w5?g#{X&foXgWsPC!-$shJe7msHU1j7xXq;E=`tx_6^szM8 z>?^(GIt3zGsgUnqS8;Ez5^1x)-P!iTz?&CtG@U~4v%i?Dsre?i`yVsM4=p=!-_Gbu zjx1gOxLwwFWyNl|4iD%umAu6 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_1_4_2.png b/resources/g2/track/wooden/medium_half_loop_left_1_4_2.png new file mode 100644 index 0000000000000000000000000000000000000000..6c2c1f1fb89d07c1eb1ab854bb6071bc6aa491c0 GIT binary patch literal 1183 zcmX9-eTdU`82))5P48>H(Lr|xsn?>>MX8WM=Hf`boa-G?a~Ma_!aB`d2W19~&|#TD zds|Pdgsp0og5}Jl%*b`~*fJ@j^Ws)r*#h2Ng{U2NvoHsBtMl9(`>i58@5l4c`@s9W z@1cp!fq~w|y#RoL@v+e@?Yh1lguSz!p>g~x06M|M#;qILbkU+k9UUE=ot<4>UEST? zHk%DW5WC&p)6?Vfdc6eUV;Gv}SwRR%l9)&&GMQYVpc}@#Wi?wZ!Ut#yaBN>FMDaHL8?z=U2@Q^2v|-cW)n;)6RZ?OtDJ0D>O#{9pdgHc z7!4F2$%{xS<*4SJtqKYoKG+Jw#|ngo7XS``FoK8sMq$*yL_CR3S$8g56Xm~P*RpjXl%O3tCg^BMcgFn3wS9WX9Y4OGGdZT=E6B$)J@s2 z(qSqFKr;m>R4b4kwA>L4u6XOpNDKf{=~H3aL~nmos&}Hb38NHX%SofMpOO?_i23 zU%?|aCRq=ujaad%%(n`S$JGVchdUgk%N1~YdE6&Zl*Dq$aC=z1kV=>H1mH;52m&Ahpa7r&PzIom0N4h{z_3labxgDs9IY7=t;(v1Xsju7pR@&5EYtzC0EBHXl5M%CKojw7y-sE`Pa#z*Oen-hqe46`621iK%g}_z5GB?( z&*6=r7lz$X#$c9!It@*>ef;F=zCWJ)z}_vJdEmc$-&d4ntrtBm7(#;J1l?w=-8=ge?PVB$`r~_tM}D5< zCm$YkLfrF@wbEDrwDbWF$!AvvZG&?Ue%-Nr+pC9KmyQpQ9rOCTJ{i8VwCBLmo)Kp+ m_x90c_Dw6+9e6l>1(mO!Tlnz(v61#-!T5&FqcbCK9Q+^C2LHeS literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_1_5.png b/resources/g2/track/wooden/medium_half_loop_left_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..3166c43185ea85f1fb585fcf2daab7fa0bf04cb1 GIT binary patch literal 1284 zcmXAoZ)_8F7{`C?-))SgK$Vi6p}49wIiVq^bgaTLZc7=bySW29QbNH~N^Itd9qWrS zFHo`3vYe(1#gtK#B4u_^!yGj`VnYg6t=nlTbmYVWRm&VuU1JJ^@w0^F`}}+Jd|!N? z=cA5xW8M7v`2c{rwv8>FrP@>qRdsnOcbkT104N6?uWW8Djq~QsD=RB2FE6jCsHm*0 ztg5O)5Tv@gx~8T^rO{|`Tt|`w!%!@1w%a+E%jNS0B9Ul3o|5H!p@8cEVE{B$Yc?xw zHnqd4b9)RvKOKr##F#xPc{14`i6JIKEk~(%lUiW40Xsh8B4a*NGQ!CTcTNr#^Kl~z zEEsSQKwyv%hr~RJbVyl9qA;g}1q-|{Kp58mKm%Yw5Kf`sQB=@sg9gJ0O((3@G|x{5 z0x%XsaixY(>1egVqBU}uiN{&NVE2=*Fy$4QVA2wmt!h20GinSBMzMM`M{;i39k2wV zTvX!YvRBH5GR2sJ07?d^tU&DqS^?1qRK|$b93wc%u6i^($)see?r8o$U-*|JUTMQh%ncrFnB> zf4}#&-s$BFTDCS{o#Td9AGvirU-|U@AEq{5d!|2iV)j$E=cW4VjYa42f#^JzVyNvirmez3YOwU2Zx!zIdlNuve;IV_i*Nn_k$n(mr+codcua&6-w@zp$%W z9A2>?u~WNfOL|S?Q=cqIT)6b!k6XGA|F&nh<(D&4NB&9O-n3-z=FfJt=$`zu)z{Kt zook;Qf4})i|L}o6x^D2&$|2*DiM5`y3-7ixL=Sab@4fQw=M37gZ=KxRwfjxm(_Lj_ zcWxeXbcEY3&UBsJer)Zkq6*yV+rQ|)rh9K4v)+oG{qj&B22&Gb6F(IOzr8s+b@=xu zF7h9YjZTb>j6b)h?(Gk$ZF7Tn))$3_!Nk6<2RB6it5sF>)Dvw@;Rld10;&p!}$RQGjmJ;+ptEpJ=?zY=|&mCO)u(Mc+4sU20y29Kpp#*KM?JcJ_>^Sg0?AS%U literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_2_1.png b/resources/g2/track/wooden/medium_half_loop_left_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..55ba01ebcb1f4760d53c691e0f4fec300ecb76a2 GIT binary patch literal 1142 zcmX9-e~i;)82;{#yACD}95_PJ3PT%GahjSGDOja<46I!7iY_osF*VFMye3v$aDjS^ zILU&&xX8jyU37CQO;6$DMH`O>WUC6D~4w>WQeIBP7rJ>!0^Yp67iJ zZ0--vowIlj0ATLM4ZQ>Hy1E^UU0v;b;cN4L0J^~DC%5#q$BvGU&d$!RuC7_LW_5RW z_w@822;y?NX3w7O^ZWfI8DLpP5I9K+D~g;*Br=&?v1nMqH#7(>KL9)cB7(>skBXuij^}CmB+r*4k*car=W@_A zQPS&Yd;uP#MLZ}IA(fOgTFJ5rolBR5d_^>z2u7iSpq~~9PNKpxD<}D6PRtpyVXKyt zwi|`ojOk&3R{*{Uz~TVc5Gv;j7V)sj$aW}IQ}RvCf+u;xD^X}HNTfn^L1IgaU?-$% zMyczGrkR{GiDI1FwQzFp0c!bl`Xg;l$^t5g1 z4ab758pUzY0MG#tw!KKU>23i{#IyA}mCf9OQmL@vun>((@wiL|5>z0=kUC46TwszX z8X-RvF{t7&OG1NzHrGCWYNh+y%^!GmpkDxwUAnlV-7nwR`}mes2j8D~d2s(d^Ln?lsnL^ADMih@R;E74bcn9pNt3Dj&+H9fB1OQitr~dcDueLcAmX@7TrrwJ1**D-=7&9 z_-d`asOMaH=WW#smp@!^7;~OIvg@@&i%O5K-OxOD=!=IsaaD#jnWJ7iW$hzq~Kg77uLf>+e0jZu`Ff E0nlLeKL7v# literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_2_1_2.png b/resources/g2/track/wooden/medium_half_loop_left_2_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fcec1b03924bf959b53265fb1696f32e82339add GIT binary patch literal 1009 zcmX9-Ux?du9RJ?m-0hr&^`Uc7D^>_BZheRny*y-h>5)4#F2^z`(qT?B)`u#2h+3p* z)J*Ephp0s>R_P?Vf|={sse$z&4;ec&n{gCZB@YFw*M~!k6glzGpE(Af@Au2+<@@=- z=lk7QTjdWPIC2004z4U`PDOJ*sv|QKQNR7I`zXK!terf)6w$GH97t(N0?oiH4ZMpPPD21H>lmx~t) z$zmy8t}wN_*lfvdSM!5PuWxZAmSyHtA)#lJrb09{YSZA{TGnr=;Z}JNTDwD!$3Z5c z$buP@eIBpVz#W0(qxRuX$b$zGNK(32Z z@f4d#i%CW%c$LiRlwvYkoil8q+LkO|cEWs;#?yR?kw`(Ib1J8n#d1S#II0uqURVtV z&EBpXV<9dvV?0Ap%?lqJ~k;7}v%npUn5T zazAGcitVA<8MOv`-CZy1V`hy}<3XaFXF4X_2!#{fkTIaJb+ZK1F$5};C0Wx?Sg z6ah(q)C8(f$P$rLKz)1% z$YD_+M8{7boBMPB2VOk2D#3~EpU&-*=L9|jZ%;k29Fg}{G7G1l@PF$p-23`N_e`EZ z=<%No^^H5%tA{fS7uGKS@$T8HYwJ(H7C*_Y-??=gHZFep!7pze{piW5rSq3Q>n%Qf z?!n^6-tnccP3EyLt{y+1nf!2mbmhX~XYapphWhf@#qZz0v3&HU?9FTceE$18xBTZ{ zUgW=`m%cl*Gylk6FYNsA_cNc|JoJ=#-va&W_OBa1{(IIQCl0Or_sXSjwpSu|u(Gt8 JxxBdk=KlkDv9ACC literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_2_2.png b/resources/g2/track/wooden/medium_half_loop_left_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..f147689031e98d27c99e4c6fb0b77dcf6c4966f5 GIT binary patch literal 1062 zcmX9-VQ3p=82;L{y|i)0Eu$%hdbJTEJ4Yr5-sIeF-L;q4xxpGCQnsUR+wb~kuAu-Y?u|XwjPVszB6pN`;C6_ZxCCe~c+uPl47lM!kA_W95`{`Ps2fHnf43yy|q8R{Cen_L7) zILK4LV1Ug5$O9+^VGf5H2aP0bWTCBryT%iMr9q5Cl44LvVR@A)YhtyUu`IpQv7oCJ zN&r0Vqtqa$p@I>SY*OvUbthHr6&m|S3pTrv03c9=iTdLdn&k0xf>o8ImRG8J-m2*x zy9S*W!LrZ*&;}5?USwUldkAIH#de!07VbfAH0XGoPbS55TEe3lB3htuoyJWzy3Jvo zSQrW@R3fm5LxX}A>xQ2=>brgS2i`a{&x2FH-#G7*pJ%71&L02x@|CI4%*1_z^2KXC z^UBEgAHDtRx7UX!4<1_jWA2@kM^3?4JU_hu?gK-o$GpoE$6CyK*vtI2GA%64k5Aos zVIolZ8eQGE@DH8X{9^yfjdRxMBmey*U7lTjS$cT4v3lX5jl-p#&-fFI&g9(H@vFNl z$Fj`1#n(p{o%9pGe*VeK@lSsXZ0+8;>AU^G>iU-*b$sjZOUm9a#;revx7OdhR^MxX zSDjtHc>dobE$?%y2Y=jr?C`TkhsJJBj@^3kwa0zW3*Q`i>Bi>D*8L~cwY`(d)2kDU U3r}6L-21@n%>4BA(@XFD4@{%VWdHyG literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_2_2_2.png b/resources/g2/track/wooden/medium_half_loop_left_2_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..dc8a082e062a48351a2f9e58b7d87e83af5e832f GIT binary patch literal 1107 zcmX9-e~8<36o2Ibg%4;^+>nWaN-w9mN-kP2DQ+#(am_Wa8VQ0# zLXrhT#EJ@5(S6OLzgrKY4u!fB+At8Rh5!Tr3BwehPYVVOf-uA3WkIOL<4sLlEfi3t z5~TehHb4n@SRx_{8P#an2&;K6ZSmQ%Xx1g$jpIy^iiE-<$;(Vk;gpP!DM$rdu^p}I zW}Qy4wN~-5;1?kf2RsFYfiZm~mOZ1$slEYz@7cx?BS*oOGYsHdVb-FDUBpy>m zpC;i(g3PB_D3)79a|s0vG@mKnr- z1v>(+07wL+1dvW6Q$ThC)icO7;a>0z@Ek-1EFlN9B$+iLMN=-9(~e_xIu7b-1>-=c z##kdDn7CvUiW@e(nAJ^|*K+j@yM>w_;RgoCB9t%2;t7#X#d$+Zm|3lCWu2p0`1z%KWS);q!dpWRP4&oM)06w=rfQ#j@Z;7K z+eRigkl@a1kNmPIEfSKdO66GyicjecLJF`O{zAz404EIJbU1b@+{M zb#B`geCX>eZuYO9!qXE6A7*E-zvFx0%!Q+S&wMp>vj4F^BIEgs_96Dp{Ab?czMryJ zU*Gla$F(iaYe%q&-*;{<3;3(nzm+3@JG+FM|S zw{QOE3E!XRR}NtdJHC8;JaKqs@Vjdm>?s~Qd-E2 Downyw literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_2_3.png b/resources/g2/track/wooden/medium_half_loop_left_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..ae7d1ba66ab8fbcc51b77f0fc90237dd992ca259 GIT binary patch literal 1462 zcmX9-ad1*~9RInou?>|ua+H`jDN%8<^QolFo{ddhulBY*jXLt)CY_|D&+}QRn6xp& zh54q;k)lK83hk+QXA={X9H;X}C+DzXQsTtqa!pdSbuImc=iTS~{oLoD@8^%t=i6Fa zqaIT*p#T6drg}+beTK_2)0mf?*`Bd|NdU4z?ORK$GIG?YQCV48+1c3~4ksrkCpR~j z%jM?f<>lw+3ndZ>g2+`WlprvjPD|62#bR+dTwbp)7>vYXsdO5V15^ocjHlHK34kzyMlKuc43ftldw@Sv92YA|shW~$%!rOr(oU6y#q55<9U^@(y;vcVt0hW8hUpYqN<~?5tBZ8` zC|}qdjM>9UPkcDQM}dFAfvs*D6-)9IW>qt|8&xLjeMFCK}cQYi>T z6p%W&h=;H8i-?d+A6HouT6fauPcf0SH#rg=hCCUcuMi5=VhJIW>y%0w!>wfIn8|Ci z_jtUqU^pE|0f}*Gf^R0pj6vo!p{$kgJM}%RIT~;#qrr4~5TXER0H6V20AK;=0U*Hz zFaul#O*CZPFc!t7fI@&B1wJ*1;Q$f->I8ILs!KVVLm}=>cNmp^OlBi%Fl9iYb|tmQ5S|!;a91FAk$AsQ@U%T(z99 zMa2dJG3hbJY;fDne%2livdLHwrsE0>gFXOb0K!Zb){NbAh%6>&BB5|Po`VjBR9Y=z zFz8Gs3XxkBatDgADkOl(Be*Q7kw8)m%~I$@pbv#%EK`0(Deu9vAJ|Y|Lx4qhudjS2 zR$%H%us!GHB>-e;sw>}E`fhNKMtk_!?n^*N3XRops?>%AJ z$sb(cKV)HC!LzSL$GKZpEw||APiq`KaGgm^Zo9Q*vDkF4A!}&l@~2ioN7cU5g%x?l z-M1VccNOg@D4DroJ-M~3k(zVlT2Rp-ijz+|9q$Ox{~m=3ZvJrR z=k7okJ5c)g*Sl#0J~Hm%OmfqA<$ZmV=F5lb)A8Td@bN7pWZv@O5*7ccY3{K-lBBqH Y)@MIm{;>3;Oy59tRZZoIiiYO@0iP*_I{*Lx literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_2_4.png b/resources/g2/track/wooden/medium_half_loop_left_2_4.png new file mode 100644 index 0000000000000000000000000000000000000000..5c61a14d5f2f49c4acdbe44ad5b47bd97ece7674 GIT binary patch literal 2094 zcmX9;e^k(0)3?tRYv=RSWt&%LKIGiU+6b9?~+ z0cmSfvZgtHy5!#Q=|1!Kp=pAH%=C?^(<2N9^YHM1!{G=7!qd~!%gYOiM0$IB`}p{v zBO@b;L;{scVKV7lE?X!R$Ye65Qe9VPFq^w=HkaE?BmfE-Fz9}4b`YPB6^RKYaZ}vkI!c^2?YPTK!vGE*h$uk8 zMCt@clN@E$1-UyhkdpwpInbm6g3OTsFaY2nkpdJ-g25LWf@FGAYL`ddOi$1(9%g7LmlGP(@6poXb^-M0IkxNv*aR4EFAB zm&*kKi~!)2NTLo!HDZ{Zc%GeF;$Ul?BBM*u?XGi9TE`(jJPJiZqiNVkCZ510lZA9f z31@nlxK3W#p{ui*Ep9snaOg-O6D8qb6@0u(OwpGxjVfM;USc(=oK~~jJq%F*U;!Wm zKmmXrfDQm0NB~WPL50LZNUw!#Rt63Th@g@J3^ZV40Eh`70UDAMAuR(k@S)BU$fgDV z7*7IpDqt~?d@fod!dEJ2IxW{|lvyl#r_%yWYhieRDE6Z$&W55Y)WQB{ZcZ-bU z%FaoH9kRM`L4brs(g-Lv1ki z_b)IqvC82fsg(ah*x5;CvzdH8S1c9~2{IBvNg?W~L=&CR&A>ZZkq`$9NpO&g2pK4l zg+3jA(jvdV{<(p|tPCbd9(vBX?6l2w<@zXYu=B!Q{ z9DF}lHCaGto>_1`?~NrV1BFU$i8CYHVtssz(7zT7#uhg-{TAk@T}~!8FOAiGynN4k z7a!tS?kUn3Yl^OHm-Z*j3}(#q{&C`G@9(n`MvAk$QK?5fQ;T6&PQ-Dix|3>vyL7SX zd-0yvr(WMcMelNZt$a|!Huc)3{6-4X!vDAt^ZelQvZ4}A^z+NBdlp;{?rS`p87z9% z?23)5&Ag4S)ikMugeb?;Z__s-Li#@aosf9ohnL2dn9Rf@&H-3(7kWr@x!#dcxV@eo zvmtt2`jth|hMUz-whl+$Ik%H(oCgmXIyawT%X7Lm6 ztPhJ{3rk}5#?|u{FNhb&&q24#Q!~!fDi-MsAz!zRW|5!Pk`T%HlB=bY8DXtcK2vuT z@&BvPeNO$cs`tD4x{*UW@*l`TizH)b(wr6LEUC|tb=z)Ukj=7{CStf1hkgw;^&hC> zW)_vWS8|YoLVHW1^vxmuE1sKWo;xe@C#r^fA5zgHY+_c52;0+_A+>bNJzKd3` z(hVN2%@?Dpy@8|aMVoP9L~GStR=eV2t@lO2{h{b~!lQOdL0IbIR_6V97s{3pMBrjE_d zJyzY392)Ru#nBvOM9n-`#BMBF-E(h#U~UD@xic;oKjE=?S%Zbvx%)MK?N8klJS_3fb0&aJVnlU@HpAhGx z`Fh#KJI&kAEP?gqNu46NzBjSCJ2(!uOt`{cyngqwvv1`y8sD){?;as}mJscB;!z+HmZhbG13bsJ7T|wK53J|xFXraRMe7t6JuYXra-wV*$ zFXJC|#^fx1y!39;yN6w$KGxX%_l1Y~H}3y@uggDrcmoxq2@R08I~!kPz>60+OPNpC zCy(3N0oTGqFh8ZDG3i{Yb7W0=gCL}9qBI9q9vCKl)Oc5)jhSP08XC7JD+VFYz1ar% z#C-o#AanwJXxx-MDLizc>#sTgjk-lUPb)uDdh%82$;UMdl36ML>ALyd+j8%6Tho^y zEvfov%Th$)EdLe+Rrd`jT(e|!mVcG+yqY@u7ch6*D^*@&^WgN;18J!lDc4u$9{WEV C+q>id literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_2_5.png b/resources/g2/track/wooden/medium_half_loop_left_2_5.png new file mode 100644 index 0000000000000000000000000000000000000000..30f99a6445b4111888ed08fb2c1a345d430e5ed6 GIT binary patch literal 1328 zcmX9-Z)_5G82Z#Wb$!)#1XGME$ZVr_#%-zgsXo3k_ zQBj#PCGI*g()H}9-jr?KL`9{B4>e+TXszg&BN?kSwiz|db<^12FecCYKJWA8eLg(z zd#JI&D6Ooi1OP})8|s=1ys%J9%S#HqGcvFjfD+L7?#B9pEGjB0E-o%9DJd;2Eh{UV zHf@?jA}KE~uc)X{sMTr&(P0=$lDNe}u`J_qxi~Hm3WZ~_p;RiD&m%g38UTS;QIy(VCrz#cN>wm`lKY5t5J7;gnUSSL%#v1F6L=dWyjqH{lM@ zfiM#mow1Zp%m&kwQ5g#4Bv4p^$^kT9i9Vn(hBQK4E7URxkazE8?_#@ zA!xxOEGfDyNsi43u3VIx6a|=x$>e&C){N+_C}t-~kHzA*+e02tG!PKO;q=f@E|-Hq z$p8%}L4q{ztGQC1!RH;d=&SEgIIN_!X%N!w( zZ!j22#l(CX1vD;UNtu&Yd2L$10~Oq4#BUuGoXMy^n~df2V-N+v3;+v&7XSf(K>#um z01F^6=wPA1!&H*c00sd*6oic+MF2Dl8e6xr(rUukpsO-V${hf zRAnO(hZXlaZM@GJ5qx4y$fja2pVs3z32mlp8NHu-4K^OfD2lY% zEDi^Q=v;aohav)oL~-2^q0O4rkXAvb2Ko^gMxlroj$gl|>glT=*xlSfg0+ty?06+U zz>Rg_VA-4vh53%DZr#SW<3~0;e78&n@Vw z{(0}jA6qUDyPv%=I!h{U=q5I2e;c}JSV+KyjxUe*ogSHCl9pC(vh6Y5 zz58DGv)#M?{c(KT&`3j9YofY-^^^U+26}7p(a5;6EP`qus5ha^AJ{i<+iL$&B4CU8{Q%Bh9-aMJ=EVXJ3sHp`pRA!CU#Z5bE>I*+ljpj zbLQe9WaZdQu6N|Hs8Efb@s+uHd1044(AUtu<>8w*hMmVRE$LRTn0M@vbaV84W!wFl z>ctC>UVeV%K)< z@VxK2xucQs(I-X$V0`w-^s(N2rdRuieZ9V=|NAh259VGyKGUOpeSQ7?{XU;>U|?Wy zaByg72*a@9;o*^y5j+$M(R7&SIY|-}C8lX=I-Snvi{-Lit!{W;yVIe=z_B0-W3gBu zksy+(a3;&<3u37(R~)V8W*beDr?4nHrV6+oB@BfuYV>NFcktC1kc z6eKw?B&?)jPS#&91v<4LYK2ipMtcTA)ewLPAY+*7_v^u+L6RoRu8QJ%JYLuJJH;Y$ zoFE+tad=oHSecBdR8*%GgVhRr+7faV$*jq?7blotI1*wdN>G@X%BvYMQ_DN#QG+8r^B7(7^Oc}f zqv8!d(~Oy|WTkCvbjq#0dKZmRem{fb5h5f}VTENiLCna#WvOyDw_YlHRkzdNKo&4f z^6N5TB&b4)vocbp5MQ_Sx>IP?tDVjr!~sMBGyns@0$2xVVt{%Od6d$SWg@RGlAzL% zFB0|F0G5lbkzo}_X{q+}|UO4@a;R?9^_tzaDJ z)EH;rqDja$sd}u@j#-^#rJJwq*$q^0lL24|EE4v|I3gj@skmV12{Wfxteji5T3!`( z8jK(y8;}PG^|HwHrjUOCtybe>F)5KyQYn=Vr|EY_{q8qUm3)(*9$0v5zw>nF_LnC{ z=l6Y<@c;Jq3)+R3?p<0~d+gL!-*;U4*R{X4mp}ZocK+{s&;EGp^GR)OVt3)fwR1nu zeZ6a)r!QXr-~@i1dwl%OKhP`RPwg7-qm_4k`{EPAcI(nq&kW4Y9G$*$_>HCi0kW9O AfB*mh literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_3_1_2.png b/resources/g2/track/wooden/medium_half_loop_left_3_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..9d98bfc5fa3328c3080c85a87d6479f7f905e537 GIT binary patch literal 941 zcmX9-F=*pv82u8*krOv~FjQ@IMJ*mQs6{z6h$32DDj!NtM-)y04=(7adNtI8T6A|F zR1ln@ZfiI}J$TUIK@<;yddMI+Q&iC4!Gi`5E(p%0F42&|w1#>Jy}t?v@B2R9^4{>? z_ruw#bg=)ov=Oz=I+e>-BQ8NwzGe z)8+fFG8}2+(45BI#nKaLti~4&8MkYsqf-Nuy=aSJzcw8i$)uAe-ewg^1ZXt01aMSr zXkcNtG#{4NQv#(7T5IUqK`5#KC;%FU8Ksg<5DrCoJb$4mlSX51+gF1D3PXY|R|K3< zNM55PgRa@E?(n87wtcxbR=uefBn^@y7^%Xmw5)S=Lo_-{XP^xNBZ%!N>BZ@Au?b58 zlvThRKw3aK7&pMB5mgTbBd&E9rnhn;bfM5?og-Qj-L3IMT^yTg+}7uPbLqENVSf|* zXc?8t97Weyt|5pmRqg7!+iH!v-Ec67gJ3b6tyU`pgaK3^V}~ViOsG@3u@F1Ux|g=b zD`&PIrPuQfD$=DAhvO1iQE5i!c~e$8S|(^3I8JrCV<9=9`OsOuAO_jA8vST;Bo;~(^apb2-gw_jAmQesG0fe$FI+@*T z5N*p{E;+aV8s>B=*6V7ssaux8GHs6O3#>1)q0Gz_I;~ZZMk1R+E{g&I#d21D?!)5W zH$U+B!Kn&&E`R^>hI}qdRro&t?r}y=PpU`fZ_S=OKidE8u(0zVTHgCse&N6TN__9~ zk6Ukk^V!+?&qw&LAKfbdrQiPP>fsyjAHR5X`07y8pT0b}BYu}Yuike5IWoSUJ-+gR{GMnmc28cvoBMmq*VP82`{kTFaRg>)P@NYZ54bx~}lQf*y-RH>jw z1E<4LE)o+7Rwm;rmC$L$V6`%zvxH(@GF!6kr3eO(#iOi52?~=`c{MNQD{{qFZC7`^ zqT8!>wi_W1!V*MMKxBb5Fs2fT*T`gpQ{6 z(z;g8ZgB!su#Gb3_0+Il!5mca&DIzam8OwECI)cB!>vcTn3W!@v+&JQhlFL|US=DZ$XwW>K$OMc1)y+DPl4yMDhxY*VCqi71i@ zq?4#jBb!66FgSkZ$mE|-e&FK5yadw^e>yiH-_Fg>oSnM%(F5T*=U{O3{^6Tj=<}sd zwpK2`QkeR0;iXl7`Pk{*+OgH;XCKaeIQ1&~%f-D*fm2`K$EWZ9@E!C01>>#6*!=bM ziRHf*f;a9=%-kKhwELfbpZV(LqrbnqXZqfi7v8+Ge>(c zbByx$%4-{6EbV)7_||G~t$#Yb`25!E@0V_UnfdJM+NG82`z|~_e)zY&kBvh|qZ|5x mskJ*l6N~4Y=Wc8Se;xLZm=E4)zjJwD0On54&)z<<_`(0f^SLPi literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_3_3.png b/resources/g2/track/wooden/medium_half_loop_left_3_3.png new file mode 100644 index 0000000000000000000000000000000000000000..8ed92faca6066b1637afc6538b274e17f51d49c8 GIT binary patch literal 1550 zcmXAoe{d6Z8pgkEX}1s{V5E_zbKwk~2n)nxwV~#&i)>3;f-JJd?HNjXu1CrQiFAuW za-CFylVX_0A>~#{Y=lKKV@4tbNx2l_8EOwxT)3*Kt{OGaP<{m`Fjaf-y*SQ%-uIpN zpZEFWdER~N*Xd`?sGI=+nAOx+zo9VIg=#M^Df9+*{#gJ@!1}e#4TZI+sHnKOxTK_H z+O%n_G3nF^O{NTtrC)>~29fiWH(>m!^YgEvO;NmEobE42!ZUZtZ@1EV!s z39E~A1x$gcH7Ym~qF2ZU)01&24rCONn}N~})E-0|kn6*0V;r{%v^&l6IZpycNL0pX z6*fKUrgcGvh_RI5WKtZP2|06dZc+%rOhPKts!NnO>)VpXd0$+Y8lWf z5xqug#FZ8bvzrYbhlTe#Vj-`P2xY|t%%`;m1B?PF0tgFUxC(N=qj1`NnT*!Q{SKQ< z5=J9su`qVK71KDi8V<)o1Qs`FMoBbFtDs2<9ct*qU=)Xfp%8xUQpr!h{Xpl2bre`R zKDGsb;=!i+C!1SdeVdH2nQljE1ZT{C2U zniXo!Pc&^0tkn(wRYLh+sonnOs(R8{oG?!~z$&QH|NZtc&s9aGA?eLp-i zi@G;<@;=@BXy0=)KmBRW&HCVHCN6>Z9GbQ0o-WN>dWi0iha6zWq|OxD`Q&bHMdyjv zhkse8NI&I2{!st=tcSn!$}(>7PRHR60%g8fRMoNU%$EoDkM$lBA4sjebzy#oX2-Dc z7S?ZDJ#p^w<)>U-Z94zUB679APGNjKqBS$k`>2U;`{>rWwzD5Lyk8~#54SDy(N^D; zEwcly-&dR}9lRFhUzG1??;QWy`NCuD<%?ftPIPUZ9qC#nUgX+G4xVuzJ@@w#ezUhl z-61CA*F4<+D0J$E*U?9RUol>M!6e{c`~Qp_9tnId-FRW+snX1c`6JtU>G=Z&|Bqcv z^CA4i!)(iD|5kteCH!jV?LQ1%1)InCLy{Wl+hcQvN)n$`-R#f)dgM>XmW+qbXqF7r ztbXiv#mMElikWrCpC4)Lss8thuWEW^{HO1VD^-!M^25EmvLlu1)r)Ue@Ac2GXsOLV zy})alUDk6_QiAYU=h5>M#50>#&zt9LwMWAHyU_0%hPa~xfq}}(<|WUzZY-}6_B{Vb z&0CV6?`B?0HO^?SZF_`TS~mDbsBdQRcdOdp8?xW2lU$UxAGo|Suw@q{&l8CS3m0`? zkZE?JSNi_tuckLV^7ex2(!s^m3*Yh9HWiWjg=^+6_pOO!Mt+>Tef#xGOD}!ye8{jZ zyy@WS4_b~~tT0-d{Qsz0PK)w8tgAn^s%_8z0ny#QWdHyG literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_3_4.png b/resources/g2/track/wooden/medium_half_loop_left_3_4.png new file mode 100644 index 0000000000000000000000000000000000000000..c80bb52235d5d9898ebc12bea58e8e1353be11a0 GIT binary patch literal 1686 zcmXAoe^lD_8pl71_|-Y%6iwD;lawYaD(rr*W5uqxn9&Z-Zw?oBs7R=>LicUqWRp9| zk+DLf#VNK};gJ?M*@n9|zbBcY(DH877^96jax^`T`+1)8{PVp3 zct5WXUZ@u4ulU;v06_lM=eKN6&rRv7%^{`xRQp#N07&44s@lr*nvs!_nVCrojT zNu^YkilNbR3`U;CiaA^|w@2*{7^4$*0UMF<@^BGNCt;WrESnnb(+fNniQk1sMhvlt zJr(x}=|IK?8a^WaK!zYVg`%U=O)Qq3$Lqte z5v4M$)6Ljy(Bq+_R3@Ls!5BOlONg^2I#glesjULNQ)G6F?S2^%Q8Ku6j*!U{vqcK7 z6c^wI%wUt*2%HG$d=YaX=7^>|6h5Ge0Zj=QTEH?PTpLa3Vo5!GJRmVf)%Li_2m3HK zRl%ieglwaP=THdTYH>iX2wT(>PJP^CNd=s6!bhQUS!@Z)Rq_QIvDm0kST!1#(de<+ z0t68ah2rrz1aus*EC}kL2;6kBpRJ4v3=>j&OyiE5LJ3!FDV&0NYzl=-qX`*IF`J{{ z@zf&BAWI+9x{T%#hb!U>B%*vE6Cr9bMJHpJRBWr3?=*BBt2mliZfN5a@s8vI!9Y(?!3*aa)^8q0Q5ez^vfH(~rQE0~?p@Mz`jM%}S z!E=E~03;ZqQqXi7w%H_f*cEQKJ`ixmVgZ=;qALNa&EuPBn4KXbSa^hIic6gdjXP!W zFA-4~jb#iBYXmWYVeZW}Vw<4)~n0hz};BT#*P807d|W=`0LsyT3%& zYpoL#T&v|Tsr`O|R4P`f6k08ga`aq|g^xM~s7J&JVeFWM31tkZV?iql2|f&n($CL* zB5&?b2AZ~4i$TS$Ydh0mY}vYHb8TJw7Zy>AzI5e#-@)Jmv;E59Po5gB#S{ZW-J_38 z&e#r@F*kp z^tTl+cJ>kjXPc5koxY-M#mD5?N@8u>HuqKT7LO!tth`jjfY~r*@wnQM3p)HBJ|J>|Yel2ipgwam3pycjsfV zo5dad+U^1w*73=yYf z{Yl2VWsjY0^PTCPF5%{%D!KGlMX7BlR`>m*P2=7>Emz7%j#=IG-~X3ewJb*(q%V-Hs6_?ll|Zph7L z>_5z;-@Vmk_#*(8);o~UdJcU>&BZkrksZ9BF1U_eW-id0H+E_*8(%@waDlCr)mu(I I``W?(13mW@xBvhE literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_3_5.png b/resources/g2/track/wooden/medium_half_loop_left_3_5.png new file mode 100644 index 0000000000000000000000000000000000000000..2a1155423912ba5f5290ef659b6128acde2407c4 GIT binary patch literal 1279 zcmXAoeQXnT7{`BOFSplpq{b>mFIi_Q98lyi#azO{Zg`B6-Q1DYQAu&99@vm$7E(qD z4eLmOIxkDXLu+WVLmN4@gbo^4Ls^>8kqX^Qv}n;P4OASlfo={m!_N|u@ALN0^Zn!V zJjXlQ>4w@RwE%#Iw#}`brMjvV&DG_lJoeus4uEpdv31*~(pXkjwrJ6!^78VEii*n0 z%Brd=1VO5+t7~d%G&-FQ#|;!kvaE^YEOxu#cDp4h5DG=&@###aP%PpGKoWp4)mbcR zn+Qy5|<>I9RFTr1_Krb8(g0sK?B>ktZn!%X&G^?{I{?-dG@zibS&0(}h9-0<8e_ z5`qU+R8-3*F+NLqauzx7h!(`@Vkp0mo`-dqN@dh&XjI2y296-?CdOkeEpvvvzC*jW zI_*%AVJ6M!fq(-a2_iJeFaWXu3L5Ceq0GRD4JJJ>BZH^ljle_!GlSSTjmv@gL^>#Q z(WpC>Qu6r}EO}{pfII6*QNzfnHKG?XgjldBMMrdAN-jjQFkR5Afe}S$gUUjpHWqjC zCedY+eXgkDOU0FZCJu{Pqsas#0A>J$B^I8N-7{(3PJb?E^h?iVPbMjgg|*o@r&GWU zZlggWafQNTCc`v?<;^;1MWIU%{Wy$}Fl8zozj0;VgQq{Rud|&68}8oxpwxfc*1B=q zy1~JdmP`Gs>o`$ftMOoJ%Ja|$+p#$_WD$K+$o}G>dO6hk;oQc@4|)=Nb~oj^55Yd$ZKi3^ mb8UZ9cE6Op{I9DqJBP^a!$o1m=WmuMg0@ZVt>3lm?EfFm_&dY^ literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_4_1.png b/resources/g2/track/wooden/medium_half_loop_left_4_1.png new file mode 100644 index 0000000000000000000000000000000000000000..a18729959b2528061d84249cac26c58e4f08a266 GIT binary patch literal 1451 zcmXAoad3-w7{`Co^0vxis-n_~HX|b}t=HY#$<3>MTWO{9I&V)#Rxf)?SddkaTIMps zvI>ogN++#!f^?0O-8ym;E=M{kK}uM*h2~C>twL_iw(j)ow>Wp7=Xvh==lTBe{XR|0 zmP*EtojMi(FuuB~VtIO^>3TOSBi+BpZr1^j0hZO&R;Jfcqeih}(F7&qq-aLEsc6Wf-|yt2T2=uR0JkMq_qDh{(h_Dk(=NG39m&KaH%4GLp)+1PWmKV zKnsBe2PO(}s1UD_9d_iV0$dmu!4wTgOc46`0FVIC2%=)MbzH7VAh3(YJtXN@D8f43 zQ=1KXy<9Yxk8?yMPfQCWDxpk=GA6OwO6Z+Zvxl+=Xm>=x!?+>|UrY(53?^3*Dg$Y- z(Kffr9n|?E=3v|r9rm(ukV^rM0`RmzU_vk(N8%F5y|^kUGe*_+q{#<+NMSC6aWxX5 zQ6_dUghx#U^-S2Jjyd&7uVpysgfSmG7ZV6&D5k&(4MiCl#;Vb{j7G1`7IeF#p-?iJ zgn+980tI+|xv3awh)X`nn-h2Nks7od8-<=*D4CnhrlUH|Nh+Kd^22QVJ}3 z^2>SvSSzb5%4(~cI*vTsYA+sFxpU9r9RqORoeAHyb5<_gR6N4C>NlA4LsveVXa4zG z+0gCn-GjS!(j9e2+sLB&8h?EDdo!7vv%1c9U@}6`*^t@$&bEtpqLrPKpXEQbAuYvc zo~_Io%sN~yO0rtcbv%B8)gQMUffvHhH}((QgRGw>(1qleegBPnzpha~Rn&S$m*5{7 zVXf01{Bc$6!NRSD(X;(O%voD8W6P;a@i!iov^19zABOss+UAp&&hLFhR(H02(Ob3y ze~O4JPQ;d<;x1gr^fj(N`qvCrAKYr1 zOAJ-9`?`l_o%-r#SBWOGtF&twUO*rCD3N#U&O~=xu{p^HAmWt<5XCc!hm+iM-aqqP>zQ1)D=1Jqrb2&l&VJ{d#%YX8qxC>HYJz$y9O4 z{k-z)?SaKJwY0KimJMylTon>vOTL+4Dw}%p zIXkg$O7rxID+>l=u{U=YbhF|a>!Wwe!i@*M?X5Uh4G(W1# TuH2GN9H_2bT5+~~&7S`ObJ2~2 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_4_2.png b/resources/g2/track/wooden/medium_half_loop_left_4_2.png new file mode 100644 index 0000000000000000000000000000000000000000..7f7e1c452612d8ff046a56e18129538bcc201608 GIT binary patch literal 1610 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 M@>gD7QS$Zw0oUDn#Q*>R literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_4_4.png b/resources/g2/track/wooden/medium_half_loop_left_4_4.png new file mode 100644 index 0000000000000000000000000000000000000000..0c2ea09feec51d469884af1022f0c814472476f5 GIT binary patch literal 1986 zcmX9;aZu9t8~%VOs2PeGDHRqKGjdpDG^xiO9i=sE)U43xH+8PQKX$u&-uJ!tpZB@vp7(wCWo5F%LSjMy z0AcBAsq6hU!5;!lfIt6S*`5SI0LWUGv&P>d5C|j^84wVFLZJc!1A~Hs&}cLUg9#1} z#*;`S8jZ?gF(HT}6!N7~iBhT5YV~Hb#cuC)yS+XijS83yz~zMU`H^BVQ6{IVY8hG` z*Ju`4ZBmD`c5ukRqM&(trqJtM*18C*h7VV0(epl!*&t?T)zr5T7tzY2n02mY+x|jxZF;W$fZyW>-DhB zMxaHKn0P9e$Pkd(5(-a26RH_f9ZPBAXsnRIA+WebL^^@WCNUriM@Z*OSP~Uir5ETe z5{pw|cWay;5G;4#;XWU5{s*$$T4A;^fs1N)2AM9d6@NB87B0}CzMi((zG6<>_3UxA>xwh7(*E=ni!QNi4 z*9!xJ1dz38ni0#g5+DafG{{m7@eLlC)vNCHnLU%PF*uZh#nSP3HjxBTs6qxq%HgU6 z{$X-+t)|mxcH5o4K_(Dz&{7Di5D?X3icZcnsUWLP)M-+~MfFU%1{ot}-xfC`TV7H4)1`-<3FoA^)+*|-d0G8n4S{iKN!WJ>?P{D2k_}6$k z;IIIXixvy<3K>PCW*ZGct5xZAnmisS?B^ng08JjsRO7h@qQF9yxEX3M-{g~7$Fz<~ z%OLFXk|P0~h-Oot!sMpe?OS|-iJqS-jqUM|JMBf$b9tRTZW8f;<0PL6;1 z>G7eX|K7m1^_dVz{^M~m0H~7m)RdgOJx#o~jmHzhKLox@do}>?%84aDQHG~u5T>)_ z&H2v6Y@g6nVx;vxr734m#dcol&j&DZmoX ztb|s`TVC5%9GcNNUfQk=xG`li`?l=J-IL>IV?0H#_4CKEtD`QjtfZbHOgK?v2j8Ch zY**|09ilwJUi~lFr?VBDg6_a%TuY3?*`J9@Xg*l=S!#ZTXU@ausM6l3xJ!8#BidG` zW<*nRmwwT6e$zEwWYO)^xEn95Gx{nK6&r&(x>Jx0Z`Huasg4Ppsb!sKMe0#dZ~!kS z9Gu+0*z?bl{Q8!?(b>Q6NMHK#4f(@7#HI3ONP2f#0`7WmH{;ijl5Roi+KA#BG4$f= zYgvi8OG84dGQdXMzSR}EDSh)1GpO6w_h3L*LWC%{eb;8hF;-2{T5?2H(^qOx6I!yM z=}yhx6Xlfwe^0$h9dM$NA7&-BqLxQiW!Ffm7B%%<+>}bqL$1qSGM;;rpmvfQDjHCPwi%GtZS#iv1LOC)PAz+7+ZuwQMk6<63{M{^<6U?@Fjx12c7>Mp+Xzvb1uM9>nqbv7l8 zy5xRvgW+jN-FM9`Ld&^)Ub(Swjpl7>-=f8jUp(D@t#N%H_dfBcVdwFnqIHuc*EULq zTU&j(?MwRG^DRZ3+y_zrNa~l}TOdJSCG~%Y{tz&9dD4&>gP*!|n#+9Iq0&U*@b6QE z?h{A4$Q7Ns;#lul9|7~K`mb-=OIlvnji+9?@xFYFyeh4yZ?o=sdPrZ+gHg{HW5g$! z=-eGa$&Sj9@`<)j&o6Ni+8*y=qi0k!q48n&FL~EC`G9oW|A;{Pn#|O*s|$AjAJ#~H Aga7~l literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_left_4_5.png b/resources/g2/track/wooden/medium_half_loop_left_4_5.png new file mode 100644 index 0000000000000000000000000000000000000000..11756d0a2778d6fa34909b89ba4c9158d6388a07 GIT binary patch literal 1196 zcmX9-eP|PR7=CL%t{>WrM#wOXIOBF=l>Bkq&U&(Qy-Fr}pP$inqgo}LKvTf6T^^6w z@3#el&PbGsC%9C`o6SiDEm|roj01C1T_S4SoahK?DhX_HYqy!UAv#~6%6uheLvyoP(%TDnQRv`PW*#g)umu5^F*0d!WpGc97BzRYBq@fRM^l``ERfcK%Mo=`DS^pK zycQOUajBdR8@YH*OQUk$WF~Qkn;?BO6X5x%AS42TOf;HHCN)(p&CD2vfxs#P9><83 ziOE{|g2Pv0B4v+K31kgE&x|L5Wx&m0e!&t7IAXFZr3l$Yw^NUwSsNjPxt7Fjn{7(A4W#b6)x{Rb?c3dSNx~fe0Q$qHa_xmJ%c(hl1{Q>&3X6)UzmOOU9X`yq4^!0^N znEz@Y&RoB}?9x!Sr+wwWH*WL2i_8nb!ug~XmpMO5@Ki==p z(N#6loXpvo0DzpT%Ca?yi6m-KdP<^ykKU>WAO);iSzDf1lai8>lao_YQl?FtmYSNH zmX^k1vC`AiGcq!`0)YTQ#5j(Tq>Q2z8VzkQ7%Uc>%jNd@21B7(JdTI~CIN&jOQGPX z)qJf^Y&1zMR>I*@db}Ecz!Z+yaS=-{$)aUky`0ZbLYoG;WWc=^x!*;H`i#+#eLUuq z@_0GWmV;(_P3)k96Zi9AR1D)vILSch697N}pk%RVHe1i*F+!nTBDq8meJWK@ zuOGG9px4VoI0B3-CioJiP)dvBdW2#m8Y^ya%FG_p?pL})Dn7~+O9c{AB%@FTjnhWL zXj9tUv^${ph0KAdBRuY9V}L^ft_tvVK*+FA8&~QQD!dpSkek99dyMhHON59+p**cr zWRgo96zVN@oL z>0BmrpTiaM1>#{0C}k`S$<{0Rj9O&XVNN6Iv8wu<`k>bu4f^8oQHTK`2S5V=1Ar5N zJ^&&t022^6)M=p84nsjg2xtVDG2oVh5CI?wAkBp)1lkGcRztrLhV0;_@hFhtKu)mK z6j!emnHj0WPI)|rK)@M|24F&qrvivB3uCy1ov(BY>5znpDV%YwXWZhSbcbOuCgcE= z&ytGS3XHEN5uHlL=+$CWCGOLjb~r7siC#D|iN-H4;IsmRD%} zeq5m-)oMzoqY<$I6%OBXariKK| z{vO%}K=SOWvgNgvM^BwnU+J8ieW?DYPbR~+(sM1P>l?P~ZnVGo?Ec0E#Y8lMT69~4g% z6&FlR-#Tx9@A?g&?V$1mPi-?s>iGRs@Mm|%{Nc2ld0Q$vPQNo}Z1u4Rb9d)|UDUMf zB*VIW<>2+y-D9rG*nGJt<>|^EUwildNBflLpKV&< zJNe=6ZQB;i+^4uob#9*3rL@lB6^zUuey@D#{e}4QGsTPc`1_Fs`>XJw&M!|49#K6ZOB{Ig;B^+x+&0C1b~VT@|g_@e3`( zCFg!jCcawig?OuDK?*PbBj%r>M!EF#SVwVhRCCYHX`Fp%@8dh~-tWI$DU LO<7mzri1?j|9ouc literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_1_2.png b/resources/g2/track/wooden/medium_half_loop_right_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..6524bc8e42f86d3452d15a1e05b0417e1de557f8 GIT binary patch literal 1450 zcmXAoad3-w7{`CwYFaHhil`vH2C;<(@41)Dc&l$Uc)PxMO;k$E+cqp*wx;AP^u1f0 z=%u_W$XrIWIn7x{OwWRJOEt9JV%~L~2Dx4C7Hx)YSp^-Xzs0%xJkN8_KhO7%@As)+ zQ>GX@X6hIKz}QtQi`OM5lB~rUsmZRnIzJ3RDp*sxenoN}HEL8!N=j;KYFb*_=+UFo z)6;o8UPeYnW@e^9EEXe(4978wB4}Er*Xv9slg;Mvc)Wo?Z#W!JBoGavIP^%X3HRHSL60unWsZfNL-Bw@ z2-H$wzyM3}TsofL!VkG}5%VgN`0)I6S!&u4@}Rw8lA<*g*yrO|{K z=83}r{eB^mBgO+_4x3lUhOzK#W-!DlhGcHqITOm^uZvm zQc+qhZ8Yi-nF*EIFvN``enQquN@GefREr=Zfp!FXF~||g@T2px2H*Zb?Yc4w6b{_0 z1|VhQs^aDASJt06x%Rp{FZ;met*apo*2`Qy;@YI;Tc zfB!09%+4!$=2J|v9y4_;J1`==d7IFz8*iQP?Ufe$(gQCix7OXgxGkSB+s@SWtb69V zlDA#3ui|9O_$|+Ur$=_r>bRBvGm)q%E2(asJE`-~mzQqOtNgWbaJahT@*FgapbqEl z!9PLP&a~`MO(sTqXJi%@k=ad|ZHG%AVarFxcE9%QC_gT5zpUsvGd`oC8TJ%!t=avu z{Ail(l=0Q~X^;0;_TBw)*ELt9vC6lo|&u^-J*!x}G++4k7@015BqhYp~ayFpf468g zzc#L%QRR{~?Alg4U--&fF)%Ikep9D^(E_}TDJ#v*z0mRd3+c1Qx>JNU-o&1j4_6Fy zwqO3|*n1jwd%==D51BJl7v8bES}Ro<%@q%rLv80Gt7QzUcF5+fb^gV*wFIBG9yDIt zsXX?uYTkvTi`a2+T0vgmQ}4j0NlU)&pOB9)lLcR5TRvaYAIo2uEh%^*`g@#g+w|gV RqGaH}sug9$7mK!j@jtgNj}ZU> literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_1_3.png b/resources/g2/track/wooden/medium_half_loop_right_1_3.png new file mode 100644 index 0000000000000000000000000000000000000000..e09e5c99927e6f27b5265d7e51157ab123bfbd37 GIT binary patch literal 1688 zcmXAoe_Yac9>+flfufGPNIBy=DsyCCmD+duZE=e!8W~O0uZt%0aI(j!utOu`VYHz! zWy$s+=MTDgBo*uEq(wJexL7geIy$`_Gj7q2Ix^2#>SRjJwASa?V~@w{{eC^(|GZy+ zydKYEWu^QS%1R0VAf;q`QAN!2VzV=W5Zg}4P`0zOICjRx#l^?R69@z%k+^Kx zG7^bICX*8q5)u;==@}UrD9YyXxHvA5O2ta0LaWspjb^*u>GAl3!ALZUvH_O^gn}fo zm?oDqRcf|Q&oP>WR=dRIR*v}ep>YcjA&WRk3ISasVj83@vl4Y^d2XX<#I6W>b>X08 zA>!dPfCK?5E->I^tAgy-Qv+67bc6xJY#5cmCk6;T82|_YkdVm=DpkW^7+5R|hvN_m zy)s!qqnR?Bq1(+sX&GEPTgc={SbPN{(x6fUM`_||ZGui0ZW)m{gEA(@VDmFLI3kc@ zVg*m36Y9(ovs2;pX*|JBU)UO2a8tQ}h6B0`Fx7x%AY*1a-_8=dxeA|1A5vN(1`l)y z5twIPRg+Fcu<0F&USq!g0M+YEr4}dcE6h z_Bov)zdsU*K)_G{mXVBFsXP}0A3LjseYP-JEYqbYGzG#RGBm%M$r)nfjgB&rbxi%f{GReF)O~7pm2RzZ}6yyRR z0ze6X0RS5SUI50)0LCQbLA4UvEHD@lvVZ~wom}ALgP;&V96$vf>QQJBLZ=*#=wQ$S zel8vZ0v-?v$#N-Oqe40je5*z3a%p`&TR7~4u`GrRpz0*9fiAQ#B~F$i$T393wy4Ur zU>tek48cHzMFSX<%x6=@T&5gH)iQxWBe!&FT((Z1#}*EHU^IjY1ked!5I`8~LKlns zMGURlG(L`*jK4@ZGQty!ak*ToRx41p7GoQ^sEvoZ1#G_%35znIgb6h)XhNZr3w<#N z0G5+9`!fRvD@t+j%7fc)$H3TDQdCg6yR}uwQ zsW49>@=YZFb7Ql=f1&W83q}`jyu^2tnoi32gD@?1?)R*@YuQ}lsrA;sm3`LpX_x)X z+Tl5?d~Bdso@TPm}< zTW@gY%Hw;uV-e(R&+!*DQeOEE$AL|+uKw$t6RS#_$ooiLl8ZTm>JJ`2sN;S9l5HsI zQ7vij+wowXlA59S{zo8`r zZkIi`&V9OQEIIdV;zWMg+4}$3cHA9k8O}w!&h!}Tj#9GAutQb7>BB!zwvhLiBi@p) z30eHMl^nk^|7Oe0cXp`bTV|Ihuiti{qPu^&^E#nF_*!ee^spnq;T2qS#5EoXw0lnO zB7MK+;^}_XUS}We%=r&@wZ2h0+IF9)G^Z5@hvM$`QJ!nkuHEv#_xff$>nqU0d-*vt zU5L&iagx^cn^s>hrSJaHpE!4~Dji)xG7FTC_hTi(Af3}v9_UpnTLVJm(X?AJF z3I6F#o3(W_m*#5=+36P?E!Bsr`_4IXt2eb(w1uu5&BRvy_TZf+&HjSs;VbEEXT!Tn zwEp|Wjth9wj%vfxw7mMi)T*<4*QD;d{(Lv(>6aZfhesDu)|z{^B40n-Cfb8vcWL5i>>38;HJ^dfuj=peb zupl>hDCg>hriqTqUeVg&!s$^Pn+n^lYO%8^EFrR ze~HfTSG>A3RGc~MEiF@D&3a4pC+rsgxOeQtw0!S;&#e_-xx=%hKe)p!mr%*pp%d5M z9Xta47k4$>$39jJ?ao?rx31j~{;}=B>YYED8n9<@!W`|SdrSNOD=PkpkUY?xxBZKH RT?{W!Qe0Yev9RXo{{i|j0I&c6 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_1_4.png b/resources/g2/track/wooden/medium_half_loop_right_1_4.png new file mode 100644 index 0000000000000000000000000000000000000000..02a40254afddcf95b16959b827db874c58387fb3 GIT binary patch literal 1863 zcmX9;e^k=<8vghb$&5N&qr%3z+{B`WT}&!UG&J&}Vt!qCE+rP-(8zHN4U=OeG||Yo zhDKK^R7`5D&@6FLF^A1Io3wCJqeX>E_CqW(E8D)8ot^W%?|a^V-simMd7rm7JBtxD zYtbwKKveqX)SN&i2Z9?B63F|~QELGR0ofV3X@NEzb`vT-UNK_?=2$>~-Nd%z@g^((wC{j|@?Of|Epr=y1Sgd|N-zk+o z*XdxZ6-!3rX&4d01W!CfpOnn%Hk z8AK(UYT(f=BFHZ1IW;1WQSP&9rtL=9V?&`S1R|SE;nV112vYKRTCv!qR9ba9yV>k^ zID9@I46s5#&>+YL6y1V_28et&UE$&Ay<&?`$Lg(&tVz>Yyd<6 zr~ohm&<}tI0pI{wbXX#Sje6MSWD$Un4AeAWW&jrpzz~3i7+6V$^(@#dfCm(?OAr1O zo&uP3z-A!?Jd9LKRI3;UJL`qJADK+px_V;5{g5^2_UkB&s0eTdbQMIRNHMvugeDe-4rGhHUroNU^t+KB0%>S zuyTpk?Cx4UI;9>Td!GNaQ8_tzESzKg7@qx777{laKQEyccQD5*t-AKO^tai@)o?g)PkAgo= zo@u^T)ZSHXtNU%`=m`G4Yv}Q3DGAT!&z(q)SQPz>C_nzpd1n6BCd$f+!3Y0i4lh7` zue^GvcJ1EO@A!2+os?alA*(Y}=;_6`Z$^#NG%>tk!4`*T*6 zEh$Ufd3XD#OD<-1zkpWNY=0XxB!AIkBifh)MP|3)`YQQ3+|oPWEj{-hYudE%uf z`+(*1$_{&J*`n&E*Z8!llnu=qRh1M}()4T7)w%mK#2(v2 z?UFr7&DM|fPj>glEx5DktA51yH4IMi$sSvHgP~_l;R0gCy@nH<{q6;f}@(Yx7JBAwOuOFBBGnE^+e7)jXO>4B{#L&+-qivW+ zWum^zMSAGa<9;k(^yJ>y0d(2NmN=8EZ&!l-oHljK!l)y$`Q>$qA8XEa-CAd9&9KiX z*L!aW{{udW{dmerH>m*0<$HV-I*L zrKZ8Sr23kF4zGu{ydJ)Fj#oM;n}1E9NOY7J-tuR*?a(4m-uU5iW3Ddjbi81uOqSSN z`1fNGS6k|ejwK!$5tocyb&R~s6N^i}YEHV;`QgaB$tc{`d9w>q?(9=@EtAHi`QBXjs%+-e oPsH2PaM!clqxK&5l)4Je_*>C3%ACfwz&8NtX<4ZkHx|hL4`6L&egFUf literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_1_5.png b/resources/g2/track/wooden/medium_half_loop_right_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..6c1d3e81687df05f1aec01d8d4b0444d50c1ba6b GIT binary patch literal 12457 zcmeHtWmKEn)^2cj_ux?6-QC@bgb*AO65QQgTc9`;cPkVrQmkl^7H^?NTBL9#RUKW1X`M^#>iJ`g?tT0s02PAV5fHU0>{t#B z3Vpu*{-cL%{A{|D<%ib}S=w2W@%N`BgPad`@>Ul&?4h7X^JixV3ZUK6ml>N8wpUDd zTZttU%{h*;+-&pnxi>B-T6gU_CeYCE=kqfn5W=GGVuPF}z&j3og(1l~TRyS76Qv=i zcL(-EkcKeu`|x@5^c|HYs8X{+#NEjU{@k5yO@$VwyWn@5LlNWl_E4G2`Q-4F!Jk_m zKL$hI^E)@k_Ju=_C-?@3B)xrbZ2M&L&BONW-;ke#5e>?i4RB*zYzPbnP%~#|(7{^; zM+pvoY=b(+=rdAOd7k%zg9WaZ-zFBNV!$T?dfTeAc>RR??AH;=3Tvd>kc6F6+a?4A zkDeBd6EAe%KB7P3HY#KVmzgX7BnPxgQ5iieoGbNXUr?CzRHF7B#@C7KGy7=|mKZf7 z^Avp4e)-3i?B9tSAdvT|AkIC-tK_bRI{& zWkD;?b>$UalFZw@tkt>5qTDWTQ?>JdO86ivDcjwB-?>Vw9nQaOF!PAEkUj6dc3pLz zo%%zumHRqPU1m{lJ?kKA+6_%z+v-JfUp94G2EJ@-l(MFyyXG5d(1oQ6ajq2?2Yo)8 zLP0e5E=@P|npxO{rHM(r>$u?WKkdF{46*KX+D$O?SoL}(`^He4vlM>p_PEsNef6?8 zTw(|Q!K-J-=U~1u?B&hG_0XjCS7*LK-J{_v5s#lr5K&$Nu@G^u$>Cj(7zxejZK zzcIqor;Fk5HL7^DowC%VI?7VBo`ov&N_?Mulv0{{4{_J>^htiil+E`c=Q(b_J7Gk` z`;)VF=Zf+l!dFMi7%QB88P^7-Z3bCeOha2|0x+-RWr3fy;?5tkWZrqa6yqdQZ5Q^Vc+?CT`qxT1Qtq<7G`A80ZyEurDjIr>TK$*gDiNjkE-&p zM+dl1R)n8Zo&eW|L@-g6@gm|IEBT zP4Q4QhWF88?|!dq5hLZM3eQf_0kd-6++>3C#*fQw?BNIZ{UmT(;c1&?3t?LfU*HCB zjBlS(*rE8BOW$?v2wJ_^ggAegomUfmNi?snKPUL!aE_6Oy5}L&4 z;isaE5M0M<#dkUTuNaPMKEEgQw{xv5g+Yx?8kbYLo-8>_^;lF)*tQLa^-h33Y&jO1 zE~vRy*N>o*o=%-L=>!sa7=|Cbc=G7m)Pp?w4xj2k#XP`n)|H1}$?FDI@)JuIPMNK| zveC(Lzmyh7R}Gf+Q&fT(OxWR6PCySVJ-ON=%=O~PTP7y{X@~b<`Yi4UIbDNRz*jNH zmkQID%W=*X*tF=&x9APS0*>Ra1N^E+#N8c=8#_pB0WjTqh>>daY`bGg>??oXlL{|P zR~5AFPL)Cj7b`l4ndKdPV4M96S|44UH652l+yjX7*j?Vohw!-6|vobBJbS5 z?GDOD#t!>|cBPWReO&1z1nK|@fe~&`FP0yQqw%DvnG87_v8d}}u=f6B$8FU(UVC~4 z;ECMRj>A>mGwh~S@u>T|T!NXeBrGH6v$|d!pVEpHjBPEhZ_;E{F-!BJk7Dy%VI37= zKG|x2&cP5#yXE|(FpJp2yvD+c{CePO4&;fy$d{zsD5ZNN5mheqsocU~RzL1+4F%pk zB&uC~Vnrg!#O@(ULiOp~gnofF&DiC71D|Z|y&R5pnJM;J#W^hjE)L`6t==GI0I4Cq zRD#emlbNPyInxRnGsEPGsz{NGVwrKDp84fx@#;q_7>m(%;%U@gqVOZseV@d}cRFWw9IWx8KI{5>3Me1H<6H;KZx%h7R=V=lNPD$Kwz6(1*WrC)jhZNJO21UL$ zLKCF>SmAt64uwG8_@c1^kJ7NK-rkm*Xs*LiAgY$^Gifu!f_jU*GZ0sbIPvfes&-1d zywA75qCkRemd>UoSXm6Yrejgj@s>EYL6kI6+PWq6E_Uh$aqN;a-lrkv+?A$rz19X( z6mp_mH@B>Kdh*F*v{tLQU@x3ut7^dNMPvpR6Svi+Rp`amobRO+x)xt_VhvGxw-!U1 z?1D5leg~DiLI9So3R`N!ieoV@98GtD2_wvuZyCoLl>u*GB-cih3j5s4tPJ0^-D<2Z zKz238u~pBlSukoi6*JNt&o1`G{Z2EA(C!OC;d=xn9C2EU@Sx#AdbPX5Ijr`Iv;_&S zl8^){$skxGA%sb!Aw}slR)wqB%mKnf&69{zu4X&YYUpdx=7mi_jS=qYifO0423oA; zSDnD=6O_{_f69a9q&$+~`nf!@bvmhbziF!8P~vMAUH5VNE2)t-;oj#if~1@MY$PXx zKOUD9P{;0|X5U#m5V#TVKmgv1hs+U0qd-;7GUid!@{+PkWVqcxe@OWt7Fs z5pUL@sWOiK1y)aG;h5{k?pkB(;LA!5t)+SrT(6edn*4(qy$U$qgB669c?79zA~g%Z z`f}{xQD0bMV72bQ5QTuq*JEtl`TpT1*+j>*gDaSp06y-DGi)2@?Y z=l7_o=J}eRZ`I?dkh~X9z%L=Xjm}Pg9@j=-{@}r5ldss0aVzn9-51YbzP=Q3={N4| zOOvk%UYl#QDc57fqoPVu`e|Li;Otny;AMT<6?1MX_VGml)=6FELjnW1_<-sv7nT!^ zI|`G6F_Dd>Qgay&v!HRkmey8)qj~kTerF&@y}CE0x8m_m7#oKmZtm{Gc(+a?+QvkkXbzM$4!`2Iv|Q~{zF8u^79?wrz)TUleJS4Fyb{|;@Ng-i+mRt@ zKUb)4-z^sCH(Kj=>AfDQTrhp0_+S-arHvw4^~K8i+iF z0HhO*+*X1TQ>%~?L{lV#8IyHjDA`Alfv-{?uS}naeoBAMVlYKP52vwEk&#gOhT&bh z9;^E)x|6RuJ<%%9i3`Rfc4IjKxWC8HVUYPwjWJ;V-aCsz07+Dumir@OH*3Jdhx>t) z6w{5OIBX4!E`6C_Yo+eH%_qu7o+KS=%K+zneVA#2!zv#{nYsUfV59}JS!9Ldy&W5# ze3>mmiW|tHzNj>oe?`TuTPLDBM6#%9&+1v55tmht4kOX1Qz`XBy?8;u1DKfjOqk~z z>9H?ZM}quNzLfHk%eSV4bH3fAYA0~9Xw&l-^bv_xZuK*>iWUUWebxy^agrf*!g&>6 z%UPT0DlRO0h--ZO#`xWX7kktqUyNaoLIE$X-?#SGB6hG=-J#lauiHzLVkv4T3u~`1 zx~EOh##D!%xkmO=Y)2&vKuh0LP-5p&y((SN`PxM#;XvG_!A2X6y-GvIY`XvB8LueW zl5un+g;eB%{mXmxY#b&1BMHII5%~qpV#^j78aEvm9=5u`0}IqL`A9X{2y@t8zW9x`kmo;Gw4g=Oy#V!Iq*0fR?>l7-D|k4mmoI; zH#r&O8%%;RDS99MEtl*^HbUWHLI83139#UKR&>>FFRy!}?`}f)PA!8r0YriAhmtmi z<!A2S^h#WpPE%t zt{hLqKQ&*bh_a@t%5xH|FUT<%(5Z=Tt!gtetu@HB;<_wXYODFs8#cbTg)O~X7CBC- zB&tgiKr}XYZ!48~RN?-teeb~@rfbfkh_Ln7+q7faLq$=oN@mf5x9x?-_=$PR3GBBe zKZ^;ql%mTl6QsITR)Q89XKq`fU#J%YuQJbgfvmE1Ax9SV*165Jqv3lix|RO4B+N;! z9)wL=VP5qpN<`n8x3v;f?cBIXV%^a_guFfc7HF9aJUmz2$-nW9bw3Wwz{{LbO4G8^ zW{6IpsZ@#?-4}Nupw(DNo|Mx*e(%+Z9+}sRWxD_Dd0Q`vay{G}ZAaEm4;O`kK<9kI zQi%WM0#GclscX|CF_z!3)&J6`oO8a?7NE z;ZjU5JYgYMk)?5Byr-Y-^w!1ctgaXJi?Xnq&N8nO1n-6C1I1JSw+>N_?W5{9K7yd} zWan95AI}G2hIHO8I98|>4rrmQ)5bP}J&8eYM#^`U8Aql0Pz_%$E_2;Wze*U`5GgN= z0PO?icHWS>M=W)`(o-d~byn^tykUox1X3O(U|I^I#MPMk9{X^xqg(dzS<9o*b+hAy z#A|mRBp6B2cEaq{DzA(O7%X+NmH;~Wq+6$H-S`}Cwrp3S4qVwg~) zufH0FM4J5p@0ZvQl?p;TOAZy{Hz8=B0YM*M$M9>J=?tx`F7gX*(*huhnU)VD6&Q(w zQi|eN+YrRr1x`cRgTvUQ-tji0c?h)NEUqy-uc(&;uA)N5Rq5`uuRWf#N<+l-p3_#5 zq&;Or8;JdyDiOlR(LgvG7u(GBK50sk7r^S(6xiOqg32|;w6E&!JGlWa=;D@o^ImAQ zwTFw`c(H;Rg2BrhUCKT6-eQe% zsD#5(Mofeh#(B44vBeg#p+F&x`?Px2WHoAA!!3@LB8R4<>jg00u!baTGOL#4rc91R zOX@B2yzu7MLt36UAT5PxO5B{{O#5u(v`xJZ-FZyvMVB$}({%p*_;2(^%dG?*Ht?D= zS@9b8UjEWGH18ik5}2-BG`iGMtj-kP+Zk|rqA{%l-{bNhB+Yf|))h>Ns9S4wR4iOk zJ)eX$w&UA3vy*8Ji3}DQoM!X&jD2z*CrJ_&4(TPajXg404g@~moLDuVEpx0r`*ih0 zXRTeRJLxA}(jzec)kl|}Dh=#6$|KC`*gTOj+`}x4*t7wHUDq$~QOD->YECKp8;{ao z4Ej48J;4lfdy4NgCC#Xti;3PU(C1Ztz9^%$VbV6CNKu)pTH|1$>e^fq5tG8TdGZuBSZZs^Wld!UXbAi>KgRM9{OKx#qX<8Up?GYJOVX~FM88tIt%S-Y?vsHllopc5VVBKdtL zXd2UX4s&)X=BdDfGs-e-$!P1M=%ls44UYT#n(Y6&sMWj`^QQAqA#u8wC{rgRDjv?1?X>DUhS& z{0HgSa28D4Z$VI4}bAaH58+0B`nzk@uoKN(1dAAZC(E z4bvCwmpNM!y?EJcI^L&A^f?Gd(!Puk?&O@KREq^*Bofn%B{T6B#E&{eKIN`cNcx;! zYrWJ)aHhP);?XUipvuvgxRUBMVuVU?>s(q5aE^8mGye>r9eZ??@wR`X8hAQS_uMHX zFc8-kH_37Aqqos@s#ZSP4oW*=stm-SmN5;dm!I-&oe8h#N$LKgbx1cAQ5Z;|uz|t1 zNV0glUXt6-Ac6q@wSx+8j4g&(bdw1-w-JztSp)5jfW-?wj_80lAJmLSM!&nP5UP+- z18{I!67eK4(?(b(Jouxw0pi=_-T|jO9&{}p9(LjZ$m_&eI<21BO6c;jSd(!?b6c+-ahT6&k}sz>vqjjj_OmC6*zP&DHY9X8c}bXO z@vzC|`t5q3)aotZ*Wv~fD>-9R;oH1%(x0h`E@O6L#x$qC(;9cy+iz2TClVKyqH&Xr zwwwJKUsUI09h)VC>JeJmmWF(qLqQ(A8bPnsa zT52!!^JIU|UC}kq1`e(K;%`CiU-;{#oli8D(b+O22%|)CE+#P(agFP|q)}10qNxMd z*}5{GpOQEV=6VK^lIiJ(x$`R-ClT$64LpYfUsQ{hJDXy^m42(E?*~1IHarx{Z#sI1 z0mL?0MR2wjf)wLxY-@jVDJ4fNh;YO%R(*(4)148dsQi&r2RunT;z8=M4|9qB9TZIY?9Iu$_4Egjic6A~Kgc)nH&4 zNwIQ6>uwXLp(36d8SzuAZwBajYV0QwaJ=nm-ig+s_m+zjbf7WT7vc-O2sR1~>4B>?ks8s4 z?qR4p{i44#p#<g zC@;PFYQr5+jLbLbKH8jEQbWIsAoBW*o2ND0hYF4`tl7%N`!64mE&5@kZ`P&`nmOvI z(u?Awxn;9*D9?Kk->8a0DzM6ddadP+*P%?uG;H5Kx@}aF+z<}3s+Vs`?NpT;k)bK2 z`m)9POJ8gIR3zzF?_tFg%<2m{iYeX<+iroB)jl|X`bB0s zu~M^&e)hqD|C`m7DttPjmAOkbe^cD<(&X|h3>U5nc8m8GidOD@sP|(_Z5VA3XFci7 z&yUxuW7fT%RBsJ`6^;R`0UnlE-O6rOxIJYoVmZa?`TQCeNK|;`B=kU)e%Gj+tdKJ6 zL1$0Odkh=`Jw;HDX_lBP+bP~74>`9FTNV`b!%D;s{mfM(Eymd|L4K0x$8P5YCjuBs z2t@-;+qC%S96vEq>-_DzJB2XM;;MWcnlVlb$*T^!-yB~(pX)t(s7QBWqtZ;xgs$9j z%-pOhdP!Y4)v}H4kFI14loQQlOvEGDc#-$5c=7D4F;q1t7T`LofrfK!+G&4d{zZ!2 z_I2ViDNBC?&V{8`K02yQbcxZIWyW$)*C!)pS2aw=7G62|Pc)@eW;K1MgR?IdM4u8# zUc^vq6@JQQzdXh@q^`%{{>S%chzt$Futn%-mqrMZfK%b`YXk{%!eHEaW~`ndV*hg zbC~Ewbsi;Ze2zY18lkMp=S$NIwK-jYJz7%jMdf^jkW)8a^SrlSiXQ`5=(C%S z8&qrD^AxgvrA*e+zg&8*&NN>6h8AF~a8i+A--Rql7j0}W>v2wZZif}1Z4vu z|6HGRFK+ZMQDR3-PDM)YS6gFOl0AkAxu@3y0s%WH${o|D9h{i8g^(&TAE5$!id#F9 zGO0vj4tD3`sTYovC3_zjwN)y%FaCeHMcaDD0a52XlxokQ^UA8t`k~rjwN5l>+=lBpX5)R;AX><-1gSa zR!@Y-`j1n{y;An@{kt*kW~nTfxsRR zU!Wtz#m!re<*a{*1?c7^$6_I-C#VNgfw;P92E!pH!TP4)U=OgA6N`d8u56$*62J@M z3jzjud3qzH1LatL<4Pmn{~8ux0sa>8^^jw+)H4LCK;aOeD8DGbAfH;Go4+uNJT6cc z?&K_Otg8Me1hOZ`;_B-QlNJyN2ngU05aEZyT?B-rq@)A{g$0C#`H&KPh#+rYP#~W- zg7p`~9~i0-1Q_lH^L2xI1Ak$H9HD-`ax5&!dEmeN^MdK={RQuh_>%=B9|D0On1B$! zpn#W`z~40xzH0tRkUt&zA2krB$g^+(V+aE32M0sc{2|`Htbd1a0{^8C^MiZ-4#x>B z0P%!)Aw>~Lt3v-_QbSA6@Gp&D6u7u~!G3EY$^H*XUpMD}ll33I{hIk5&fgtDs{e)i zAJYGd{kJeuN>5K(6$z22?-}Y zNpT@3K5;RSl#r9Sv!n2zP)=ZJbtv2mgiNQK7sv%70P}YFZQ~c=(n^L}axB99g8v>d z^aS}jBNdQqz|GqU8i4rsl&PB+#Kaf$i%%g5VM#GbDG_9o5)zgAo4z>&jzHGpFH|8x zei6yv>c0{rjSL4#E$COJA_0DnBcqX4fkQyPP`D`+>M6(a%PHV5&A+DgkPFHQ(Em&N*YW|%{*iP|Hw4mt(C?u? z)|3gv=a1eWT~D{)iwOw)y)2|b;6Fk@fcznUqzj4l#}wEVg*c;fzvA~Fy8fZ-zhdCO68@*U{-Nu?V&K0L z{-?VBztM&J@0%%zH}V@$0PYAz{Z?{lTP*71((a_M)(a|w5FfcJO zv9PePv9WP*aHv>WSw%zyR8$m9Omx6t8w3Ix6BAQVP}`NLPP+dAOkSa z!LzX;^YCB_2oXp~ktrxLc-&&&KZKZ>Pubb4RN=w0kimoMP(@fUWq>(L5h5KiDnkVp zGcC}KiG+iV%ImXH4LX254YHNLbUdn>|%!Q?m*z~!v5|yyyE-q^k5g$rR?}moxM95ebs00j{Wb8RLpga~4BH#=e zM3G8NgHBGrN#%@v&xQ+=1f75etBeVc4p_nlssc?gNGP>0?Sb~pM~rUd%pW}7xgH`? z0Fapgs9XR{App({EQwMojTTOuAqD8XMamAM@+@QYuET(b3@kwxpuv-3A@dll(vL8i zj{&b0Aodz!&V~xE=Nsb$q0-X%o}QhTFVD`- z?f`U90A~S~$YUavemavG9+w@Jggu+egMj|CjF%TJ2e)h2cX&KRL=sd~8ceJvJOW@D z8HA2Of;|!}q$MS1;&IEy=={Zw0>EAe3t>VOVb7G|!BZ5X(2!u#U*s~;5V1B?bg(vh zaq;0!0RXT701yB`1_00i089V?dsu)wWHV5?3qjm9RNif@8E^uiB7htPK#vAs!vJt+ z0=R=x-KB`!RT|v&c-+k-+-+0>ekEQ4prZn?Fu?KvQ$+;uCoO;O-8Yiv*;(KN?+3NYUP&L{Y&X4KXvL zVq;_C;Q$9Sv1LA_jvdvV#NDv_g`FNA~MN0TdP^f4l%-`D*E@VIAV) zlJVf6qULxbbvCqAl}sgP@^X!`_kj4SQc9;0HAzB}oUfPHfy5>2-p{JCeS{ybU^S!4 z^|7PP{h;3Hu1?iFjX>4quHLTD{7F#|o9pf&Q^9PSG-R>^wCFl1O;z%@_Lw?Dm%-BR zw?Z_hTED|^jebM3ImyLf~@+3d|xVf}RyIPbe`&B3P<@o!#0Lt2)@d2~< z5V24P;T>kvO1#N>-a*v%!?Q~)y~Sc*BM{-)P`HHb~ICjUPOwa#!hx-See3`3)TK13Np s)B7qJFkrXG{xm|g^s(&KrP+71@f7E9J-pdQWaa@{YWk|p$_~;02jP9|Gux$-Vo>I<%{+Yu&na-QC^m*RSvC z>FMq5#W1X|udlzq-xml3NHWB-j39856jc;Cl}hDug;L41?W*gx+HEof3=KRt7>#=4 zaXgU>r89Ic&lgK#*-|P_rryw50*latGUrnxxF!V)3OS!*tz4v1lHJ90)74j7cGwRh z0SN{)0V~RwmGRVy-gd>0njzE{(VB*k9RT0~L=2NX9@X#Hf)>#f|IDI%*ts#T@VYVY&xp# zW}RlSzG`_G@Cx9I0iJ}QhEWAyxDTAauy86z!}^RY!kty%eI&2G1s5d#nbPyjRl17H!LfdT4(XHil?hK}4C9|W0% zECXg3Tpo}BNcN!&iF6*Baa2hoSBIOyQ^2th;jy^nQxim13m0{%TuwQT(QG=XqvekQ znH*#^AFt!08I)aGYekKAqP&``teJIGYX!YP;aE82i86RxAd@jpQ{#G8EgM29?jNol(WnrQOUa~6hEh~0$B+g~T3o2g6U|5f zi8xY&C{H4jK@QhBeroIBwVOXMy>CK*C;qs6utTnn@7}q8`@3Hqiw+&#cH3AP;>L=~ zUKri;YwvSicN{$Y(!%hy+vz>(W1}bfn;%?1I%18Se(OEz?4h}(9Rr&uyEdIaaOtPl zdVGiao?*^i8Cl>rezp{jun(Mk<;X72?Ckwl_WalL&ggenZ=5-I=CHFc{Nww-ADepm zp11ksrRLgQQy<-Ub!BMbuch$W>YrO$Tjw4*;;dDlpZ)mz`%dq>^pCeC=rhyo@l(&f zj!#|OIWum2{_u_i;;Bua95L`;zP$I*6DLbT($f1V{L3$``4vQNlhaP6(-wX@y`##>~y~BIo z#oaUM@Zj|W06087Il5Qg*UCBAtCaiU=haUDDscDC`Eg0Nwzjsnw=0#(&dyG?THW2< z#V~AdZ*PBpztL!rJ`JQI!nuXGMS(#BG`IUXfO)N zYm{WrEsND1-W-dzFONdin`=SZAvuDPn!HNOI@dNtW1tKs+9WW7#ER2Vl1*2e2p6EP zLZbs@A1DXoCJkvuwIjhuTEms;}WV1<@BRR@m5BnEE_WLIVT9oezE-pC65Q4;%E8lz&x$ubH6rGQYG#h|o%0mAN& z*K2O;#?(3nMmfD*YZKlfJc|C=9p zaPLfocOU=#=?(cKi8|5l@e9pTD~J(YgIHyt#Ay5Bltf_g8P<|M~pGKVJFi zd;EiMPTo0u`h|E4|Ldji7+wG6f%oTs55IkczRqra`D}2%_PF|6rMPqP>%~Unzpm9{`Fb_ov>%$#XDbm3`{OmFKe7|2lFW=7x zK74Mit)`DG99sZ@BP(w#t&i`C@hr|wjW@ga)-wQ8u=eKpVEEcO(yV3Akt#%X*hC_x1o&!mYWwY^o zo-hh@smxVtQoW%xeLV=v-JT;*ScZ#fV#3T2mP*<>vt1PYY9?rC(Qc_9Iio=Kf*k@lHKH43el%qoINhEQDGq00}_BFb&7eWYQu@hvT*-X*ZYanC6~sBi~Ol z@f4q+C4y7Pv_@r2MzuJ-CKO$<(v+P*@uD2TCh2sFlPOVUvznllq>`=Jp5}#SE2@P3 zdUxdGJj7*4ghd z;=r$tLKpQ~c$_7v48!Jl!I0&$s@4pnQ7-$o9eQ53-5v}E2$C9*Rg9_QLNh4`RIV$O zdReD$GzV6D*yta0Mkq$%IGaeMiIhyyD#z)fR8q#z3XO7Qx88_a;jqhtB4WCXn+jp& zsak<|OLDW8+jY&3U+Z^T!{Hv{0WttOfCb;m*KKx0S(D(J{{P}Gq~&={!j;H4pw z0Lg%~1S&Jgk&u^1K?y|;90t#VC_qNS@@m2~sEU=YJ8H983`4iy57AgFnFFQ}-E@L^(piq5VBc0pH~Y7jiHMyUF8{9V0@8oOH@CTLJEOQ64e;w z@hB7zyKpM@?_mcv)>mbC?eU{)V{&I@>Gks`zubH%9^E-HH@)`3>5;#F=kd!gZT|P^ zlUtwt6?NYE1orjgi~GOeGfn#9!}of|Mmf*!U%PPg(v^$PZJql2-WO+n-J7|wv;5Qj z{{08-+t#LW{jG zeVY043v#Ky8Rs9*laJ~*d6|KQ2N)#I=5FOWMo-+s~D`s41zx0klQ8oPy+<<+I{ I&t3lbe+;p-UH||9 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_2_3.png b/resources/g2/track/wooden/medium_half_loop_right_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..fbfcce509509b205050b61bd0409887bec9e3ad8 GIT binary patch literal 1520 zcmXAoe{@oH7{&7n<=wn?sOW?n z$Ee7zwI&rN9m!$cqvWRHq(X;tCKees)Vn05jdj{YBO^8YMyGQ=@B5zjpZEFWdEPgc zRO`o$nLGvnFmB;fmCN!|l`nH?QNAC%U$6jB1ePp%W zY7~MXrKP2#M~{{(l}a2}>vRM~85oA0cnuXw9H~b ztv0pOrFDBqf4~$9bJ3V9neyo{#Hf|92D#mc@{G#M;hhd$*lmmkSh3fc7Ja!)M6UoQ z3|I-kQ;45M!Y*mTFUv+1Fs+7J6THPk7*PU10$@TARw}hC6ue61(`q|Ove#@**zLc0 zy)YbB;4&p4SCgpLq|&pP(T+2`mh*gmNSq}Q~sDO;A-vl z2gFD$nWw9_e z8;h$Q8nv6i1sxtXsN*D-HY%YBg?1J6;4nzQm?0m2&2-7N|9)WevT6!EF?g;HfWlo1 zE9XD+?AC2N&g>BG9lPKLB!%`Gt$j-Ksne0ETlOwKd-Y+}~hY{z?36Y~e>qJNFwdP%qQTqC07O1itJAAjTM%te9m z%B2_0WvPzs^CuL|KZ1H_TtnQIo>lzf&4a(RT&h_9*_$U$Hv7gt_GI(lyJV7I@9S7k z#8zycsPw*Fw!Lph$<5g)*Nrv}cQx&~_(d3H8em6PUf4$ZR@lUGR2S|0H= zi}m+a|5%7jzp=7BcKGb>MEu}`1CMU3cs2FMo&6gIjkDjo)^c&uDNBtyx}twWj9oq? z7<)y!V%s|-BR|x>6%4khR&`#!J?G*=`lf&97b}(yPsHd8tzZ0Pz3?%8=7*|7BiG8F ztDY_|d-nVIq?fpHww3$a*PG7Yh0HE_sQd`?rm(5^+d=)vl!i|?FS~LqzP9X4_lAMW z(yvw_&I#Au5zA^`5mjzj-E(5ey4!t+>S{iEWt?^S{`hOuk*9}e9G|mu*+#2NJqs}{ zcGR8Q2QiV^yS94WDOKO$MrQ?m=)_jn-Zt7+TZ3I6`@YD0w!KaA!0G4DO|0n(t!u;A qT$y1`P3yVac3{aLiZ#3YiMI}^|13Gtm(Ir)EL>1sx&O&EE&l>O7QHV3 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_2_4.png b/resources/g2/track/wooden/medium_half_loop_right_2_4.png new file mode 100644 index 0000000000000000000000000000000000000000..64f4b21108a6db1342687394bc95648133e1bcd3 GIT binary patch literal 1920 zcmX9Wp7XIZID&x=&85R}CF=LFBwYQ>;skcNUC8d1r;KWW$y=^#>zPUI{BioWO z#Y{A^Wg8h96}i-);p7K9l2L~oPtk}U86_o&uJkpL0~3|&yh~@!dG5XEIp?1H{PEm- z?l+qXxC!xd;{gB(xf`+z!}a5E6vak{^OJ+;WdKBiO&g1H!gR)r84(c?k&%&6QBl#+ z(J?VG1Og#8Ha0FUj*^m+0zpg;2SyMciVCGtOsQ0AwR*GJVz&>v-TpuTVgi^A_&lOe zNR~)wGC5PFW@~kPqgiCNNgYnLXUxE15Cm)@#-k_%G!07EOQBXJ$EFoH%$U1J<#QWC zemj>6L<}He5QbOiI5^8*-ZPF*}LOqB8^#OAK>l2%<(&olIs{t8IF{ z(_--q4*LCm98fVp*AgHjiDRWA4u;snQH===KAF|884Q?xQ?3wBWROTK3WZBcK^RPw z&6e``Dp7ct+^nwcF`C_WXTSpk5sx56ND2{6BVp*|ut|kjb>beA!e!I>T=qcV84d#= z06+?W1^^QPJpham03HUPgUhA3$$-0Ed^*4&PzwVK7r6NVM*xmda5aP*__#%aJ5;#a z0NxqT0z3{7@Cg!>qL49aHC&?swOW-*p3+q4Z3}bHdhU=qo&I%a^_$VI zeGfca0^+>4M<&gSsMRAKIaU5pPy0kheINS}%<=5sw#eVmwQuo+cTU$*1w?B+{^;Yl zN#?56$tORlddzuJcI@&QT7J2{zv}6hd`Tmvzc0UBar$P`>Y(IOLf@G2!RVKz56MSL zYv8O`V~;|X2N`R~ze&VR567EEFXS#so~PmU_tyXINW(qigQe)J;i<-Pm1524omukR zzM<{G_{rpZf6%v_%4|3nmloQeanzeyjJT5wosXkCoAO@_KkR!}_vl|2-S_&so6fyY zu=>8M-6j_Oysr1~jv{X}CzokYN?4n+I`^?*ZCSti&WrpTn=g%jluTdt3%Zy3?ZAr< zY&R1#cQqx*`iY5jZ`v2Us}~cYGaGy5si&I{WIS;WtjtEYGJ!io8P)?yu#j+x5e6NDt-Td#S;*b#Q;DYAIH`F~!HkN0gGt81J!_wQMcUN5=6*iqataQXeS zmVey3D|_NSK6llRl}j(rzMq!$Kk};6N2;T|kJk-m+1e-O|NDO0Q>gNX<+JF)@A4hP zS7Qoy%sH5aRuq;T7Ve(N+f{uDpy}kG9`9&kwC$F{raCh;qUHeHV z?5FOSBg4&ys&C4-l$I5`s#>qF{JCW2VctMZ!h+nV5gpwh-H^XN!0I|qT^3mI`pVFf zSMkkP2rK+snpM&_b${;mPHb$BKF`!QZr>$3y@2VU}v*Z=?k literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_2_5.png b/resources/g2/track/wooden/medium_half_loop_right_2_5.png new file mode 100644 index 0000000000000000000000000000000000000000..175d009513a92b91d6f33c9709cdb2d0b6bff6dd GIT binary patch literal 1221 zcmXAoZ)_8F7{`BI*=}Plhbh{*#@w)mOK7ygLk@By2i!$NJ)s1Bz+nhR0H{ zhMN{Fq`Qe)$)>98gjt-44v3U;$d6Dv7n3B?>zXEPhJU?Yba$w+>dkbIwiZ=Uaq z&-0wxy2aD6uxlXzpkvd<-ffNgY9n55wKnqP<3}O@RgQBjoaONsm^lDaM6(sdkCAD_%?$@uW^rw1niNXgO^&OAc6bLsNkBDue|m02}}Uf=DQ;I26>`E$QB9MNZY#0vzL9Hj#7$J+7#iN{dWR z=Jl{xj>}aoT+henbPZMusEx#3UV`+~OpxcJqL>H1nbfn{%G6Z7UWdRT0X&Wn zX_U!1_>#+CVIoyusus-E)hRPmn=jA7b{C40cDo02@-DYXQ8LR#gvPQ^CK@ZIGe$u- zD>M*TMCMUNz|?>%5u&vSpG)|Qno`auYUP4y&O#ahF90$CDgYV)MF6S@fDLgB49QSS zL8Hv!Kq5el23ZdhKavozG%#_^M{wEz3$2M%xB!h^Mc-`?No3&|XU%0{`GJLZnvb6zvUH3d9vT{6K0;mk>BQOL$lAWyBm0qqpWRzk zw|sR(8n`{+iB3EaKN?tV@>XJV=NImGEGs&`p6$zpJ-_->Dat&77ETdkgywpIDLaq0d}De(OK-(Q6yqRvqf^-xEBz z^y-h(#LaatogmV_7t8y4C+C+_wWwB623p4K-G@e^ z-;J369KN!6aDD3c%MW%={Jg(w$I@ljjGgbNe;B^7X#2Q+|IUr^VRYBg8~3btZVc>x zI1awNYQ1uS+SN1dDb1cex_++MU$oAkUFYE>&wS79{gueQzSq`%d3490c#k;KIX|Nv eDq`4U%Z6hk$>-l>I~y#(rVU$qzgfTg!~X$=(ivv} literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_3_1.png b/resources/g2/track/wooden/medium_half_loop_right_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..8f367259a7672187c9460ec4933d19330f3be8b4 GIT binary patch literal 1173 zcmX9-Z)_8F82)YTxQ#*jp~wXqt)$Z%IrM_J>~JR>aKk#z^yY5nz@kOZSYt_!cqWCE zSY1M&NEbO$j@`ZExB>-5!@XMoXT4P&VTYG!E#bU8qtsNa5 zvu4dg5TvuSv#YBMb-7$5Nw6#<2%IE&6-5q*!|`}BlgSneWz%dln2M<-pE1&~RQht&#*y3h)Pl-7|cYY`DD__W~=3LqtSrCAp1HrD6EEG(R$--q*#YH5+=R``I0FJ1@^hLR&|_*Y z9Wx5)x>!J(#oKVGJf`nNH8eHr6sb{*U9{#`wBOU>)yz%Qht)3kkTs69E_ZNEuUVbAImCTO+&1s0%ysGgp4A4!!!q z4^yWra!6e3Uv~Y#@{B${a^(7^Ee|%V9J8!*y|(!5#G4!952ld!PV(ozkV)aCv9Uq?31={c}kxpR@~`(@tx%*{83(ciaivu?q@8oX~myp$fj zZT=~wHqXyox%NFea`Ej!>C(-0tDaaq;OXlB?91u<2sA`Y-=oJKEDWXQ@u~tvHda4?H#IX?l(=x;fAG?tJT=%iEu| z6MY}nr}zhptG+`jku>o;Q8nB$%OJ%>LH k^gh>D6npn=`tM&nksU0P=;8?FkPJ?i4;61Sx)W}rYNXduYlQm{Bw&z<*@)6%DL+#N&-=bSU*3m@ z=Y5yw=c4;Z#zz2P|Ln}vLU$hO*7#6gx8MHJc^04#=8r8-cWF;gPj7E;UteE;fB(S1 zz~JB@hG9cPL&L+vp-3b`(-hBhk|ZcfT+`G{CQ~SsDizyxH+{d|>ChB#EQrErJRVFY z@l=}1=Ga0}ELY^Jqt(1zqiOOa7GpBc zDGm$?E32533)IWOPA!aD6za%m$3V!90EhrGhN*#o9u6A>VY2M1D6SQAqC}jPiKt4(bXqZ3t;lCAAzziunr!HltR%85qCJ%i{%=c**09XDw08k38$iDF2zN$%HMyVIH zrj=BD5O*ar^2r@=9364)mQch8dsZ=GGb4n%8wi}z9?RFbMSOubh(d7VN4NEmL z(crVqxYD)maKny?wFaRuoHGn1ts0)!tX$@H>^6Mf2Dh+uK z>?rsmAPJBfLOB|lBC?aHmPNh^d%-gx@DLNRq!Q9oWZsCDO{H4Rc%Id2d8n%uP5_-A z<&2PM;<8PsK5Mk&Rwq^6F4T7H2CBD-ATT%f!0m7MdvDsvbg$K}TH9j7fl1U|*c-j%DO_6NHB1p!O zPM{)G!4$LXJvs8`qU|RWo+M>jPc>8 zKV5$DG3A%$%I}54Cl?y`Z(kj~F%dlSZSd!bux2?Q%^YLR7hF1xa z;bAjLXF5)rVygL&4>uO|#3-Ev7bUpB3Wjl|{Se_kgc(^r>_eEDjZ*B-8-wTl_vL-y zeV+Hq+-%^$z|a5y9GE^kdCsmQcAV&Q+WD(ap8?>6x!2B5*<)8%m&4(3I-T9!-90@$ zy}i8{hV}LJ_4oI?eLf#W`8kdiMP8CZiXtZxiA*L}C=@G|9m{I9+ms(z1_XXE6mmtQ z-dNn9Ofi|PkS~NwWuJ6PEu^=-j^KLch)g&UPP#X!ZoC#J7vbC9PT6(8d33wn( zLW~7X#PTv$PT{q@t6lY=rXRJ#Xir0^;sX!>!Wbswxa#p}1fes`h9GQ4A~jXLpUa_g z*+aQ}tlKYmnJ^KM$)HL}8lz;ngu$mvqFxObt%#TQ_yayhBzcJr$()=NlDTlMC>Kq& zVx`SyzTPS0EVx8)N5C5gLc{2sJ5V4(WmYzWsk)-KvtdL5Tb2+nEtnci!S}g<~8Hfx<<#Dd$ z5vydR&LtZmy%{UDw4HXLxmW9;K@!Jlw>#kViKJg*7=;&-VS8D;kVX(F4; z69Fnd$ZBpu_lApvY%y9ZWVBWp)bJY)(((Fb$IHaQA1@x=yfyL6!55s%*T?pM z`CwxWKm6d^uhT1A4?9t8VCL>RObSnFzjlA`+;Tepla9Im`ta6?+izaJGxgBuSs57% zeDh*-<;kDMPTx2zE%`1StxlaEok$;AP680mg>27huvB_E+4saeBV9~ OOi#^De)q~-OaB8Z=hmVC literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_3_2_2.png b/resources/g2/track/wooden/medium_half_loop_right_3_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..5d9e53296d4d37bfdae6441adea760a389953288 GIT binary patch literal 1162 zcmX9-Z)_8F7=HKn2HR|<3nesqa}6tcnN^Q?A1?6*SLo)E-QY(0p=yy+8mxH2X)dJ9 zQwo-)(HoRdv5AdT(nysO7jkITs+}8H@q#lc$px!4QW7wQG-M_yKTAlS_s{d?eUkTi z->LC2Z|~BTO97yFbi}i{S%;gkx~r|3_gH&OfHoN4II+G-TUuILTU*=O+S=ROJ32Z# zJ3BE9>+0%SvSf+f>2#8$n`Ie6;6%|c%Tgo~NhDIaoL($0m}b4vAl<;wz;oSxzbzEP zm9RS+qZ3I!lMCbva>k=6tkfrWfl)uLA-E zC=6%$S8YKs+xltp4?q~=Vod7&Q0K+7UMRhndmn%)vGdw>Z43<^(dMbqq z1qW$!GIlqQ(*c)PB77<-YP6hWBUvt<7t*DGZU%A6;r2Rdf#5{SFR@aTkEQ}CUD6G; zXvU3Nrm|SDFklnF9t1oLE)Annc5lw*FEEnfi&f-wT`Qs)p0J6OL-7(ZADt1|yet?I zv7C^r*+{*RSTwSzTC~_G7vUqRAj2wx5EI3uqU2(+LMmnGdSzjuUauo?NZ?9fWX8hg z9YTo+R@i9OpROtSy0*~B)$WuRQ8!_+P!a6YS+3&~o!*l1iw41frjc3Z zT_BMVXF&IY$paDqNp=(?QJP132$iD9Ov63nDd1S}@mNT-s|pdB0%bVskCa@}PE3dg)|i=V+m0vQf+ni@*S)qFN? z6tgw6h#D1&1caJiM4NK=;fREj)hd-t+=pB$v3|c03W?#cM7krCJHe1ymMn1Y z1)iw+oG5@J)rFEI(ivoM&Euzrx^Lb4fj2gf2{3&1()N2~8|U@F!H$PUnmsY57aOS1cYesKhpvS`xT%G%_^N$|uVAt8gkz><(@Ahr8 z>qdePzPQ5LadG!Qw+4<|e;J%oqEGa!e)6$ZGtbQ)Y@f4z|8?rkp@E*yUtjkAikEv= z9J@7r_QUDN&n&}d$Bu6~|JHCTJ+-^ zHG1Z~o9^m6*K$O7eCoGN;kiE_K|RXUzi;pTXyxRI#JQ(F+4Y~YJHPqzAT{?le&gHJ Xjm|yS57-YicL<~F$2_OjZQb`jO$hK* literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_3_3.png b/resources/g2/track/wooden/medium_half_loop_right_3_3.png new file mode 100644 index 0000000000000000000000000000000000000000..93aee24e93dfef3f7db3337594d2bcbc5688f264 GIT binary patch literal 10644 zcmeHtcTkgC*Y5)eq4(aUBZdS*?+}n)BuG^;BmqJT5Fqs4iy%b=l#VnJq!$$srArk- zI0%XgiWEgbP{|FR@}4vIo4NDO-0#1W*-3U;>$leat+n^$S(6ki3quB4URnSE7>ted ztx4Zd(i=%lLHev_oLL6|cK1*l`v7YsLD<(H=Zf{h2nU4tVuUflSXTfDUaTs_2Jv-q zBoI*?4&=9!kgD91BaF>I!aIy=y&bl-ER0MmQw`X66V*#UPDC9?EcXV#x!gQv>-4@V zSg>nd5QHm?(j44V|MufYq~QCXEK$UO-|`Olgj92n)mrin4uysW)`7LN-`(X@7^x#)qG!l z=h@BD@seyB)O3%BIRM^_VSjN zrz?jjm)@n9X-D>>dsp`)@~5hbP##b0BGXTQ*!!r#cj19l!d8BXhTX>L>`XrY1!O$m z#9sF!msC|jE*YH5MLA87Q{BBGgY8E-J^Vg*YO8PY@?5f9#HW_vX(ll}&f8s%YoqGE z9`y8_-$sSBmrEjFU2fB(J{AZcjSYEHa|OnLvFKIJNRR){Sf@#L92^-T)tEwGSbm4| z{i&dbi8nZp^sri+EI{MIWbr1&VJ+8_anIcooYRgJ@*;O3mC6DnEbB6}R&n%y2@bX?iTjX%h<7szB zwu!8*Nv%Ptibvgx3-wjc7d;v)s;(Ec&3Je=bWEcxqi=tm@x(nikn4PRh=~>f2Vu#gXhQ2St{+I7l9qi2P&_uOeBTW-#(kQ&|b6lQ0^*f zT=w7e?pXO$(6;Nd)Hta<>=^6@)+(4u`3m#oZ}^Hz7FLman;vhFPr=h@LPjZ&2V2pb zIA4I62+s^iFp$8GzF-{X<{6jN?|CIkkbNj$H~!N(1g}WU?fBN~Iw2hxb)(C9Z~xNs zc6WD8p0L2O*bi*Wgtdb8Bl35-Eb~%tSsw&`U#u6K$F;)~VmOj9!pBD+XUI;g?rz+Xr|RPeW)~J zuyLjJ&aPOQm7>^NAKqd14M28h39T($@a?Cus!A3GLDU{DHC7YFlI>2e(OyR%uzB(& zTzEB2i6z72yf0iAlq_(zi?RdH8P_WVW6go@h0Dd+l1|rDp0$x>k89h%`T35}$i6bO z+Y=kwX0~u8qwK=Bf&K-hv}IK_&KFC(Z2Y2NIp50<9#~YcPud?Zc)#V3qTvrLAYeBi z3FfqOH!*Rv)m2gGwnu*Ee`32NW4+;!=4Gqy0RL@@>Sgp3^G{X+W^Gpkoop{1C}JZ& z1PI!RnEN?=jZkw7SPJB~Pkx(w^q4-K|2nSaO2h|hT}{+W`&3P`CeFL2TPX>~JU@SW zR$Ur3tI&vR2;n%^wb?edy*YiVER%npr#2Dx8BKLZB);9c)X1NSJ>gb6?gg9d&U$TG z5bvDd1w6*JqwMfn&9z|-We&whw~?DE56(v4k{PFA`DXNNJH-=muOrZ;r2T4jn@MEc@a%QTAjYW!>+1W92bc!y&Ut8+wWSn|q-aXbSS^xRm zQ@LxOBnv~dr_*yUe_u+)Yv;ZcbL+S;sB<~#EvezmcCbXnIrL|qS{B*g%R{4uF)XQAXZT>(AMNtJR+%0H#&?>09 zfZ5a)S_P?`E%XA7@s)ONI^Lp;o}^nW>&JaMZ(M*EkEV%KK~Nm_oR-D$KU}9`28+OF zqr-+ZFg^-DPvs@QAdl_7AZ|+S3(|e9Q)ziu2HQx9uzC;sHmeLPr(`_86K9%T8@}Q7 zIp=&1ep@^}gl&uSCTUKq%JLl8?FR^&1WevFKJA7XvPXs zb{Sgq3!|CG;xBaMaxq=rNj&O(@5Os1KbPz~kb3Zj>02{x!lx!W!XaZ6s$}30W0pjd1f#i#{=xNUr?(9O`j7N;7^VBI zr{utgVzEDbs6LKszdDQ;4jUDV5gtV-#d4{IRxO#FrGi#1y?>pNNShV7Y?@5{O_r$) z{4PLga4sZS{Tlo^CHms%_Cj{@82WlKxu9u_f`U3TgFu$6&a*yhY8Kxl9s1I#TLBa{ zmgcGE77ehS98G7R(;qLMzigC+et!KhrPv`{K{=+JYwYUa;hklEK$~u1@tQlL+21&r z1s`u5zpTs)@e0k6^-Ox+fbbeQ^IB9t6*R4Ol*|k<6U&X(S)FnKWGEci)_omgKe{RQ zfnHaotGbQAJLp@P2Ty0;9grI`!icU~@oY_~Ow3ij>#1O_KJIyW)K!(v(?&Cw6JAFZ z;vHBBKHCI3GI}Uhfl5wFQ3 z>QXH3eJ<WrOcrQZ@*1rp9oNSL5nQkTiwa$d};Jx(mrKqI*GUV!ZY|=@u^p z<@&OPyt*qM`Oy?5v}1VH4Qh&F-y<4g)!-)>{N;pebxuWgDA zkIbVBL!PDrDtlG6Lu>4BsQL&;3p2KzEL?d!iP6$zhvz=rn^3DV-A2%Hn-x-oBe$8xf&_W%LqeB_a%D212a0BA5KTb)YZC zm|8B|n2Dvvwdj;rzGXA^comWd{5rzW>ayNH@K(j4|achr-sy({L3-vY*%P>HBb|#G4pDWD!PW z_0F%;y^7PVyl8ypQJD7)hObJmC2+S|QEW})H%6Ln&YN%_>1NCHM4qS6>y3-q>Qeyc z?)DkooFQ*!02jzfK-qO>?{Cn42^5ig7{@a>iruk#O)S$ZWCB!-)ZF90#wX_@&9v^84Kv~@q-ny8YT3e4Smeva>1y1qzQauPa5G5JU=r(Lq# zrV73+ezc^aL0kTqic_xv6sMf+c+;ZnHUPkd;ay^BnLJs?8#ylx#2V7MVocb3EM44r@@q$svn?X)^p-s1HJJXx+d=Eq*49r6Q=85ney7pqh7MEKpORQ zKE5ls%Kk)?e7oQRMO1CfZ_CmCqN(yexySr-+dw;=XT>PlPZP6G_$AYf>2bz;u|Y~( zAI#7n9g_2!n6*Mq-&NMSGCQ9T9P8(;x0QyOQBCw{GWH=a+zQ|l?`ornHI8@kqA;+R zf1Wdax^!gP;;ekh41bz*96&```rukk+m74h1CXSOZVJ29@GQf|4_|2?vGC3*Dlkp(b1r$#=fj9|i?%V#cb8%{esI6ltei$37EM37c!ps1W5g`}!}!H+>FBa5 zUC)5)Xi9drup? z`4$SDW&BO8phr*3t&`$+SJm1}#|qa)yY<%`&kyfXP8R1GPH%E@3`$z*R0vZ$aqRNZ z#7j5FS?lyX=6!Uj{_E6Rv$4wtv71VI)SX_P+jr%#9nl{Y$pjN@sd%a`O!HZgulsa! zTse2KrJH=RgEe0xASQ{^A``gaNcpVV&+bvDU$}c1tD;~{)hphvu?2p|2t9D8rN~R+ z7OQ3@Rz8j7`GFnLtdP>r)jI>T6q*!5+@QYK3U+NFcA~H58BaksBeIP*fGB;5*+=7O zdwV01Ru!!u=N5<{o+^;RO6{8nHs*WBY_rhT9$=jz(Z99K1nt1MQlf)JbwHV7? z{R$E+BB!H?@etm6dH;~X=25sp9LyVsj%UzZV4YYdSdk4GPCb!|M!%S1wstwFVbI!Y zmXD(5_hf^|UoxiS%|1P13YtH|>teRCnY~DtdW-6Yjz9o3>rwe*#BQY40))9knS;*R zK+tlx@V1Upd6Z0_@|?To>2r{g#|X3Eq%0m@6VUckRS^=Q!K`L#P>C`3P4PEG-}WRM z+L-pA{H+FkgW_Jr&oZ+88`8(E=N>iXINY{?j*7>>8lFdF1$*m?^EzGq#vdZ@E$Yn7 z{N>gc&e5Cu@amKbL(k1J^W|^pGg2IO59>rRyA)gDJ30P-%0k#M4x4{bF;r zHQ&pM=$9#v__jX*;g5X`TgOT%qs_Z%KUWfqz{X|$6zJ8~B|-+Y&m8aP=4B*{piQ-2;u9l_dH$vlJ>2?As8v93)KL6q&1ymc&v|;AN{Ae) zCPNVQnvY#(<>{P;H{JbJmaNL&8^#BbaCfQK(#0wtLKaf%ZpI8sz)h7^UNIhiO%Wqo zw{7TDlC|CHr!%~t{f7N<@>(Oin03r`afl5Sw6itlC1GzdGgwUE>ytKCcLs|&??o?K zS=}$x20XjQzSg-8b*EP>4@4l+12lQl`;Xl`;mznv#MjXb0{L}4(Q}1t_I*^GkG1NH znnapeNBlVtA0Jn&7jT6NE<9Dl$WqxttWyNvr>hh%qaqlc8qcc7x3pDvjPkqWYokM&jzxVN#zyhn4-uii%&jph%2tB3rSnNfBO^G}it)o6RG zLT;Vre&iO%q033{XJm5yikNpFw@<~0z?O1zFJ{-gKl_Xyfc})??AM;R z&N-+F@}O7B(MY`<7@(Fwp`RR^qjYC8PlDncuZgbSz0KQF$a88V9JAinWG~W;5FC`T zU&7A&S>^2$vW25O*0Zhe1~2Mm3VTgy*$bc}W1o=gof zk3Grr;qijhl@uZwmFVRu3$y!K7%MVf1%NzDePlrGEPmdXYmN*PJ=IMuQX6v-6Pio40Z!9)SPU&q{+!2G{u7y1 z%$dG;oq1_iu$663y!o}d2y|{?l6cqX)+!=Yyo-5-<^0P;A9u`|QTbHHIfGCt`OME< zhZNHZb4~;!b8hRp_UZt_gB6GL2@^^uQ$L-u?=R9MoaAM19M=&g#ody#pDrpr#RP2) zqqiKeMH!vfiwo-*pJ%Sr_;XAd*`t=!r(=!9pkHubJD$uOx0{Ii3j-EAHVg zOnq@agu6-|!STUVhW=Fq@Qr--%QsgE#{OF|^psO_+`cv6As^&m_mi3UTL6G80Skv) z8N=a!)*MNd#+wn>G>ryyxD!`yr&`wud=!42Ri@@}io@^hg|o2ltMyy45;qV^^7yTjFxc({jIEvUX=#6ByFGfA9c8SRvDE8MSGVq^c>z zRI>TWKl|rRE8=u}Vmg+TxX#mQn*{X0 zIJBa|;A-@glCR(L^c&4pe-L-%j5yq1OdDKgf9mDrM$zZKDKN7={`+&Sq4yM7RhPjl z04S+1IHh@B^X2l&az~Ws;?M774Uzs2yZ6$$NyXtHEU5@=Z*HcB!gUuOkHMq-vAzLVoR9DcCej5L7@#R4LRuI8(?4%tbMwF8eei#< zK;i=ujP!-b$wDFC-jKg*-~$YTNFaYW^gn9gZAi6rh&2X}3-m`}41zE|0iu70K%@TB z_YL&-`n4T23WD*%c#}l&B&%}&FllIPZuOVO2?cIgZ{J^9B(nb@8Gv>D4_W{4?PTTG zcK+@NN&PR}e@Oqi_g}&!DRXl*eH<$A#64quO_3A(YG@n^i&p#9m3MJfRYWPtffX>S zE?@;kMHCo`RFMNCRTNZJlwB2+pmNB+K^gnt1CTx_%n1|;Toy~h!Jrh7Xk}MDV$huq#Fj}>*Mxo;e>ECT`OZv5qVkY ze`c(_kO8hF1=1P7`k-+H{C}2gu-+I%0P=)SIc0ejMHN*AMR^z$Cab}R9-<%4oYe^@=!GeQeRF6DyIhhn>-GUbq)D{NuL}aVU6E|ZiK~??1%iC z`u$8HFn+&}ejj>ae;p=a;a|r>4T<`F3wUG@2K~!V64viaD0iff8-{d${E@JK&SU?F zWKe**%B#4dmB7l1t}w8IvXT;5MO6t2MnYjwq!LCEjX}x(6CICp4Im)>F}iLf9!Xr0 z67&~W!cu>PO8TGj1b56y97vRb<)EbYCuQ;?kUusHIk_?Z+^q)W|KdaAm%!hy7?R%a zbEK<_bQ41Ux(ff`>*Uh;Uwr)$hyO(jBh#;#|^!>zIrhSjw4PuU!+Bk6?h^LyXC|t-zDkoGR7{Jv*7RdyVVg=MRWoJ_;&3RF)|+~j2a`uZf1WQ)%YfQ8X%XL4Cq2sw91 z;+E7icbw|?2t5b+W8XVgi1Ry=Y=E*5$PmKhq%Gu$fQ7l4W=45d3BOPL${@M2wOo7Qu)e+QdmyQt~T<={}vDfdFd@1fcV7f%F$NfXv0zP#;L9 z6fhzUXnc(vNMzBmoxI6_!keVx1po>#Ha7rm(9*Jf*vUbqUeCYUy}t>4_!E#?;3xANDG5jb@t`9T%= z<{JDroj!3^VLN_b?T;Bcvp=r(pZZ1!UyEkax=)~B4yT|8hlKbtGw-)^gJ^mpqEEpXYtj7oc)^o zQn{#X`-arqqfphp1D6%h2a(v*pb?+AP?sZN+^~HLm`?vlB14cOH0WY!F}g~zM@TVf zDB7AHxj9|KN^nYL$XcFAPdCgYACVQ%w`BMGS!g6J=Tu%Ac@!E6PK_q3R=+Ftns-V{ z)@@+Mq1)7VX7{@I20~?u8f!=TB(`|)U`e{Omg)TZ<0+f# zTWn2$yqeC}v(GHnFAj3AI2^rCpPe%zs?8mD51=({$@Gu3+VS;1Jd1hfir)rp`+?zZ z`nS)hx1G^@RQoRMTu>JGJ`U#aWbZB&4_EHy{rYReU%iH=))Y-5a(l1qAK7XhvW6r# za(#S!r)-d+b+!d(N`SmKc!*f)m6w?5P5Hq>K0YUWNhE;zlM#fmv+F^F#f2mmP5l>H n_m4&RQ(IYwK}(nP!;a_<(Xk+dGZdqwBn6BOEcEZ{U5Wiab%frI literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_3_4.png b/resources/g2/track/wooden/medium_half_loop_right_3_4.png new file mode 100644 index 0000000000000000000000000000000000000000..0ef117ec503b3ce918f6c61260dd78b0c9ee05f0 GIT binary patch literal 1872 zcmX9<4^Yy17XKnDpcYNIaf%)aDz)U{N{Yr#l&I*^iHRHTaxJc;xM4?oSh$kmiWgl} zI8x$9Nf#9s>z~a(sBEE;*&ZgltD6>Hc2T0|>~h9-dNTDpnw|N)_n9~I=6&AGdvD&~ z3JX~4!lJ_f0PFJevWo(o5->Fq9`GA}_;-Ndpm29_P9TKAU_n7aa5y|TI5;FEBs4S> zfj}UUNE8Z%B@&5LDuu~paJg)ukS~==luD&eXXxs(*zJ=pm)GZ`QUHSvIP7pfA0rmy zWpav2P1or;rY?ciCUrQ~b8aJ(jNsA3C2XvMht~*61}U{i$+YQsjxLF7OyzMISG;x> z4hYCV#sC^F!X!c1)aYpw#^=C69tz|WKz0ZD_P8L+G_65qyZa zMo7cSSY$PiZW1!BQm#`eoYqO*W~JArTXC8pw;he4k;ptMO~hczxLmbRsF%sQ)M}f- z;IvrgCMUgKF9dKBK+++oCN$HE<2uNqIi||ZH+p1NuV&KMrA0C?@YxYsXAoF1yn=#{dF0Ldr!e1bB^@td}#)Dy~&88Z#@VZF6*96`!!j9#R;$wKGNC0jfNlp}}&Dc!7l^anUti zzS$?UuIL-?2vDc#%4nn0J#7J z1!kcN$o&SKQm%KqX?opnkUAVpKA$TV3*~YNm7=6kbPTGQNwu*llN_>#M}!1;NI`=1 zRLH`Bob15z(~`rN-`+rVQ2`h1oS&%(9LAgc>|Mnre?3adPX0Hu?kYcO8 zI-0)WCJuR~c=1-t;&@F}o^fj7ap~$Zge@V%-|vW6F5x9-eZ6#`!#BB<7IXn^`|cGd z3F$Xv^d0-I;h6;Ozq?la!`21tGw&zozNyZ%L1lMVf8N_P|7!E*TjR;fYsjNBiV?5B zt{nf<=f6()*2;tPmSVR*St*Tw{psSZzsC{smf(O8v%tgeA<6gJ zE15S*9kxxyL(!-U(*F2?O;a07Gh+|^)O^XibbPpBS7VPXcs;7@S5(uHq{eQyrz!4u z>6V^|FY5jf@~_s+&{dEmB?wuCU-fKIqO+UW(VfIXaa3>i({Nbk?Nf2i(}@kpbt8Tw z1vd0?f%FJr;7Iq`@5{PlK8j!cq@_0z6g-NEZ9g9O;L*W~wBGvQ=W)#1;GxD%%`JZ- zTzum_TgevVa{96#uOQEy)e;Cb5!6d<*H50jcPupV#g+S_oN)BKr3d$pBR<1%GIeC7 zwhlES{Kvzr{#m^;ch6tIKpJenBR1$FD(LDdX~oa&qh~*Bwbsc>Hm6-~K3s4?8=_Zz^~-3MWGZs33OYTgk8XSHX*IZ` zx9nSc7AcigcP4-RdZN>x)7O2SEVTBcQrt4b=1wdwRXjLG}Hm-o;2{&?^E zvc67NQZ%&)08mm>UDc4~S=lKs$jfel`qWhb@<9E{)yuOoCnqO2H#aXYPaqHog~I&& ze33|0P*6}SVyE z0u~Igq{vT;B2G!dUz&-@U`h=$MmWJj7*zm30ALh}XoFvy{qX#R3j8>@g1nY>9{`m563CBM<{X4*&xI3qSyX0RVNoupG zT&<Glj!;jtitx9L##j%mA^9F;+_W-Mpu95)%o$lrI7_! za<@g8a~<<9HNMmAAFyKoT;9~W;t@-_1{zP=1MmAbw0HX3nq-xVXVhO6m)8pfbN2pd zz2A5i4z3&g$XxaOk6N~E=B*psg#G2*nJw4AstcP>e2UPRI!$WI!myNft;k`eVefr(aQ|%TCdRnIcv*In4zrHaPyJ$A_MP~`9Zft5V zdN)qBy(aH&H}p}OEt5=>x9T_euIh(ntvmh)F`M@5Y~L{vpI%#@Ij;HLo?)E+Q?0H`A_xpMO^L{`c09d}gs$80y8&b6`1DER4L!MOt;6QE7&WhB!Y}vB3v@{$JhsWay z1VVaxI*~}s$jBg(NK^)c!QrrlLOu+Ol}fo*t1%jlR;%6ZM*aTDNFKrRz!Z-- zmJ)su4JcSZ#|H>ZbZUq`Gdb*}B!e_8&c>1o>=}Y#eg*^eLna$&G=#}?@OZ-z z6i}(c2E)AFj`@5v4u!#|vLQN8!4zp&G6P46@U%9e(IxKm!j7NA#&|hk((*^@iiftIjVIe5I;5y zu_#I|O($ZRWjv=+=+(j@qcUvO#$3jP&$<+HVKG0M!ez2#9IlEl)WNV>skG^IZnN2E zw}((PIysq0BrrhJ0H&45agv2z8XRP)qC!(l?uhHW31l+qjz0@8VOcCPnMT9|B5&=EDursum%u-B#vxC~*REgtqKlk*rK z02u&U01yCN00aPt5doG0B*gSu%;mr$VTcJd9MH)Js0c(LfWZLMP%$$Hb3hoX#)2j+ z;s8Gz&jn&3kU>PXl4{VgIuVi6q4auFIp_+MsfqBAgxr!yLUzj2P68PJ`Fg8S=a05kHoUa>Zf{1y}@NSjr1i zitZQCjCxxv#u^9JZ0mw(>bHA;%|XPeQD?jDacWn1PAeI2g*u zLgLi(b4#)of6l-=QV9%7XTN(R6^!3*FBj~rdarMHR&(DgEAQjSH!b=8reE~a+bm#K zNhumuAA*b4*XC5589%C0wQSls%|(7%cw`Fb(1Plr=#%Gfw@!aKyKjj5@I&cMpRC#@ zdFk&@pR9N=)OSJJYIyj#WLC;%4_Lw(FE`p2dHANAmL1yusjc74cTWTYIU_BV8>tzu z@pc@3_T9vDr>fBxr-OHU%erd&aQL47hLT>(+*EN~PvW6#@WZ)p?bZ$wrmm-jJ&kpR zjj#W8PulAL6pop09L1drl@8oi{l42$wq`VcwBFq%ELvHQ{5aS#;axpP8ZE92pyjXZ z*tPMTfacDrb^j)_E~DVr?_Ze7v<~mtAaT}J6?|Fz^>}wf9`S#LT`y5i)LnE=m6uMW z8T*mN)!E*ePbh-V`aLBj`A2)VkRnj^@%@a7K<3~<{(NzU=kj>Xsk3`l5Z)g#ZvCJq z(DC)un(@ztt<%?eCxCf zNbh(5V=24!>|+w?aj@)L&wuI9wXD5T{;*ka=hjt)if)|JiR+68*4;UI!tj9pIo&=I zEE44&$*;`28;z1?`wEZM|8#yK^y2enHI=!swGRXhwPkm!8J>K${RmaF?r#bJ+ ziI%#(XmWW?MZ-wj46~lNsN1Goc=v^qo&UPsbk~EsaS#S6_WCg I%J#SaA9`x;X#fBK literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_4_2.png b/resources/g2/track/wooden/medium_half_loop_right_4_2.png new file mode 100644 index 0000000000000000000000000000000000000000..2751708b2d9b35307531870c51d13b0b3d937010 GIT binary patch literal 1696 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/wooden/medium_half_loop_right_4_5.png b/resources/g2/track/wooden/medium_half_loop_right_4_5.png new file mode 100644 index 0000000000000000000000000000000000000000..1c53187cfab5a9ed6e3c048070e280a7768156de GIT binary patch literal 1162 zcmX9-Z;aD)7=G_|NAFlJBR8bc1&23a#)ed_v0zDx_Q*JkSD>d0>_blrOkJ>Q(Geyz zI&_|klrYJFkqlX6TuK=6l566C83rE742@iHn0**BWg%!5EN}^z@N1zI3*z@vQpMmOiL@* zQdToxpDDRmaEpM4!5ag=j?q~>Q1FLJtYQU|bv4)0%VeFw-E~v1W*BV00UqOpn(BuL*P(MMMe(Qs)8RB z3Q{bX0jLRpL_i9Tk`&4b$c&&$0@ZTx$aorf4uS#}k#Q|br1U^OCl`xx%QBix3$?jC zVW478R>y^$S2F!djnP{n!;Thb(v?}Wj;bxc8)z>UAYCEW8xg5knAf#PE~OQXlvOsG zwKB5nG|wXwPz?}jdy#0E=NG;2TCsFXfBdb`y9-V$uOAz_^aHu8FTQ@krOq7(XLet{s^9;R9Hi>= z|8d?O-&LpkCmnl@1Bl=L_Is0C_Z_y+j25pSo +static void WoodenRCTrackLeftMediumHalfLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 0), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 5), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 40), + { 0, 0, height }, { { 0, 0, height + 44 }, { 32, 20, 2 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 10), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 45), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 15), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 7, height, session.SupportColours); + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 1), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 6), + { 0, 0, height }, { { 0, 0, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 41), + { 0, 0, height }, { { 0, 0, height + 70 }, { 32, 20, 2 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 11), + { 0, 0, height }, { { 0, 32, height }, { 40, 0, 64 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 16), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::topCorner), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 2), + { 0, 0, height }, { { 0, 0, height + 2 }, { 32, 32, 0 } }); + MetalBSupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::TopLeftSide, 14, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 7), + { 0, 0, height }, { { 29, 0, height }, { 1, 32, 96 } }); + MetalBSupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::TopRightSide, 16, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 12), + { 0, 0, height }, { { 31, 0, height }, { 1, 32, 96 } }); + MetalBSupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::BottomRightSide, 18, height, + session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 17), + { 0, 0, height }, { { 0, 0, height }, { 32, 32, 0 } }); + MetalBSupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::BottomLeftSide, 14, height, + session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::centre, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 144); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 3), + { 0, 0, height }, { { 0, 0, height }, { 0, 32, 160 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 44), + { 0, 0, height }, { { 0, 0, height + 144 }, { 32, 20, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 8), + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 32, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 13), + { 0, 0, height }, { { 29, 0, height }, { 1, 32, 160 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 18), + { 0, 0, height }, { { 0, 0, height }, { 1, 32, 160 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::centre, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 144); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 4), + { 0, 0, height }, { { 0, 2, height + 48 }, { 32, 32, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 9), + { 0, 0, height }, { { 0, 2, height + 48 }, { 32, 32, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 14), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 19), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topRightSide, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::rightCorner), + direction), + 0xFFFF, 0); + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height + 16, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +template +static void WoodenRCTrackRightMediumHalfLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 20), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 25), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 46), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 30), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 42), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 35), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 7, height, session.SupportColours); + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 21), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 26), + { 0, 0, height }, { { 0, 32, height }, { 40, 0, 64 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 31), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 2 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 43), + { 0, 0, height }, { { 0, 6, height + 70 }, { 32, 20, 2 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 36), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topRightSide, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::rightCorner), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 22), + { 0, 0, height }, { { 0, 0, height }, { 32, 32, 0 } }); + MetalBSupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::BottomRightSide, 14, height, + session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 27), + { 0, 0, height }, { { 30, 16, height }, { 0, 32, 96 } }); + MetalBSupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::BottomLeftSide, 18, height, + session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 32), + { 0, 0, height }, { { 29, 0, height }, { 0, 32, 96 } }); + MetalBSupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::TopLeftSide, 16, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 37), + { 0, 0, height }, { { 0, 0, height + 2 }, { 32, 32, 0 } }); + MetalBSupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::TopRightSide, 14, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::centre, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 144); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 23), + { 0, 0, height }, { { -12, 0, height }, { 0, 32, 160 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 28), + { 0, 0, height }, { { 29, 16, height }, { 0, 16, 160 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 33), + { 0, 0, height }, { { 30, 0, height }, { 0, 32, 160 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 38), + { 0, 0, height }, { { 0, 0, height }, { 0, 32, 160 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 47), + { 0, 0, height }, { { 0, 0, height + 144 }, { 32, 20, 0 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 144); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 24), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 29), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 34), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 39), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::topCorner), + direction), + 0xFFFF, 0); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height + 16, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +template +static void WoodenRCTrackLeftMediumHalfLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + WoodenRCTrackRightMediumHalfLoopUp( + session, ride, 4 - trackSequence, direction, height, trackElement, supportType); +} + +template +static void WoodenRCTrackRightMediumHalfLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + WoodenRCTrackLeftMediumHalfLoopUp( + session, ride, 4 - trackSequence, direction, height, trackElement, supportType); +} + +template +static void WoodenRCTrackLeftLargeHalfLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 0)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 7)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 14)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 21)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 5, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 1)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 12, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 8)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 9 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 6, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 15)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 58)), + { 0, 0, height }, { { 0, 6, height + 64 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 0, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 22)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 0, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 2)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 9)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 0 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 57)), + { 0, 0, height }, { { 0, 0, height + 70 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 16)), + { 0, 0, height }, { { 0, 16, height + 80 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 23)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 88); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 3)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::TopLeftSide, 22, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 10)), + { 0, 0, height }, { { 0, 0, height + 200 }, { 32, 16, 0 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::TopRightSide, 14, height + 8, + session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 17)), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 0 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::BottomRightSide, 0, height + 21, + session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 24)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::BottomLeftSide, 22, height, + session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 224); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 4)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 11)), + { 0, 0, height }, { { 0, 16, height + 110 }, { 16, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 18)), + { 0, 0, height }, { { 0, 0, height + 100 }, { 16, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 25)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 128); + break; + case 5: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 5)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 56)), + { 0, 0, height }, { { 0, 16, height + 210 }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 12)), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 19)), + { 0, 0, height }, { { 0, 0, height + 200 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 26)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 59)), + { 0, 0, height }, { { 0, 0, height + 210 }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 224); + break; + case 6: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 6)), + { 0, 0, height }, { { 0, 16, height + 32 }, { 32, 16, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 13)), + { 0, 0, height }, { { 0, 16, height + 32 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 20)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 27)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 16, 0 } }); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + } +} + +template +static void WoodenRCTrackRightLargeHalfLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 28)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 35)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 42)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 49)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 5, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 29)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 0, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 36)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 61)), + { 0, 0, height }, { { 0, 6, height + 64 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 0, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 43)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 9 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 6, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 50)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::Centre, 12, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 30)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 37)), + { 0, 0, height }, { { 0, 16, height + 80 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 44)), + { 0, 0, height }, { { 0, 0, height + 0 }, { 32, 16, 0 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 62)), + { 0, 0, height }, { { 0, 0, height + 70 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 51)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 88); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 31)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::BottomRightSide, 22, height, + session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 38)), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 0 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::BottomLeftSide, 0, height + 21, + session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 45)), + { 0, 0, height }, { { 0, 0, height + 200 }, { 32, 16, 0 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::TopLeftSide, 14, height + 8, + session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 52)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, MetalSupportPlace::TopRightSide, 22, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 224); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 32)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 39)), + { 0, 0, height }, { { 0, 0, height + 100 }, { 16, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 46)), + { 0, 0, height }, { { 0, 16, height + 110 }, { 16, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 53)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 128); + break; + case 5: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 33)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 60)), + { 0, 0, height }, { { 0, 0, height + 210 }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 40)), + { 0, 0, height }, { { 0, 0, height + 200 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 47)), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 54)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 63)), + { 0, 0, height }, { { 0, 16, height + 210 }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 224); + break; + case 6: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 34)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 16, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 41)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 48)), + { 0, 0, height }, { { 0, 16, height + 32 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 55)), + { 0, 0, height }, { { 0, 16, height + 32 }, { 32, 16, 0 } }); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + } +} + +template +static void WoodenRCTrackLeftLargeHalfLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + WoodenRCTrackRightLargeHalfLoopUp( + session, ride, 6 - trackSequence, direction, height, trackElement, supportType); +} + +template +static void WoodenRCTrackRightLargeHalfLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + WoodenRCTrackLeftLargeHalfLoopUp(session, ride, 6 - trackSequence, direction, height, trackElement, supportType); +} + template TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenAndClassicWoodenRC(OpenRCT2::TrackElemType trackType) { switch (trackType) @@ -16915,6 +17926,22 @@ template TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenAndClas return WoodenRCTrackDiagBrakes; case TrackElemType::DiagBlockBrakes: return WoodenRCTrackDiagBlockBrakes; + case TrackElemType::LeftMediumHalfLoopUp: + return WoodenRCTrackLeftMediumHalfLoopUp; + case TrackElemType::RightMediumHalfLoopUp: + return WoodenRCTrackRightMediumHalfLoopUp; + case TrackElemType::LeftMediumHalfLoopDown: + return WoodenRCTrackLeftMediumHalfLoopDown; + case TrackElemType::RightMediumHalfLoopDown: + return WoodenRCTrackRightMediumHalfLoopDown; + case TrackElemType::LeftLargeHalfLoopUp: + return WoodenRCTrackLeftLargeHalfLoopUp; + case TrackElemType::RightLargeHalfLoopUp: + return WoodenRCTrackRightLargeHalfLoopUp; + case TrackElemType::LeftLargeHalfLoopDown: + return WoodenRCTrackLeftLargeHalfLoopDown; + case TrackElemType::RightLargeHalfLoopDown: + return WoodenRCTrackRightLargeHalfLoopDown; default: return nullptr; } diff --git a/src/openrct2/park/Legacy.cpp b/src/openrct2/park/Legacy.cpp index 46a1a002f3..3b99aa1d06 100644 --- a/src/openrct2/park/Legacy.cpp +++ b/src/openrct2/park/Legacy.cpp @@ -2404,6 +2404,25 @@ bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, OpenRCT2::TrackElemType break; } } + else if ( + (rideType == RIDE_TYPE_WOODEN_ROLLER_COASTER || rideType == RIDE_TYPE_CLASSIC_WOODEN_ROLLER_COASTER) + && parkFileVersion < kWoodenRollerCoasterMediumLargeHalfLoopsVersion) + { + switch (trackType) + { + case TrackElemType::LeftMediumHalfLoopUp: + case TrackElemType::RightMediumHalfLoopUp: + case TrackElemType::LeftMediumHalfLoopDown: + case TrackElemType::RightMediumHalfLoopDown: + case TrackElemType::LeftLargeHalfLoopUp: + case TrackElemType::RightLargeHalfLoopUp: + case TrackElemType::LeftLargeHalfLoopDown: + case TrackElemType::RightLargeHalfLoopDown: + return true; + default: + break; + } + } return false; } diff --git a/src/openrct2/park/ParkFile.h b/src/openrct2/park/ParkFile.h index 03c8b36187..d6be3f4944 100644 --- a/src/openrct2/park/ParkFile.h +++ b/src/openrct2/park/ParkFile.h @@ -11,7 +11,7 @@ namespace OpenRCT2 struct GameState_t; // Current version that is saved. - constexpr uint32_t PARK_FILE_CURRENT_VERSION = 40; + constexpr uint32_t PARK_FILE_CURRENT_VERSION = 41; // The minimum version that is forwards compatible with the current version. constexpr uint32_t PARK_FILE_MIN_VERSION = 40; @@ -31,6 +31,7 @@ namespace OpenRCT2 constexpr uint16_t kWoodenFlatToSteepVersion = 37; constexpr uint16_t k16BitParkHistoryVersion = 38; constexpr uint16_t kPeepNamesObjectsVersion = 39; + constexpr uint16_t kWoodenRollerCoasterMediumLargeHalfLoopsVersion = 41; } // namespace OpenRCT2 class ParkFileExporter diff --git a/src/openrct2/ride/rtd/coaster/ClassicWoodenRollerCoaster.h b/src/openrct2/ride/rtd/coaster/ClassicWoodenRollerCoaster.h index e4987dd487..fab16a757a 100644 --- a/src/openrct2/ride/rtd/coaster/ClassicWoodenRollerCoaster.h +++ b/src/openrct2/ride/rtd/coaster/ClassicWoodenRollerCoaster.h @@ -22,7 +22,7 @@ constexpr RideTypeDescriptor ClassicWoodenRollerCoasterRTD = .TrackPaintFunctions = TrackDrawerDescriptor({ .Drawer = GetTrackPaintFunctionClassicWoodenRC, .supportType = WoodenSupportType::Truss, - .enabledTrackGroups = {TrackGroup::flat, TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::verticalLoop, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::waterSplash, TrackGroup::blockBrakes, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeSteepLong}, + .enabledTrackGroups = {TrackGroup::flat, TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::verticalLoop, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::waterSplash, TrackGroup::blockBrakes, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeSteepLong, TrackGroup::halfLoopMedium, TrackGroup::halfLoopLarge}, .extraTrackGroups = {}, }), .InvertedTrackPaintFunctions = {}, diff --git a/src/openrct2/ride/rtd/coaster/WoodenRollerCoaster.h b/src/openrct2/ride/rtd/coaster/WoodenRollerCoaster.h index 5a92f1371e..5cf58d8ffe 100644 --- a/src/openrct2/ride/rtd/coaster/WoodenRollerCoaster.h +++ b/src/openrct2/ride/rtd/coaster/WoodenRollerCoaster.h @@ -22,7 +22,7 @@ constexpr RideTypeDescriptor WoodenRollerCoasterRTD = .TrackPaintFunctions = TrackDrawerDescriptor({ .Drawer = GetTrackPaintFunctionWoodenRC, .supportType = WoodenSupportType::Truss, - .enabledTrackGroups = {TrackGroup::flat, TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::verticalLoop, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::waterSplash, TrackGroup::slopeCurveBanked, TrackGroup::blockBrakes, TrackGroup::slopeRollBanking, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeSteepLong}, + .enabledTrackGroups = {TrackGroup::flat, TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::verticalLoop, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::waterSplash, TrackGroup::slopeCurveBanked, TrackGroup::blockBrakes, TrackGroup::slopeRollBanking, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeSteepLong, TrackGroup::halfLoopMedium, TrackGroup::halfLoopLarge}, .extraTrackGroups = {TrackGroup::booster}, }), .InvertedTrackPaintFunctions = {}, diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index e11a9d154f..16c4b0b237 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -1306,7 +1306,9 @@ enum : ImageIndex SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS = SPR_G2_WOODEN_RC_FLAT_TO_STEEP + 32, SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT = SPR_G2_WOODEN_RC_FLAT_TO_STEEP_RAILS + 32, SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT_RAILS = SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT + 16, - SPR_G2_WOODEN_RC_END = SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT_RAILS + 16, + SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP = SPR_G2_WOODEN_RC_FLAT_TO_STEEP_FRONT_RAILS + 16, + SPR_G2_WOODEN_RC_LARGE_HALF_LOOP = SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 48, + SPR_G2_WOODEN_RC_END = SPR_G2_WOODEN_RC_LARGE_HALF_LOOP + 64, SPR_G2_BM_INVERT_RC_BEGIN = SPR_G2_WOODEN_RC_END, SPR_G2_BM_INVERT_BOOSTER_1 = SPR_G2_BM_INVERT_RC_BEGIN, From 7b614f22873359637258d6489adb4410bca3b52f Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sun, 27 Oct 2024 12:50:17 +0100 Subject: [PATCH 58/97] ParkInfoCommands: mark typeToName, sourceGameToName constexpr --- src/openrct2/command_line/ParkInfoCommands.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/openrct2/command_line/ParkInfoCommands.cpp b/src/openrct2/command_line/ParkInfoCommands.cpp index c3c015f1c7..19161f8ffe 100644 --- a/src/openrct2/command_line/ParkInfoCommands.cpp +++ b/src/openrct2/command_line/ParkInfoCommands.cpp @@ -90,12 +90,12 @@ static exitcode_t HandleObjectsInfo(CommandLineArgEnumerator* argEnumerator) Console::WriteLine("File contains the following objects: "); Console::WriteLine(); - const std::array typeToName = { + constexpr std::array typeToName = { "Ride", "SmallScenery", "LargeScenery", "Walls", "Banners", "Paths", "PathAdditions", "SceneryGroup", "ParkEntrance", "Water", "ScenarioText", "TerrainSurface", "TerrainEdge", "Station", "Music", "FootpathSurface", "FootpathRailings", }; - const std::array sourceGameToName = { + constexpr std::array sourceGameToName = { "Custom", "WackyWorlds", "TimeTwister", "OpenRCT2Official", "RCT1", "AddedAttractions", "LoopyLandscapes", "", "RCT2", }; @@ -120,7 +120,7 @@ static exitcode_t HandleObjectsInfo(CommandLineArgEnumerator* argEnumerator) }) { auto& list = loadResult.RequiredObjects.GetList(objType); - Console::WriteLine("ObjectType: %s, Number of Objects: %d", typeToName[EnumValue(objType)].c_str(), list.size()); + Console::WriteLine("ObjectType: %s, Number of Objects: %d", typeToName[EnumValue(objType)], list.size()); for (auto& obj : list) { if (obj.Generation == ObjectGeneration::JSON && obj.Identifier.size() == 0) @@ -129,7 +129,7 @@ static exitcode_t HandleObjectsInfo(CommandLineArgEnumerator* argEnumerator) continue; } auto* ori = OpenRCT2::GetContext()->GetObjectRepository().FindObject(obj); - Console::WriteFormat("%s Object: ", sourceGameToName[EnumValue(ori->GetFirstSourceGame())].c_str()); + Console::WriteFormat("%s Object: ", sourceGameToName[EnumValue(ori->GetFirstSourceGame())]); std::string name{ obj.GetName() }; if (obj.Generation == ObjectGeneration::DAT) From e6665504fb3c416659459e95c1f7bbd8247d5da2 Mon Sep 17 00:00:00 2001 From: mix <167040362+mixiate@users.noreply.github.com> Date: Sun, 27 Oct 2024 17:14:02 +0000 Subject: [PATCH 59/97] Stop large corks, medium loops, zero g being built if no train sprites --- src/openrct2/ride/Ride.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index a239f4b4c2..2099f08551 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -4902,10 +4902,18 @@ OpenRCT2::BitSet RideEntryGetSupportedTrackPieces( {}, // TrackGroup::miniGolfHole { SpriteGroupType::SlopeFlat, SpritePrecision::Sprites4 }, // TrackGroup::rotationControlToggle { SpriteGroupType::Slopes60, SpritePrecision::Sprites4 }, // TrackGroup::slopeSteepUp - {}, // TrackGroup::corkscrewLarge - {}, // TrackGroup::halfLoopMedium - {}, // TrackGroup::zeroGRoll - {}, // TrackGroup::zeroGRollLarge + { SpriteGroupType::Corkscrews, SpritePrecision::Sprites4, SpriteGroupType::SlopeInverted, + SpritePrecision::Sprites4 }, // TrackGroup::corkscrewLarge + { SpriteGroupType::Slopes60, SpritePrecision::Sprites4, SpriteGroupType::Slopes75, SpritePrecision::Sprites4, + SpriteGroupType::Slopes90, SpritePrecision::Sprites4, SpriteGroupType::SlopesLoop, SpritePrecision::Sprites4, + SpriteGroupType::SlopeInverted, SpritePrecision::Sprites4 }, // TrackGroup::halfLoopMedium + { SpriteGroupType::Slopes25Banked67, SpritePrecision::Sprites4, SpriteGroupType::Slopes25Banked90, + SpritePrecision::Sprites4, SpriteGroupType::Slopes25InlineTwists, + SpritePrecision::Sprites4 }, // TrackGroup::zeroGRoll + { SpriteGroupType::Slopes42Banked22, SpritePrecision::Sprites4, SpriteGroupType::Slopes42Banked45, + SpritePrecision::Sprites4, SpriteGroupType::Slopes42Banked67, SpritePrecision::Sprites4, + SpriteGroupType::Slopes42Banked90, SpritePrecision::Sprites4, SpriteGroupType::Slopes60Banked22, + SpritePrecision::Sprites4 }, // TrackGroup::zeroGRollLarge { SpriteGroupType::Slopes25, SpritePrecision::Sprites4, SpriteGroupType::Slopes60, SpritePrecision::Sprites4, SpriteGroupType::Slopes75, SpritePrecision::Sprites4, SpriteGroupType::Slopes90, SpritePrecision::Sprites4 }, // TrackGroup::flyingLargeHalfLoopUninvertedUp From db3642197448ad90346ec70c2c002c2aec9379c5 Mon Sep 17 00:00:00 2001 From: mix <167040362+mixiate@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:38:10 +0000 Subject: [PATCH 60/97] Fix #21221: Improve car sprite fallback on sloped diag banked track --- distribution/changelog.txt | 1 + src/openrct2/paint/vehicle/VehiclePaint.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 7494e672a7..726c729f25 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -2,6 +2,7 @@ ------------------------------------------------------------------------ - Improved: [#22967] Add medium and large half loops to the Wooden and Classic Wooden Roller Coasters. - Improved: [#23010] Make AppImage compatible with Ubuntu 22.04 and Debian Bookworm again. +- Fix: [#21221] Trains use unbanked sprites on flat to gentle diagonal banked track pieces. - Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. - Fix: [#22633] Crash when drawing loading screen with an outdated g2.dat. - Fix: [#22918] Zooming with keyboard moves the view off centre. diff --git a/src/openrct2/paint/vehicle/VehiclePaint.cpp b/src/openrct2/paint/vehicle/VehiclePaint.cpp index f953c67881..6f7ca3b2c5 100644 --- a/src/openrct2/paint/vehicle/VehiclePaint.cpp +++ b/src/openrct2/paint/vehicle/VehiclePaint.cpp @@ -3224,7 +3224,7 @@ static void VehiclePitchUp8BankedLeft45( } else { - VehiclePitchUp8Unbanked(session, vehicle, imageDirection, z, carEntry); + VehiclePitchFlatBankedLeft45(session, vehicle, imageDirection, z, carEntry); } } @@ -3239,7 +3239,7 @@ static void VehiclePitchUp8BankedRight45( } else { - VehiclePitchUp8Unbanked(session, vehicle, imageDirection, z, carEntry); + VehiclePitchFlatBankedRight45(session, vehicle, imageDirection, z, carEntry); } } @@ -3304,7 +3304,7 @@ static void VehiclePitchUp16BankedLeft22( } else { - VehiclePitchUp16Unbanked(session, vehicle, imageDirection, z, carEntry); + VehiclePitchUp25BankedLeft45(session, vehicle, imageDirection, z, carEntry); } } @@ -3319,7 +3319,7 @@ static void VehiclePitchUp16BankedRight22( } else { - VehiclePitchUp16Unbanked(session, vehicle, imageDirection, z, carEntry); + VehiclePitchUp25BankedRight45(session, vehicle, imageDirection, z, carEntry); } } @@ -3466,7 +3466,7 @@ static void VehiclePitchDown8BankedLeft45( } else { - VehiclePitchFlat(session, vehicle, imageDirection, z, carEntry); + VehiclePitchFlatBankedLeft45(session, vehicle, imageDirection, z, carEntry); } } @@ -3481,7 +3481,7 @@ static void VehiclePitchDown8BankedRight45( } else { - VehiclePitchFlat(session, vehicle, imageDirection, z, carEntry); + VehiclePitchFlatBankedRight45(session, vehicle, imageDirection, z, carEntry); } } @@ -3546,7 +3546,7 @@ static void VehiclePitchDown16BankedLeft22( } else { - VehiclePitchDown16Unbanked(session, vehicle, imageDirection, z, carEntry); + VehiclePitchDown25BankedLeft45(session, vehicle, imageDirection, z, carEntry); } } @@ -3561,7 +3561,7 @@ static void VehiclePitchDown16BankedRight22( } else { - VehiclePitchDown16Unbanked(session, vehicle, imageDirection, z, carEntry); + VehiclePitchDown25BankedRight45(session, vehicle, imageDirection, z, carEntry); } } From 0669eba3b27d3383468d8a7912ea35f8dd3fbb99 Mon Sep 17 00:00:00 2001 From: OpenRCT2 git bot Date: Mon, 28 Oct 2024 04:02:07 +0000 Subject: [PATCH 61/97] Merge Localisation/master into OpenRCT2/develop --- data/language/de-DE.txt | 67 ++++++++++++++++++++++++++++----- data/language/fi-FI.txt | 83 +++++++++++++++++++++++++++++++++-------- 2 files changed, 124 insertions(+), 26 deletions(-) diff --git a/data/language/de-DE.txt b/data/language/de-DE.txt index 24dde399a7..c3e87031fa 100644 --- a/data/language/de-DE.txt +++ b/data/language/de-DE.txt @@ -1912,8 +1912,8 @@ STR_2670 :Rollen STR_2680 :Alle Forschungen beendet STR_2684 :Eine große Gruppe von Besuchern tritt ein STR_2685 :Simplexrauschparameter -STR_2686 :Niedrig: -STR_2687 :Hoch: +STR_2686 :Min. Landhöhe: +STR_2687 :Max. Landhöhe: STR_2688 :Basisfrequenz: STR_2689 :Oktaven: STR_2690 :Kartengenerierung @@ -2603,8 +2603,8 @@ STR_5357 :{BLACK}Übelkeitstoleranz: STR_5358 :{BLACK}Toilette: STR_5359 :Besucher entfernen STR_5360 :Alle Besucher von der Karte entfernen -STR_5361 :Gib allen Besuchern: -STR_5362 :{BLACK}Bevorzugte Bahnintensität aller Besucher: +STR_5361 :Zum Besucherinventar hinzufügen +STR_5362 :{BLACK}Bevorzugte Bahnintensität: STR_5363 :Mehr als 1 STR_5364 :Weniger als 15 STR_5365 :{BLACK}Personalgeschw.: @@ -2634,7 +2634,7 @@ STR_5457 :Stützenlimit deaktivieren STR_5458 :Im Uhrzeigersinn drehen STR_5459 :Gegen den Uhrzeigersinn drehen STR_5460 :Ansicht gegen den Uhrzeigers. drehen -STR_5461 :Besucherparameter festlegen +STR_5461 :Parameter für alle Besucher festlegen STR_5462 :{CURRENCY} STR_5463 :Ziel: Viel Spaß! STR_5464 :Allgemein @@ -3162,9 +3162,9 @@ STR_6041 :{BLACK}Es sind keine Mechaniker eingestellt! STR_6042 :Höhenkarte laden STR_6043 :Höhenkarte auswählen STR_6044 :Höhenkarte glätten -STR_6045 :Stärke +STR_6045 :Stärke: STR_6046 :Höhenkarte normalisieren -STR_6047 :Kacheln glätten +STR_6047 :Kachelkanten glätten STR_6048 :Fehler beim Verarbeiten der Höhenkarte STR_6049 :Fehler beim Lesen der PNG-Datei STR_6050 :Fehler beim Lesen der Bitmap-Datei @@ -3713,14 +3713,14 @@ STR_6644 :Verbesserungen für die Touch-Bedienung STR_6645 :Vergrößert einige Bedienelemente, damit sie leichter angeklickt oder angetippt werden können. STR_6646 :Autor: {STRING} STR_6647 :Autoren: {STRING} -STR_6648 :Pluginengine laden… -STR_6649 :Szenario laden… +STR_6648 :Pluginengine laden … +STR_6649 :Szenario laden … STR_6650 :Gespeichertes Spiel laden… STR_6651 :{STRING} ({COMMA32}%) STR_6652 :Fehlermeldung STR_6653 :Alle Quellen angezeigt STR_6654 :{POP16}{UINT16} Quellen angezeigt -STR_6655 :Nur ‘{POP16}{STRINGID}’ +STR_6655 :Nur ‚{POP16}{STRINGID}‘ STR_6656 :Alle Zäune vom Park entfernen STR_6657 :Gelände nicht im Besitz STR_6658 :Legen Sie das Gelände fest,{NEWLINE}das weder dem Park gehören soll noch gekauft werden kann @@ -3728,6 +3728,53 @@ STR_6659 :Gäste ignorieren Preise STR_6660 :Gäste werden den Preis von Fahrgeschäften und Läden ignorieren STR_6661 :Alle zufällig STR_6662 :Zufallsfarben für jeden Zug oder jedes Fahrzeug +STR_6663 :Datumscheats +STR_6664 :Datumscheats anzeigen +STR_6665 :Natur-/Wettercheats +STR_6666 :Natur-/Wettercheats anzeigen +STR_6667 :Fauna +STR_6668 :Personalcheats +STR_6669 :Personalcheats anzeigen +STR_6670 :Gastverhalten +STR_6671 :„Reale“ Namen des Personals anzeigen +STR_6672 :Zwischen der Anzeige „realer“ Namen des Personals und Personalnummern umschalten +STR_6673 :Transluzent +STR_6674 :{MONTH}, Jahr {COMMA16} +STR_6675 :Peep-Namen +STR_6676 :Es muss mindestens ein Peep-Namensobjekt ausgewählt werden +STR_6677 :Strände um Wasserflächen hinzufügen +STR_6678 :Höhenkartenquelle: +STR_6679 :Flachland +STR_6680 :Simplexrauschen +STR_6681 :Höhenkartendatei +STR_6682 :Kartengenerator – Generator +STR_6683 :Kartengenerator – Terrain +STR_6684 :Kartengenerator – Wasser +STR_6685 :Kartengenerator – Wälder +STR_6686 :Baum-Land-Verhältnis: +STR_6687 :Min. Baumhöhe: +STR_6688 :Max. Baumhöhe: +STR_6689 :{UINT16}% +STR_6690 :Minimale Landhöhe +STR_6691 :Min. Landhöhe zwischen {COMMA16} und {COMMA16} eingeben +STR_6692 :Maximale Landhöhe +STR_6693 :Max. Landhöhe zwischen {COMMA16} und {COMMA16} eingeben +STR_6694 :Minimale Baumhöhe +STR_6695 :Min. Baumhöhe zwischen {COMMA16} und {COMMA16} eingeben +STR_6696 :Maximale Baumhöhe +STR_6697 :Max. Baumhöhe zwischen {COMMA16} und {COMMA16} eingeben +STR_6698 :Baum-Land-Verhältnis +STR_6699 :Baum-Land-Verhältnis zwischen {COMMA16} und {COMMA16} eingeben +STR_6700 :Simplexbasisfrequenz +STR_6701 :Basisfrequenz zwischen {COMMA2DP32} und {COMMA2DP32} eingeben +STR_6702 :Simplexoktaven +STR_6703 :Oktaven zwischen {COMMA16} und {COMMA16} eingeben +STR_6704 :{COMMA2DP32} +STR_6705 :Durchsuchen … +STR_6706 :{WINDOW_COLOUR_2}Aktuelle Bilddatei: {BLACK}{STRING} +STR_6707 :(keine ausgewählt) +STR_6708 :Weiche Stärke +STR_6709 :Weiche Stärke zwischen {COMMA16} und {COMMA16} eingeben ############# # Scenarios # diff --git a/data/language/fi-FI.txt b/data/language/fi-FI.txt index 10e82e9fd2..1fdd738839 100644 --- a/data/language/fi-FI.txt +++ b/data/language/fi-FI.txt @@ -1834,7 +1834,7 @@ STR_2482 :Tuotto: {CURRENCY} viikossa, puiston arvo: {CURRENCY} STR_2483 :{WINDOW_COLOUR_2}Viikottainen tuotto: {BLACK}+{CURRENCY2DP} STR_2484 :{WINDOW_COLOUR_2}Viikottainen tuotto: {RED}{CURRENCY2DP} STR_2487 :Käytä kävijöiden ”oikeita” nimiä -STR_2488 :Vaihda kävijöiden nimen ja numeron näyttämisen välillä +STR_2488 :Tunnista kävijät nimellä numeron sijaan STR_2489 :Pikanäppäimet… STR_2490 :Näppäimistön pikanäppäimet STR_2491 :Palauta näppäinasetukset @@ -1915,17 +1915,17 @@ STR_2669 :NumLock STR_2670 :Scroll STR_2680 :Kaikki kehitys on saatu päätökseen STR_2684 :Suuri kävijäryhmä saapuu -STR_2685 :Simplex-melun parametrit -STR_2686 :Matala: -STR_2687 :Korkea: +STR_2685 :Simplex-kohinan parametrit +STR_2686 :Min. maastokorkeus: +STR_2687 :Maks. maastokorkeus: STR_2688 :Perustaajuus: STR_2689 :Oktaaveja: STR_2690 :Kartan luonti STR_2691 :Pohjakorkeus: -STR_2692 :Veden taso: -STR_2693 :Ympäristö: +STR_2692 :Vesistön taso: +STR_2693 :Maasto: STR_2694 :Luo -STR_2695 :Satunnainen ympäristö +STR_2695 :Satunnainen maasto STR_2696 :Sijoita puita STR_2700 :Autom. tallennus: STR_2701 :1 minuutin välein @@ -1956,7 +1956,8 @@ STR_2732 :{COMMA32}jalka STR_2733 :{COMMA32}m STR_2734 :{COMMA16}mph STR_2735 :{COMMA16}km/h -STR_2736 :{MONTH}n, vuoden {COMMA16} +# Used only as part of label-value pair. +STR_2736 :{MONTH}, vuosi {COMMA16} STR_2737 :{STRINGID} {MONTH}ta, vuosi {COMMA16} STR_2738 :Päävalikon musiikki: STR_2739 :Ei mitään @@ -2459,8 +2460,8 @@ STR_5181 :Näytä laitehuijaukset STR_5182 :{INT32} STR_5183 :Pohjakorkeus STR_5184 :Anna pohjakorkeus {COMMA16}-{COMMA16} -STR_5185 :Veden taso -STR_5186 :Anna veden taso väliltä {COMMA16}-{COMMA16} +STR_5185 :Vesistön taso +STR_5186 :Anna vesistön taso väliltä {COMMA16}-{COMMA16} STR_5187 :Talous STR_5188 :Uusi kampanja STR_5189 :Kehitys @@ -2609,8 +2610,8 @@ STR_5357 :{BLACK}Pahoinvoinnin sieto: STR_5358 :{BLACK}Vessa: STR_5359 :Poista kävijät STR_5360 :Poista kaikki kävijät kartalta -STR_5361 :Anna kaikille kävijöille: -STR_5362 :{BLACK}Aseta kävijöiden mieluisin jännitystaso: +STR_5361 :Lisää kävijöiden taskuun +STR_5362 :{BLACK}Mieluisin jännitystaso: STR_5363 :Yli 1 STR_5364 :Alle 15 STR_5365 :{BLACK}Henkilöstön nopeus: @@ -2640,7 +2641,7 @@ STR_5457 :Poista tukirakenteiden rajat STR_5458 :Käännä myötäpäivään STR_5459 :Käännä vastapäivään STR_5460 :Käännä näkymää vastapäivään -STR_5461 :Määritä kävijöiden määritteitä +STR_5461 :Aseta kaikille kävijöille STR_5462 :{CURRENCY} STR_5463 :Tavoite: Pidä hauskaa! STR_5464 :Yleiset @@ -3171,10 +3172,10 @@ STR_6040 :Muuta skenaarioasetuksia STR_6041 :{BLACK}Yhtään mekaanikkoa ei ole palkattu! STR_6042 :Lataa korkeuskartta STR_6043 :Valitse korkeuskartta -STR_6044 :Sileä korkeuskartta -STR_6045 :Voima +STR_6044 :Tasoita korkeuskartta +STR_6045 :Voimakkuus: STR_6046 :Normalisoi korkeuskartta -STR_6047 :Sileät ruudut +STR_6047 :Tasoita ruutujen reunat STR_6048 :Korkeuskarttavirhe STR_6049 :Virhe lukiessa PNG:tä STR_6050 :Virhe lukiessa bittikarttakuvaa @@ -3737,6 +3738,56 @@ STR_6657 :Maa ei omistettu STR_6658 :Määritä, että ruutu ei ole puiston omistuksessa eikä ostettavissa STR_6659 :Kävijät eivät huomioi hintoja STR_6660 :Kävijät jättävät laitteiden ja kojujen hinnat huomioimatta. +STR_6661 :Arvo kaikki +STR_6662 :Valitse satunnaiset värit jokaiselle vaunulle tai ajoneuvolle. +STR_6663 :Päiväyshuijaukset +STR_6664 :Näytä päiväyshuijaukset +STR_6665 :Luonto- ja säähuijaukset +STR_6666 :Näytä luonto- ja säähuijaukset +STR_6667 :Eläimistö +STR_6668 :Henkilöstöhuijaukset +STR_6669 :Näytä henkilöstöhuijaukset +STR_6670 :Kävijöiden käytös +STR_6671 :Käytä henkilöstön ”oikeita” nimiä +STR_6672 :Tunnista henkilöstön jäsenet nimellä numeron sijaan +STR_6673 :Läpinäkyvä +# Used as part of a sentence (see https://github.com/OpenRCT2/OpenRCT2/issues/22072). +STR_6674 :{MONTH}n, vuoden {COMMA16} +STR_6675 :Henkilöiden nimet +STR_6676 :Ainakin yksi henkilönimilista tulee olla valittuna +STR_6677 :Lisää rantoja vesistöiden ympärille +STR_6678 :Korkeuskartta: +STR_6679 :Tasamaa +STR_6680 :Simplex-kohina +STR_6681 :Korkeuskarttatiedosto +STR_6682 :Kartan luonti - Perusasetukset +STR_6683 :Kartan luonti - Maasto +STR_6684 :Kartan luonti - Vesistö +STR_6685 :Kartan luonti - Metsät +STR_6686 :Metsä/aukea -suhde: +STR_6687 :Min. maastokorkeus puille: +STR_6688 :Maks. maastokorkeus puille: +STR_6689 :{UINT16}% +STR_6690 :Min. maastokorkeus +STR_6691 :Anna min. maastokorkeus väliltä {COMMA16}-{COMMA16} +STR_6692 :Maks. maastokorkeus +STR_6693 :Anna maks. maastokorkeus väliltä {COMMA16}-{COMMA16} +STR_6694 :Min. maastokorkeus puille +STR_6695 :Anna min. maastokorkeus puille väliltä {COMMA16}-{COMMA16} +STR_6696 :Maks. maastokorkeus puille +STR_6697 :Anna maks. maastokorkeus puille väliltä {COMMA16}-{COMMA16} +STR_6698 :Metsä/aukea -suhde +STR_6699 :Anna metsä/aukea -suhde väliltä {COMMA16}-{COMMA16} +STR_6700 :Simplex-perustaajuus +STR_6701 :Anna perustaajuus väliltä {COMMA2DP32}-{COMMA2DP32} +STR_6702 :Simplex-oktaavit +STR_6703 :Anna oktaavit väliltä {COMMA16}-{COMMA16} +STR_6704 :{COMMA2DP32} +STR_6705 :Selaa... +STR_6706 :{WINDOW_COLOUR_2}Valittu kuvatiedosto: {BLACK}{STRING} +STR_6707 :(ei mitään) +STR_6708 :Tasoitusvoimakkuus +STR_6709 :Anna tasoitusvoimakkuus väliltä {COMMA16}-{COMMA16} ############# # Scenarios # From b8aa7dda2e979aa37bdf75568509973aa61be220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Fri, 18 Oct 2024 23:47:06 +0200 Subject: [PATCH 62/97] Be more verbose when setting artifact names --- .github/workflows/ci.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cdbab306f..43b8131534 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,10 +51,14 @@ jobs: - name: Git describe id: ghd run: | - TAG=$(git describe --abbrev=0 --tags) - DESCRIBE=$(git describe --tags) + TAG=$(git describe --abbrev=0) + DESCRIBE=$(git describe) SHORT_SHA=$(git rev-parse --short HEAD) DISTANCE=$(git rev-list --count $TAG..HEAD) + echo "tag=$TAG" + echo "describe=$DESCRIBE" + echo "short-sha=$SHORT_SHA" + echo "distance=$DISTANCE" echo "tag=$TAG" >> $GITHUB_OUTPUT echo "describe=$DESCRIBE" >> $GITHUB_OUTPUT echo "short-sha=$SHORT_SHA" >> $GITHUB_OUTPUT @@ -62,16 +66,19 @@ jobs: - name: Set env id: setenv run: | - . scripts/setenv -q + . scripts/setenv + echo "push=$OPENRCT2_PUSH" echo "push=$OPENRCT2_PUSH" >> $GITHUB_OUTPUT # Name is very similar to "describe", but skips the "v" prefix - name: Get artifact name id: artifact-name run: | if [ ${{ steps.ghd.outputs.distance }} -eq 0 ]; then + echo "name=${{ env.OPENRCT2_VERSION }}" echo "name=${{ env.OPENRCT2_VERSION }}" >> $GITHUB_OUTPUT else - echo "name=${{ env.OPENRCT2_VERSION }}-${{ steps.ghd.outputs.distance }}-${{ steps.ghd.outputs.short-sha }}" >> $GITHUB_OUTPUT + echo "name=${{ env.OPENRCT2_VERSION }}-${{ steps.ghd.outputs.distance }}-g${{ steps.ghd.outputs.short-sha }}" + echo "name=${{ env.OPENRCT2_VERSION }}-${{ steps.ghd.outputs.distance }}-g${{ steps.ghd.outputs.short-sha }}" >> $GITHUB_OUTPUT fi lint-commit: name: Lint Commit Message From 775a2982c7d08d2ee151f00514b8301427331fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 29 Oct 2024 00:32:47 +0100 Subject: [PATCH 63/97] Change binary name to include `git describe` --- .github/workflows/ci.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43b8131534..133b235baa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,17 +69,12 @@ jobs: . scripts/setenv echo "push=$OPENRCT2_PUSH" echo "push=$OPENRCT2_PUSH" >> $GITHUB_OUTPUT - # Name is very similar to "describe", but skips the "v" prefix + # Name now uses the same format as "describe" - name: Get artifact name id: artifact-name run: | - if [ ${{ steps.ghd.outputs.distance }} -eq 0 ]; then - echo "name=${{ env.OPENRCT2_VERSION }}" - echo "name=${{ env.OPENRCT2_VERSION }}" >> $GITHUB_OUTPUT - else - echo "name=${{ env.OPENRCT2_VERSION }}-${{ steps.ghd.outputs.distance }}-g${{ steps.ghd.outputs.short-sha }}" - echo "name=${{ env.OPENRCT2_VERSION }}-${{ steps.ghd.outputs.distance }}-g${{ steps.ghd.outputs.short-sha }}" >> $GITHUB_OUTPUT - fi + echo "name=${{ steps.ghd.outputs.describe }}" + echo "name=${{ steps.ghd.outputs.describe }}" >> $GITHUB_OUTPUT lint-commit: name: Lint Commit Message if: github.event_name == 'pull_request' From 9436a9501e7a0b61660861a3e321eb4f8a3e144c Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 29 Oct 2024 11:08:39 +0100 Subject: [PATCH 64/97] Move bitScanForward from Util.h to Numerics.hpp --- src/openrct2-ui/interface/ViewportQuery.cpp | 5 +- .../windows/EditorObjectSelection.cpp | 2 +- src/openrct2-ui/windows/ScenarioSelect.cpp | 2 +- src/openrct2-ui/windows/Staff.cpp | 2 +- src/openrct2/actions/TrackPlaceAction.cpp | 4 +- src/openrct2/core/Numerics.hpp | 48 +++++++++++++++++++ src/openrct2/entity/Guest.cpp | 6 +-- src/openrct2/entity/Staff.cpp | 4 +- src/openrct2/object/RideObject.cpp | 3 +- src/openrct2/peep/GuestPathfinding.cpp | 14 +++--- src/openrct2/ride/Ride.cpp | 4 +- src/openrct2/ride/TrackDesign.cpp | 3 +- src/openrct2/util/Util.h | 48 ------------------- src/openrct2/world/Footpath.cpp | 2 +- 14 files changed, 75 insertions(+), 72 deletions(-) diff --git a/src/openrct2-ui/interface/ViewportQuery.cpp b/src/openrct2-ui/interface/ViewportQuery.cpp index a143d67fc5..679b569c85 100644 --- a/src/openrct2-ui/interface/ViewportQuery.cpp +++ b/src/openrct2-ui/interface/ViewportQuery.cpp @@ -12,6 +12,7 @@ #include "Window.h" #include +#include #include #include #include @@ -150,7 +151,7 @@ namespace OpenRCT2::Ui uint32_t directions = (*tileElement)->AsEntrance()->GetDirections(); if (directions & 0x0F) { - int32_t bx = UtilBitScanForward(directions); + int32_t bx = Numerics::bitScanForward(directions); bx += (*tileElement)->AsEntrance()->GetDirection(); bx &= 3; if (direction != nullptr) @@ -167,7 +168,7 @@ namespace OpenRCT2::Ui uint32_t directions = (*tileElement)->AsEntrance()->GetDirections(); if (directions & 0x0F) { - int32_t bx = (*tileElement)->GetDirectionWithOffset(UtilBitScanForward(directions)); + int32_t bx = (*tileElement)->GetDirectionWithOffset(Numerics::bitScanForward(directions)); if (direction != nullptr) *direction = bx; return info.Loc; diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index fea0a1c252..05875a95af 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -890,7 +890,7 @@ namespace OpenRCT2::Ui::Windows if (numSourcesActive == 1) { widgets[WIDX_FILTER_DROPDOWN].text = STR_OBJECT_SELECTION_ONLY_STRINGID; - auto firstActiveSource = UtilBitScanForward(sources); + auto firstActiveSource = Numerics::bitScanForward(sources); ft.Add(kSourceStringIds[firstActiveSource]); } else diff --git a/src/openrct2-ui/windows/ScenarioSelect.cpp b/src/openrct2-ui/windows/ScenarioSelect.cpp index bdfda4915f..8c4ab4d378 100644 --- a/src/openrct2-ui/windows/ScenarioSelect.cpp +++ b/src/openrct2-ui/windows/ScenarioSelect.cpp @@ -717,7 +717,7 @@ namespace OpenRCT2::Ui::Windows } else { - int32_t firstPage = UtilBitScanForward(showPages); + int32_t firstPage = Numerics::bitScanForward(showPages); if (firstPage != -1) { selected_tab = firstPage; diff --git a/src/openrct2-ui/windows/Staff.cpp b/src/openrct2-ui/windows/Staff.cpp index 469c99b369..62ea364b92 100644 --- a/src/openrct2-ui/windows/Staff.cpp +++ b/src/openrct2-ui/windows/Staff.cpp @@ -883,7 +883,7 @@ namespace OpenRCT2::Ui::Windows } uint32_t staffOrders = staff->StaffOrders; - for (auto index = UtilBitScanForward(staffOrders); index != -1; index = UtilBitScanForward(staffOrders)) + for (auto index = Numerics::bitScanForward(staffOrders); index != -1; index = Numerics::bitScanForward(staffOrders)) { staffOrders &= ~(1 << index); SetCheckboxValue(WIDX_CHECKBOX_1 + index, true); diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index 4fcc2e39c6..500b21416d 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -640,8 +640,8 @@ GameActions::Result TrackPlaceAction::Execute() const { if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !gameState.Cheats.DisableClearanceChecks) { - for (int32_t chosenDirection = UtilBitScanForward(availableDirections); chosenDirection != -1; - chosenDirection = UtilBitScanForward(availableDirections)) + for (int32_t chosenDirection = Numerics::bitScanForward(availableDirections); chosenDirection != -1; + chosenDirection = Numerics::bitScanForward(availableDirections)) { availableDirections &= ~(1 << chosenDirection); CoordsXY tempLoc{ mapLoc.x, mapLoc.y }; diff --git a/src/openrct2/core/Numerics.hpp b/src/openrct2/core/Numerics.hpp index 87e523f81a..2a770a56d1 100644 --- a/src/openrct2/core/Numerics.hpp +++ b/src/openrct2/core/Numerics.hpp @@ -14,8 +14,56 @@ #include #include +#ifdef _MSC_VER +# include +#endif + namespace OpenRCT2::Numerics { + inline int32_t bitScanForward(uint32_t source) + { +#if defined(_MSC_VER) && (_MSC_VER >= 1400) // Visual Studio 2005 + unsigned long i; + uint8_t success = _BitScanForward(&i, source); + return success != 0 ? i : -1; +#elif defined(__GNUC__) + int32_t success = __builtin_ffs(source); + return success - 1; +#else +# pragma message("Falling back to iterative bitscan forward, consider using intrinsics") + // This is a low-hanging optimisation boost, check if your compiler offers + // any intrinsic. + // cf. https://github.com/OpenRCT2/OpenRCT2/pull/2093 + for (int32_t i = 0; i < 32; i++) + if (source & (1u << i)) + return i; + + return -1; +#endif + } + + inline int64_t bitScanForward(uint64_t source) + { +#if defined(_MSC_VER) && (_MSC_VER >= 1400) && defined(_M_X64) // Visual Studio 2005 + unsigned long i; + uint8_t success = _BitScanForward64(&i, source); + return success != 0 ? i : -1; +#elif defined(__GNUC__) + int32_t success = __builtin_ffsll(source); + return success - 1; +#else +# pragma message("Falling back to iterative bitscan forward, consider using intrinsics") + // This is a low-hanging optimisation boost, check if your compiler offers + // any intrinsic. + // cf. https://github.com/OpenRCT2/OpenRCT2/pull/2093 + for (int32_t i = 0; i < 64; i++) + if (source & (1uLL << i)) + return i; + + return -1; +#endif + } + /** * Bitwise left rotate * @tparam _UIntType unsigned integral type diff --git a/src/openrct2/entity/Guest.cpp b/src/openrct2/entity/Guest.cpp index 060601edb3..8950d68c9c 100644 --- a/src/openrct2/entity/Guest.cpp +++ b/src/openrct2/entity/Guest.cpp @@ -820,7 +820,7 @@ void Guest::UpdateConsumptionMotives() if (TimeToConsume == 0) { - int32_t chosen_food = UtilBitScanForward(GetFoodOrDrinkFlags()); + int32_t chosen_food = Numerics::bitScanForward(GetFoodOrDrinkFlags()); if (chosen_food != -1) { ShopItem food = ShopItem(chosen_food); @@ -1513,7 +1513,7 @@ bool Guest::DecideAndBuyItem(Ride& ride, const ShopItem shopItem, money64 price) const auto& shopItemDescriptor = GetShopItemDescriptor(shopItem); if (shopItemDescriptor.IsFoodOrDrink()) { - int32_t food = UtilBitScanForward(GetFoodOrDrinkFlags()); + int32_t food = Numerics::bitScanForward(GetFoodOrDrinkFlags()); if (food != -1) { InsertNewThought(PeepThoughtType::HaventFinished, static_cast(food)); @@ -5371,7 +5371,7 @@ void Guest::UpdateWalking() if ((!GetNextIsSurface()) && (static_cast(Id.ToUnderlying() & 0x1FF) == (currentTicks & 0x1FF)) && ((0xFFFF & ScenarioRand()) <= 4096)) { - int32_t container = UtilBitScanForward(GetEmptyContainerFlags()); + int32_t container = Numerics::bitScanForward(GetEmptyContainerFlags()); auto litterType = Litter::Type::Vomit; if (container != -1) diff --git a/src/openrct2/entity/Staff.cpp b/src/openrct2/entity/Staff.cpp index a496d9add6..5e5a6f82fb 100644 --- a/src/openrct2/entity/Staff.cpp +++ b/src/openrct2/entity/Staff.cpp @@ -683,7 +683,7 @@ Direction Staff::MechanicDirectionPath(uint8_t validDirections, PathElement* pat pathDirections |= (1 << DirectionReverse(PeepDirection)); } - Direction direction = UtilBitScanForward(pathDirections); + Direction direction = Numerics::bitScanForward(pathDirections); pathDirections &= ~(1 << direction); if (pathDirections == 0) { @@ -801,7 +801,7 @@ Direction Staff::DirectionPath(uint8_t validDirections, PathElement* pathElement pathDirections |= (1u << DirectionReverse(PeepDirection)); } - Direction direction = UtilBitScanForward(pathDirections); + Direction direction = Numerics::bitScanForward(pathDirections); // If this is the only direction they can go, then go if (pathDirections == (1u << direction)) { diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 5a96645fd8..11b734f86a 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -17,6 +17,7 @@ #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../core/Memory.hpp" +#include "../core/Numerics.hpp" #include "../core/String.hpp" #include "../drawing/Drawing.h" #include "../entity/Yaw.hpp" @@ -112,7 +113,7 @@ static constexpr SpritePrecision PrecisionFromNumFrames(uint32_t numRotationFram if (numRotationFrames == 0) return SpritePrecision::None; else - return static_cast(UtilBitScanForward(numRotationFrames) + 1); + return static_cast(Numerics::bitScanForward(numRotationFrames) + 1); } static void RideObjectUpdateRideType(RideObjectEntry& rideEntry) diff --git a/src/openrct2/peep/GuestPathfinding.cpp b/src/openrct2/peep/GuestPathfinding.cpp index 3bcbb584ca..be3b10f1de 100644 --- a/src/openrct2/peep/GuestPathfinding.cpp +++ b/src/openrct2/peep/GuestPathfinding.cpp @@ -602,7 +602,7 @@ namespace OpenRCT2::PathFinding uint32_t edges = path->GetEdges(); - int32_t testEdge = UtilBitScanForward(edges); + int32_t testEdge = Numerics::bitScanForward(edges); if (testEdge == -1) return false; @@ -627,7 +627,7 @@ namespace OpenRCT2::PathFinding break; } edges &= ~(1 << testEdge); - } while ((testEdge = UtilBitScanForward(edges)) != -1); + } while ((testEdge = Numerics::bitScanForward(edges)) != -1); return isThinJunction; } @@ -1008,7 +1008,7 @@ namespace OpenRCT2::PathFinding /* Remove the reverse edge (i.e. the edge back to the previous map element.) */ edges &= ~(1 << DirectionReverse(testEdge)); - int32_t nextTestEdge = UtilBitScanForward(edges); + int32_t nextTestEdge = Numerics::bitScanForward(edges); /* If there are no other edges the current search ends here. * Continue to the next map element without updating the parameters (best result so far). */ @@ -1205,7 +1205,7 @@ namespace OpenRCT2::PathFinding LogPathfinding( &peep, "Returned to %d,%d,%d; Steps: %u; edge: %d; Score: %d", loc.x >> 5, loc.y >> 5, loc.z, numSteps, nextTestEdge, *endScore); - } while ((nextTestEdge = UtilBitScanForward(edges)) != -1); + } while ((nextTestEdge = Numerics::bitScanForward(edges)) != -1); } while (!(tileElement++)->IsLastForTile()); @@ -1377,7 +1377,7 @@ namespace OpenRCT2::PathFinding if (edges == 0) return INVALID_DIRECTION; - int32_t chosenEdge = UtilBitScanForward(edges); + int32_t chosenEdge = Numerics::bitScanForward(edges); // Peep has multiple edges still to try. if (edges & ~(1 << chosenEdge)) @@ -1398,7 +1398,7 @@ namespace OpenRCT2::PathFinding * or for different edges with equal value, the edge with the * least steps (best_sub). */ int32_t numEdges = std::popcount(edges); - for (int32_t testEdge = chosenEdge; testEdge != -1; testEdge = UtilBitScanForward(edges)) + for (int32_t testEdge = chosenEdge; testEdge != -1; testEdge = Numerics::bitScanForward(edges)) { edges &= ~(1 << testEdge); uint8_t height = loc.z; @@ -1945,7 +1945,7 @@ namespace OpenRCT2::PathFinding edges &= ~(1 << direction); } - direction = UtilBitScanForward(edges); + direction = Numerics::bitScanForward(edges); // IF only one edge to choose from if ((edges & ~(1 << direction)) == 0) { diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 2099f08551..9262504fb2 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -1481,7 +1481,7 @@ static int32_t RideGetNewBreakdownProblem(const Ride& ride) int32_t breakdownProblem; while (problemBits != 0) { - breakdownProblem = UtilBitScanForward(problemBits); + breakdownProblem = Numerics::bitScanForward(problemBits); problemBits &= ~(1 << breakdownProblem); totalProbability += _breakdownProblemProbabilities[breakdownProblem]; } @@ -1495,7 +1495,7 @@ static int32_t RideGetNewBreakdownProblem(const Ride& ride) problemBits = availableBreakdownProblems; do { - breakdownProblem = UtilBitScanForward(problemBits); + breakdownProblem = Numerics::bitScanForward(problemBits); problemBits &= ~(1 << breakdownProblem); randomProbability -= _breakdownProblemProbabilities[breakdownProblem]; } while (randomProbability >= 0); diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 29f0832e5a..677965d7ff 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -888,7 +888,8 @@ static void TrackDesignMirrorMaze(TrackDesign& td) uint32_t mazeEntry = maze.mazeEntry; uint16_t newEntry = 0; - for (uint8_t position = UtilBitScanForward(mazeEntry); position != 0xFF; position = UtilBitScanForward(mazeEntry)) + for (uint8_t position = Numerics::bitScanForward(mazeEntry); position != 0xFF; + position = Numerics::bitScanForward(mazeEntry)) { mazeEntry &= ~(1 << position); newEntry |= (1 << maze_segment_mirror_map[position]); diff --git a/src/openrct2/util/Util.h b/src/openrct2/util/Util.h index c7db420d9a..3db5be95c2 100644 --- a/src/openrct2/util/Util.h +++ b/src/openrct2/util/Util.h @@ -19,10 +19,6 @@ #include #include -#ifdef _MSC_VER -# include -#endif - int32_t SquaredMetresToSquaredFeet(int32_t squaredMetres); int32_t MetresToFeet(int32_t metres); int32_t FeetToMetres(int32_t feet); @@ -35,50 +31,6 @@ int32_t ToHumanReadableSpeed(int32_t baseSpeed); uint16_t ToHumanReadableAirTime(uint16_t airTime); int32_t ToHumanReadableRideLength(int32_t rideLength); -inline int32_t UtilBitScanForward(uint32_t source) -{ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) // Visual Studio 2005 - unsigned long i; - uint8_t success = _BitScanForward(&i, source); - return success != 0 ? i : -1; -#elif defined(__GNUC__) - int32_t success = __builtin_ffs(source); - return success - 1; -#else -# pragma message("Falling back to iterative bitscan forward, consider using intrinsics") - // This is a low-hanging optimisation boost, check if your compiler offers - // any intrinsic. - // cf. https://github.com/OpenRCT2/OpenRCT2/pull/2093 - for (int32_t i = 0; i < 32; i++) - if (source & (1u << i)) - return i; - - return -1; -#endif -} - -inline int32_t UtilBitScanForward(uint64_t source) -{ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) && defined(_M_X64) // Visual Studio 2005 - unsigned long i; - uint8_t success = _BitScanForward64(&i, source); - return success != 0 ? i : -1; -#elif defined(__GNUC__) - int32_t success = __builtin_ffsll(source); - return success - 1; -#else -# pragma message("Falling back to iterative bitscan forward, consider using intrinsics") - // This is a low-hanging optimisation boost, check if your compiler offers - // any intrinsic. - // cf. https://github.com/OpenRCT2/OpenRCT2/pull/2093 - for (int32_t i = 0; i < 64; i++) - if (source & (1uLL << i)) - return i; - - return -1; -#endif -} - int32_t StrLogicalCmp(char const* a, char const* b); char* SafeStrCpy(char* destination, const char* source, size_t num); char* SafeStrCat(char* destination, const char* source, size_t size); diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index aca0df9433..cff8649020 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -1020,7 +1020,7 @@ static void FootpathFixOwnership(const CoordsXY& mapPos) static bool GetNextDirection(uint32_t edges, int32_t* direction) { - int32_t index = UtilBitScanForward(edges); + int32_t index = Numerics::bitScanForward(edges); if (index == -1) return false; From 4e27bac292ddff428d946a43044bb6768ccf9336 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 29 Oct 2024 11:16:26 +0100 Subject: [PATCH 65/97] Move Compression from Util into its own compilation unit --- src/openrct2/core/Compression.cpp | 176 ++++++++++++++++++++++++++++++ src/openrct2/core/Compression.h | 21 ++++ src/openrct2/core/OrcaStream.hpp | 7 +- src/openrct2/libopenrct2.vcxproj | 2 + src/openrct2/platform/Crash.cpp | 3 +- src/openrct2/util/Util.cpp | 157 -------------------------- src/openrct2/util/Util.h | 4 - 7 files changed, 205 insertions(+), 165 deletions(-) create mode 100644 src/openrct2/core/Compression.cpp create mode 100644 src/openrct2/core/Compression.h diff --git a/src/openrct2/core/Compression.cpp b/src/openrct2/core/Compression.cpp new file mode 100644 index 0000000000..23c5885a3e --- /dev/null +++ b/src/openrct2/core/Compression.cpp @@ -0,0 +1,176 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "Compression.h" + +#include "../Diagnostic.h" +#include "zlib.h" + +#include +#include +#include + +namespace OpenRCT2::Compression +{ + constexpr size_t CHUNK = 128 * 1024; + + // Compress the source to gzip-compatible stream, write to dest. + // Mainly used for compressing the crashdumps + bool gzipCompress(FILE* source, FILE* dest) + { + if (source == nullptr || dest == nullptr) + { + return false; + } + int ret, flush; + size_t have; + z_stream strm{}; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + unsigned char in[CHUNK]; + unsigned char out[CHUNK]; + int windowBits = 15; + int GZIP_ENCODING = 16; + ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits | GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + { + LOG_ERROR("Failed to initialise stream"); + return false; + } + do + { + strm.avail_in = uInt(fread(in, 1, CHUNK, source)); + if (ferror(source)) + { + deflateEnd(&strm); + LOG_ERROR("Failed to read data from source"); + return false; + } + flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; + strm.next_in = in; + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = deflate(&strm, flush); + if (ret == Z_STREAM_ERROR) + { + LOG_ERROR("Failed to compress data"); + return false; + } + have = CHUNK - strm.avail_out; + if (fwrite(out, 1, have, dest) != have || ferror(dest)) + { + deflateEnd(&strm); + LOG_ERROR("Failed to write data to destination"); + return false; + } + } while (strm.avail_out == 0); + } while (flush != Z_FINISH); + deflateEnd(&strm); + return true; + } + + std::vector gzip(const void* data, const size_t dataLen) + { + assert(data != nullptr); + + std::vector output; + z_stream strm{}; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + { + const auto ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + { + throw std::runtime_error("deflateInit2 failed with error " + std::to_string(ret)); + } + } + + int flush = 0; + const auto* src = static_cast(data); + size_t srcRemaining = dataLen; + do + { + const auto nextBlockSize = std::min(srcRemaining, CHUNK); + srcRemaining -= nextBlockSize; + + flush = srcRemaining == 0 ? Z_FINISH : Z_NO_FLUSH; + strm.avail_in = static_cast(nextBlockSize); + strm.next_in = const_cast(src); + do + { + output.resize(output.size() + nextBlockSize); + strm.avail_out = static_cast(nextBlockSize); + strm.next_out = &output[output.size() - nextBlockSize]; + const auto ret = deflate(&strm, flush); + if (ret == Z_STREAM_ERROR) + { + throw std::runtime_error("deflate failed with error " + std::to_string(ret)); + } + output.resize(output.size() - strm.avail_out); + } while (strm.avail_out == 0); + + src += nextBlockSize; + } while (flush != Z_FINISH); + deflateEnd(&strm); + return output; + } + + std::vector ungzip(const void* data, const size_t dataLen) + { + assert(data != nullptr); + + std::vector output; + z_stream strm{}; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + { + const auto ret = inflateInit2(&strm, 15 | 16); + if (ret != Z_OK) + { + throw std::runtime_error("inflateInit2 failed with error " + std::to_string(ret)); + } + } + + int flush = 0; + const auto* src = static_cast(data); + size_t srcRemaining = dataLen; + do + { + const auto nextBlockSize = std::min(srcRemaining, CHUNK); + srcRemaining -= nextBlockSize; + + flush = srcRemaining == 0 ? Z_FINISH : Z_NO_FLUSH; + strm.avail_in = static_cast(nextBlockSize); + strm.next_in = const_cast(src); + do + { + output.resize(output.size() + nextBlockSize); + strm.avail_out = static_cast(nextBlockSize); + strm.next_out = &output[output.size() - nextBlockSize]; + const auto ret = inflate(&strm, flush); + if (ret == Z_STREAM_ERROR) + { + throw std::runtime_error("deflate failed with error " + std::to_string(ret)); + } + output.resize(output.size() - strm.avail_out); + } while (strm.avail_out == 0); + + src += nextBlockSize; + } while (flush != Z_FINISH); + inflateEnd(&strm); + return output; + } +} // namespace OpenRCT2::Compression diff --git a/src/openrct2/core/Compression.h b/src/openrct2/core/Compression.h new file mode 100644 index 0000000000..999d05db9b --- /dev/null +++ b/src/openrct2/core/Compression.h @@ -0,0 +1,21 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace OpenRCT2::Compression +{ + bool gzipCompress(FILE* source, FILE* dest); + std::vector gzip(const void* data, const size_t dataLen); + std::vector ungzip(const void* data, const size_t dataLen); +} // namespace OpenRCT2::Compression diff --git a/src/openrct2/core/OrcaStream.hpp b/src/openrct2/core/OrcaStream.hpp index 3a54b81039..257c8952a5 100644 --- a/src/openrct2/core/OrcaStream.hpp +++ b/src/openrct2/core/OrcaStream.hpp @@ -9,7 +9,7 @@ #pragma once -#include "../util/Util.h" +#include "../core/Compression.h" #include "../world/Location.hpp" #include "Crypt.h" #include "FileStream.h" @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -99,7 +100,7 @@ namespace OpenRCT2 // Uncompress if (_header.Compression == COMPRESSION_GZIP) { - auto uncompressedData = Ungzip(_buffer.GetData(), _buffer.GetLength()); + auto uncompressedData = Compression::ungzip(_buffer.GetData(), _buffer.GetLength()); if (_header.UncompressedSize != uncompressedData.size()) { // Warning? @@ -135,7 +136,7 @@ namespace OpenRCT2 std::optional> compressedBytes; if (_header.Compression == COMPRESSION_GZIP) { - compressedBytes = Gzip(uncompressedData, uncompressedSize); + compressedBytes = Compression::gzip(uncompressedData, uncompressedSize); if (compressedBytes) { _header.CompressedSize = compressedBytes->size(); diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 74ea55ec6e..c1268858a1 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -186,6 +186,7 @@ + @@ -745,6 +746,7 @@ + diff --git a/src/openrct2/platform/Crash.cpp b/src/openrct2/platform/Crash.cpp index f5a0add067..6fb17cbdde 100644 --- a/src/openrct2/platform/Crash.cpp +++ b/src/openrct2/platform/Crash.cpp @@ -31,6 +31,7 @@ # include "../PlatformEnvironment.h" # include "../Version.h" # include "../config/Config.h" +# include "../core/Compression.h" # include "../core/Console.hpp" # include "../core/Guard.hpp" # include "../core/Path.hpp" @@ -139,7 +140,7 @@ static bool OnCrash( FILE* input = _wfopen(dumpFilePath, L"rb"); FILE* dest = _wfopen(dumpFilePathGZIP, L"wb"); - if (UtilGzipCompress(input, dest)) + if (Compression::gzipCompress(input, dest)) { // TODO: enable upload of gzip-compressed dumps once supported on // backtrace.io (uncomment the line below). For now leave compression diff --git a/src/openrct2/util/Util.cpp b/src/openrct2/util/Util.cpp index 0ac29fe1ef..b82533016b 100644 --- a/src/openrct2/util/Util.cpp +++ b/src/openrct2/util/Util.cpp @@ -16,7 +16,6 @@ #include "../interface/Window.h" #include "../platform/Platform.h" #include "../scenes/title/TitleScene.h" -#include "zlib.h" #include #include @@ -225,162 +224,6 @@ float UtilRandNormalDistributed() return _distributor(_prng); } -constexpr size_t CHUNK = 128 * 1024; - -// Compress the source to gzip-compatible stream, write to dest. -// Mainly used for compressing the crashdumps -bool UtilGzipCompress(FILE* source, FILE* dest) -{ - if (source == nullptr || dest == nullptr) - { - return false; - } - int ret, flush; - size_t have; - z_stream strm{}; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - int windowBits = 15; - int GZIP_ENCODING = 16; - ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits | GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY); - if (ret != Z_OK) - { - LOG_ERROR("Failed to initialise stream"); - return false; - } - do - { - strm.avail_in = uInt(fread(in, 1, CHUNK, source)); - if (ferror(source)) - { - deflateEnd(&strm); - LOG_ERROR("Failed to read data from source"); - return false; - } - flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; - strm.next_in = in; - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = deflate(&strm, flush); - if (ret == Z_STREAM_ERROR) - { - LOG_ERROR("Failed to compress data"); - return false; - } - have = CHUNK - strm.avail_out; - if (fwrite(out, 1, have, dest) != have || ferror(dest)) - { - deflateEnd(&strm); - LOG_ERROR("Failed to write data to destination"); - return false; - } - } while (strm.avail_out == 0); - } while (flush != Z_FINISH); - deflateEnd(&strm); - return true; -} - -std::vector Gzip(const void* data, const size_t dataLen) -{ - assert(data != nullptr); - - std::vector output; - z_stream strm{}; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - - { - const auto ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY); - if (ret != Z_OK) - { - throw std::runtime_error("deflateInit2 failed with error " + std::to_string(ret)); - } - } - - int flush = 0; - const auto* src = static_cast(data); - size_t srcRemaining = dataLen; - do - { - const auto nextBlockSize = std::min(srcRemaining, CHUNK); - srcRemaining -= nextBlockSize; - - flush = srcRemaining == 0 ? Z_FINISH : Z_NO_FLUSH; - strm.avail_in = static_cast(nextBlockSize); - strm.next_in = const_cast(src); - do - { - output.resize(output.size() + nextBlockSize); - strm.avail_out = static_cast(nextBlockSize); - strm.next_out = &output[output.size() - nextBlockSize]; - const auto ret = deflate(&strm, flush); - if (ret == Z_STREAM_ERROR) - { - throw std::runtime_error("deflate failed with error " + std::to_string(ret)); - } - output.resize(output.size() - strm.avail_out); - } while (strm.avail_out == 0); - - src += nextBlockSize; - } while (flush != Z_FINISH); - deflateEnd(&strm); - return output; -} - -std::vector Ungzip(const void* data, const size_t dataLen) -{ - assert(data != nullptr); - - std::vector output; - z_stream strm{}; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - - { - const auto ret = inflateInit2(&strm, 15 | 16); - if (ret != Z_OK) - { - throw std::runtime_error("inflateInit2 failed with error " + std::to_string(ret)); - } - } - - int flush = 0; - const auto* src = static_cast(data); - size_t srcRemaining = dataLen; - do - { - const auto nextBlockSize = std::min(srcRemaining, CHUNK); - srcRemaining -= nextBlockSize; - - flush = srcRemaining == 0 ? Z_FINISH : Z_NO_FLUSH; - strm.avail_in = static_cast(nextBlockSize); - strm.next_in = const_cast(src); - do - { - output.resize(output.size() + nextBlockSize); - strm.avail_out = static_cast(nextBlockSize); - strm.next_out = &output[output.size() - nextBlockSize]; - const auto ret = inflate(&strm, flush); - if (ret == Z_STREAM_ERROR) - { - throw std::runtime_error("deflate failed with error " + std::to_string(ret)); - } - output.resize(output.size() - strm.avail_out); - } while (strm.avail_out == 0); - - src += nextBlockSize; - } while (flush != Z_FINISH); - inflateEnd(&strm); - return output; -} - uint8_t Lerp(uint8_t a, uint8_t b, float t) { if (t <= 0) diff --git a/src/openrct2/util/Util.h b/src/openrct2/util/Util.h index 3db5be95c2..94bea63235 100644 --- a/src/openrct2/util/Util.h +++ b/src/openrct2/util/Util.h @@ -38,10 +38,6 @@ char* SafeStrCat(char* destination, const char* source, size_t size); uint32_t UtilRand(); float UtilRandNormalDistributed(); -bool UtilGzipCompress(FILE* source, FILE* dest); -std::vector Gzip(const void* data, const size_t dataLen); -std::vector Ungzip(const void* data, const size_t dataLen); - template constexpr T AddClamp(T value, T valueToAdd) { From ece199176e1db93f97d55c33edec339c6e9bcfec Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 29 Oct 2024 11:27:00 +0100 Subject: [PATCH 66/97] Move UnitConversion from Util into its own compilation unit --- src/openrct2-ui/windows/InstallTrack.cpp | 2 +- src/openrct2-ui/windows/MapGen.cpp | 2 +- src/openrct2-ui/windows/Park.cpp | 2 +- src/openrct2-ui/windows/Ride.cpp | 1 + src/openrct2-ui/windows/TrackList.cpp | 1 + src/openrct2/core/UnitConversion.cpp | 78 +++++++++++++++++++ src/openrct2/core/UnitConversion.h | 27 +++++++ src/openrct2/libopenrct2.vcxproj | 2 + src/openrct2/localisation/Formatting.cpp | 2 +- src/openrct2/ride/RideRatings.cpp | 1 + src/openrct2/ride/TrackDesign.cpp | 1 + src/openrct2/scenario/Scenario.cpp | 1 + .../scripting/bindings/ride/ScRide.cpp | 1 + src/openrct2/util/Util.cpp | 65 ---------------- src/openrct2/util/Util.h | 12 --- 15 files changed, 117 insertions(+), 81 deletions(-) create mode 100644 src/openrct2/core/UnitConversion.cpp create mode 100644 src/openrct2/core/UnitConversion.h diff --git a/src/openrct2-ui/windows/InstallTrack.cpp b/src/openrct2-ui/windows/InstallTrack.cpp index ac0dc485ff..6636334a91 100644 --- a/src/openrct2-ui/windows/InstallTrack.cpp +++ b/src/openrct2-ui/windows/InstallTrack.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/src/openrct2-ui/windows/MapGen.cpp b/src/openrct2-ui/windows/MapGen.cpp index bfc7dc89a7..0fd661cb60 100644 --- a/src/openrct2-ui/windows/MapGen.cpp +++ b/src/openrct2-ui/windows/MapGen.cpp @@ -16,13 +16,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include diff --git a/src/openrct2-ui/windows/Park.cpp b/src/openrct2-ui/windows/Park.cpp index cc951ae8a6..d238b16a40 100644 --- a/src/openrct2-ui/windows/Park.cpp +++ b/src/openrct2-ui/windows/Park.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include #include namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 90038c6eed..7825032de6 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/src/openrct2-ui/windows/TrackList.cpp b/src/openrct2-ui/windows/TrackList.cpp index 30da441681..60ef169386 100644 --- a/src/openrct2-ui/windows/TrackList.cpp +++ b/src/openrct2-ui/windows/TrackList.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/src/openrct2/core/UnitConversion.cpp b/src/openrct2/core/UnitConversion.cpp new file mode 100644 index 0000000000..2dcaf979ec --- /dev/null +++ b/src/openrct2/core/UnitConversion.cpp @@ -0,0 +1,78 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "UnitConversion.h" + +namespace OpenRCT2 +{ + int32_t SquaredMetresToSquaredFeet(int32_t squaredMetres) + { + // 1 metre squared = 10.7639104 feet squared + // RCT2 approximates as 11 + return squaredMetres * 11; + } + + int32_t MetresToFeet(int32_t metres) + { + // 1 metre = 3.2808399 feet + // RCT2 approximates as 3.28125 + return (metres * 840) / 256; + } + + int32_t FeetToMetres(int32_t feet) + { + return feet * 256 / 840; + } + + int32_t MphToKmph(int32_t mph) + { + // 1 mph = 1.60934 kmph + // RCT2 approximates as 1.609375 + return (mph * 1648) >> 10; + } + + int32_t MphToDmps(int32_t mph) + { + // 1 mph = 4.4704 decimeters/s + return (mph * 73243) >> 14; + } + + int32_t BaseZToMetres(int16_t baseZ) + { + return (baseZ / 2 - 7) * 1.5; + } + + uint8_t MetresToBaseZ(int16_t metres) + { + return ((metres / 1.5) + 7) * 2; + } + + int32_t HeightUnitsToMetres(int32_t heightUnit) + { + // 1 unit = 0.75 metres + return (heightUnit * 3) >> 2; + } + + int32_t ToHumanReadableSpeed(int32_t baseSpeed) + { + // Divide this value by 29127 to get the human-readable max speed + // (in RCT2, display_speed = (max_speed * 9) >> 18) + return (baseSpeed * 9) >> 18; + } + + uint16_t ToHumanReadableAirTime(uint16_t airTime) + { + return airTime * 3; + } + + int32_t ToHumanReadableRideLength(int32_t rideLength) + { + return rideLength >> 16; + } +} // namespace OpenRCT2 diff --git a/src/openrct2/core/UnitConversion.h b/src/openrct2/core/UnitConversion.h new file mode 100644 index 0000000000..89614ff0a0 --- /dev/null +++ b/src/openrct2/core/UnitConversion.h @@ -0,0 +1,27 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include + +namespace OpenRCT2 +{ + int32_t SquaredMetresToSquaredFeet(int32_t squaredMetres); + int32_t MetresToFeet(int32_t metres); + int32_t FeetToMetres(int32_t feet); + int32_t MphToKmph(int32_t mph); + int32_t MphToDmps(int32_t mph); + int32_t BaseZToMetres(int16_t baseZ); + uint8_t MetresToBaseZ(int16_t metres); + int32_t HeightUnitsToMetres(int32_t heightUnit); + int32_t ToHumanReadableSpeed(int32_t baseSpeed); + uint16_t ToHumanReadableAirTime(uint16_t airTime); + int32_t ToHumanReadableRideLength(int32_t rideLength); +} // namespace OpenRCT2 diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index c1268858a1..95e2371cd2 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -232,6 +232,7 @@ + @@ -771,6 +772,7 @@ + diff --git a/src/openrct2/localisation/Formatting.cpp b/src/openrct2/localisation/Formatting.cpp index 10cc645550..0002d55fca 100644 --- a/src/openrct2/localisation/Formatting.cpp +++ b/src/openrct2/localisation/Formatting.cpp @@ -13,9 +13,9 @@ #include "../Diagnostic.h" #include "../config/Config.h" #include "../core/String.hpp" +#include "../core/UnitConversion.h" #include "../object/ObjectManager.h" #include "../object/PeepNamesObject.h" -#include "../util/Util.h" #include "Currency.h" #include "FormatCodes.h" #include "Formatter.h" diff --git a/src/openrct2/ride/RideRatings.cpp b/src/openrct2/ride/RideRatings.cpp index 20226b1a4c..2a0a4e2540 100644 --- a/src/openrct2/ride/RideRatings.cpp +++ b/src/openrct2/ride/RideRatings.cpp @@ -13,6 +13,7 @@ #include "../Context.h" #include "../GameState.h" #include "../OpenRCT2.h" +#include "../core/UnitConversion.h" #include "../interface/Window.h" #include "../localisation/Localisation.Date.h" #include "../profiling/Profiling.h" diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 677965d7ff..118283752a 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -35,6 +35,7 @@ #include "../core/File.h" #include "../core/Numerics.hpp" #include "../core/String.hpp" +#include "../core/UnitConversion.h" #include "../drawing/X8DrawingEngine.h" #include "../interface/Viewport.h" #include "../localisation/StringIds.h" diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index 5500175e3b..c99959915f 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -24,6 +24,7 @@ #include "../core/Guard.hpp" #include "../core/Path.hpp" #include "../core/Random.hpp" +#include "../core/UnitConversion.h" #include "../entity/Duck.h" #include "../entity/Guest.h" #include "../entity/Staff.h" diff --git a/src/openrct2/scripting/bindings/ride/ScRide.cpp b/src/openrct2/scripting/bindings/ride/ScRide.cpp index e50dda64a0..60566ead32 100644 --- a/src/openrct2/scripting/bindings/ride/ScRide.cpp +++ b/src/openrct2/scripting/bindings/ride/ScRide.cpp @@ -12,6 +12,7 @@ # include "ScRide.hpp" # include "../../../Context.h" +# include "../../../core/UnitConversion.h" # include "../../../ride/Ride.h" # include "../../../ride/RideData.h" # include "../../Duktape.hpp" diff --git a/src/openrct2/util/Util.cpp b/src/openrct2/util/Util.cpp index b82533016b..d6d24ac6ed 100644 --- a/src/openrct2/util/Util.cpp +++ b/src/openrct2/util/Util.cpp @@ -24,71 +24,6 @@ #include #include -int32_t SquaredMetresToSquaredFeet(int32_t squaredMetres) -{ - // 1 metre squared = 10.7639104 feet squared - // RCT2 approximates as 11 - return squaredMetres * 11; -} - -int32_t MetresToFeet(int32_t metres) -{ - // 1 metre = 3.2808399 feet - // RCT2 approximates as 3.28125 - return (metres * 840) / 256; -} - -int32_t FeetToMetres(int32_t feet) -{ - return feet * 256 / 840; -} - -int32_t MphToKmph(int32_t mph) -{ - // 1 mph = 1.60934 kmph - // RCT2 approximates as 1.609375 - return (mph * 1648) >> 10; -} - -int32_t MphToDmps(int32_t mph) -{ - // 1 mph = 4.4704 decimeters/s - return (mph * 73243) >> 14; -} - -int32_t BaseZToMetres(int16_t baseZ) -{ - return (baseZ / 2 - 7) * 1.5; -} - -uint8_t MetresToBaseZ(int16_t metres) -{ - return ((metres / 1.5) + 7) * 2; -} - -int32_t HeightUnitsToMetres(int32_t heightUnit) -{ - // 1 unit = 0.75 metres - return (heightUnit * 3) >> 2; -} - -int32_t ToHumanReadableSpeed(int32_t baseSpeed) -{ - // Divide this value by 29127 to get the human-readable max speed - // (in RCT2, display_speed = (max_speed * 9) >> 18) - return (baseSpeed * 9) >> 18; -} - -uint16_t ToHumanReadableAirTime(uint16_t airTime) -{ - return airTime * 3; -} - -int32_t ToHumanReadableRideLength(int32_t rideLength) -{ - return rideLength >> 16; -} - /* Case insensitive logical compare */ // Example: // - Guest 10 diff --git a/src/openrct2/util/Util.h b/src/openrct2/util/Util.h index 94bea63235..e4fff3a7bb 100644 --- a/src/openrct2/util/Util.h +++ b/src/openrct2/util/Util.h @@ -19,18 +19,6 @@ #include #include -int32_t SquaredMetresToSquaredFeet(int32_t squaredMetres); -int32_t MetresToFeet(int32_t metres); -int32_t FeetToMetres(int32_t feet); -int32_t MphToKmph(int32_t mph); -int32_t MphToDmps(int32_t mph); -int32_t BaseZToMetres(int16_t baseZ); -uint8_t MetresToBaseZ(int16_t metres); -int32_t HeightUnitsToMetres(int32_t heightUnit); -int32_t ToHumanReadableSpeed(int32_t baseSpeed); -uint16_t ToHumanReadableAirTime(uint16_t airTime); -int32_t ToHumanReadableRideLength(int32_t rideLength); - int32_t StrLogicalCmp(char const* a, char const* b); char* SafeStrCpy(char* destination, const char* source, size_t num); char* SafeStrCat(char* destination, const char* source, size_t size); From 43be4d1d924c2367049e40859a09ef2e487c6a1e Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 29 Oct 2024 13:12:25 +0100 Subject: [PATCH 67/97] Remove dependency on Drawing.h from Climate.h --- src/openrct2/world/Climate.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/openrct2/world/Climate.h b/src/openrct2/world/Climate.h index d8bb1354df..5d7860d249 100644 --- a/src/openrct2/world/Climate.h +++ b/src/openrct2/world/Climate.h @@ -9,8 +9,8 @@ #pragma once -#include "../drawing/Drawing.h" #include "../util/Util.h" +#include enum class ClimateType : uint8_t { @@ -78,6 +78,8 @@ void ClimateUpdateSound(); void ClimateStopWeatherSound(); void ClimateForceWeather(WeatherType weather); +enum class FilterPaletteID : int32_t; + bool ClimateIsRaining(); bool ClimateIsSnowing(); bool ClimateIsSnowingHeavily(); From d2e01dde4e7c061d3f4b9acab1feb01bcb8a8240 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 29 Oct 2024 13:12:52 +0100 Subject: [PATCH 68/97] Remove a bunch of Util.h includes --- src/openrct2-ui/ride/Construction.h | 1 + src/openrct2/Cheats.cpp | 1 - src/openrct2/CommandLineSprite.cpp | 1 - src/openrct2/Context.cpp | 1 - src/openrct2/actions/BannerSetStyleAction.cpp | 1 - src/openrct2/actions/NetworkModifyGroupAction.cpp | 1 - src/openrct2/actions/PeepPickupAction.cpp | 1 - src/openrct2/actions/ScenarioSetSettingAction.cpp | 1 - src/openrct2/actions/TrackRemoveAction.cpp | 1 - src/openrct2/entity/Balloon.cpp | 1 - src/openrct2/entity/Peep.h | 2 +- src/openrct2/entity/Staff.h | 1 + src/openrct2/management/NewsItem.cpp | 1 - src/openrct2/network/NetworkServerAdvertiser.cpp | 1 - src/openrct2/object/Object.h | 1 - src/openrct2/object/StringTable.cpp | 1 + src/openrct2/object/TerrainSurfaceObject.h | 1 + src/openrct2/peep/GuestPathfinding.cpp | 1 - src/openrct2/peep/PeepAnimationData.h | 1 + src/openrct2/platform/Crash.cpp | 1 - src/openrct2/platform/Platform.Posix.cpp | 1 - src/openrct2/ride/CableLift.cpp | 1 - src/openrct2/ride/RideConstruction.cpp | 1 - src/openrct2/ride/ShopItem.h | 2 +- src/openrct2/ride/Track.cpp | 1 - src/openrct2/ride/TrackData.cpp | 1 + src/openrct2/ride/TrackDesignRepository.cpp | 1 - src/openrct2/ride/TrackDesignSave.cpp | 1 - src/openrct2/ride/VehicleSubpositionData.h | 1 + src/openrct2/world/Climate.h | 1 - src/openrct2/world/Footpath.cpp | 1 - src/openrct2/world/MapGen.cpp | 1 - 32 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/openrct2-ui/ride/Construction.h b/src/openrct2-ui/ride/Construction.h index 9ffdd9cdc7..42d2f347c1 100644 --- a/src/openrct2-ui/ride/Construction.h +++ b/src/openrct2-ui/ride/Construction.h @@ -11,6 +11,7 @@ #include #include +#include namespace OpenRCT2 { diff --git a/src/openrct2/Cheats.cpp b/src/openrct2/Cheats.cpp index c0f94c984e..5a3d0a237d 100644 --- a/src/openrct2/Cheats.cpp +++ b/src/openrct2/Cheats.cpp @@ -16,7 +16,6 @@ #include "network/network.h" #include "ride/Ride.h" #include "scenario/Scenario.h" -#include "util/Util.h" #include "world/Climate.h" #include "world/Footpath.h" #include "world/Map.h" diff --git a/src/openrct2/CommandLineSprite.cpp b/src/openrct2/CommandLineSprite.cpp index 3fb3d96830..9bd58d2566 100644 --- a/src/openrct2/CommandLineSprite.cpp +++ b/src/openrct2/CommandLineSprite.cpp @@ -22,7 +22,6 @@ #include "object/ObjectLimits.h" #include "object/ObjectManager.h" #include "object/ObjectRepository.h" -#include "util/Util.h" #include #include diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 9eff422afe..d19f79c02c 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -74,7 +74,6 @@ #include "scripting/ScriptEngine.h" #include "ui/UiContext.h" #include "ui/WindowManager.h" -#include "util/Util.h" #include "world/Park.h" #include diff --git a/src/openrct2/actions/BannerSetStyleAction.cpp b/src/openrct2/actions/BannerSetStyleAction.cpp index eaf2c9ca8d..5d23331a76 100644 --- a/src/openrct2/actions/BannerSetStyleAction.cpp +++ b/src/openrct2/actions/BannerSetStyleAction.cpp @@ -12,7 +12,6 @@ #include "../Context.h" #include "../Diagnostic.h" #include "../management/Finance.h" -#include "../util/Util.h" #include "../windows/Intent.h" #include "../world/Banner.h" #include "../world/tile_element/BannerElement.h" diff --git a/src/openrct2/actions/NetworkModifyGroupAction.cpp b/src/openrct2/actions/NetworkModifyGroupAction.cpp index d0ea39590c..b959e440b8 100644 --- a/src/openrct2/actions/NetworkModifyGroupAction.cpp +++ b/src/openrct2/actions/NetworkModifyGroupAction.cpp @@ -10,7 +10,6 @@ #include "NetworkModifyGroupAction.h" #include "../network/network.h" -#include "../util/Util.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/PeepPickupAction.cpp b/src/openrct2/actions/PeepPickupAction.cpp index f51675278b..b4ca9e897e 100644 --- a/src/openrct2/actions/PeepPickupAction.cpp +++ b/src/openrct2/actions/PeepPickupAction.cpp @@ -14,7 +14,6 @@ #include "../entity/EntityRegistry.h" #include "../entity/Peep.h" #include "../network/network.h" -#include "../util/Util.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/ScenarioSetSettingAction.cpp b/src/openrct2/actions/ScenarioSetSettingAction.cpp index fccd3b6305..a1dd6f7479 100644 --- a/src/openrct2/actions/ScenarioSetSettingAction.cpp +++ b/src/openrct2/actions/ScenarioSetSettingAction.cpp @@ -16,7 +16,6 @@ #include "../interface/Window.h" #include "../management/Finance.h" #include "../scenario/Scenario.h" -#include "../util/Util.h" #include "../world/Park.h" using namespace OpenRCT2; diff --git a/src/openrct2/actions/TrackRemoveAction.cpp b/src/openrct2/actions/TrackRemoveAction.cpp index d3ec9ef4c9..59e21498bf 100644 --- a/src/openrct2/actions/TrackRemoveAction.cpp +++ b/src/openrct2/actions/TrackRemoveAction.cpp @@ -16,7 +16,6 @@ #include "../ride/Track.h" #include "../ride/TrackData.h" #include "../ride/TrackDesign.h" -#include "../util/Util.h" #include "../world/Footpath.h" #include "../world/MapAnimation.h" #include "../world/tile_element/SurfaceElement.h" diff --git a/src/openrct2/entity/Balloon.cpp b/src/openrct2/entity/Balloon.cpp index 8d55d2047e..27145b92da 100644 --- a/src/openrct2/entity/Balloon.cpp +++ b/src/openrct2/entity/Balloon.cpp @@ -16,7 +16,6 @@ #include "../paint/Paint.h" #include "../profiling/Profiling.h" #include "../scenario/Scenario.h" -#include "../util/Util.h" #include "../world/tile_element/TrackElement.h" #include "EntityRegistry.h" diff --git a/src/openrct2/entity/Peep.h b/src/openrct2/entity/Peep.h index 35a7d84842..517961c5ca 100644 --- a/src/openrct2/entity/Peep.h +++ b/src/openrct2/entity/Peep.h @@ -14,11 +14,11 @@ #include "../localisation/StringIdType.h" #include "../ride/RideTypes.h" #include "../ride/Station.h" -#include "../util/Util.h" #include "../world/Location.hpp" #include #include +#include constexpr uint8_t kPeepMinEnergy = 32; constexpr uint8_t kPeepMaxEnergy = 128; diff --git a/src/openrct2/entity/Staff.h b/src/openrct2/entity/Staff.h index 1831002e8a..4e0cfdea5d 100644 --- a/src/openrct2/entity/Staff.h +++ b/src/openrct2/entity/Staff.h @@ -9,6 +9,7 @@ #pragma once +#include "../util/Util.h" #include "../world/Map.h" #include "Peep.h" diff --git a/src/openrct2/management/NewsItem.cpp b/src/openrct2/management/NewsItem.cpp index 85614b46a4..b0b58ef38b 100644 --- a/src/openrct2/management/NewsItem.cpp +++ b/src/openrct2/management/NewsItem.cpp @@ -26,7 +26,6 @@ #include "../profiling/Profiling.h" #include "../ride/Ride.h" #include "../ride/Vehicle.h" -#include "../util/Util.h" #include "../windows/Intent.h" #include "../world/Location.hpp" diff --git a/src/openrct2/network/NetworkServerAdvertiser.cpp b/src/openrct2/network/NetworkServerAdvertiser.cpp index f6ae41364d..e45bfa333f 100644 --- a/src/openrct2/network/NetworkServerAdvertiser.cpp +++ b/src/openrct2/network/NetworkServerAdvertiser.cpp @@ -23,7 +23,6 @@ # include "../localisation/Localisation.Date.h" # include "../management/Finance.h" # include "../platform/Platform.h" -# include "../util/Util.h" # include "../world/Map.h" # include "../world/Park.h" # include "Socket.h" diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index 367fd4701e..ed2005bac9 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -12,7 +12,6 @@ #include "../core/JsonFwd.hpp" #include "../core/StringTypes.h" #include "../drawing/ImageIndexType.h" -#include "../util/Util.h" #include "ImageTable.h" #include "ObjectAsset.h" #include "ObjectTypes.h" diff --git a/src/openrct2/object/StringTable.cpp b/src/openrct2/object/StringTable.cpp index 13eb669c22..db3c6310d5 100644 --- a/src/openrct2/object/StringTable.cpp +++ b/src/openrct2/object/StringTable.cpp @@ -16,6 +16,7 @@ #include "../core/String.hpp" #include "../localisation/LocalisationService.h" #include "../rct12/CSStringConverter.h" +#include "../util/Util.h" #include "Object.h" using namespace OpenRCT2; diff --git a/src/openrct2/object/TerrainSurfaceObject.h b/src/openrct2/object/TerrainSurfaceObject.h index 9b06c21855..1cfb4b5a87 100644 --- a/src/openrct2/object/TerrainSurfaceObject.h +++ b/src/openrct2/object/TerrainSurfaceObject.h @@ -9,6 +9,7 @@ #pragma once +#include "../core/Money.hpp" #include "Object.h" struct CoordsXY; diff --git a/src/openrct2/peep/GuestPathfinding.cpp b/src/openrct2/peep/GuestPathfinding.cpp index be3b10f1de..77e1652548 100644 --- a/src/openrct2/peep/GuestPathfinding.cpp +++ b/src/openrct2/peep/GuestPathfinding.cpp @@ -19,7 +19,6 @@ #include "../ride/Station.h" #include "../ride/Track.h" #include "../scenario/Scenario.h" -#include "../util/Util.h" #include "../world/Entrance.h" #include "../world/Footpath.h" #include "../world/tile_element/BannerElement.h" diff --git a/src/openrct2/peep/PeepAnimationData.h b/src/openrct2/peep/PeepAnimationData.h index c944a38631..3dadeb678d 100644 --- a/src/openrct2/peep/PeepAnimationData.h +++ b/src/openrct2/peep/PeepAnimationData.h @@ -1,6 +1,7 @@ #pragma once #include "../entity/Peep.h" +#include "../util/Util.h" #include diff --git a/src/openrct2/platform/Crash.cpp b/src/openrct2/platform/Crash.cpp index 6fb17cbdde..b999eeb3de 100644 --- a/src/openrct2/platform/Crash.cpp +++ b/src/openrct2/platform/Crash.cpp @@ -43,7 +43,6 @@ # include "../park/ParkFile.h" # include "../scenario/Scenario.h" # include "../util/SawyerCoding.h" -# include "../util/Util.h" # include "Platform.h" # define WSZ(x) L"" x diff --git a/src/openrct2/platform/Platform.Posix.cpp b/src/openrct2/platform/Platform.Posix.cpp index 40db7f6f0c..f56fc144bd 100644 --- a/src/openrct2/platform/Platform.Posix.cpp +++ b/src/openrct2/platform/Platform.Posix.cpp @@ -16,7 +16,6 @@ # include "../core/Memory.hpp" # include "../core/Path.hpp" # include "../core/String.hpp" -# include "../util/Util.h" # include # include diff --git a/src/openrct2/ride/CableLift.cpp b/src/openrct2/ride/CableLift.cpp index 6dd960b5d3..a91c1c93eb 100644 --- a/src/openrct2/ride/CableLift.cpp +++ b/src/openrct2/ride/CableLift.cpp @@ -12,7 +12,6 @@ #include "../audio/audio.h" #include "../entity/EntityList.h" #include "../rct12/RCT12.h" -#include "../util/Util.h" #include "../world/tile_element/TileElement.h" #include "../world/tile_element/TrackElement.h" #include "Ride.h" diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp index f5f57f7e5f..d310e5c3f1 100644 --- a/src/openrct2/ride/RideConstruction.cpp +++ b/src/openrct2/ride/RideConstruction.cpp @@ -28,7 +28,6 @@ #include "../network/network.h" #include "../ui/UiContext.h" #include "../ui/WindowManager.h" -#include "../util/Util.h" #include "../windows/Intent.h" #include "../world/Banner.h" #include "../world/Climate.h" diff --git a/src/openrct2/ride/ShopItem.h b/src/openrct2/ride/ShopItem.h index 23c706b7b3..3cbcca0b42 100644 --- a/src/openrct2/ride/ShopItem.h +++ b/src/openrct2/ride/ShopItem.h @@ -11,9 +11,9 @@ #include "../core/Money.hpp" #include "../entity/Litter.h" -#include "../util/Util.h" struct Ride; + enum class PeepThoughtType : uint8_t; enum class ShopItem : uint8_t diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index b03c3730c3..c432f8ca85 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -22,7 +22,6 @@ #include "../rct1/RCT1.h" #include "../ride/RideColour.h" #include "../util/SawyerCoding.h" -#include "../util/Util.h" #include "../world/Footpath.h" #include "../world/Map.h" #include "../world/MapAnimation.h" diff --git a/src/openrct2/ride/TrackData.cpp b/src/openrct2/ride/TrackData.cpp index ea93d8643d..8b7db7a82a 100644 --- a/src/openrct2/ride/TrackData.cpp +++ b/src/openrct2/ride/TrackData.cpp @@ -10,6 +10,7 @@ #include "TrackData.h" #include "../localisation/StringIds.h" +#include "../util/Util.h" #include "Track.h" #include "TrackPaint.h" diff --git a/src/openrct2/ride/TrackDesignRepository.cpp b/src/openrct2/ride/TrackDesignRepository.cpp index 20754ae482..8e4d30663a 100644 --- a/src/openrct2/ride/TrackDesignRepository.cpp +++ b/src/openrct2/ride/TrackDesignRepository.cpp @@ -21,7 +21,6 @@ #include "../localisation/LocalisationService.h" #include "../object/ObjectRepository.h" #include "../ride/RideData.h" -#include "../util/Util.h" #include "TrackDesign.h" #include diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index e793fc579e..11ea57859a 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -21,7 +21,6 @@ #include "../object/ObjectManager.h" #include "../rct2/RCT2.h" #include "../util/SawyerCoding.h" -#include "../util/Util.h" #include "../windows/Intent.h" #include "../world/Footpath.h" #include "../world/Scenery.h" diff --git a/src/openrct2/ride/VehicleSubpositionData.h b/src/openrct2/ride/VehicleSubpositionData.h index dd74c5cc24..cfb5f3538c 100644 --- a/src/openrct2/ride/VehicleSubpositionData.h +++ b/src/openrct2/ride/VehicleSubpositionData.h @@ -9,6 +9,7 @@ #pragma once +#include "../util/Util.h" #include "Track.h" #include diff --git a/src/openrct2/world/Climate.h b/src/openrct2/world/Climate.h index 5d7860d249..bf82d4daa8 100644 --- a/src/openrct2/world/Climate.h +++ b/src/openrct2/world/Climate.h @@ -9,7 +9,6 @@ #pragma once -#include "../util/Util.h" #include enum class ClimateType : uint8_t diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index cff8649020..a3f8a5ea6d 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -32,7 +32,6 @@ #include "../ride/RideData.h" #include "../ride/Track.h" #include "../ride/TrackData.h" -#include "../util/Util.h" #include "Location.hpp" #include "Map.h" #include "MapAnimation.h" diff --git a/src/openrct2/world/MapGen.cpp b/src/openrct2/world/MapGen.cpp index 163fc9d467..aed07fb54d 100644 --- a/src/openrct2/world/MapGen.cpp +++ b/src/openrct2/world/MapGen.cpp @@ -24,7 +24,6 @@ #include "../object/TerrainEdgeObject.h" #include "../object/TerrainSurfaceObject.h" #include "../platform/Platform.h" -#include "../util/Util.h" #include "../world/tile_element/Slope.h" #include "../world/tile_element/SmallSceneryElement.h" #include "../world/tile_element/SurfaceElement.h" From 80b63a5ae794488cd6af91a0362ffec4f910e619 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 29 Oct 2024 16:54:01 +0100 Subject: [PATCH 69/97] Add line breaks after template declarations (#23086) * Add line breaks after template declarations * Additional clang-format patches --- .clang-format | 2 +- src/openrct2-ui/Ui.cpp | 3 +- src/openrct2-ui/audio/AudioChannel.cpp | 3 +- .../drawing/engines/opengl/DrawCommands.h | 3 +- .../drawing/engines/opengl/GLSLTypes.h | 9 +- src/openrct2-ui/input/ShortcutManager.h | 3 +- src/openrct2-ui/interface/Dropdown.h | 6 +- src/openrct2-ui/interface/Graph.h | 3 +- src/openrct2-ui/ride/VehicleSounds.cpp | 18 ++- src/openrct2-ui/scripting/CustomImages.cpp | 6 +- src/openrct2-ui/scripting/CustomListView.cpp | 36 +++-- src/openrct2-ui/scripting/CustomListView.h | 43 ++++-- src/openrct2-ui/scripting/CustomMenu.cpp | 6 +- src/openrct2-ui/scripting/CustomMenu.h | 6 +- src/openrct2-ui/scripting/ScTitleSequence.hpp | 12 +- src/openrct2-ui/scripting/ScUi.hpp | 6 +- src/openrct2-ui/windows/GuestList.cpp | 3 +- src/openrct2-ui/windows/RideList.cpp | 3 +- src/openrct2-ui/windows/Scenery.cpp | 3 +- src/openrct2-ui/windows/TopToolbar.cpp | 6 +- src/openrct2/AssetPackManager.cpp | 3 +- src/openrct2/Cheats.cpp | 3 +- src/openrct2/GameStateSnapshots.cpp | 6 +- src/openrct2/actions/GameAction.h | 15 +- src/openrct2/actions/GameActionRegistry.cpp | 3 +- src/openrct2/actions/GameActionResult.h | 6 +- src/openrct2/config/ConfigEnum.hpp | 9 +- src/openrct2/config/IniReader.hpp | 6 +- src/openrct2/config/IniWriter.hpp | 6 +- src/openrct2/core/BitSet.hpp | 42 ++++-- src/openrct2/core/ChecksumStream.h | 3 +- src/openrct2/core/CircularBuffer.h | 3 +- src/openrct2/core/Collections.hpp | 9 +- src/openrct2/core/Crypt.CNG.cpp | 9 +- src/openrct2/core/Crypt.OpenSSL.cpp | 3 +- src/openrct2/core/Crypt.h | 3 +- src/openrct2/core/DataSerialiser.h | 6 +- src/openrct2/core/DataSerialiserTag.h | 6 +- src/openrct2/core/DataSerialiserTraits.h | 138 ++++++++++++------ src/openrct2/core/Endianness.h | 18 ++- src/openrct2/core/EnumMap.hpp | 3 +- src/openrct2/core/FileIndex.hpp | 3 +- src/openrct2/core/FixedVector.h | 6 +- src/openrct2/core/FlagHolder.hpp | 3 +- src/openrct2/core/GroupVector.hpp | 3 +- src/openrct2/core/Guard.hpp | 12 +- src/openrct2/core/IStream.hpp | 21 ++- src/openrct2/core/Identifier.hpp | 3 +- src/openrct2/core/Json.hpp | 12 +- src/openrct2/core/Memory.hpp | 12 +- src/openrct2/core/MemoryStream.h | 6 +- src/openrct2/core/Meta.hpp | 6 +- src/openrct2/core/Numerics.hpp | 6 +- src/openrct2/core/OrcaStream.hpp | 33 +++-- src/openrct2/core/Path.hpp | 3 +- src/openrct2/core/Random.hpp | 15 +- src/openrct2/core/Range.hpp | 3 +- src/openrct2/core/String.cpp | 3 +- src/openrct2/core/String.hpp | 6 +- src/openrct2/drawing/Drawing.Sprite.BMP.cpp | 9 +- src/openrct2/drawing/Drawing.Sprite.RLE.cpp | 6 +- src/openrct2/drawing/Drawing.h | 3 +- src/openrct2/drawing/DrawingLock.hpp | 6 +- src/openrct2/entity/Balloon.cpp | 3 +- src/openrct2/entity/Duck.cpp | 3 +- src/openrct2/entity/EntityBase.cpp | 3 +- src/openrct2/entity/EntityBase.h | 9 +- src/openrct2/entity/EntityList.h | 12 +- src/openrct2/entity/EntityRegistry.cpp | 12 +- src/openrct2/entity/EntityRegistry.h | 12 +- src/openrct2/entity/Fountain.cpp | 3 +- src/openrct2/entity/Guest.cpp | 9 +- src/openrct2/entity/Litter.cpp | 3 +- src/openrct2/entity/MoneyEffect.cpp | 3 +- src/openrct2/entity/Particle.cpp | 15 +- src/openrct2/entity/Peep.cpp | 3 +- src/openrct2/entity/Staff.cpp | 3 +- src/openrct2/interface/Window.cpp | 9 +- src/openrct2/interface/Window.h | 3 +- src/openrct2/interface/ZoomLevel.h | 6 +- src/openrct2/localisation/Formatter.h | 3 +- src/openrct2/localisation/Formatting.cpp | 18 ++- src/openrct2/localisation/Formatting.h | 24 ++- src/openrct2/management/NewsItem.h | 9 +- src/openrct2/network/NetworkPacket.h | 6 +- src/openrct2/network/NetworkTypes.h | 3 +- src/openrct2/object/ObjectAsset.h | 3 +- src/openrct2/object/ObjectEntryManager.h | 3 +- src/openrct2/object/ObjectManager.cpp | 3 +- src/openrct2/object/ObjectManager.h | 3 +- src/openrct2/paint/Paint.cpp | 9 +- .../track/coaster/JuniorRollerCoaster.cpp | 6 +- .../track/coaster/WoodenRollerCoaster.cpp | 3 +- .../paint/track/coaster/WoodenRollerCoaster.h | 6 +- src/openrct2/park/ParkFile.cpp | 63 +++++--- src/openrct2/platform/Platform.macOS.mm | 7 +- src/openrct2/profiling/Profiling.h | 9 +- src/openrct2/rct1/S4Importer.cpp | 42 ++++-- src/openrct2/rct12/CSStringConverter.cpp | 3 +- src/openrct2/rct12/EntryList.h | 3 +- src/openrct2/rct12/RCT12.h | 12 +- src/openrct2/rct12/SawyerChunkReader.h | 3 +- src/openrct2/rct12/SawyerChunkWriter.h | 3 +- src/openrct2/rct2/S6Importer.cpp | 42 ++++-- src/openrct2/ride/TrackData.cpp | 3 +- src/openrct2/ride/Vehicle.cpp | 6 +- src/openrct2/scripting/Duktape.hpp | 99 ++++++++----- .../scripting/bindings/entity/ScVehicle.cpp | 6 +- .../scripting/bindings/entity/ScVehicle.hpp | 6 +- .../scripting/bindings/ride/ScRide.hpp | 12 +- .../bindings/ride/ScTrackSegment.cpp | 3 +- .../scripting/bindings/ride/ScTrackSegment.h | 6 +- .../bindings/world/ScParkMessage.hpp | 3 +- .../scripting/bindings/world/ScResearch.cpp | 9 +- src/openrct2/util/Util.h | 15 +- src/openrct2/windows/Intent.h | 3 +- src/openrct2/world/Location.hpp | 6 +- src/openrct2/world/Map.h | 6 +- src/openrct2/world/MapGen.cpp | 3 +- src/openrct2/world/Park.cpp | 3 +- src/openrct2/world/TileElementsView.h | 6 +- src/openrct2/world/TilePointerIndex.hpp | 3 +- .../world/tile_element/TileElementBase.h | 6 +- test/tests/AssertHelpers.hpp | 6 +- test/tests/CryptTests.cpp | 3 +- test/tests/EnumMapTest.cpp | 6 +- test/tests/PlayTests.cpp | 6 +- test/tests/ReplayTests.cpp | 3 +- test/tests/TileElementsView.cpp | 12 +- 129 files changed, 867 insertions(+), 430 deletions(-) diff --git a/.clang-format b/.clang-format index b81be7ebba..6ca231784a 100644 --- a/.clang-format +++ b/.clang-format @@ -16,7 +16,7 @@ AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: false +AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true BraceWrapping: diff --git a/src/openrct2-ui/Ui.cpp b/src/openrct2-ui/Ui.cpp index c7fb10a1b6..f4f5c1f328 100644 --- a/src/openrct2-ui/Ui.cpp +++ b/src/openrct2-ui/Ui.cpp @@ -28,7 +28,8 @@ using namespace OpenRCT2; using namespace OpenRCT2::Audio; using namespace OpenRCT2::Ui; -template static std::shared_ptr ToShared(std::unique_ptr&& src) +template +static std::shared_ptr ToShared(std::unique_ptr&& src) { return std::shared_ptr(std::move(src)); } diff --git a/src/openrct2-ui/audio/AudioChannel.cpp b/src/openrct2-ui/audio/AudioChannel.cpp index ea26da4603..12eba42d64 100644 --- a/src/openrct2-ui/audio/AudioChannel.cpp +++ b/src/openrct2-ui/audio/AudioChannel.cpp @@ -18,7 +18,8 @@ namespace OpenRCT2::Audio { - template class AudioChannelImpl final : public ISDLAudioChannel + template + class AudioChannelImpl final : public ISDLAudioChannel { static_assert(std::is_base_of_v); diff --git a/src/openrct2-ui/drawing/engines/opengl/DrawCommands.h b/src/openrct2-ui/drawing/engines/opengl/DrawCommands.h index 64c21bb9ac..14f280cf2e 100644 --- a/src/openrct2-ui/drawing/engines/opengl/DrawCommands.h +++ b/src/openrct2-ui/drawing/engines/opengl/DrawCommands.h @@ -16,7 +16,8 @@ #include namespace OpenRCT2::Ui { - template class CommandBatch + template + class CommandBatch { private: std::vector _instances; diff --git a/src/openrct2-ui/drawing/engines/opengl/GLSLTypes.h b/src/openrct2-ui/drawing/engines/opengl/GLSLTypes.h index 2aef1c79e7..6635185b3c 100644 --- a/src/openrct2-ui/drawing/engines/opengl/GLSLTypes.h +++ b/src/openrct2-ui/drawing/engines/opengl/GLSLTypes.h @@ -16,7 +16,8 @@ namespace OpenRCT2::Ui #pragma pack(push, 1) namespace detail { - template struct Vec2 + template + struct Vec2 { using ValueType = T_; @@ -37,7 +38,8 @@ namespace OpenRCT2::Ui template struct Vec2; template struct Vec2; - template struct Vec3 + template + struct Vec3 { using ValueType = T_; @@ -64,7 +66,8 @@ namespace OpenRCT2::Ui template struct Vec3; template struct Vec3; - template struct Vec4 + template + struct Vec4 { using ValueType = T_; diff --git a/src/openrct2-ui/input/ShortcutManager.h b/src/openrct2-ui/input/ShortcutManager.h index ce248b2048..b2c4d73a9f 100644 --- a/src/openrct2-ui/input/ShortcutManager.h +++ b/src/openrct2-ui/input/ShortcutManager.h @@ -133,7 +133,8 @@ namespace OpenRCT2::Ui void SaveUserBindings(); void RegisterShortcut(RegisteredShortcut&& shortcut); - template void RegisterShortcut(Args&&... args) + template + void RegisterShortcut(Args&&... args) { RegisterShortcut(RegisteredShortcut(std::forward(args)...)); } diff --git a/src/openrct2-ui/interface/Dropdown.h b/src/openrct2-ui/interface/Dropdown.h index 949a3ab87f..70fd512833 100644 --- a/src/openrct2-ui/interface/Dropdown.h +++ b/src/openrct2-ui/interface/Dropdown.h @@ -119,7 +119,8 @@ namespace OpenRCT2::Dropdown return ItemExt(-1, Dropdown::SeparatorString, STR_EMPTY); } - template void SetItems(const Dropdown::ItemExt (&items)[N]) + template + void SetItems(const Dropdown::ItemExt (&items)[N]) { for (int i = 0; i < N; ++i) { @@ -129,7 +130,8 @@ namespace OpenRCT2::Dropdown } } - template constexpr bool ItemIDsMatchIndices(const Dropdown::ItemExt (&items)[N]) + template + constexpr bool ItemIDsMatchIndices(const Dropdown::ItemExt (&items)[N]) { for (int i = 0; i < N; ++i) { diff --git a/src/openrct2-ui/interface/Graph.h b/src/openrct2-ui/interface/Graph.h index ff6398b751..8a41ba7817 100644 --- a/src/openrct2-ui/interface/Graph.h +++ b/src/openrct2-ui/interface/Graph.h @@ -18,7 +18,8 @@ namespace OpenRCT2::Graph { constexpr int32_t kYTickMarkPadding = 8; - template struct GraphProperties + template + struct GraphProperties { ScreenRect internalBounds; const T* series; diff --git a/src/openrct2-ui/ride/VehicleSounds.cpp b/src/openrct2-ui/ride/VehicleSounds.cpp index 2eed807354..8530bee3ab 100644 --- a/src/openrct2-ui/ride/VehicleSounds.cpp +++ b/src/openrct2-ui/ride/VehicleSounds.cpp @@ -22,8 +22,10 @@ namespace OpenRCT2::Audio { namespace { - template class TrainIterator; - template class Train + template + class TrainIterator; + template + class Train { public: explicit Train(T* vehicle) @@ -47,7 +49,8 @@ namespace OpenRCT2::Audio private: T* FirstCar; }; - template class TrainIterator + template + class TrainIterator { public: using iterator = TrainIterator; @@ -91,7 +94,8 @@ namespace OpenRCT2::Audio }; } // namespace - template int32_t Train::GetMass() const + template + int32_t Train::GetMass() const { return std::accumulate( begin(), end(), 0, [](int32_t totalMass, const Vehicle& vehicle) { return totalMass + vehicle.mass; }); @@ -430,7 +434,8 @@ namespace OpenRCT2::Audio OtherNoises, // e.g. Screams }; - template static uint16_t SoundFrequency(const SoundId id, uint16_t baseFrequency) + template + static uint16_t SoundFrequency(const SoundId id, uint16_t baseFrequency) { if constexpr (type == SoundType::TrackNoises) { @@ -450,7 +455,8 @@ namespace OpenRCT2::Audio } } - template static bool ShouldUpdateChannelRate(const SoundId id) + template + static bool ShouldUpdateChannelRate(const SoundId id) { return type == SoundType::TrackNoises || !IsFixedFrequencySound(id); } diff --git a/src/openrct2-ui/scripting/CustomImages.cpp b/src/openrct2-ui/scripting/CustomImages.cpp index 93d2854890..76b5ac3acd 100644 --- a/src/openrct2-ui/scripting/CustomImages.cpp +++ b/src/openrct2-ui/scripting/CustomImages.cpp @@ -341,7 +341,8 @@ namespace OpenRCT2::Scripting return imageData; } - template<> PixelDataKind FromDuk(const DukValue& d) + template<> + PixelDataKind FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::STRING) { @@ -358,7 +359,8 @@ namespace OpenRCT2::Scripting return PixelDataKind::Unknown; } - template<> PixelDataPaletteKind FromDuk(const DukValue& d) + template<> + PixelDataPaletteKind FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::STRING) { diff --git a/src/openrct2-ui/scripting/CustomListView.cpp b/src/openrct2-ui/scripting/CustomListView.cpp index e9486c434c..8550a34709 100644 --- a/src/openrct2-ui/scripting/CustomListView.cpp +++ b/src/openrct2-ui/scripting/CustomListView.cpp @@ -28,7 +28,8 @@ namespace OpenRCT2::Scripting { constexpr size_t COLUMN_HEADER_HEIGHT = kListRowHeight + 1; - template<> ColumnSortOrder FromDuk(const DukValue& d) + template<> + ColumnSortOrder FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::STRING) { @@ -41,7 +42,8 @@ namespace OpenRCT2::Scripting return ColumnSortOrder::None; } - template<> DukValue ToDuk(duk_context* ctx, const ColumnSortOrder& value) + template<> + DukValue ToDuk(duk_context* ctx, const ColumnSortOrder& value) { switch (value) { @@ -54,7 +56,8 @@ namespace OpenRCT2::Scripting } } - template<> std::optional FromDuk(const DukValue& d) + template<> + std::optional FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::NUMBER) { @@ -63,7 +66,8 @@ namespace OpenRCT2::Scripting return std::nullopt; } - template<> ListViewColumn FromDuk(const DukValue& d) + template<> + ListViewColumn FromDuk(const DukValue& d) { ListViewColumn result; result.CanSort = AsOrDefault(d["canSort"], false); @@ -86,7 +90,8 @@ namespace OpenRCT2::Scripting return result; } - template<> DukValue ToDuk(duk_context* ctx, const ListViewColumn& value) + template<> + DukValue ToDuk(duk_context* ctx, const ListViewColumn& value) { DukObject obj(ctx); obj.Set("canSort", value.CanSort); @@ -100,7 +105,8 @@ namespace OpenRCT2::Scripting return obj.Take(); } - template<> ListViewItem FromDuk(const DukValue& d) + template<> + ListViewItem FromDuk(const DukValue& d) { ListViewItem result; if (d.type() == DukValue::Type::STRING) @@ -129,7 +135,8 @@ namespace OpenRCT2::Scripting return result; } - template<> std::vector FromDuk(const DukValue& d) + template<> + std::vector FromDuk(const DukValue& d) { std::vector result; if (d.is_array()) @@ -143,7 +150,8 @@ namespace OpenRCT2::Scripting return result; } - template<> std::vector FromDuk(const DukValue& d) + template<> + std::vector FromDuk(const DukValue& d) { std::vector result; if (d.is_array()) @@ -157,7 +165,8 @@ namespace OpenRCT2::Scripting return result; } - template<> std::optional FromDuk(const DukValue& d) + template<> + std::optional FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::OBJECT) { @@ -171,7 +180,8 @@ namespace OpenRCT2::Scripting return std::nullopt; } - template<> DukValue ToDuk(duk_context* ctx, const RowColumn& value) + template<> + DukValue ToDuk(duk_context* ctx, const RowColumn& value) { DukObject obj(ctx); obj.Set("row", value.Row); @@ -179,7 +189,8 @@ namespace OpenRCT2::Scripting return obj.Take(); } - template<> ScrollbarType FromDuk(const DukValue& d) + template<> + ScrollbarType FromDuk(const DukValue& d) { auto value = AsOrDefault(d, ""); if (value == "horizontal") @@ -191,7 +202,8 @@ namespace OpenRCT2::Scripting return ScrollbarType::None; } - template<> DukValue ToDuk(duk_context* ctx, const ScrollbarType& value) + template<> + DukValue ToDuk(duk_context* ctx, const ScrollbarType& value) { switch (value) { diff --git a/src/openrct2-ui/scripting/CustomListView.h b/src/openrct2-ui/scripting/CustomListView.h index 3a4cb591fc..3a473e723f 100644 --- a/src/openrct2-ui/scripting/CustomListView.h +++ b/src/openrct2-ui/scripting/CustomListView.h @@ -159,17 +159,38 @@ namespace OpenRCT2::Scripting { using namespace OpenRCT2::Ui::Windows; - template<> ColumnSortOrder FromDuk(const DukValue& d); - template<> std::optional FromDuk(const DukValue& d); - template<> ListViewColumn FromDuk(const DukValue& d); - template<> ListViewItem FromDuk(const DukValue& d); - template<> std::vector FromDuk(const DukValue& d); - template<> std::vector FromDuk(const DukValue& d); - template<> std::optional FromDuk(const DukValue& d); - template<> DukValue ToDuk(duk_context* ctx, const RowColumn& value); - template<> DukValue ToDuk(duk_context* ctx, const ListViewColumn& value); - template<> ScrollbarType FromDuk(const DukValue& d); - template<> DukValue ToDuk(duk_context* ctx, const ScrollbarType& value); + template<> + ColumnSortOrder FromDuk(const DukValue& d); + + template<> + std::optional FromDuk(const DukValue& d); + + template<> + ListViewColumn FromDuk(const DukValue& d); + + template<> + ListViewItem FromDuk(const DukValue& d); + + template<> + std::vector FromDuk(const DukValue& d); + + template<> + std::vector FromDuk(const DukValue& d); + + template<> + std::optional FromDuk(const DukValue& d); + + template<> + DukValue ToDuk(duk_context* ctx, const RowColumn& value); + + template<> + DukValue ToDuk(duk_context* ctx, const ListViewColumn& value); + + template<> + ScrollbarType FromDuk(const DukValue& d); + + template<> + DukValue ToDuk(duk_context* ctx, const ScrollbarType& value); } // namespace OpenRCT2::Scripting #endif diff --git a/src/openrct2-ui/scripting/CustomMenu.cpp b/src/openrct2-ui/scripting/CustomMenu.cpp index 8fc255c519..898d600e9e 100644 --- a/src/openrct2-ui/scripting/CustomMenu.cpp +++ b/src/openrct2-ui/scripting/CustomMenu.cpp @@ -82,7 +82,8 @@ namespace OpenRCT2::Scripting { "banner", ViewportInteractionItem::Banner }, }); - template<> DukValue ToDuk(duk_context* ctx, const CursorID& cursorId) + template<> + DukValue ToDuk(duk_context* ctx, const CursorID& cursorId) { auto value = EnumValue(cursorId); if (value < std::size(CursorNames)) @@ -94,7 +95,8 @@ namespace OpenRCT2::Scripting return ToDuk(ctx, undefined); } - template<> CursorID FromDuk(const DukValue& s) + template<> + CursorID FromDuk(const DukValue& s) { if (s.type() == DukValue::Type::STRING) { diff --git a/src/openrct2-ui/scripting/CustomMenu.h b/src/openrct2-ui/scripting/CustomMenu.h index 172d4126c6..7a30868b4b 100644 --- a/src/openrct2-ui/scripting/CustomMenu.h +++ b/src/openrct2-ui/scripting/CustomMenu.h @@ -108,8 +108,10 @@ namespace OpenRCT2::Scripting void InitialiseCustomMenuItems(ScriptEngine& scriptEngine); void InitialiseCustomTool(ScriptEngine& scriptEngine, const DukValue& dukValue); - template<> DukValue ToDuk(duk_context* ctx, const CursorID& value); - template<> CursorID FromDuk(const DukValue& s); + template<> + DukValue ToDuk(duk_context* ctx, const CursorID& value); + template<> + CursorID FromDuk(const DukValue& s); } // namespace OpenRCT2::Scripting diff --git a/src/openrct2-ui/scripting/ScTitleSequence.hpp b/src/openrct2-ui/scripting/ScTitleSequence.hpp index 7b91d16d60..5d179018ef 100644 --- a/src/openrct2-ui/scripting/ScTitleSequence.hpp +++ b/src/openrct2-ui/scripting/ScTitleSequence.hpp @@ -61,12 +61,14 @@ namespace OpenRCT2::Scripting { OpenRCT2::Title::EndCommand::ScriptingName, TitleScript::End }, }); - template<> DukValue ToDuk(duk_context* ctx, const TitleScript& value) + template<> + DukValue ToDuk(duk_context* ctx, const TitleScript& value) { return ToDuk(ctx, TitleScriptMap[value]); } - template<> DukValue ToDuk(duk_context* ctx, const OpenRCT2::Title::TitleCommand& value) + template<> + DukValue ToDuk(duk_context* ctx, const OpenRCT2::Title::TitleCommand& value) { using namespace OpenRCT2::Title; DukObject obj(ctx); @@ -115,14 +117,16 @@ namespace OpenRCT2::Scripting return obj.Take(); } - template<> TitleScript FromDuk(const DukValue& value) + template<> + TitleScript FromDuk(const DukValue& value) { if (value.type() == DukValue::Type::STRING) return TitleScriptMap[value.as_string()]; throw DukException() << "Invalid title command id"; } - template<> OpenRCT2::Title::TitleCommand FromDuk(const DukValue& value) + template<> + OpenRCT2::Title::TitleCommand FromDuk(const DukValue& value) { using namespace OpenRCT2::Title; auto type = FromDuk(value["type"]); diff --git a/src/openrct2-ui/scripting/ScUi.hpp b/src/openrct2-ui/scripting/ScUi.hpp index 76aaeee54d..c1b8a3d4ae 100644 --- a/src/openrct2-ui/scripting/ScUi.hpp +++ b/src/openrct2-ui/scripting/ScUi.hpp @@ -61,7 +61,8 @@ namespace OpenRCT2::Scripting { "other", ScenarioSource::Other }, }); - template<> inline DukValue ToDuk(duk_context* ctx, const SCENARIO_CATEGORY& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const SCENARIO_CATEGORY& value) { const auto& entry = ScenarioCategoryMap.find(value); if (entry != ScenarioCategoryMap.end()) @@ -69,7 +70,8 @@ namespace OpenRCT2::Scripting return ToDuk(ctx, ScenarioCategoryMap[SCENARIO_CATEGORY_OTHER]); } - template<> inline DukValue ToDuk(duk_context* ctx, const ScenarioSource& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const ScenarioSource& value) { const auto& entry = ScenarioSourceMap.find(value); if (entry != ScenarioSourceMap.end()) diff --git a/src/openrct2-ui/windows/GuestList.cpp b/src/openrct2-ui/windows/GuestList.cpp index 8b46fbf4ce..e873bbf185 100644 --- a/src/openrct2-ui/windows/GuestList.cpp +++ b/src/openrct2-ui/windows/GuestList.cpp @@ -933,7 +933,8 @@ namespace OpenRCT2::Ui::Windows } } - template static bool CompareGuestItem(const GuestItem& a, const GuestItem& b) + template + static bool CompareGuestItem(const GuestItem& a, const GuestItem& b) { const auto* peepA = GetEntity(a.Id); const auto* peepB = GetEntity(b.Id); diff --git a/src/openrct2-ui/windows/RideList.cpp b/src/openrct2-ui/windows/RideList.cpp index 7ebd900152..d9aa62f08d 100644 --- a/src/openrct2-ui/windows/RideList.cpp +++ b/src/openrct2-ui/windows/RideList.cpp @@ -791,7 +791,8 @@ namespace OpenRCT2::Ui::Windows * Used in RefreshList() to handle the sorting of the list. * Uses a lambda function (predicate) as exit criteria for the algorithm. */ - template void SortListByPredicate(const TSortPred& pred) + template + void SortListByPredicate(const TSortPred& pred) { std::sort(_rideList.begin(), _rideList.end(), [&pred](const auto& lhs, const auto& rhs) { const Ride* rideLhs = GetRide(lhs.Id); diff --git a/src/openrct2-ui/windows/Scenery.cpp b/src/openrct2-ui/windows/Scenery.cpp index e8b2c53275..b20d1d2c49 100644 --- a/src/openrct2-ui/windows/Scenery.cpp +++ b/src/openrct2-ui/windows/Scenery.cpp @@ -1071,7 +1071,8 @@ namespace OpenRCT2::Ui::Windows return contentWidth / SCENERY_BUTTON_WIDTH; } - template T CountRows(T items) const + template + T CountRows(T items) const { const auto rows = items / GetNumColumns(); return rows; diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 33b2e95096..319bc78b0b 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -783,7 +783,8 @@ namespace OpenRCT2::Ui::Windows } // TODO: look into using std::span - template uint16_t GetToolbarWidth(T toolbarItems) + template + uint16_t GetToolbarWidth(T toolbarItems) { bool firstItem = true; auto totalWidth = 0; @@ -803,7 +804,8 @@ namespace OpenRCT2::Ui::Windows } // TODO: look into using std::span - template void AlignButtons(T toolbarItems, uint16_t xPos) + template + void AlignButtons(T toolbarItems, uint16_t xPos) { bool firstItem = true; for (auto widgetIndex : toolbarItems) diff --git a/src/openrct2/AssetPackManager.cpp b/src/openrct2/AssetPackManager.cpp index e50b58a5e6..4cb2c118dc 100644 --- a/src/openrct2/AssetPackManager.cpp +++ b/src/openrct2/AssetPackManager.cpp @@ -143,7 +143,8 @@ void AssetPackManager::AddAssetPack(const fs::path& path) } } -template static void EnumerateCommaSeparatedList(std::string_view csl, TFunc func) +template +static void EnumerateCommaSeparatedList(std::string_view csl, TFunc func) { size_t elStart = 0; for (size_t i = 0; i <= csl.size(); i++) diff --git a/src/openrct2/Cheats.cpp b/src/openrct2/Cheats.cpp index 58d86ba487..c0f94c984e 100644 --- a/src/openrct2/Cheats.cpp +++ b/src/openrct2/Cheats.cpp @@ -66,7 +66,8 @@ void CheatsSet(CheatType cheatType, int64_t param1 /* = 0*/, int64_t param2 /* = GameActions::Execute(&cheatSetAction); } -template static void CheatEntrySerialise(DataSerialiser& ds, CheatType type, const T& value, uint16_t& count) +template +static void CheatEntrySerialise(DataSerialiser& ds, CheatType type, const T& value, uint16_t& count) { ds << static_cast(type) << value; count++; diff --git a/src/openrct2/GameStateSnapshots.cpp b/src/openrct2/GameStateSnapshots.cpp index 43b23a87d9..d8e046f95e 100644 --- a/src/openrct2/GameStateSnapshots.cpp +++ b/src/openrct2/GameStateSnapshots.cpp @@ -54,7 +54,8 @@ struct GameStateSnapshot_t OpenRCT2::MemoryStream storedSprites; OpenRCT2::MemoryStream parkParameters; - template bool EntitySizeCheck(DataSerialiser& ds) + template + bool EntitySizeCheck(DataSerialiser& ds) { uint32_t size = sizeof(T); ds << size; @@ -64,7 +65,8 @@ struct GameStateSnapshot_t } return true; } - template bool EntitiesSizeCheck(DataSerialiser& ds) + template + bool EntitiesSizeCheck(DataSerialiser& ds) { return (EntitySizeCheck(ds) && ...); } diff --git a/src/openrct2/actions/GameAction.h b/src/openrct2/actions/GameAction.h index 2531d45273..753f0e9220 100644 --- a/src/openrct2/actions/GameAction.h +++ b/src/openrct2/actions/GameAction.h @@ -87,7 +87,8 @@ public: Visit("y2", param.Point2.y); } - template void Visit(std::string_view name, T& param) + template + void Visit(std::string_view name, T& param) { static_assert(std::is_arithmetic_v || std::is_enum_v, "Not an arithmetic type"); auto value = static_cast(param); @@ -95,14 +96,16 @@ public: param = static_cast(value); } - template void Visit(std::string_view name, TIdentifier& param) + template + void Visit(std::string_view name, TIdentifier& param) { auto value = param.ToUnderlying(); Visit(name, value); param = TIdentifier::FromUnderlying(value); } - template void Visit(std::string_view name, NetworkObjectId& param) + template + void Visit(std::string_view name, NetworkObjectId& param) { Visit(name, param.id); } @@ -247,11 +250,13 @@ public: # pragma GCC diagnostic pop #endif -template struct GameActionNameQuery +template +struct GameActionNameQuery { }; -template struct GameActionBase : GameAction +template +struct GameActionBase : GameAction { public: static constexpr GameCommand TYPE = TType; diff --git a/src/openrct2/actions/GameActionRegistry.cpp b/src/openrct2/actions/GameActionRegistry.cpp index 7b12548a9f..8c778be043 100644 --- a/src/openrct2/actions/GameActionRegistry.cpp +++ b/src/openrct2/actions/GameActionRegistry.cpp @@ -117,7 +117,8 @@ namespace OpenRCT2::GameActions registry[idx] = { factory, name }; } - template static constexpr void Register(GameActionRegistry& registry, const char* name) + template + static constexpr void Register(GameActionRegistry& registry, const char* name) { GameActionFactory factory = []() -> GameAction* { return new T(); }; Register(registry, factory, name); diff --git a/src/openrct2/actions/GameActionResult.h b/src/openrct2/actions/GameActionResult.h index 2fad9f8538..07c9455383 100644 --- a/src/openrct2/actions/GameActionResult.h +++ b/src/openrct2/actions/GameActionResult.h @@ -81,7 +81,8 @@ namespace OpenRCT2::GameActions // It is recommended to use strong types since a type alias such as 'using MyType = uint32_t' // is still just uint32_t, this guarantees the data is associated with the correct type. - template void SetData(const T&& data) + template + void SetData(const T&& data) { #ifdef __ANDROID__ ResultData = std::make_shared(data); @@ -90,7 +91,8 @@ namespace OpenRCT2::GameActions #endif } - template T GetData() const + template + T GetData() const { #ifdef __ANDROID__ return *static_cast(ResultData.get()); diff --git a/src/openrct2/config/ConfigEnum.hpp b/src/openrct2/config/ConfigEnum.hpp index d343451fd6..3b0bf048c4 100644 --- a/src/openrct2/config/ConfigEnum.hpp +++ b/src/openrct2/config/ConfigEnum.hpp @@ -15,7 +15,8 @@ #include #include -template struct ConfigEnumEntry +template +struct ConfigEnumEntry { std::string Key; T Value; @@ -27,14 +28,16 @@ template struct ConfigEnumEntry } }; -template struct IConfigEnum +template +struct IConfigEnum { virtual ~IConfigEnum() = default; virtual std::string GetName(T value) const = 0; virtual T GetValue(const std::string& key, T defaultValue) const = 0; }; -template class ConfigEnum final : public IConfigEnum +template +class ConfigEnum final : public IConfigEnum { private: const std::vector> _entries; diff --git a/src/openrct2/config/IniReader.hpp b/src/openrct2/config/IniReader.hpp index 757e5f5c34..a65a75e216 100644 --- a/src/openrct2/config/IniReader.hpp +++ b/src/openrct2/config/IniReader.hpp @@ -17,7 +17,8 @@ namespace OpenRCT2 struct IStream; } -template struct IConfigEnum; +template +struct IConfigEnum; struct IIniReader { @@ -32,7 +33,8 @@ struct IIniReader virtual std::string GetString(const std::string& name, const std::string& defaultValue) const = 0; virtual bool TryGetString(const std::string& name, std::string* outValue) const = 0; - template T GetEnum(const std::string& name, T defaultValue, const IConfigEnum& configEnum) const + template + T GetEnum(const std::string& name, T defaultValue, const IConfigEnum& configEnum) const { std::string szValue; if (!TryGetString(name, &szValue)) diff --git a/src/openrct2/config/IniWriter.hpp b/src/openrct2/config/IniWriter.hpp index 321eae8458..88277b134d 100644 --- a/src/openrct2/config/IniWriter.hpp +++ b/src/openrct2/config/IniWriter.hpp @@ -19,7 +19,8 @@ namespace OpenRCT2 struct IStream; } -template struct IConfigEnum; +template +struct IConfigEnum; struct IIniWriter { @@ -34,7 +35,8 @@ struct IIniWriter virtual void WriteString(const std::string& name, const std::string& value) = 0; virtual void WriteEnum(const std::string& name, const std::string& key) = 0; - template void WriteEnum(const std::string& name, T value, const IConfigEnum& configEnum) + template + void WriteEnum(const std::string& name, T value, const IConfigEnum& configEnum) { static_assert(sizeof(T) <= sizeof(int32_t), "Type too large"); diff --git a/src/openrct2/core/BitSet.hpp b/src/openrct2/core/BitSet.hpp index 4aef9c567f..9c2c52784b 100644 --- a/src/openrct2/core/BitSet.hpp +++ b/src/openrct2/core/BitSet.hpp @@ -25,7 +25,8 @@ namespace OpenRCT2 { static constexpr size_t BitsPerByte = std::numeric_limits>::digits; - template static constexpr size_t ByteAlignBits() + template + static constexpr size_t ByteAlignBits() { const auto reminder = TNumBits % BitsPerByte; if constexpr (reminder == 0u) @@ -48,7 +49,8 @@ namespace OpenRCT2 static_assert(ByteAlignBits<31>() == 32); // Returns the amount of bytes required for a single block. - template static constexpr size_t ComputeBlockSize() + template + static constexpr size_t ComputeBlockSize() { constexpr size_t numBits = ByteAlignBits(); if constexpr (numBits >= std::numeric_limits::digits) @@ -67,7 +69,8 @@ namespace OpenRCT2 } } - template static constexpr size_t ComputeBlockCount() + template + static constexpr size_t ComputeBlockCount() { size_t numBits = TNumBits; size_t numBlocks = 0; @@ -90,7 +93,8 @@ namespace OpenRCT2 static_assert(ComputeBlockSize<33>() == sizeof(uintptr_t)); // TODO: Replace with std::popcount when C++20 is enabled. - template static constexpr size_t popcount(const T val) + template + static constexpr size_t popcount(const T val) { size_t res = 0; auto x = static_cast>(val); @@ -103,36 +107,43 @@ namespace OpenRCT2 return res; } - template struct StorageBlockType; + template + struct StorageBlockType; - template<> struct StorageBlockType<1> + template<> + struct StorageBlockType<1> { using value_type = uint8_t; }; - template<> struct StorageBlockType<2> + template<> + struct StorageBlockType<2> { using value_type = uint16_t; }; - template<> struct StorageBlockType<4> + template<> + struct StorageBlockType<4> { using value_type = uint32_t; }; - template<> struct StorageBlockType<8> + template<> + struct StorageBlockType<8> { using value_type = uint64_t; }; - template struct storage_block_type_aligned + template + struct storage_block_type_aligned { using value_type = typename StorageBlockType()>::value_type; }; } // namespace BitSet } // namespace Detail - template class BitSet + template + class BitSet { static constexpr size_t ByteAlignedBitSize = Detail::BitSet::ByteAlignBits(); @@ -154,7 +165,8 @@ namespace OpenRCT2 using Storage = std::array; // Proxy object to access the bits as single value. - template class reference_base + template + class reference_base { T& _storage; const size_t _blockIndex; @@ -196,7 +208,8 @@ namespace OpenRCT2 using reference = reference_base; using const_reference = reference_base; - template class iterator_base + template + class iterator_base { T* _bitset{}; size_t _pos{}; @@ -275,7 +288,8 @@ namespace OpenRCT2 { } - template constexpr BitSet(const std::initializer_list& indices) + template + constexpr BitSet(const std::initializer_list& indices) { for (auto idx : indices) { diff --git a/src/openrct2/core/ChecksumStream.h b/src/openrct2/core/ChecksumStream.h index a6629a2671..4b63f53880 100644 --- a/src/openrct2/core/ChecksumStream.h +++ b/src/openrct2/core/ChecksumStream.h @@ -97,7 +97,8 @@ namespace OpenRCT2 Write<16>(buffer); } - template void Write(const void* buffer) + template + void Write(const void* buffer) { Write(buffer, N); } diff --git a/src/openrct2/core/CircularBuffer.h b/src/openrct2/core/CircularBuffer.h index ae3af3982a..ffe1c57b11 100644 --- a/src/openrct2/core/CircularBuffer.h +++ b/src/openrct2/core/CircularBuffer.h @@ -12,7 +12,8 @@ #include #include -template class CircularBuffer +template +class CircularBuffer { public: using value_type = TType; diff --git a/src/openrct2/core/Collections.hpp b/src/openrct2/core/Collections.hpp index 4c0710bb81..f9cf990f89 100644 --- a/src/openrct2/core/Collections.hpp +++ b/src/openrct2/core/Collections.hpp @@ -49,7 +49,8 @@ namespace OpenRCT2::Collections return SIZE_MAX; } - template static size_t IndexOf(const TCollection& collection, TPred predicate) + template + static size_t IndexOf(const TCollection& collection, TPred predicate) { size_t index = 0; for (const auto& item : collection) @@ -65,13 +66,15 @@ namespace OpenRCT2::Collections #pragma region String helpers - template static bool Contains(TCollection& collection, const char* item, bool ignoreCase = false) + template + static bool Contains(TCollection& collection, const char* item, bool ignoreCase = false) { return Contains( collection, item, [ignoreCase](const char* a, const char* b) { return String::Equals(a, b, ignoreCase); }); } - template static size_t IndexOf(TCollection& collection, const char* item, bool ignoreCase = false) + template + static size_t IndexOf(TCollection& collection, const char* item, bool ignoreCase = false) { return IndexOf( collection, item, [ignoreCase](const char* a, const char* b) { return String::Equals(a, b, ignoreCase); }); diff --git a/src/openrct2/core/Crypt.CNG.cpp b/src/openrct2/core/Crypt.CNG.cpp index 139d830fa9..7622668364 100644 --- a/src/openrct2/core/Crypt.CNG.cpp +++ b/src/openrct2/core/Crypt.CNG.cpp @@ -52,7 +52,8 @@ static void ThrowBadAllocOnNull(const void* ptr) } } -template class CngHashAlgorithm final : public TBase +template +class CngHashAlgorithm final : public TBase { private: const wchar_t* _algName; @@ -143,14 +144,16 @@ class DerReader private: ivstream _stream; - template T Read(std::istream& stream) + template + T Read(std::istream& stream) { T value; stream.read(reinterpret_cast(&value), sizeof(T)); return value; } - template std::vector Read(std::istream& stream, size_t count) + template + std::vector Read(std::istream& stream, size_t count) { std::vector values(count); stream.read(reinterpret_cast(values.data()), sizeof(T) * count); diff --git a/src/openrct2/core/Crypt.OpenSSL.cpp b/src/openrct2/core/Crypt.OpenSSL.cpp index da16f49ca4..08821c9137 100644 --- a/src/openrct2/core/Crypt.OpenSSL.cpp +++ b/src/openrct2/core/Crypt.OpenSSL.cpp @@ -40,7 +40,8 @@ static void OpenSSLInitialise() } } -template class OpenSSLHashAlgorithm final : public TBase +template +class OpenSSLHashAlgorithm final : public TBase { private: const EVP_MD* _type; diff --git a/src/openrct2/core/Crypt.h b/src/openrct2/core/Crypt.h index 3d9fbd507b..ba142fdb65 100644 --- a/src/openrct2/core/Crypt.h +++ b/src/openrct2/core/Crypt.h @@ -17,7 +17,8 @@ namespace OpenRCT2::Crypt { - template class HashAlgorithm + template + class HashAlgorithm { public: using Result = std::array; diff --git a/src/openrct2/core/DataSerialiser.h b/src/openrct2/core/DataSerialiser.h index 8bf85990c4..fab23d87c4 100644 --- a/src/openrct2/core/DataSerialiser.h +++ b/src/openrct2/core/DataSerialiser.h @@ -57,7 +57,8 @@ public: return _activeStream; } - template DataSerialiser& operator<<(const T& data) + template + DataSerialiser& operator<<(const T& data) { if (!_isLogging) { @@ -74,7 +75,8 @@ public: return *this; } - template DataSerialiser& operator<<(DataSerialiserTag data) + template + DataSerialiser& operator<<(DataSerialiserTag data) { if (!_isLogging) { diff --git a/src/openrct2/core/DataSerialiserTag.h b/src/openrct2/core/DataSerialiserTag.h index 62c7ead353..2210d4a25f 100644 --- a/src/openrct2/core/DataSerialiserTag.h +++ b/src/openrct2/core/DataSerialiserTag.h @@ -9,7 +9,8 @@ #pragma once -template class DataSerialiserTag +template +class DataSerialiserTag { public: DataSerialiserTag(const char* name, T& data) @@ -33,7 +34,8 @@ private: T& _data; }; -template inline DataSerialiserTag CreateDataSerialiserTag(const char* name, T& data) +template +inline DataSerialiserTag CreateDataSerialiserTag(const char* name, T& data) { DataSerialiserTag r(name, data); return r; diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index b8257a2f81..26fa5c735b 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -30,14 +30,16 @@ #include #include -template struct DataSerializerTraitsT +template +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const T& v) = delete; static void decode(OpenRCT2::IStream* stream, T& val) = delete; static void log(OpenRCT2::IStream* stream, const T& val) = delete; }; -template struct DataSerializerTraitsEnum +template +struct DataSerializerTraitsEnum { using TUnderlying = std::underlying_type_t; @@ -65,7 +67,8 @@ template struct DataSerializerTraitsEnum template using DataSerializerTraits = std::conditional_t, DataSerializerTraitsEnum, DataSerializerTraitsT>; -template struct DataSerializerTraitsIntegral +template +struct DataSerializerTraitsIntegral { static void encode(OpenRCT2::IStream* stream, const T& val) { @@ -88,7 +91,8 @@ template struct DataSerializerTraitsIntegral } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const bool& val) { @@ -107,43 +111,53 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT : public DataSerializerTraitsIntegral +template<> +struct DataSerializerTraitsT : public DataSerializerTraitsIntegral { }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const std::string& str) { @@ -180,7 +194,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const NetworkPlayerId_t& val) { @@ -215,7 +230,8 @@ template<> struct DataSerializerTraitsT } }; -template struct DataSerializerTraitsT> +template +struct DataSerializerTraitsT> { static void encode(OpenRCT2::IStream* stream, const DataSerialiserTag& tag) { @@ -240,7 +256,8 @@ template struct DataSerializerTraitsT> } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const OpenRCT2::MemoryStream& val) { @@ -266,7 +283,8 @@ template<> struct DataSerializerTraitsT } }; -template struct DataSerializerTraitsPODArray +template +struct DataSerializerTraitsPODArray { static void encode(OpenRCT2::IStream* stream, const _Ty (&val)[_Size]) { @@ -308,23 +326,28 @@ template struct DataSerializerTraitsPODArray } }; -template struct DataSerializerTraitsT : public DataSerializerTraitsPODArray +template +struct DataSerializerTraitsT : public DataSerializerTraitsPODArray { }; -template struct DataSerializerTraitsT : public DataSerializerTraitsPODArray +template +struct DataSerializerTraitsT : public DataSerializerTraitsPODArray { }; -template struct DataSerializerTraitsT : public DataSerializerTraitsPODArray +template +struct DataSerializerTraitsT : public DataSerializerTraitsPODArray { }; -template struct DataSerializerTraitsT : public DataSerializerTraitsPODArray +template +struct DataSerializerTraitsT : public DataSerializerTraitsPODArray { }; -template struct DataSerializerTraitsT : public DataSerializerTraitsPODArray +template +struct DataSerializerTraitsT : public DataSerializerTraitsPODArray { }; @@ -334,7 +357,8 @@ struct DataSerializerTraitsT[_Size]> { }; -template struct DataSerializerTraitsT> +template +struct DataSerializerTraitsT> { static void encode(OpenRCT2::IStream* stream, const std::array<_Ty, _Size>& val) { @@ -376,7 +400,8 @@ template struct DataSerializerTraitsT struct DataSerializerTraitsT> +template +struct DataSerializerTraitsT> { static void encode(OpenRCT2::IStream* stream, const std::vector<_Ty>& val) { @@ -417,7 +442,8 @@ template struct DataSerializerTraitsT> } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const MapRange& v) { @@ -445,7 +471,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const TileElement& tileElement) { @@ -489,7 +516,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const TileCoordsXY& coords) { @@ -510,7 +538,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const CoordsXY& coords) { @@ -531,7 +560,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const CoordsXYZ& coord) { @@ -556,7 +586,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const CoordsXYZD& coord) { @@ -584,7 +615,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const NetworkCheatType_t& val) { @@ -604,7 +636,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const RCTObjectEntry& val) { @@ -626,7 +659,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const ObjectEntryDescriptor& val) { @@ -670,7 +704,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const TrackDesignTrackElement& val) { @@ -698,7 +733,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const TrackDesignMazeElement& val) { @@ -720,7 +756,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const TrackDesignEntranceElement& val) { @@ -742,7 +779,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const TrackDesignSceneryElement& val) { @@ -778,7 +816,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const TrackColour& val) { @@ -801,7 +840,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const VehicleColour& val) { @@ -823,7 +863,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const RatingTuple& val) { @@ -847,7 +888,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const IntensityRange& val) { @@ -867,7 +909,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const PeepThought& val) { @@ -893,7 +936,8 @@ template<> struct DataSerializerTraitsT } }; -template<> struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const TileCoordsXYZD& coord) { @@ -922,7 +966,8 @@ template<> struct DataSerializerTraitsT } }; -template struct DataSerializerTraitsT> +template +struct DataSerializerTraitsT> { static void encode(OpenRCT2::IStream* stream, const TIdentifier& id) { @@ -943,7 +988,8 @@ template struct DataSerializerTraitsT struct DataSerializerTraitsT +template<> +struct DataSerializerTraitsT { static void encode(OpenRCT2::IStream* stream, const Banner& banner) { diff --git a/src/openrct2/core/Endianness.h b/src/openrct2/core/Endianness.h index 9e6fb23782..76d01b052f 100644 --- a/src/openrct2/core/Endianness.h +++ b/src/openrct2/core/Endianness.h @@ -13,11 +13,13 @@ #include #include -template struct ByteSwapT +template +struct ByteSwapT { }; -template<> struct ByteSwapT<1> +template<> +struct ByteSwapT<1> { using UIntType = uint8_t; static uint8_t SwapBE(uint8_t value) @@ -26,7 +28,8 @@ template<> struct ByteSwapT<1> } }; -template<> struct ByteSwapT<2> +template<> +struct ByteSwapT<2> { using UIntType = uint16_t; static uint16_t SwapBE(uint16_t value) @@ -35,7 +38,8 @@ template<> struct ByteSwapT<2> } }; -template<> struct ByteSwapT<4> +template<> +struct ByteSwapT<4> { using UIntType = uint32_t; static uint32_t SwapBE(uint32_t value) @@ -45,7 +49,8 @@ template<> struct ByteSwapT<4> } }; -template<> struct ByteSwapT<8> +template<> +struct ByteSwapT<8> { using UIntType = uint64_t; static uint64_t SwapBE(uint64_t value) @@ -57,7 +62,8 @@ template<> struct ByteSwapT<8> } }; -template static T ByteSwapBE(const T& value) +template +static T ByteSwapBE(const T& value) { using ByteSwap = ByteSwapT; using UIntType = typename ByteSwap::UIntType; diff --git a/src/openrct2/core/EnumMap.hpp b/src/openrct2/core/EnumMap.hpp index f34562c163..9b8828d4a2 100644 --- a/src/openrct2/core/EnumMap.hpp +++ b/src/openrct2/core/EnumMap.hpp @@ -18,7 +18,8 @@ /** * Bi-directional map for converting between strings and enums / numbers. */ -template class EnumMap +template +class EnumMap { private: std::vector> _map; diff --git a/src/openrct2/core/FileIndex.hpp b/src/openrct2/core/FileIndex.hpp index cd2ddc82cc..548df7c6c4 100644 --- a/src/openrct2/core/FileIndex.hpp +++ b/src/openrct2/core/FileIndex.hpp @@ -26,7 +26,8 @@ #include #include -template class FileIndex +template +class FileIndex { private: struct DirectoryStats diff --git a/src/openrct2/core/FixedVector.h b/src/openrct2/core/FixedVector.h index 056eda03b3..4b6ebe86e3 100644 --- a/src/openrct2/core/FixedVector.h +++ b/src/openrct2/core/FixedVector.h @@ -15,7 +15,8 @@ #include #include -template class FixedVector +template +class FixedVector { public: using container = std::array; @@ -127,7 +128,8 @@ public: return _data.begin() + offset; } - template constexpr reference_type emplace_back(Args&&... args) + template + constexpr reference_type emplace_back(Args&&... args) { OpenRCT2::Guard::Assert(_count < MAX); reference_type res = _data[_count++]; diff --git a/src/openrct2/core/FlagHolder.hpp b/src/openrct2/core/FlagHolder.hpp index 34ff10afe4..7d294a8c88 100644 --- a/src/openrct2/core/FlagHolder.hpp +++ b/src/openrct2/core/FlagHolder.hpp @@ -11,7 +11,8 @@ #include "../util/Util.h" -template struct FlagHolder +template +struct FlagHolder { THolderType holder{}; diff --git a/src/openrct2/core/GroupVector.hpp b/src/openrct2/core/GroupVector.hpp index db2fa0aa36..7fb6fe51a4 100644 --- a/src/openrct2/core/GroupVector.hpp +++ b/src/openrct2/core/GroupVector.hpp @@ -14,7 +14,8 @@ #include #include -template class GroupVector +template +class GroupVector { std::vector> _data; diff --git a/src/openrct2/core/Guard.hpp b/src/openrct2/core/Guard.hpp index 9809af5195..495db209db 100644 --- a/src/openrct2/core/Guard.hpp +++ b/src/openrct2/core/Guard.hpp @@ -37,7 +37,8 @@ namespace OpenRCT2::Guard std::optional GetLastAssertMessage(); - template static void ArgumentNotNull(T* argument, const char* message = nullptr, ...) + template + static void ArgumentNotNull(T* argument, const char* message = nullptr, ...) { va_list args; va_start(args, message); @@ -45,7 +46,8 @@ namespace OpenRCT2::Guard va_end(args); } - template static void ArgumentNotNull(const std::shared_ptr& argument, const char* message = nullptr, ...) + template + static void ArgumentNotNull(const std::shared_ptr& argument, const char* message = nullptr, ...) { va_list args; va_start(args, message); @@ -53,7 +55,8 @@ namespace OpenRCT2::Guard va_end(args); } - template static void ArgumentInRange(T argument, T min, T max, const char* message = nullptr, ...) + template + static void ArgumentInRange(T argument, T min, T max, const char* message = nullptr, ...) { va_list args; va_start(args, message); @@ -61,7 +64,8 @@ namespace OpenRCT2::Guard va_end(args); } - template static void IndexInRange(size_t index, const T& container) + template + static void IndexInRange(size_t index, const T& container) { Guard::Assert(index < container.size(), "Index %zu out of bounds (%zu)", index, container.size()); } diff --git a/src/openrct2/core/IStream.hpp b/src/openrct2/core/IStream.hpp index bd99afc0ca..9d08e2afe8 100644 --- a/src/openrct2/core/IStream.hpp +++ b/src/openrct2/core/IStream.hpp @@ -112,7 +112,8 @@ namespace OpenRCT2 /** * Reads the size of the given type from the stream directly into the given address. */ - template void Read(T* value) + template + void Read(T* value) { // Selects the best path at compile time if constexpr (sizeof(T) == 1) @@ -144,7 +145,8 @@ namespace OpenRCT2 /** * Writes the size of the given type to the stream directly from the given address. */ - template void Write(const T* value) + template + void Write(const T* value) { // Selects the best path at compile time if constexpr (sizeof(T) == 1) @@ -176,7 +178,8 @@ namespace OpenRCT2 /** * Reads the given type from the stream. Use this only for small types (e.g. int8_t, int64_t, double) */ - template T ReadValue() + template + T ReadValue() { T buffer; Read(&buffer); @@ -186,19 +189,22 @@ namespace OpenRCT2 /** * Writes the given type to the stream. Use this only for small types (e.g. int8_t, int64_t, double) */ - template void WriteValue(const T value) + template + void WriteValue(const T value) { Write(&value); } - template [[nodiscard]] std::unique_ptr ReadArray(size_t count) + template + [[nodiscard]] std::unique_ptr ReadArray(size_t count) { auto buffer = std::make_unique(count); Read(buffer.get(), sizeof(T) * count); return buffer; } - template void WriteArray(T* buffer, size_t count) + template + void WriteArray(T* buffer, size_t count) { Write(buffer, sizeof(T) * count); } @@ -224,7 +230,8 @@ public: } }; -template class ivstream : public std::istream +template +class ivstream : public std::istream { private: class vector_streambuf : public std::basic_streambuf> diff --git a/src/openrct2/core/Identifier.hpp b/src/openrct2/core/Identifier.hpp index 9970c6fc97..873da6a8a8 100644 --- a/src/openrct2/core/Identifier.hpp +++ b/src/openrct2/core/Identifier.hpp @@ -12,7 +12,8 @@ #include #include -template class TIdentifier +template +class TIdentifier { enum class ValueType : T { diff --git a/src/openrct2/core/Json.hpp b/src/openrct2/core/Json.hpp index 0c05da97f4..c66ffd6ece 100644 --- a/src/openrct2/core/Json.hpp +++ b/src/openrct2/core/Json.hpp @@ -66,7 +66,8 @@ namespace OpenRCT2::Json * @param defaultValue Default value to return if the JSON object is not a number type * @return Copy of the JSON value converted to the given type */ - template T GetNumber(const json_t& jsonObj, T defaultValue = 0) + template + T GetNumber(const json_t& jsonObj, T defaultValue = 0) { static_assert(std::is_arithmetic::value, "GetNumber template parameter must be arithmetic"); @@ -80,7 +81,8 @@ namespace OpenRCT2::Json * @param defaultValue Default value to return if the JSON object is not an enum type * @return Copy of the JSON value converted to the given enum type */ - template T GetEnum(const json_t& jsonObj, T defaultValue) + template + T GetEnum(const json_t& jsonObj, T defaultValue) { static_assert(std::is_enum::value, "GetEnum template parameter must be an enum"); @@ -124,7 +126,8 @@ namespace OpenRCT2::Json * @param list List of pairs of keys and bits to enable if that key in the object is true * @return Value with relevant bits flipped */ - template T GetFlags(const json_t& jsonObj, std::initializer_list> list) + template + T GetFlags(const json_t& jsonObj, std::initializer_list> list) { static_assert(std::is_convertible::value, "GetFlags template parameter must be integral or a weak enum"); @@ -158,7 +161,8 @@ namespace OpenRCT2::Json * @return Value with relevant bits flipped * @note FLAG_NORMAL behaves like the other GetFlags function, but FLAG_INVERTED will turn the flag on when false */ - template T GetFlags(const json_t& jsonObj, std::initializer_list> list) + template + T GetFlags(const json_t& jsonObj, std::initializer_list> list) { static_assert(std::is_convertible::value, "GetFlags template parameter must be integral or a weak enum"); diff --git a/src/openrct2/core/Memory.hpp b/src/openrct2/core/Memory.hpp index eef2c28451..34a0e69982 100644 --- a/src/openrct2/core/Memory.hpp +++ b/src/openrct2/core/Memory.hpp @@ -20,21 +20,24 @@ */ namespace OpenRCT2::Memory { - template static T* Allocate() + template + static T* Allocate() { T* result = static_cast(malloc(sizeof(T))); Guard::ArgumentNotNull(result, "Failed to allocate %zu bytes for %s", sizeof(T), typeid(T).name()); return result; } - template static T* Allocate(size_t size) + template + static T* Allocate(size_t size) { T* result = static_cast(malloc(size)); Guard::ArgumentNotNull(result, "Failed to allocate %zu bytes for %s", size, typeid(T).name()); return result; } - template static T* Reallocate(T* ptr, size_t size) + template + static T* Reallocate(T* ptr, size_t size) { T* result; if (ptr == nullptr) @@ -49,7 +52,8 @@ namespace OpenRCT2::Memory return result; } - template static void Free(T* ptr) + template + static void Free(T* ptr) { free(const_cast(reinterpret_cast(ptr))); } diff --git a/src/openrct2/core/MemoryStream.h b/src/openrct2/core/MemoryStream.h index 871e0df962..c740cc7157 100644 --- a/src/openrct2/core/MemoryStream.h +++ b/src/openrct2/core/MemoryStream.h @@ -67,7 +67,8 @@ namespace OpenRCT2 void Read8(void* buffer) override; void Read16(void* buffer) override; - template void Read(void* buffer) + template + void Read(void* buffer) { uint64_t position = GetPosition(); if (position + N > _dataSize) @@ -86,7 +87,8 @@ namespace OpenRCT2 void Write8(const void* buffer) override; void Write16(const void* buffer) override; - template void Write(const void* buffer) + template + void Write(const void* buffer) { uint64_t position = GetPosition(); uint64_t nextPosition = position + N; diff --git a/src/openrct2/core/Meta.hpp b/src/openrct2/core/Meta.hpp index 4a374bb15b..4076e65982 100644 --- a/src/openrct2/core/Meta.hpp +++ b/src/openrct2/core/Meta.hpp @@ -16,7 +16,8 @@ namespace OpenRCT2::Meta /** * Meta function for checking that all Conditions are true types. */ - template struct all : std::true_type + template + struct all : std::true_type { }; @@ -25,6 +26,7 @@ namespace OpenRCT2::Meta { }; - template using all_convertible = all...>; + template + using all_convertible = all...>; } // namespace OpenRCT2::Meta diff --git a/src/openrct2/core/Numerics.hpp b/src/openrct2/core/Numerics.hpp index 0dcfad3c04..87e523f81a 100644 --- a/src/openrct2/core/Numerics.hpp +++ b/src/openrct2/core/Numerics.hpp @@ -23,7 +23,8 @@ namespace OpenRCT2::Numerics * @param shift positions to shift * @return rotated value */ - template static constexpr _UIntType rol(_UIntType x, size_t shift) + template + static constexpr _UIntType rol(_UIntType x, size_t shift) { static_assert(std::is_unsigned<_UIntType>::value, "result_type must be an unsigned integral type"); using limits = typename std::numeric_limits<_UIntType>; @@ -49,7 +50,8 @@ namespace OpenRCT2::Numerics * @param shift positions to shift * @return rotated value */ - template static constexpr _UIntType ror(_UIntType x, size_t shift) + template + static constexpr _UIntType ror(_UIntType x, size_t shift) { static_assert(std::is_unsigned<_UIntType>::value, "result_type must be an unsigned integral type"); using limits = std::numeric_limits<_UIntType>; diff --git a/src/openrct2/core/OrcaStream.hpp b/src/openrct2/core/OrcaStream.hpp index 87250bcdfe..3a54b81039 100644 --- a/src/openrct2/core/OrcaStream.hpp +++ b/src/openrct2/core/OrcaStream.hpp @@ -181,7 +181,8 @@ namespace OpenRCT2 return _header; } - template bool ReadWriteChunk(const uint32_t chunkId, TFunc f) + template + bool ReadWriteChunk(const uint32_t chunkId, TFunc f) { if (_mode == Mode::READING) { @@ -287,7 +288,8 @@ namespace OpenRCT2 } } - template::value, bool> = true> void ReadWrite(T& v) + template::value, bool> = true> + void ReadWrite(T& v) { if (_mode == Mode::READING) { @@ -299,7 +301,8 @@ namespace OpenRCT2 } } - template::value, bool> = true> void ReadWrite(T& v) + template::value, bool> = true> + void ReadWrite(T& v) { using underlying = typename std::underlying_type::type; if (_mode == Mode::READING) @@ -312,7 +315,8 @@ namespace OpenRCT2 } } - template void ReadWrite(TIdentifier& value) + template + void ReadWrite(TIdentifier& value) { if (_mode == Mode::READING) { @@ -376,7 +380,8 @@ namespace OpenRCT2 ReadWrite(coords.direction); } - template::value>> T Read() + template::value>> + T Read() { T v{}; ReadWrite(v); @@ -395,7 +400,8 @@ namespace OpenRCT2 } } - template::value>> void Write(T v) + template::value>> + void Write(T v) { if (_mode == Mode::READING) { @@ -434,7 +440,8 @@ namespace OpenRCT2 Write(std::string_view(v)); } - template void ReadWriteVector(TVec& vec, TFunc f) + template + void ReadWriteVector(TVec& vec, TFunc f) { if (_mode == Mode::READING) { @@ -460,7 +467,8 @@ namespace OpenRCT2 } } - template void ReadWriteArray(TArr (&arr)[TArrSize], TFunc f) + template + void ReadWriteArray(TArr (&arr)[TArrSize], TFunc f) { auto& arr2 = *(reinterpret_cast*>(arr)); ReadWriteArray(arr2, f); @@ -500,7 +508,8 @@ namespace OpenRCT2 } } - template void Ignore() + template + void Ignore() { T value{}; ReadWrite(value); @@ -517,7 +526,8 @@ namespace OpenRCT2 _buffer.Write(buffer, len); } - template::value>> T ReadInteger() + template::value>> + T ReadInteger() { if constexpr (sizeof(T) > 4) { @@ -559,7 +569,8 @@ namespace OpenRCT2 } } - template::value>> void WriteInteger(const T value) + template::value>> + void WriteInteger(const T value) { if constexpr (sizeof(T) > 4) { diff --git a/src/openrct2/core/Path.hpp b/src/openrct2/core/Path.hpp index 942ca6ae47..d1499c29e6 100644 --- a/src/openrct2/core/Path.hpp +++ b/src/openrct2/core/Path.hpp @@ -15,7 +15,8 @@ namespace OpenRCT2::Path { [[nodiscard]] u8string Combine(u8string_view a, u8string_view b); - template static u8string Combine(u8string_view a, u8string_view b, Args... args) + template + static u8string Combine(u8string_view a, u8string_view b, Args... args) { return Combine(a, Combine(b, args...)); } diff --git a/src/openrct2/core/Random.hpp b/src/openrct2/core/Random.hpp index 60aba243ec..fc0bee4a16 100644 --- a/src/openrct2/core/Random.hpp +++ b/src/openrct2/core/Random.hpp @@ -27,7 +27,8 @@ namespace OpenRCT2::Random /** * FixedSeedSequence adheres to the _Named Requirement_ `SeedSequence`. */ - template class FixedSeedSequence + template + class FixedSeedSequence { public: using result_type = uint32_t; @@ -60,7 +61,8 @@ namespace OpenRCT2::Random { } - template void generate(TIt begin, TIt end) const + template + void generate(TIt begin, TIt end) const { std::copy_n(v.begin(), std::min(static_cast(end - begin), N), begin); } @@ -70,7 +72,8 @@ namespace OpenRCT2::Random return N; } - template constexpr void param(TIt ob) const + template + constexpr void param(TIt ob) const { std::copy(v.begin(), v.end(), ob); } @@ -79,7 +82,8 @@ namespace OpenRCT2::Random std::array v; }; - template struct RotateEngineState + template + struct RotateEngineState { using value_type = TUIntType; @@ -143,7 +147,8 @@ namespace OpenRCT2::Random s1 = s; } - template typename std::enable_if::value, void>::type seed(TSseq& seed_seq) + template + typename std::enable_if::value, void>::type seed(TSseq& seed_seq) { std::array s; seed_seq.generate(s.begin(), s.end()); diff --git a/src/openrct2/core/Range.hpp b/src/openrct2/core/Range.hpp index e841fb0af5..27c57654f8 100644 --- a/src/openrct2/core/Range.hpp +++ b/src/openrct2/core/Range.hpp @@ -12,7 +12,8 @@ #include #include -template struct Range +template +struct Range { static_assert(std::is_integral(), "type must be integral"); diff --git a/src/openrct2/core/String.cpp b/src/openrct2/core/String.cpp index 630ca6b165..ebc599e947 100644 --- a/src/openrct2/core/String.cpp +++ b/src/openrct2/core/String.cpp @@ -150,7 +150,8 @@ namespace OpenRCT2::String return strcmp(a, b); } - template static bool EqualsImpl(TString&& lhs, TString&& rhs, bool ignoreCase) + template + static bool EqualsImpl(TString&& lhs, TString&& rhs, bool ignoreCase) { return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [ignoreCase](auto a, auto b) { const auto first = static_cast(a); diff --git a/src/openrct2/core/String.hpp b/src/openrct2/core/String.hpp index 7de19f9bb1..19ccf5d77b 100644 --- a/src/openrct2/core/String.hpp +++ b/src/openrct2/core/String.hpp @@ -98,7 +98,8 @@ namespace OpenRCT2::String */ std::string ToUpper(std::string_view src); - template std::optional Parse(std::string_view input) + template + std::optional Parse(std::string_view input) { if (input.size() == 0) return std::nullopt; @@ -130,7 +131,8 @@ namespace OpenRCT2::String /** * Returns string representation of a hexadecimal input, such as SHA256 hash */ - template std::string StringFromHex(T input) + template + std::string StringFromHex(T input) { std::string result; result.reserve(input.size() * 2); diff --git a/src/openrct2/drawing/Drawing.Sprite.BMP.cpp b/src/openrct2/drawing/Drawing.Sprite.BMP.cpp index d7a936d422..0607ab46a5 100644 --- a/src/openrct2/drawing/Drawing.Sprite.BMP.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.BMP.cpp @@ -9,7 +9,8 @@ #include "Drawing.h" -template static void FASTCALL DrawBMPSpriteMagnify(DrawPixelInfo& dpi, const DrawSpriteArgs& args) +template +static void FASTCALL DrawBMPSpriteMagnify(DrawPixelInfo& dpi, const DrawSpriteArgs& args) { auto& paletteMap = args.PalMap; auto src0 = args.SourceImage.offset; @@ -34,7 +35,8 @@ template static void FASTCALL DrawBMPSpriteMagnify(DrawPix } } -template static void FASTCALL DrawBMPSpriteMinify(DrawPixelInfo& dpi, const DrawSpriteArgs& args) +template +static void FASTCALL DrawBMPSpriteMinify(DrawPixelInfo& dpi, const DrawSpriteArgs& args) { auto& g1 = args.SourceImage; auto src = g1.offset + ((static_cast(g1.width) * args.SrcY) + args.SrcX); @@ -59,7 +61,8 @@ template static void FASTCALL DrawBMPSpriteMinify(DrawPixe } } -template static void FASTCALL DrawBMPSprite(DrawPixelInfo& dpi, const DrawSpriteArgs& args) +template +static void FASTCALL DrawBMPSprite(DrawPixelInfo& dpi, const DrawSpriteArgs& args) { if (dpi.zoom_level < ZoomLevel{ 0 }) { diff --git a/src/openrct2/drawing/Drawing.Sprite.RLE.cpp b/src/openrct2/drawing/Drawing.Sprite.RLE.cpp index defed692ee..8713cc5f8c 100644 --- a/src/openrct2/drawing/Drawing.Sprite.RLE.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.RLE.cpp @@ -12,7 +12,8 @@ #include #include -template static void FASTCALL DrawRLESpriteMagnify(DrawPixelInfo& dpi, const DrawSpriteArgs& args) +template +static void FASTCALL DrawRLESpriteMagnify(DrawPixelInfo& dpi, const DrawSpriteArgs& args) { auto& paletteMap = args.PalMap; auto imgData = args.SourceImage.offset; @@ -151,7 +152,8 @@ static void FASTCALL DrawRLESpriteMinify(DrawPixelInfo& dpi, const DrawSpriteArg } } -template static void FASTCALL DrawRLESprite(DrawPixelInfo& dpi, const DrawSpriteArgs& args) +template +static void FASTCALL DrawRLESprite(DrawPixelInfo& dpi, const DrawSpriteArgs& args) { auto zoom_level = static_cast(dpi.zoom_level); switch (zoom_level) diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index 475ce68e8a..5a69037d41 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -451,7 +451,8 @@ struct DrawSpriteArgs } }; -template bool FASTCALL BlitPixel(const uint8_t* src, uint8_t* dst, const PaletteMap& paletteMap) +template +bool FASTCALL BlitPixel(const uint8_t* src, uint8_t* dst, const PaletteMap& paletteMap) { if constexpr (TBlendOp & BLEND_TRANSPARENT) { diff --git a/src/openrct2/drawing/DrawingLock.hpp b/src/openrct2/drawing/DrawingLock.hpp index 44a7f5303e..2d0de20ae0 100644 --- a/src/openrct2/drawing/DrawingLock.hpp +++ b/src/openrct2/drawing/DrawingLock.hpp @@ -13,7 +13,8 @@ using namespace OpenRCT2; -template class DrawingUniqueLock +template +class DrawingUniqueLock { T& _mutex; const bool _enabled; @@ -33,7 +34,8 @@ public: } }; -template class DrawingSharedLock +template +class DrawingSharedLock { T& _mutex; const bool _enabled; diff --git a/src/openrct2/entity/Balloon.cpp b/src/openrct2/entity/Balloon.cpp index 3bc32aaade..8d55d2047e 100644 --- a/src/openrct2/entity/Balloon.cpp +++ b/src/openrct2/entity/Balloon.cpp @@ -20,7 +20,8 @@ #include "../world/tile_element/TrackElement.h" #include "EntityRegistry.h" -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::Balloon; } diff --git a/src/openrct2/entity/Duck.cpp b/src/openrct2/entity/Duck.cpp index 14f6cd2482..7c291c9483 100644 --- a/src/openrct2/entity/Duck.cpp +++ b/src/openrct2/entity/Duck.cpp @@ -71,7 +71,8 @@ static constexpr const uint8_t * kDuckAnimations[] = }; // clang-format on -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::Duck; } diff --git a/src/openrct2/entity/EntityBase.cpp b/src/openrct2/entity/EntityBase.cpp index 862211a732..48322a8e62 100644 --- a/src/openrct2/entity/EntityBase.cpp +++ b/src/openrct2/entity/EntityBase.cpp @@ -15,7 +15,8 @@ using namespace OpenRCT2; // Required for GetEntity to return a default -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return true; } diff --git a/src/openrct2/entity/EntityBase.h b/src/openrct2/entity/EntityBase.h index bee06c1021..77b887aff2 100644 --- a/src/openrct2/entity/EntityBase.h +++ b/src/openrct2/entity/EntityBase.h @@ -65,12 +65,15 @@ struct EntityBase CoordsXYZ GetLocation() const; void Invalidate(); - template bool Is() const; - template T* As() + template + bool Is() const; + template + T* As() { return Is() ? reinterpret_cast(this) : nullptr; } - template const T* As() const + template + const T* As() const { return Is() ? reinterpret_cast(this) : nullptr; } diff --git a/src/openrct2/entity/EntityList.h b/src/openrct2/entity/EntityList.h index e0368d507b..a2ce3ae351 100644 --- a/src/openrct2/entity/EntityList.h +++ b/src/openrct2/entity/EntityList.h @@ -24,7 +24,8 @@ uint16_t GetMiscEntityCount(); uint16_t GetNumFreeEntities(); const std::vector& GetEntityTileList(const CoordsXY& spritePos); -template class EntityTileIterator +template +class EntityTileIterator { private: std::vector::const_iterator iter; @@ -75,7 +76,8 @@ public: using iterator_category = std::forward_iterator_tag; }; -template class EntityTileList +template +class EntityTileList { private: const std::vector& vec; @@ -96,7 +98,8 @@ public: } }; -template class EntityListIterator +template +class EntityListIterator { private: std::list::const_iterator iter; @@ -147,7 +150,8 @@ public: using iterator_category = std::forward_iterator_tag; }; -template class EntityList +template +class EntityList { private: using EntityListIterator_t = EntityListIterator; diff --git a/src/openrct2/entity/EntityRegistry.cpp b/src/openrct2/entity/EntityRegistry.cpp index 3a0104a815..b3a5f76991 100644 --- a/src/openrct2/entity/EntityRegistry.cpp +++ b/src/openrct2/entity/EntityRegistry.cpp @@ -222,7 +222,8 @@ void ResetEntitySpatialIndices() #ifndef DISABLE_NETWORK -template void NetworkSerialseEntityType(DataSerialiser& ds) +template +void NetworkSerialseEntityType(DataSerialiser& ds) { for (auto* ent : EntityList()) { @@ -230,7 +231,8 @@ template void NetworkSerialseEntityType(DataSerialiser& ds) } } -template void NetworkSerialiseEntityTypes(DataSerialiser& ds) +template +void NetworkSerialiseEntityTypes(DataSerialiser& ds) { (NetworkSerialseEntityType(ds), ...); } @@ -380,7 +382,8 @@ EntityBase* CreateEntityAt(const EntityId index, const EntityType type) return entity; } -template void MiscUpdateAllType() +template +void MiscUpdateAllType() { for (auto misc : EntityList()) { @@ -388,7 +391,8 @@ template void MiscUpdateAllType() } } -template void MiscUpdateAllTypes() +template +void MiscUpdateAllTypes() { (MiscUpdateAllType(), ...); } diff --git a/src/openrct2/entity/EntityRegistry.h b/src/openrct2/entity/EntityRegistry.h index 7fea52cd94..b33230e710 100644 --- a/src/openrct2/entity/EntityRegistry.h +++ b/src/openrct2/entity/EntityRegistry.h @@ -30,7 +30,8 @@ constexpr uint16_t MAX_ENTITIES = 65535; EntityBase* GetEntity(EntityId sprite_idx); -template T* GetEntity(EntityId sprite_idx) +template +T* GetEntity(EntityId sprite_idx) { auto spr = GetEntity(sprite_idx); return spr != nullptr ? spr->As() : nullptr; @@ -38,7 +39,8 @@ template T* GetEntity(EntityId sprite_idx) EntityBase* TryGetEntity(EntityId spriteIndex); -template T* TryGetEntity(EntityId sprite_idx) +template +T* TryGetEntity(EntityId sprite_idx) { auto spr = TryGetEntity(sprite_idx); return spr != nullptr ? spr->As() : nullptr; @@ -46,7 +48,8 @@ template T* TryGetEntity(EntityId sprite_idx) EntityBase* CreateEntity(EntityType type); -template T* CreateEntity() +template +T* CreateEntity() { return static_cast(CreateEntity(T::cEntityType)); } @@ -54,7 +57,8 @@ template T* CreateEntity() // Use only with imports that must happen at a specified index EntityBase* CreateEntityAt(const EntityId index, const EntityType type); // Use only with imports that must happen at a specified index -template T* CreateEntityAt(const EntityId index) +template +T* CreateEntityAt(const EntityId index) { return static_cast(CreateEntityAt(index, T::cEntityType)); } diff --git a/src/openrct2/entity/Fountain.cpp b/src/openrct2/entity/Fountain.cpp index 7125959be8..78f8f06572 100644 --- a/src/openrct2/entity/Fountain.cpp +++ b/src/openrct2/entity/Fountain.cpp @@ -83,7 +83,8 @@ const uint8_t _fountainPatternFlags[] = { FOUNTAIN_FLAG::FAST, // FAST_RANDOM_CHASERS }; -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::JumpingFountain; } diff --git a/src/openrct2/entity/Guest.cpp b/src/openrct2/entity/Guest.cpp index ca22b6f587..060601edb3 100644 --- a/src/openrct2/entity/Guest.cpp +++ b/src/openrct2/entity/Guest.cpp @@ -454,7 +454,8 @@ static void PeepLeavePark(Guest* peep); static void PeepHeadForNearestRideWithFlag(Guest* peep, bool considerOnlyCloseRides, RtdFlag rtdFlag); bool Loc690FD0(Peep* peep, RideId* rideToView, uint8_t* rideSeatToView, TileElement* tileElement); -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::Guest; } @@ -472,7 +473,8 @@ static bool IsValidLocation(const CoordsXYZ& coords) return false; } -template static void ApplyEasterEggToNearbyGuests(Guest* guest) +template +static void ApplyEasterEggToNearbyGuests(Guest* guest) { const auto guestLoc = guest->GetLocation(); if (!IsValidLocation(guestLoc)) @@ -3140,7 +3142,8 @@ static void PeepLeavePark(Guest* peep) WindowInvalidateByNumber(WindowClass::Peep, peep->Id); } -template static void PeepHeadForNearestRide(Guest* peep, bool considerOnlyCloseRides, T predicate) +template +static void PeepHeadForNearestRide(Guest* peep, bool considerOnlyCloseRides, T predicate) { if (peep->State != PeepState::Sitting && peep->State != PeepState::Watching && peep->State != PeepState::Walking) { diff --git a/src/openrct2/entity/Litter.cpp b/src/openrct2/entity/Litter.cpp index 0919ea9825..3a8d38fe33 100644 --- a/src/openrct2/entity/Litter.cpp +++ b/src/openrct2/entity/Litter.cpp @@ -15,7 +15,8 @@ using namespace OpenRCT2; -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::Litter; } diff --git a/src/openrct2/entity/MoneyEffect.cpp b/src/openrct2/entity/MoneyEffect.cpp index 88a66b92d2..54ad6635bd 100644 --- a/src/openrct2/entity/MoneyEffect.cpp +++ b/src/openrct2/entity/MoneyEffect.cpp @@ -32,7 +32,8 @@ static constexpr CoordsXY _moneyEffectMoveOffset[] = { { -1, -1 }, }; -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::MoneyEffect; } diff --git a/src/openrct2/entity/Particle.cpp b/src/openrct2/entity/Particle.cpp index c648687298..8440539e64 100644 --- a/src/openrct2/entity/Particle.cpp +++ b/src/openrct2/entity/Particle.cpp @@ -24,27 +24,32 @@ static constexpr uint32_t _VehicleCrashParticleSprites[kCrashedVehicleParticleNu 22577, 22589, 22601, 22613, 22625, }; -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::SteamParticle; } -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::ExplosionFlare; } -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::ExplosionCloud; } -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::CrashedVehicleParticle; } -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::CrashSplash; } diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index 962221d2ce..a3806d5077 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -125,7 +125,8 @@ const bool gAnimationGroupToSlowWalkMap[] = { true, true, true, true, true, true, false, true, false, true, true, true, true, true, true, true, }; -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::Guest || Type == EntityType::Staff; } diff --git a/src/openrct2/entity/Staff.cpp b/src/openrct2/entity/Staff.cpp index 2bc911ab5f..a496d9add6 100644 --- a/src/openrct2/entity/Staff.cpp +++ b/src/openrct2/entity/Staff.cpp @@ -75,7 +75,8 @@ const StringId StaffCostumeNames[] = { // Maximum manhattan distance that litter can be for a handyman to seek to it const uint16_t MAX_LITTER_DISTANCE = 3 * kCoordsXYStep; -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::Staff; } diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index 03e48f1409..cbc7a730f4 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -244,7 +244,8 @@ void WindowFlushDead() g_window_list.remove_if([](auto&& w) -> bool { return w->flags & WF_DEAD; }); } -template static void WindowCloseByCondition(TPred pred, uint32_t flags = WindowCloseFlags::None) +template +static void WindowCloseByCondition(TPred pred, uint32_t flags = WindowCloseFlags::None) { for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); ++it) { @@ -476,7 +477,8 @@ WidgetIndex WindowFindWidgetFromPoint(WindowBase& w, const ScreenCoordsXY& scree * * @param window The window to invalidate (esi). */ -template static void WindowInvalidateByCondition(TPred pred) +template +static void WindowInvalidateByCondition(TPred pred) { WindowVisitEach([pred](WindowBase* w) { if (pred(w)) @@ -541,7 +543,8 @@ void WidgetInvalidate(WindowBase& w, WidgetIndex widgetIndex) { w.windowPos + ScreenCoordsXY{ widget.right + 1, widget.bottom + 1 } } }); } -template static void widget_invalidate_by_condition(TPred pred) +template +static void widget_invalidate_by_condition(TPred pred) { WindowVisitEach([pred](WindowBase* w) { if (pred(w)) diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index d14ebd9a04..7595214fe3 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -198,7 +198,8 @@ struct Focus ZoomLevel zoom{}; std::variant data; - template constexpr explicit Focus(T newValue, ZoomLevel newZoom = {}) + template + constexpr explicit Focus(T newValue, ZoomLevel newZoom = {}) { data = newValue; zoom = newZoom; diff --git a/src/openrct2/interface/ZoomLevel.h b/src/openrct2/interface/ZoomLevel.h index bed59b820d..cca7f2b750 100644 --- a/src/openrct2/interface/ZoomLevel.h +++ b/src/openrct2/interface/ZoomLevel.h @@ -53,7 +53,8 @@ public: friend constexpr bool operator>(const ZoomLevel& lhs, const ZoomLevel& rhs); friend constexpr bool operator<(const ZoomLevel& lhs, const ZoomLevel& rhs); - template constexpr T ApplyTo(const T& lhs) const + template + constexpr T ApplyTo(const T& lhs) const { if (_level < 0) return lhs >> -_level; @@ -61,7 +62,8 @@ public: return lhs << _level; } - template constexpr T ApplyInversedTo(const T& lhs) const + template + constexpr T ApplyInversedTo(const T& lhs) const { if (_level < 0) return lhs << -_level; diff --git a/src/openrct2/localisation/Formatter.h b/src/openrct2/localisation/Formatter.h index f9ca912bb0..fb29af30cb 100644 --- a/src/openrct2/localisation/Formatter.h +++ b/src/openrct2/localisation/Formatter.h @@ -79,7 +79,8 @@ public: return CurrentBuf - StartBuf; } - template Formatter& Add(TDeduced value) + template + Formatter& Add(TDeduced value) { static_assert(sizeof(TSpecified) <= sizeof(uint64_t), "Type too large"); static_assert(sizeof(TDeduced) <= sizeof(uint64_t), "Type too large"); diff --git a/src/openrct2/localisation/Formatting.cpp b/src/openrct2/localisation/Formatting.cpp index 24df9fe32f..10cc645550 100644 --- a/src/openrct2/localisation/Formatting.cpp +++ b/src/openrct2/localisation/Formatting.cpp @@ -317,7 +317,8 @@ namespace OpenRCT2 } } - template void FormatNumber(FormatBuffer& ss, T value) + template + void FormatNumber(FormatBuffer& ss, T value) { char buffer[32]; size_t i = 0; @@ -395,7 +396,8 @@ namespace OpenRCT2 } } - template void FormatCurrency(FormatBuffer& ss, T rawValue) + template + void FormatCurrency(FormatBuffer& ss, T rawValue) { auto currencyDesc = &CurrencyDescriptors[EnumValue(Config::Get().general.CurrencyFormat)]; auto value = static_cast(rawValue) * currencyDesc->rate; @@ -450,7 +452,8 @@ namespace OpenRCT2 } } - template static void FormatMinutesSeconds(FormatBuffer& ss, T value) + template + static void FormatMinutesSeconds(FormatBuffer& ss, T value) { static constexpr StringId Formats[][2] = { { STR_DURATION_SEC, STR_DURATION_SECS }, @@ -472,7 +475,8 @@ namespace OpenRCT2 } } - template static void FormatHoursMinutes(FormatBuffer& ss, T value) + template + static void FormatHoursMinutes(FormatBuffer& ss, T value) { static constexpr StringId Formats[][2] = { { STR_REALTIME_MIN, STR_REALTIME_MINS }, @@ -494,7 +498,8 @@ namespace OpenRCT2 } } - template void FormatArgument(FormatBuffer& ss, FormatToken token, T arg) + template + void FormatArgument(FormatBuffer& ss, FormatToken token, T arg) { switch (token) { @@ -777,7 +782,8 @@ namespace OpenRCT2 return CopyStringStreamToBuffer(buffer, bufferLen, ss); } - template static T ReadFromArgs(const void*& args) + template + static T ReadFromArgs(const void*& args) { T value; std::memcpy(&value, args, sizeof(T)); diff --git a/src/openrct2/localisation/Formatting.h b/src/openrct2/localisation/Formatting.h index b60bb586d7..dad8215edb 100644 --- a/src/openrct2/localisation/Formatting.h +++ b/src/openrct2/localisation/Formatting.h @@ -26,7 +26,8 @@ namespace OpenRCT2 // TODO: find a better spot for this (RCT12.h?) constexpr size_t kUserStringMaxLength = 32; - template> class FormatBufferBase + template> + class FormatBufferBase { T _storage[StackSize]; T* _buffer; @@ -79,7 +80,8 @@ namespace OpenRCT2 return _buffer; } - template auto& operator<<(T const (&v)[N]) + template + auto& operator<<(T const (&v)[N]) { append(v, N); return *this; @@ -200,7 +202,8 @@ namespace OpenRCT2 std::string WithoutFormatTokens() const; }; - template void FormatArgument(FormatBuffer& ss, FormatToken token, T arg); + template + void FormatArgument(FormatBuffer& ss, FormatToken token, T arg); bool IsRealNameStringId(StringId id); void FormatRealName(FormatBuffer& ss, StringId id); @@ -264,14 +267,16 @@ namespace OpenRCT2 } } - template static void FormatString(FormatBuffer& ss, const FmtString& fmt, TArgs&&... argN) + template + static void FormatString(FormatBuffer& ss, const FmtString& fmt, TArgs&&... argN) { std::stack stack; stack.push(fmt.begin()); FormatString(ss, stack, argN...); } - template std::string FormatString(const FmtString& fmt, TArgs&&... argN) + template + std::string FormatString(const FmtString& fmt, TArgs&&... argN) { auto& ss = GetThreadFormatStream(); FormatString(ss, fmt, argN...); @@ -286,19 +291,22 @@ namespace OpenRCT2 return CopyStringStreamToBuffer(buffer, bufferLen, ss); } - template static void FormatStringID(FormatBuffer& ss, StringId id, TArgs&&... argN) + template + static void FormatStringID(FormatBuffer& ss, StringId id, TArgs&&... argN) { auto fmt = GetFmtStringById(id); FormatString(ss, fmt, argN...); } - template std::string FormatStringID(StringId id, TArgs&&... argN) + template + std::string FormatStringID(StringId id, TArgs&&... argN) { auto fmt = GetFmtStringById(id); return FormatString(fmt, argN...); } - template size_t FormatStringID(char* buffer, size_t bufferLen, StringId id, TArgs&&... argN) + template + size_t FormatStringID(char* buffer, size_t bufferLen, StringId id, TArgs&&... argN) { auto& ss = GetThreadFormatStream(); FormatStringID(ss, id, argN...); diff --git a/src/openrct2/management/NewsItem.h b/src/openrct2/management/NewsItem.h index 5896346876..a5a381822d 100644 --- a/src/openrct2/management/NewsItem.h +++ b/src/openrct2/management/NewsItem.h @@ -120,7 +120,8 @@ namespace OpenRCT2::News constexpr int32_t MaxItemsArchive = 50; constexpr int32_t MaxItems = News::ItemHistoryStart + News::MaxItemsArchive; - template class ItemQueue + template + class ItemQueue { public: static_assert(N > 0, "Cannot instantiate News::ItemQueue with size=0"); @@ -264,7 +265,8 @@ namespace OpenRCT2::News return Archived; } - template void ForeachRecentNews(Predicate&& p) + template + void ForeachRecentNews(Predicate&& p) { for (auto& newsItem : Recent) { @@ -272,7 +274,8 @@ namespace OpenRCT2::News } } - template void ForeachArchivedNews(Predicate&& p) + template + void ForeachArchivedNews(Predicate&& p) { for (auto& newsItem : Archived) { diff --git a/src/openrct2/network/NetworkPacket.h b/src/openrct2/network/NetworkPacket.h index 1bf26372b7..20f4a7cd87 100644 --- a/src/openrct2/network/NetworkPacket.h +++ b/src/openrct2/network/NetworkPacket.h @@ -43,7 +43,8 @@ struct NetworkPacket final void Write(const void* bytes, size_t size); void WriteString(std::string_view s); - template NetworkPacket& operator>>(T& value) + template + NetworkPacket& operator>>(T& value) { if (BytesRead + sizeof(value) > Header.Size) { @@ -59,7 +60,8 @@ struct NetworkPacket final return *this; } - template NetworkPacket& operator<<(T value) + template + NetworkPacket& operator<<(T value) { T swapped = ByteSwapBE(value); Write(&swapped, sizeof(T)); diff --git a/src/openrct2/network/NetworkTypes.h b/src/openrct2/network/NetworkTypes.h index 3ce6496d3c..2595e35987 100644 --- a/src/openrct2/network/NetworkTypes.h +++ b/src/openrct2/network/NetworkTypes.h @@ -108,7 +108,8 @@ struct NetworkServerState // this structure can be used in combination with DataSerialiser // to provide extra details with template specialization. #pragma pack(push, 1) -template struct NetworkObjectId +template +struct NetworkObjectId { NetworkObjectId(T v) : id(v) diff --git a/src/openrct2/object/ObjectAsset.h b/src/openrct2/object/ObjectAsset.h index 2582a01537..8c23d62cca 100644 --- a/src/openrct2/object/ObjectAsset.h +++ b/src/openrct2/object/ObjectAsset.h @@ -48,7 +48,8 @@ public: friend bool operator==(const ObjectAsset& l, const ObjectAsset& r); }; -template<> struct std::hash +template<> +struct std::hash { std::size_t operator()(const ObjectAsset& asset) const noexcept { diff --git a/src/openrct2/object/ObjectEntryManager.h b/src/openrct2/object/ObjectEntryManager.h index de8a1a143d..0cf2e733b2 100644 --- a/src/openrct2/object/ObjectEntryManager.h +++ b/src/openrct2/object/ObjectEntryManager.h @@ -15,7 +15,8 @@ namespace OpenRCT2::ObjectManager { const void* GetObjectEntry(ObjectType type, ObjectEntryIndex idx); - template const T* GetObjectEntry(ObjectEntryIndex idx) + template + const T* GetObjectEntry(ObjectEntryIndex idx) { return reinterpret_cast(GetObjectEntry(T::kObjectType, idx)); } diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index 64cf37bf76..4c1f202ba4 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -472,7 +472,8 @@ private: LOG_VERBOSE("%u / %u objects unloaded", numObjectsUnloaded, totalObjectsLoaded); } - template void UpdateSceneryGroupIndexes(ObjectType type) + template + void UpdateSceneryGroupIndexes(ObjectType type) { auto& list = GetObjectList(type); for (auto* loadedObject : list) diff --git a/src/openrct2/object/ObjectManager.h b/src/openrct2/object/ObjectManager.h index eee1357f8e..43377730ee 100644 --- a/src/openrct2/object/ObjectManager.h +++ b/src/openrct2/object/ObjectManager.h @@ -26,7 +26,8 @@ struct IObjectManager } virtual Object* GetLoadedObject(ObjectType objectType, size_t index) = 0; - template TClass* GetLoadedObject(size_t index) + template + TClass* GetLoadedObject(size_t index) { return static_cast(GetLoadedObject(TClass::kObjectType, index)); } diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index 209d317f1d..b52aa7a68e 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -216,7 +216,8 @@ static PaintStruct* CreateNormalPaintStruct( return ps; } -template void PaintSessionGenerateRotate(PaintSession& session) +template +void PaintSessionGenerateRotate(PaintSession& session) { // Optimised modified version of ViewportPosToMapPos ScreenCoordsXY screenCoord = { Floor2(session.DPI.WorldX(), 32), Floor2((session.DPI.WorldY() - 16), 32) }; @@ -400,7 +401,8 @@ static std::pair PaintStructsGetNextPending(PaintStr // Re-orders all nodes after the specified child node and marks the child node as traversed. The resulting // order of the children is the depth based on rotation and dimensions of the bounding box. -template static void PaintStructsSortQuadrant(PaintStruct* parent, PaintStruct* child) +template +static void PaintStructsSortQuadrant(PaintStruct* parent, PaintStruct* child) { // Mark visited. child->SortFlags &= ~PaintSortFlags::PendingVisit; @@ -493,7 +495,8 @@ static void PaintStructsLinkQuadrants(PaintSessionCore& session, PaintStruct& ps } while (++quadrantIndex <= session.QuadrantFrontIndex); } -template static void PaintSessionArrangeImpl(PaintSessionCore& session) +template +static void PaintSessionArrangeImpl(PaintSessionCore& session) { uint32_t quadrantIndex = session.QuadrantBackIndex; if (quadrantIndex == UINT32_MAX) diff --git a/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp b/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp index 71ef1bb951..f386327a34 100644 --- a/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/JuniorRollerCoaster.cpp @@ -1851,7 +1851,8 @@ static constexpr const uint32_t junior_rc_track_pieces_diag_blockbrakes[2][4] = }, }; -template constexpr uint8_t JuniorRCGetSubTypeOffset(const TrackElement& trackElement) +template +constexpr uint8_t JuniorRCGetSubTypeOffset(const TrackElement& trackElement) { return trackElement.HasChain() ? EnumValue(TSubType) : 0; } @@ -5799,7 +5800,8 @@ static void JuniorRCTrackOnRidePhoto( } /* 0x008AAA0C */ -template TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRCTemplate(OpenRCT2::TrackElemType trackType) +template +TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRCTemplate(OpenRCT2::TrackElemType trackType) { switch (trackType) { diff --git a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp index bbf9b4f551..40d2c871f4 100644 --- a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp @@ -17628,7 +17628,8 @@ static void WoodenRCTrackRightLargeHalfLoopDown( WoodenRCTrackLeftLargeHalfLoopUp(session, ride, 6 - trackSequence, direction, height, trackElement, supportType); } -template TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenAndClassicWoodenRC(OpenRCT2::TrackElemType trackType) +template +TRACK_PAINT_FUNCTION GetTrackPaintFunctionWoodenAndClassicWoodenRC(OpenRCT2::TrackElemType trackType) { switch (trackType) { diff --git a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.h b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.h index be09c32a16..0347a3d74e 100644 --- a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.h +++ b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.h @@ -40,7 +40,8 @@ static constexpr const WoodenSupportSubType WoodenRCDiagonalSupports[4][kNumOrth WoodenSupportSubType::Null } // sequence 3 }; -template ImageId WoodenRCGetTrackColour(const PaintSession& session) +template +ImageId WoodenRCGetTrackColour(const PaintSession& session) { if (isClassic) return session.TrackColours; @@ -62,7 +63,8 @@ PaintStruct* WoodenRCTrackPaint( return PaintAddImageAsChildRotated(session, direction, railsImageId, offset, boundBox); } -template void WoodenRCTrackPaintBb(PaintSession& session, const SpriteBoundBox2* bb, int16_t height) +template +void WoodenRCTrackPaintBb(PaintSession& session, const SpriteBoundBox2* bb, int16_t height) { if (bb->ImageIdA == 0) return; diff --git a/src/openrct2/park/ParkFile.cpp b/src/openrct2/park/ParkFile.cpp index 5ce16b396f..47b5b92280 100644 --- a/src/openrct2/park/ParkFile.cpp +++ b/src/openrct2/park/ParkFile.cpp @@ -1640,7 +1640,8 @@ namespace OpenRCT2 } } - template static void ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, T& entity); + template + static void ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, T& entity); static void ReadWriteEntityCommon(OrcaStream::ChunkStream& cs, EntityBase& entity) { @@ -2035,12 +2036,16 @@ namespace OpenRCT2 } } - template void WriteEntitiesOfType(OrcaStream& os, OrcaStream::ChunkStream& cs); - template void WriteEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs); + template + void WriteEntitiesOfType(OrcaStream& os, OrcaStream::ChunkStream& cs); + template + void WriteEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs); - template void ReadEntitiesOfType(OrcaStream& os, OrcaStream::ChunkStream& cs); + template + void ReadEntitiesOfType(OrcaStream& os, OrcaStream::ChunkStream& cs); - template void ReadEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs); + template + void ReadEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs); void ReadWriteEntitiesChunk(GameState_t& gameState, OrcaStream& os); @@ -2076,7 +2081,8 @@ namespace OpenRCT2 } }; - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Vehicle& entity) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Vehicle& entity) { ReadWriteEntityCommon(cs, entity); cs.ReadWrite(entity.SubType); @@ -2192,7 +2198,8 @@ namespace OpenRCT2 } } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Guest& guest) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Guest& guest) { ReadWritePeep(os, cs, guest); auto version = os.GetHeader().TargetVersion; @@ -2364,7 +2371,8 @@ namespace OpenRCT2 cs.ReadWrite(guest.ItemFlags); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Staff& entity) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Staff& entity) { ReadWritePeep(os, cs, entity); @@ -2410,14 +2418,16 @@ namespace OpenRCT2 cs.ReadWrite(entity.StaffBinsEmptied); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, SteamParticle& steamParticle) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, SteamParticle& steamParticle) { ReadWriteEntityCommon(cs, steamParticle); cs.ReadWrite(steamParticle.time_to_move); cs.ReadWrite(steamParticle.frame); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, MoneyEffect& moneyEffect) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, MoneyEffect& moneyEffect) { ReadWriteEntityCommon(cs, moneyEffect); cs.ReadWrite(moneyEffect.MoveDelay); @@ -2446,25 +2456,29 @@ namespace OpenRCT2 cs.ReadWrite(vehicleCrashParticle.acceleration_z); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, ExplosionCloud& entity) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, ExplosionCloud& entity) { ReadWriteEntityCommon(cs, entity); cs.ReadWrite(entity.frame); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, CrashSplashParticle& entity) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, CrashSplashParticle& entity) { ReadWriteEntityCommon(cs, entity); cs.ReadWrite(entity.frame); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, ExplosionFlare& entity) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, ExplosionFlare& entity) { ReadWriteEntityCommon(cs, entity); cs.ReadWrite(entity.frame); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, JumpingFountain& fountain) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, JumpingFountain& fountain) { ReadWriteEntityCommon(cs, fountain); cs.ReadWrite(fountain.NumTicksAlive); @@ -2476,7 +2490,8 @@ namespace OpenRCT2 cs.ReadWrite(fountain.Iteration); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Balloon& balloon) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Balloon& balloon) { ReadWriteEntityCommon(cs, balloon); cs.ReadWrite(balloon.popped); @@ -2485,7 +2500,8 @@ namespace OpenRCT2 cs.ReadWrite(balloon.colour); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Duck& duck) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Duck& duck) { ReadWriteEntityCommon(cs, duck); cs.ReadWrite(duck.frame); @@ -2494,14 +2510,16 @@ namespace OpenRCT2 cs.ReadWrite(duck.state); } - template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Litter& entity) + template<> + void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Litter& entity) { ReadWriteEntityCommon(cs, entity); cs.ReadWrite(entity.SubType); cs.ReadWrite(entity.creationTick); } - template void ParkFile::WriteEntitiesOfType(OrcaStream& os, OrcaStream::ChunkStream& cs) + template + void ParkFile::WriteEntitiesOfType(OrcaStream& os, OrcaStream::ChunkStream& cs) { uint16_t count = GetEntityListCount(T::cEntityType); cs.Write(T::cEntityType); @@ -2513,12 +2531,14 @@ namespace OpenRCT2 } } - template void ParkFile::WriteEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs) + template + void ParkFile::WriteEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs) { (WriteEntitiesOfType(os, cs), ...); } - template void ParkFile::ReadEntitiesOfType(OrcaStream& os, OrcaStream::ChunkStream& cs) + template + void ParkFile::ReadEntitiesOfType(OrcaStream& os, OrcaStream::ChunkStream& cs) { [[maybe_unused]] auto t = cs.Read(); assert(t == T::cEntityType); @@ -2538,7 +2558,8 @@ namespace OpenRCT2 } } - template void ParkFile::ReadEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs) + template + void ParkFile::ReadEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs) { (ReadEntitiesOfType(os, cs), ...); } diff --git a/src/openrct2/platform/Platform.macOS.mm b/src/openrct2/platform/Platform.macOS.mm index 33015a37ff..7e2011698b 100644 --- a/src/openrct2/platform/Platform.macOS.mm +++ b/src/openrct2/platform/Platform.macOS.mm @@ -101,9 +101,10 @@ namespace OpenRCT2::Platform auto exeDirectory = Path::GetDirectory(exePath); // check build and install paths - NSArray *dataSearchLocations = @[@"data", @"../share/openrct2"]; + NSArray* dataSearchLocations = @[ @"data", @"../share/openrct2" ]; - for (NSString *searchLocation in dataSearchLocations) { + for (NSString* searchLocation in dataSearchLocations) + { path = Path::Combine(exeDirectory, [searchLocation UTF8String]); NSString* nsPath = [NSString stringWithUTF8String:path.c_str()]; if ([[NSFileManager defaultManager] fileExistsAtPath:nsPath]) @@ -290,6 +291,6 @@ namespace OpenRCT2::Platform { return {}; } -} +} // namespace OpenRCT2::Platform #endif diff --git a/src/openrct2/profiling/Profiling.h b/src/openrct2/profiling/Profiling.h index f3e91bd0f4..ece1436988 100644 --- a/src/openrct2/profiling/Profiling.h +++ b/src/openrct2/profiling/Profiling.h @@ -137,7 +137,8 @@ namespace OpenRCT2::Profiling } }; - template struct FunctionWrapper : FunctionInternal + template + struct FunctionWrapper : FunctionInternal { const char* GetName() const noexcept override { @@ -149,7 +150,8 @@ namespace OpenRCT2::Profiling // This avoids the compiler generating thread-safe initialization // by making a unique type per function which hosts a global using // the inline keyword for the variable (C++17). - template struct Storage + template + struct Storage { static inline FunctionWrapper Data; }; @@ -159,7 +161,8 @@ namespace OpenRCT2::Profiling } // namespace Detail - template class ScopedProfiling + template + class ScopedProfiling { bool _enabled; T& _func; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 553efaab6d..f9f6362ac2 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1240,7 +1240,8 @@ namespace OpenRCT2::RCT1 } void ImportEntity(const RCT12EntityBase& src); - template void ImportEntity(const RCT12EntityBase& src); + template + void ImportEntity(const RCT12EntityBase& src); void ImportEntities() { @@ -2678,7 +2679,8 @@ namespace OpenRCT2::RCT1 return output; } - template<> void S4Importer::ImportEntity<::Vehicle>(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity<::Vehicle>(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt<::Vehicle>(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2800,7 +2802,8 @@ namespace OpenRCT2::RCT1 } } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2891,7 +2894,8 @@ namespace OpenRCT2::RCT1 dst->SetItemFlags(src->GetItemFlags()); } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2909,7 +2913,8 @@ namespace OpenRCT2::RCT1 ImportStaffPatrolArea(dst, src->StaffID); } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2919,7 +2924,8 @@ namespace OpenRCT2::RCT1 dst->creationTick = src->CreationTick; } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2929,7 +2935,8 @@ namespace OpenRCT2::RCT1 dst->time_to_move = src->TimeToMove; } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2943,7 +2950,8 @@ namespace OpenRCT2::RCT1 dst->Wiggle = src->Wiggle; } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2961,7 +2969,8 @@ namespace OpenRCT2::RCT1 dst->acceleration_z = src->AccelerationZ; } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2969,7 +2978,8 @@ namespace OpenRCT2::RCT1 dst->frame = src->Frame; } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2977,7 +2987,8 @@ namespace OpenRCT2::RCT1 dst->frame = src->Frame; } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -2985,7 +2996,8 @@ namespace OpenRCT2::RCT1 dst->frame = src->Frame; } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -3004,7 +3016,8 @@ namespace OpenRCT2::RCT1 dst->Iteration = src->Iteration; } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); @@ -3024,7 +3037,8 @@ namespace OpenRCT2::RCT1 } } - template<> void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) + template<> + void S4Importer::ImportEntity(const RCT12EntityBase& srcBase) { auto* dst = CreateEntityAt(EntityId::FromUnderlying(srcBase.EntityIndex)); auto* src = static_cast(&srcBase); diff --git a/src/openrct2/rct12/CSStringConverter.cpp b/src/openrct2/rct12/CSStringConverter.cpp index 5b739e249b..c3505c74af 100644 --- a/src/openrct2/rct12/CSStringConverter.cpp +++ b/src/openrct2/rct12/CSStringConverter.cpp @@ -217,7 +217,8 @@ static int32_t GetCodePageForRCT2Language(RCT2LanguageId languageId) } } -template static std::string DecodeConvertWithTable(std::string_view src, TConvertFunc func) +template +static std::string DecodeConvertWithTable(std::string_view src, TConvertFunc func) { auto decoded = DecodeToWideChar(src); std::wstring u16; diff --git a/src/openrct2/rct12/EntryList.h b/src/openrct2/rct12/EntryList.h index 31479e92e1..36e2478d27 100644 --- a/src/openrct2/rct12/EntryList.h +++ b/src/openrct2/rct12/EntryList.h @@ -55,7 +55,8 @@ namespace OpenRCT2::RCT12 } } - template void AddRange(const std::string_view (&list)[i]) + template + void AddRange(const std::string_view (&list)[i]) { for (auto entry : list) { diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h index 357c25390b..42abe290bb 100644 --- a/src/openrct2/rct12/RCT12.h +++ b/src/openrct2/rct12/RCT12.h @@ -658,11 +658,13 @@ struct RCT12TileElementBase struct RCT12TileElement : public RCT12TileElementBase { uint8_t Pad04[4]; - template const TType* as() const + template + const TType* as() const { return static_cast(GetType()) == TClass ? reinterpret_cast(this) : nullptr; } - template TType* as() + template + TType* as() { return static_cast(GetType()) == TClass ? reinterpret_cast(this) : nullptr; } @@ -1203,7 +1205,8 @@ static constexpr money32 RCT12_COMPANY_VALUE_ON_FAILED_OBJECTIVE = 0x80000001; money64 RCT12CompletedCompanyValueToOpenRCT2(money32 origValue); -template std::vector RCT12GetRideTypesBeenOn(T* srcPeep) +template +std::vector RCT12GetRideTypesBeenOn(T* srcPeep) { std::vector ridesTypesBeenOn; for (uint16_t i = 0; i < OpenRCT2::RCT12::Limits::kMaxRideObjects; i++) @@ -1215,7 +1218,8 @@ template std::vector RCT12GetRideTypesBeenOn(T* srcPeep) } return ridesTypesBeenOn; } -template std::vector RCT12GetRidesBeenOn(T* srcPeep) +template +std::vector RCT12GetRidesBeenOn(T* srcPeep) { std::vector ridesBeenOn; for (uint16_t i = 0; i < OpenRCT2::RCT12::Limits::kMaxRidesInPark; i++) diff --git a/src/openrct2/rct12/SawyerChunkReader.h b/src/openrct2/rct12/SawyerChunkReader.h index d17470ae0e..8ca5543e0c 100644 --- a/src/openrct2/rct12/SawyerChunkReader.h +++ b/src/openrct2/rct12/SawyerChunkReader.h @@ -79,7 +79,8 @@ public: * specified type. If the chunk is smaller than the size of the type * then the remaining space is padded with zero. */ - template T ReadChunkAs() + template + T ReadChunkAs() { T result; ReadChunk(&result, sizeof(result)); diff --git a/src/openrct2/rct12/SawyerChunkWriter.h b/src/openrct2/rct12/SawyerChunkWriter.h index 0b14bb413c..5a31116624 100644 --- a/src/openrct2/rct12/SawyerChunkWriter.h +++ b/src/openrct2/rct12/SawyerChunkWriter.h @@ -52,7 +52,8 @@ public: /** * Writes a chunk to the stream containing the given type. */ - template void WriteChunk(const T* src, SAWYER_ENCODING encoding) + template + void WriteChunk(const T* src, SAWYER_ENCODING encoding) { WriteChunk(src, sizeof(T), encoding); } diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index f698231114..fc05b5568a 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1617,7 +1617,8 @@ namespace OpenRCT2::RCT2 return (_s6.Header.ClassicFlag == 0xf) ? Limits::kMaxEntitiesRCTCExtended : Limits::kMaxEntities; } - template void ImportEntity(const RCT12EntityBase& src); + template + void ImportEntity(const RCT12EntityBase& src); void ImportEntityPeep(::Peep* dst, const Peep* src) { @@ -1880,7 +1881,8 @@ namespace OpenRCT2::RCT2 } }; - template<> void S6Importer::ImportEntity<::Vehicle>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::Vehicle>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::Vehicle>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2005,7 +2007,8 @@ namespace OpenRCT2::RCT2 return s6.GameTicks1 - ticksElapsed; } - template<> void S6Importer::ImportEntity<::Guest>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::Guest>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::Guest>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2079,7 +2082,8 @@ namespace OpenRCT2::RCT2 dst->FavouriteRideRating = src->FavouriteRideRating; } - template<> void S6Importer::ImportEntity<::Staff>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::Staff>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::Staff>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2099,7 +2103,8 @@ namespace OpenRCT2::RCT2 ImportStaffPatrolArea(dst, src->StaffId); } - template<> void S6Importer::ImportEntity<::SteamParticle>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::SteamParticle>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::SteamParticle>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2108,7 +2113,8 @@ namespace OpenRCT2::RCT2 dst->frame = src->Frame; } - template<> void S6Importer::ImportEntity<::MoneyEffect>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::MoneyEffect>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::MoneyEffect>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2121,7 +2127,8 @@ namespace OpenRCT2::RCT2 dst->Wiggle = src->Wiggle; } - template<> void S6Importer::ImportEntity<::VehicleCrashParticle>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::VehicleCrashParticle>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::VehicleCrashParticle>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2140,7 +2147,8 @@ namespace OpenRCT2::RCT2 dst->acceleration_z = src->AccelerationZ; } - template<> void S6Importer::ImportEntity<::ExplosionCloud>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::ExplosionCloud>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::ExplosionCloud>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2148,7 +2156,8 @@ namespace OpenRCT2::RCT2 dst->frame = src->Frame; } - template<> void S6Importer::ImportEntity<::ExplosionFlare>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::ExplosionFlare>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::ExplosionFlare>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2156,7 +2165,8 @@ namespace OpenRCT2::RCT2 dst->frame = src->Frame; } - template<> void S6Importer::ImportEntity<::CrashSplashParticle>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::CrashSplashParticle>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::CrashSplashParticle>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2164,7 +2174,8 @@ namespace OpenRCT2::RCT2 dst->frame = src->Frame; } - template<> void S6Importer::ImportEntity<::JumpingFountain>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::JumpingFountain>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::JumpingFountain>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2180,7 +2191,8 @@ namespace OpenRCT2::RCT2 : ::JumpingFountainType::Water; } - template<> void S6Importer::ImportEntity<::Balloon>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::Balloon>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::Balloon>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2191,7 +2203,8 @@ namespace OpenRCT2::RCT2 dst->colour = src->Colour; } - template<> void S6Importer::ImportEntity<::Duck>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::Duck>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::Duck>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); @@ -2202,7 +2215,8 @@ namespace OpenRCT2::RCT2 dst->state = static_cast<::Duck::DuckState>(src->State); } - template<> void S6Importer::ImportEntity<::Litter>(const RCT12EntityBase& baseSrc) + template<> + void S6Importer::ImportEntity<::Litter>(const RCT12EntityBase& baseSrc) { auto dst = CreateEntityAt<::Litter>(EntityId::FromUnderlying(baseSrc.EntityIndex)); auto src = static_cast(&baseSrc); diff --git a/src/openrct2/ride/TrackData.cpp b/src/openrct2/ride/TrackData.cpp index 5f3ad85df7..ea93d8643d 100644 --- a/src/openrct2/ride/TrackData.cpp +++ b/src/openrct2/ride/TrackData.cpp @@ -3389,7 +3389,8 @@ namespace OpenRCT2::TrackMetaData }; static_assert(std::size(TrackTypeToSpinFunction) == EnumValue(TrackElemType::Count)); - template static int32_t EvaluatorConst(const int16_t) + template + static int32_t EvaluatorConst(const int16_t) { return TConstant; } diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index c65cee8446..555b73a623 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -448,7 +448,8 @@ static constexpr OpenRCT2::Audio::SoundId DoorCloseSoundIds[] = { OpenRCT2::Audio::SoundId::Portcullis, }; -template<> bool EntityBase::Is() const +template<> +bool EntityBase::Is() const { return Type == EntityType::Vehicle; } @@ -6316,7 +6317,8 @@ void Vehicle::UpdateSceneryDoor() const AnimateSceneryDoor({ wallCoords, static_cast(direction) }, TrackLocation, next_vehicle_on_train.IsNull()); } -template static void AnimateLandscapeDoor(TrackElement* trackElement, bool isLastVehicle) +template +static void AnimateLandscapeDoor(TrackElement* trackElement, bool isLastVehicle) { auto doorState = isBackwards ? trackElement->GetDoorAState() : trackElement->GetDoorBState(); if (!isLastVehicle && doorState == LANDSCAPE_DOOR_CLOSED) diff --git a/src/openrct2/scripting/Duktape.hpp b/src/openrct2/scripting/Duktape.hpp index 2257b6ab20..8619683f80 100644 --- a/src/openrct2/scripting/Duktape.hpp +++ b/src/openrct2/scripting/Duktape.hpp @@ -24,30 +24,35 @@ namespace OpenRCT2::Scripting { - template DukValue GetObjectAsDukValue(duk_context* ctx, const std::shared_ptr& value) + template + DukValue GetObjectAsDukValue(duk_context* ctx, const std::shared_ptr& value) { dukglue::types::DukType>::template push(ctx, value); return DukValue::take_from_stack(ctx); } - template T AsOrDefault(const DukValue& value, const T& defaultValue = {}) = delete; + template + T AsOrDefault(const DukValue& value, const T& defaultValue = {}) = delete; inline std::string AsOrDefault(const DukValue& value, std::string_view defaultValue) { return value.type() == DukValue::STRING ? value.as_string() : std::string(defaultValue); } - template<> inline std::string AsOrDefault(const DukValue& value, const std::string& defaultValue) + template<> + inline std::string AsOrDefault(const DukValue& value, const std::string& defaultValue) { return value.type() == DukValue::STRING ? value.as_string() : defaultValue; } - template<> inline int32_t AsOrDefault(const DukValue& value, const int32_t& defaultValue) + template<> + inline int32_t AsOrDefault(const DukValue& value, const int32_t& defaultValue) { return value.type() == DukValue::NUMBER ? value.as_int() : defaultValue; } - template<> inline bool AsOrDefault(const DukValue& value, const bool& defaultValue) + template<> + inline bool AsOrDefault(const DukValue& value, const bool& defaultValue) { return value.type() == DukValue::BOOLEAN ? value.as_bool() : defaultValue; } @@ -163,7 +168,8 @@ namespace OpenRCT2::Scripting duk_put_prop_string(_ctx, _idx, name); } - template void Set(const char* name, const std::optional& value) + template + void Set(const char* name, const std::optional& value) { if (value) { @@ -236,7 +242,8 @@ namespace OpenRCT2::Scripting /** * Bi-directional map for converting between strings and enums / numbers. */ - template using DukEnumMap = EnumMap; + template + using DukEnumMap = EnumMap; inline duk_ret_t duk_json_decode_wrapper(duk_context* ctx, void*) { @@ -259,74 +266,88 @@ namespace OpenRCT2::Scripting std::string ProcessString(const DukValue& value); - template DukValue ToDuk(duk_context* ctx, const T& value) = delete; - template T FromDuk(const DukValue& s) = delete; + template + DukValue ToDuk(duk_context* ctx, const T& value) = delete; + template + T FromDuk(const DukValue& s) = delete; - template<> inline DukValue ToDuk(duk_context* ctx, const std::nullptr_t&) + template<> + inline DukValue ToDuk(duk_context* ctx, const std::nullptr_t&) { duk_push_null(ctx); return DukValue::take_from_stack(ctx); } - template<> inline DukValue ToDuk(duk_context* ctx, const DukUndefined&) + template<> + inline DukValue ToDuk(duk_context* ctx, const DukUndefined&) { duk_push_undefined(ctx); return DukValue::take_from_stack(ctx); } - template<> inline DukValue ToDuk(duk_context* ctx, const bool& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const bool& value) { duk_push_boolean(ctx, value); return DukValue::take_from_stack(ctx); } - template<> inline DukValue ToDuk(duk_context* ctx, const uint8_t& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const uint8_t& value) { duk_push_int(ctx, value); return DukValue::take_from_stack(ctx); } - template<> inline DukValue ToDuk(duk_context* ctx, const uint16_t& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const uint16_t& value) { duk_push_int(ctx, value); return DukValue::take_from_stack(ctx); } - template<> inline DukValue ToDuk(duk_context* ctx, const int32_t& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const int32_t& value) { duk_push_int(ctx, value); return DukValue::take_from_stack(ctx); } - template<> inline DukValue ToDuk(duk_context* ctx, const int64_t& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const int64_t& value) { duk_push_number(ctx, value); return DukValue::take_from_stack(ctx); } - template<> inline DukValue ToDuk(duk_context* ctx, const std::string_view& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const std::string_view& value) { duk_push_lstring(ctx, value.data(), value.size()); return DukValue::take_from_stack(ctx); } - template<> inline DukValue ToDuk(duk_context* ctx, const std::string& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const std::string& value) { return ToDuk(ctx, std::string_view(value)); } - template inline DukValue ToDuk(duk_context* ctx, const char (&value)[TLen]) + template + inline DukValue ToDuk(duk_context* ctx, const char (&value)[TLen]) { duk_push_string(ctx, value); return DukValue::take_from_stack(ctx); } - template inline DukValue ToDuk(duk_context* ctx, const std::optional& value) + template + inline DukValue ToDuk(duk_context* ctx, const std::optional& value) { return value ? ToDuk(ctx, *value) : ToDuk(ctx, nullptr); } - template<> CoordsXY inline FromDuk(const DukValue& d) + template<> + CoordsXY inline FromDuk(const DukValue& d) { CoordsXY result; result.x = AsOrDefault(d["x"], 0); @@ -334,7 +355,8 @@ namespace OpenRCT2::Scripting return result; } - template<> MapRange inline FromDuk(const DukValue& d) + template<> + MapRange inline FromDuk(const DukValue& d) { MapRange range; range.Point1 = FromDuk(d["leftTop"]); @@ -342,7 +364,8 @@ namespace OpenRCT2::Scripting return range.Normalise(); } - template<> DukValue inline ToDuk(duk_context* ctx, const CoordsXY& coords) + template<> + DukValue inline ToDuk(duk_context* ctx, const CoordsXY& coords) { DukObject dukCoords(ctx); dukCoords.Set("x", coords.x); @@ -350,7 +373,8 @@ namespace OpenRCT2::Scripting return dukCoords.Take(); } - template<> DukValue inline ToDuk(duk_context* ctx, const TileCoordsXY& coords) + template<> + DukValue inline ToDuk(duk_context* ctx, const TileCoordsXY& coords) { DukObject dukCoords(ctx); dukCoords.Set("x", coords.x); @@ -358,7 +382,8 @@ namespace OpenRCT2::Scripting return dukCoords.Take(); } - template<> DukValue inline ToDuk(duk_context* ctx, const ScreenCoordsXY& coords) + template<> + DukValue inline ToDuk(duk_context* ctx, const ScreenCoordsXY& coords) { DukObject dukCoords(ctx); dukCoords.Set("x", coords.x); @@ -366,7 +391,8 @@ namespace OpenRCT2::Scripting return dukCoords.Take(); } - template<> inline DukValue ToDuk(duk_context* ctx, const CoordsXYZ& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const CoordsXYZ& value) { if (value.IsNull()) { @@ -380,7 +406,8 @@ namespace OpenRCT2::Scripting return dukCoords.Take(); } - template<> inline CoordsXYZ FromDuk(const DukValue& value) + template<> + inline CoordsXYZ FromDuk(const DukValue& value) { CoordsXYZ result; if (value.type() == DukValue::Type::OBJECT) @@ -396,7 +423,8 @@ namespace OpenRCT2::Scripting return result; } - template<> inline DukValue ToDuk(duk_context* ctx, const CoordsXYZD& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const CoordsXYZD& value) { if (value.IsNull()) { @@ -411,7 +439,8 @@ namespace OpenRCT2::Scripting return dukCoords.Take(); } - template<> inline DukValue ToDuk(duk_context* ctx, const GForces& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const GForces& value) { DukObject dukGForces(ctx); dukGForces.Set("lateralG", value.LateralG); @@ -419,7 +448,8 @@ namespace OpenRCT2::Scripting return dukGForces.Take(); } - template<> inline DukValue ToDuk(duk_context* ctx, const VehicleSpriteGroup& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const VehicleSpriteGroup& value) { DukObject dukSpriteGroup(ctx); dukSpriteGroup.Set("imageId", value.imageId); @@ -427,7 +457,8 @@ namespace OpenRCT2::Scripting return dukSpriteGroup.Take(); } - template<> inline CoordsXYZD FromDuk(const DukValue& value) + template<> + inline CoordsXYZD FromDuk(const DukValue& value) { CoordsXYZD result; if (value.type() == DukValue::Type::OBJECT) @@ -444,7 +475,8 @@ namespace OpenRCT2::Scripting return result; } - template<> inline DukValue ToDuk(duk_context* ctx, const ScreenSize& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const ScreenSize& value) { DukObject dukCoords(ctx); dukCoords.Set("width", value.width); @@ -452,7 +484,8 @@ namespace OpenRCT2::Scripting return dukCoords.Take(); } - template<> ObjectEntryIndex inline FromDuk(const DukValue& d) + template<> + ObjectEntryIndex inline FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::NUMBER) { diff --git a/src/openrct2/scripting/bindings/entity/ScVehicle.cpp b/src/openrct2/scripting/bindings/entity/ScVehicle.cpp index edf18218f8..e93c137da2 100644 --- a/src/openrct2/scripting/bindings/entity/ScVehicle.cpp +++ b/src/openrct2/scripting/bindings/entity/ScVehicle.cpp @@ -336,13 +336,15 @@ namespace OpenRCT2::Scripting } } - template bool ScVehicle::flag_get() const + template + bool ScVehicle::flag_get() const { auto vehicle = GetVehicle(); return vehicle != nullptr ? vehicle->HasFlag(flag) : false; } - template void ScVehicle::flag_set(bool value) + template + void ScVehicle::flag_set(bool value) { ThrowIfGameStateNotMutable(); auto vehicle = GetVehicle(); diff --git a/src/openrct2/scripting/bindings/entity/ScVehicle.hpp b/src/openrct2/scripting/bindings/entity/ScVehicle.hpp index cc03703dce..4837bf6cbe 100644 --- a/src/openrct2/scripting/bindings/entity/ScVehicle.hpp +++ b/src/openrct2/scripting/bindings/entity/ScVehicle.hpp @@ -67,8 +67,10 @@ namespace OpenRCT2::Scripting uint8_t bankRotation_get() const; void bankRotation_set(uint8_t value); - template bool flag_get() const; - template void flag_set(bool value); + template + bool flag_get() const; + template + void flag_set(bool value); DukValue colours_get() const; void colours_set(const DukValue& value); diff --git a/src/openrct2/scripting/bindings/ride/ScRide.hpp b/src/openrct2/scripting/bindings/ride/ScRide.hpp index 53e78f93ef..a1f3165630 100644 --- a/src/openrct2/scripting/bindings/ride/ScRide.hpp +++ b/src/openrct2/scripting/bindings/ride/ScRide.hpp @@ -20,7 +20,8 @@ namespace OpenRCT2::Scripting { - template<> inline DukValue ToDuk(duk_context* ctx, const TrackColour& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const TrackColour& value) { DukObject obj(ctx); obj.Set("main", value.main); @@ -29,7 +30,8 @@ namespace OpenRCT2::Scripting return obj.Take(); } - template<> inline TrackColour FromDuk(const DukValue& s) + template<> + inline TrackColour FromDuk(const DukValue& s) { TrackColour result{}; result.main = AsOrDefault(s["main"], 0); @@ -38,7 +40,8 @@ namespace OpenRCT2::Scripting return result; } - template<> inline DukValue ToDuk(duk_context* ctx, const VehicleColour& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const VehicleColour& value) { DukObject obj(ctx); obj.Set("body", value.Body); @@ -48,7 +51,8 @@ namespace OpenRCT2::Scripting return obj.Take(); } - template<> inline VehicleColour FromDuk(const DukValue& s) + template<> + inline VehicleColour FromDuk(const DukValue& s) { VehicleColour result{}; result.Body = AsOrDefault(s["body"], 0); diff --git a/src/openrct2/scripting/bindings/ride/ScTrackSegment.cpp b/src/openrct2/scripting/bindings/ride/ScTrackSegment.cpp index cfc971a979..4a3c469eac 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackSegment.cpp +++ b/src/openrct2/scripting/bindings/ride/ScTrackSegment.cpp @@ -262,7 +262,8 @@ int32_t ScTrackSegment::getPriceModifier() const return ted.priceModifier; } -template bool ScTrackSegment::getTrackFlag() const +template +bool ScTrackSegment::getTrackFlag() const { const auto& ted = GetTrackElementDescriptor(_type); diff --git a/src/openrct2/scripting/bindings/ride/ScTrackSegment.h b/src/openrct2/scripting/bindings/ride/ScTrackSegment.h index 8e9a9ea00a..92722711aa 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackSegment.h +++ b/src/openrct2/scripting/bindings/ride/ScTrackSegment.h @@ -18,7 +18,8 @@ namespace OpenRCT2::Scripting { - template<> inline DukValue ToDuk(duk_context* ctx, const VehicleInfo& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const VehicleInfo& value) { DukObject dukSubposition(ctx); dukSubposition.Set("x", value.x); @@ -64,7 +65,8 @@ namespace OpenRCT2::Scripting int32_t getPriceModifier() const; int32_t getPreviewZOffset() const; int32_t getTrackGroup() const; - template bool getTrackFlag() const; + template + bool getTrackFlag() const; std::string getTrackCurvature() const; std::string getTrackPitchDirection() const; }; diff --git a/src/openrct2/scripting/bindings/world/ScParkMessage.hpp b/src/openrct2/scripting/bindings/world/ScParkMessage.hpp index 80f61af825..368311976c 100644 --- a/src/openrct2/scripting/bindings/world/ScParkMessage.hpp +++ b/src/openrct2/scripting/bindings/world/ScParkMessage.hpp @@ -48,7 +48,8 @@ namespace OpenRCT2::Scripting return {}; } - template<> inline News::Item FromDuk(const DukValue& value) + template<> + inline News::Item FromDuk(const DukValue& value) { News::Item result{}; result.Type = GetParkMessageType(value["type"].as_string()); diff --git a/src/openrct2/scripting/bindings/world/ScResearch.cpp b/src/openrct2/scripting/bindings/world/ScResearch.cpp index ed0ec5beaf..e61eb5a4a8 100644 --- a/src/openrct2/scripting/bindings/world/ScResearch.cpp +++ b/src/openrct2/scripting/bindings/world/ScResearch.cpp @@ -47,7 +47,8 @@ namespace OpenRCT2::Scripting { "scenery", Research::EntryType::Scenery }, }); - template<> inline DukValue ToDuk(duk_context* ctx, const ResearchItem& value) + template<> + inline DukValue ToDuk(duk_context* ctx, const ResearchItem& value) { DukObject obj(ctx); obj.Set("category", ResearchCategoryMap[value.category]); @@ -60,7 +61,8 @@ namespace OpenRCT2::Scripting return obj.Take(); } - template<> Research::EntryType inline FromDuk(const DukValue& d) + template<> + Research::EntryType inline FromDuk(const DukValue& d) { if (d.type() == DukValue::STRING) { @@ -73,7 +75,8 @@ namespace OpenRCT2::Scripting return Research::EntryType::Scenery; } - template<> ResearchItem inline FromDuk(const DukValue& d) + template<> + ResearchItem inline FromDuk(const DukValue& d) { ResearchItem result; result.baseRideType = 0; diff --git a/src/openrct2/util/Util.h b/src/openrct2/util/Util.h index 94af6c5d43..c7db420d9a 100644 --- a/src/openrct2/util/Util.h +++ b/src/openrct2/util/Util.h @@ -90,7 +90,8 @@ bool UtilGzipCompress(FILE* source, FILE* dest); std::vector Gzip(const void* data, const size_t dataLen); std::vector Ungzip(const void* data, const size_t dataLen); -template constexpr T AddClamp(T value, T valueToAdd) +template +constexpr T AddClamp(T value, T valueToAdd) { if (std::is_same_v) { @@ -118,23 +119,27 @@ uint8_t SoftLight(uint8_t a, uint8_t b); size_t StrCatFTime(char* buffer, size_t bufferSize, const char* format, const struct tm* tp); -template [[nodiscard]] constexpr uint64_t EnumToFlag(T v) +template +[[nodiscard]] constexpr uint64_t EnumToFlag(T v) { static_assert(std::is_enum_v); return 1uLL << static_cast>(v); } -template [[nodiscard]] constexpr uint64_t EnumsToFlags(T... types) +template +[[nodiscard]] constexpr uint64_t EnumsToFlags(T... types) { return (EnumToFlag(types) | ...); } -template constexpr auto EnumValue(TEnum enumerator) noexcept +template +constexpr auto EnumValue(TEnum enumerator) noexcept { return static_cast>(enumerator); } -template constexpr bool HasFlag(uint64_t holder, T v) +template +constexpr bool HasFlag(uint64_t holder, T v) { static_assert(std::is_enum_v); return (holder & EnumToFlag(v)) != 0; diff --git a/src/openrct2/windows/Intent.h b/src/openrct2/windows/Intent.h index fb73329348..ed0ffa0715 100644 --- a/src/openrct2/windows/Intent.h +++ b/src/openrct2/windows/Intent.h @@ -103,7 +103,8 @@ public: Intent* PutExtra(uint32_t key, std::string value); Intent* PutExtra(uint32_t key, close_callback value); - template Intent* PutExtra(uint32_t key, const TIdentifier& value) + template + Intent* PutExtra(uint32_t key, const TIdentifier& value) { const auto val = value.ToUnderlying(); return PutExtra(key, static_cast(val)); diff --git a/src/openrct2/world/Location.hpp b/src/openrct2/world/Location.hpp index 83cf5127c3..086495bd77 100644 --- a/src/openrct2/world/Location.hpp +++ b/src/openrct2/world/Location.hpp @@ -732,7 +732,8 @@ struct TileCoordsXYZD : public TileCoordsXYZ /** * Represents a range of the map using regular coordinates. */ -template struct CoordsRange +template +struct CoordsRange { T Point1{ 0, 0 }; T Point2{ 0, 0 }; @@ -767,7 +768,8 @@ template struct CoordsRange } }; -template struct RectRange : public CoordsRange +template +struct RectRange : public CoordsRange { using CoordsRange::CoordsRange; diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index bfe64cab2e..754277302e 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -181,13 +181,15 @@ int16_t TileElementWaterHeight(const CoordsXY& loc); void TileElementRemove(TileElement* tileElement); TileElement* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants, TileElementType type); -template T* MapGetFirstTileElementWithBaseHeightBetween(const TileCoordsXYRangedZ& loc) +template +T* MapGetFirstTileElementWithBaseHeightBetween(const TileCoordsXYRangedZ& loc) { auto* element = MapGetFirstTileElementWithBaseHeightBetween(loc, T::kElementType); return element != nullptr ? element->template as() : nullptr; } -template T* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants) +template +T* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants) { auto* element = TileElementInsert(loc, occupiedQuadrants, T::kElementType); return (element != nullptr) ? element->template as() : nullptr; diff --git a/src/openrct2/world/MapGen.cpp b/src/openrct2/world/MapGen.cpp index 25bb70d59c..163fc9d467 100644 --- a/src/openrct2/world/MapGen.cpp +++ b/src/openrct2/world/MapGen.cpp @@ -336,7 +336,8 @@ static bool MapGenSurfaceTakesSnowTrees(const TerrainSurfaceObject& surface) return id == "rct2.terrain_surface.ice"; } -template static bool TryFindTreeInList(std::string_view id, const T& treeList) +template +static bool TryFindTreeInList(std::string_view id, const T& treeList) { for (size_t j = 0; j < std::size(treeList); j++) { diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index 4eef41a9ef..24a3521dc3 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -267,7 +267,8 @@ namespace OpenRCT2::Park return peep; } - template static void HistoryPushRecord(T history[TSize], T newItem) + template + static void HistoryPushRecord(T history[TSize], T newItem) { for (size_t i = TSize - 1; i > 0; i--) { diff --git a/src/openrct2/world/TileElementsView.h b/src/openrct2/world/TileElementsView.h index edf1057e6c..9ce1754911 100644 --- a/src/openrct2/world/TileElementsView.h +++ b/src/openrct2/world/TileElementsView.h @@ -18,7 +18,8 @@ namespace OpenRCT2 { namespace Detail { - template T* NextMatchingTile(T2* element) + template + T* NextMatchingTile(T2* element) { if (element == nullptr) return nullptr; @@ -40,7 +41,8 @@ namespace OpenRCT2 } } // namespace Detail - template class TileElementsView + template + class TileElementsView { const TileCoordsXY _loc; diff --git a/src/openrct2/world/TilePointerIndex.hpp b/src/openrct2/world/TilePointerIndex.hpp index 048ac46dce..580aa48f6b 100644 --- a/src/openrct2/world/TilePointerIndex.hpp +++ b/src/openrct2/world/TilePointerIndex.hpp @@ -15,7 +15,8 @@ #include #include -template class TilePointerIndex +template +class TilePointerIndex { std::vector TilePointers; uint16_t MapSize{}; diff --git a/src/openrct2/world/tile_element/TileElementBase.h b/src/openrct2/world/tile_element/TileElementBase.h index f4b5ba44a9..00eb32c90d 100644 --- a/src/openrct2/world/tile_element/TileElementBase.h +++ b/src/openrct2/world/tile_element/TileElementBase.h @@ -84,7 +84,8 @@ struct TileElementBase uint8_t GetOwner() const; void SetOwner(uint8_t newOwner); - template const TType* as() const + template + const TType* as() const { if constexpr (std::is_same_v) return reinterpret_cast(this); @@ -92,7 +93,8 @@ struct TileElementBase return GetType() == TType::kElementType ? reinterpret_cast(this) : nullptr; } - template TType* as() + template + TType* as() { if constexpr (std::is_same_v) return reinterpret_cast(this); diff --git a/test/tests/AssertHelpers.hpp b/test/tests/AssertHelpers.hpp index 18bffce66b..722581f7b4 100644 --- a/test/tests/AssertHelpers.hpp +++ b/test/tests/AssertHelpers.hpp @@ -13,7 +13,8 @@ #include #include -template static void AssertVector(const std::vector& actual, TExpected expected) +template +static void AssertVector(const std::vector& actual, TExpected expected) { ASSERT_EQ(actual.size(), expected.size()) << "Expected vector of size " << expected.size() << ", but was " << actual.size(); size_t i = 0; @@ -24,7 +25,8 @@ template static void AssertVector(const std::vec } } -template static void AssertVector(const std::vector& actual, std::initializer_list expected) +template +static void AssertVector(const std::vector& actual, std::initializer_list expected) { AssertVector>(actual, expected); } diff --git a/test/tests/CryptTests.cpp b/test/tests/CryptTests.cpp index ad5f352981..cf9663d678 100644 --- a/test/tests/CryptTests.cpp +++ b/test/tests/CryptTests.cpp @@ -23,7 +23,8 @@ using namespace OpenRCT2; class CryptTests : public testing::Test { public: - template void AssertHash(std::string expected, T hash) + template + void AssertHash(std::string expected, T hash) { auto actual = String::StringFromHex(hash); ASSERT_EQ(expected, actual); diff --git a/test/tests/EnumMapTest.cpp b/test/tests/EnumMapTest.cpp index 6aa50639e7..e7da143a6b 100644 --- a/test/tests/EnumMapTest.cpp +++ b/test/tests/EnumMapTest.cpp @@ -31,7 +31,8 @@ enum class TestEnumClassNonContinuous G }; -template void TestEnumKeyLookup() +template +void TestEnumKeyLookup() { // clang-format off EnumMap enumMap = { @@ -78,7 +79,8 @@ template void TestEnumKeyLookup() SUCCEED(); } -template void TestEnumValueLookup() +template +void TestEnumValueLookup() { // clang-format off EnumMap enumMap = { diff --git a/test/tests/PlayTests.cpp b/test/tests/PlayTests.cpp index d2387c5b36..1cbeb80f2b 100644 --- a/test/tests/PlayTests.cpp +++ b/test/tests/PlayTests.cpp @@ -67,7 +67,8 @@ static std::unique_ptr localStartGame(const std::string& parkPath) return context; } -template static bool updateUntil(int maxSteps, Fn&& fn) +template +static bool updateUntil(int maxSteps, Fn&& fn) { while (maxSteps-- && !fn()) { @@ -76,7 +77,8 @@ template static bool updateUntil(int maxSteps, Fn&& fn) return maxSteps > 0; } -template static void execute(Args&&... args) +template +static void execute(Args&&... args) { GA ga(std::forward(args)...); GameActions::Execute(&ga); diff --git a/test/tests/ReplayTests.cpp b/test/tests/ReplayTests.cpp index 1e9dce8861..1ea1a8f777 100644 --- a/test/tests/ReplayTests.cpp +++ b/test/tests/ReplayTests.cpp @@ -104,7 +104,8 @@ static void PrintTo(const ReplayTestData& testData, std::ostream* os) struct PrintReplayParameter { - template std::string operator()(const testing::TestParamInfo& info) const + template + std::string operator()(const testing::TestParamInfo& info) const { auto data = static_cast(info.param); return data.name; diff --git a/test/tests/TileElementsView.cpp b/test/tests/TileElementsView.cpp index ffcc93bdd8..1412e221e9 100644 --- a/test/tests/TileElementsView.cpp +++ b/test/tests/TileElementsView.cpp @@ -66,7 +66,8 @@ private: std::shared_ptr TileElementsViewTests::_context; uint8_t TileElementsViewTests::_gScreenFlags; -template std::vector BuildListManual(const CoordsXY& pos) +template +std::vector BuildListManual(const CoordsXY& pos) { std::vector res; @@ -92,7 +93,8 @@ template std::vector BuildListManual(const CoordsXY& pos) return res; } -template std::vector BuildListByView(const CoordsXY& pos) +template +std::vector BuildListByView(const CoordsXY& pos) { std::vector res; @@ -104,7 +106,8 @@ template std::vector BuildListByView(const CoordsXY& pos) return res; } -template bool CompareLists(const CoordsXY& pos) +template +bool CompareLists(const CoordsXY& pos) { auto listManual = BuildListManual(pos); auto listView = BuildListByView(pos); @@ -124,7 +127,8 @@ template bool CompareLists(const CoordsXY& pos) return true; } -template void CheckMapTiles() +template +void CheckMapTiles() { for (int y = 0; y < kMaximumMapSizeTechnical; ++y) { From f40da09ab818ce80e5fe9fe2a202763ea43ada33 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 29 Oct 2024 21:59:28 +0100 Subject: [PATCH 70/97] Move SawyerCoding from util into core, and into its own namespace --- src/openrct2/FileClassifier.cpp | 8 +- src/openrct2/Game.cpp | 2 +- src/openrct2/core/SawyerCoding.cpp | 428 +++++++++++++++++++++++ src/openrct2/core/SawyerCoding.h | 63 ++++ src/openrct2/libopenrct2.vcxproj | 10 +- src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/object/ObjectList.cpp | 2 +- src/openrct2/object/ObjectRepository.cpp | 6 +- src/openrct2/platform/Crash.cpp | 2 +- src/openrct2/rct1/S4Importer.cpp | 10 +- src/openrct2/rct12/SawyerChunkReader.cpp | 10 +- src/openrct2/rct12/SawyerChunkReader.h | 2 +- src/openrct2/rct12/SawyerChunkWriter.cpp | 6 +- src/openrct2/rct2/S6Importer.cpp | 2 +- src/openrct2/ride/Track.cpp | 2 +- src/openrct2/ride/TrackDesign.cpp | 2 +- src/openrct2/ride/TrackDesignSave.cpp | 2 +- src/openrct2/scenario/Scenario.cpp | 2 +- src/openrct2/util/SawyerCoding.cpp | 428 ----------------------- src/openrct2/util/SawyerCoding.h | 55 --- test/tests/SawyerCodingTest.cpp | 14 +- 21 files changed, 534 insertions(+), 524 deletions(-) create mode 100644 src/openrct2/core/SawyerCoding.cpp create mode 100644 src/openrct2/core/SawyerCoding.h delete mode 100644 src/openrct2/util/SawyerCoding.cpp delete mode 100644 src/openrct2/util/SawyerCoding.h diff --git a/src/openrct2/FileClassifier.cpp b/src/openrct2/FileClassifier.cpp index 788e6ea97a..e91a7c37d4 100644 --- a/src/openrct2/FileClassifier.cpp +++ b/src/openrct2/FileClassifier.cpp @@ -14,12 +14,12 @@ #include "core/FileStream.h" #include "core/Memory.hpp" #include "core/Path.hpp" +#include "core/SawyerCoding.h" #include "core/String.hpp" #include "park/ParkFile.h" #include "rct12/SawyerChunkReader.h" #include "rct2/RCT2.h" #include "scenario/Scenario.h" -#include "util/SawyerCoding.h" using namespace OpenRCT2; @@ -135,7 +135,7 @@ static bool TryClassifyAsS4(OpenRCT2::IStream* stream, ClassifiedFileInfo* resul size_t dataLength = static_cast(stream->GetLength()); auto data = stream->ReadArray(dataLength); stream->SetPosition(originalPosition); - int32_t fileTypeVersion = SawyerCodingDetectFileType(data.get(), dataLength); + int32_t fileTypeVersion = SawyerCoding::DetectFileType(data.get(), dataLength); int32_t type = fileTypeVersion & FILE_TYPE_MASK; int32_t version = fileTypeVersion & FILE_VERSION_MASK; @@ -173,11 +173,11 @@ static bool TryClassifyAsTD4_TD6(OpenRCT2::IStream* stream, ClassifiedFileInfo* auto data = stream->ReadArray(dataLength); stream->SetPosition(originalPosition); - if (SawyerCodingValidateTrackChecksum(data.get(), dataLength)) + if (SawyerCoding::ValidateTrackChecksum(data.get(), dataLength)) { std::unique_ptr)> td6data( Memory::Allocate(0x10000), &Memory::Free); - size_t td6len = SawyerCodingDecodeTD6(data.get(), td6data.get(), dataLength); + size_t td6len = SawyerCoding::DecodeTD6(data.get(), td6data.get(), dataLength); if (td6data != nullptr && td6len >= 8) { uint8_t version = (td6data.get()[7] >> 2) & 3; diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index b4de059728..8940bfca52 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -30,6 +30,7 @@ #include "core/FileScanner.h" #include "core/Money.hpp" #include "core/Path.hpp" +#include "core/SawyerCoding.h" #include "entity/EntityRegistry.h" #include "entity/PatrolArea.h" #include "entity/Peep.h" @@ -59,7 +60,6 @@ #include "scripting/ScriptEngine.h" #include "ui/UiContext.h" #include "ui/WindowManager.h" -#include "util/SawyerCoding.h" #include "util/Util.h" #include "windows/Intent.h" #include "world/Banner.h" diff --git a/src/openrct2/core/SawyerCoding.cpp b/src/openrct2/core/SawyerCoding.cpp new file mode 100644 index 0000000000..7d735c7bd3 --- /dev/null +++ b/src/openrct2/core/SawyerCoding.cpp @@ -0,0 +1,428 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "SawyerCoding.h" + +#include "../platform/Platform.h" +#include "../scenario/Scenario.h" +#include "Numerics.hpp" + +#include +#include +#include + +namespace OpenRCT2::SawyerCoding +{ + static size_t DecodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length); + static size_t DecodeChunkRLEWithSize(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length, size_t dstSize); + + static size_t EncodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length); + static size_t EncodeChunkRepeat(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length); + static void EncodeChunkRotate(uint8_t* buffer, size_t length); + + uint32_t CalculateChecksum(const uint8_t* buffer, size_t length) + { + uint32_t checksum = 0; + for (size_t i = 0; i < length; i++) + checksum += buffer[i]; + + return checksum; + } + + /** + * + * rct2: 0x006762E1 + * + */ + size_t WriteChunkBuffer(uint8_t* dst_file, const uint8_t* buffer, ChunkHeader chunkHeader) + { + switch (chunkHeader.encoding) + { + case CHUNK_ENCODING_NONE: + std::memcpy(dst_file, &chunkHeader, sizeof(ChunkHeader)); + dst_file += sizeof(ChunkHeader); + std::memcpy(dst_file, buffer, chunkHeader.length); + // fwrite(&chunkHeader, sizeof(ChunkHeader), 1, file); + // fwrite(buffer, 1, chunkHeader.length, file); + break; + case CHUNK_ENCODING_RLE: + { + auto encode_buffer = std::make_unique(0x600000); + chunkHeader.length = static_cast(EncodeChunkRLE(buffer, encode_buffer.get(), chunkHeader.length)); + std::memcpy(dst_file, &chunkHeader, sizeof(ChunkHeader)); + dst_file += sizeof(ChunkHeader); + std::memcpy(dst_file, encode_buffer.get(), chunkHeader.length); + } + break; + case CHUNK_ENCODING_RLECOMPRESSED: + { + auto encode_buffer = std::make_unique(chunkHeader.length * 2); + auto encode_buffer2 = std::make_unique(0x600000); + chunkHeader.length = static_cast(EncodeChunkRepeat(buffer, encode_buffer.get(), chunkHeader.length)); + chunkHeader.length = static_cast( + EncodeChunkRLE(encode_buffer.get(), encode_buffer2.get(), chunkHeader.length)); + std::memcpy(dst_file, &chunkHeader, sizeof(ChunkHeader)); + dst_file += sizeof(ChunkHeader); + std::memcpy(dst_file, encode_buffer2.get(), chunkHeader.length); + } + break; + case CHUNK_ENCODING_ROTATE: + { + auto encode_buffer = std::make_unique(chunkHeader.length); + std::memcpy(encode_buffer.get(), buffer, chunkHeader.length); + EncodeChunkRotate(encode_buffer.get(), chunkHeader.length); + std::memcpy(dst_file, &chunkHeader, sizeof(ChunkHeader)); + dst_file += sizeof(ChunkHeader); + std::memcpy(dst_file, encode_buffer.get(), chunkHeader.length); + } + break; + } + + return chunkHeader.length + sizeof(ChunkHeader); + } + + size_t DecodeSV4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength) + { + // (0 to length - 4): RLE chunk + // (length - 4 to length): checksum + return DecodeChunkRLEWithSize(src, dst, length - 4, bufferLength); + } + + size_t DecodeSC4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength) + { + // Uncompress + size_t decodedLength = DecodeChunkRLEWithSize(src, dst, length - 4, bufferLength); + + // Decode + for (size_t i = 0x60018; i <= std::min(decodedLength - 1, static_cast(0x1F8353)); i++) + dst[i] = dst[i] ^ 0x9C; + + for (size_t i = 0x60018; i <= std::min(decodedLength - 1, static_cast(0x1F8350)); i += 4) + { + dst[i + 1] = Numerics::ror8(dst[i + 1], 3); + + uint32_t* code = reinterpret_cast(&dst[i]); + *code = Numerics::rol32(*code, 9); + } + + return decodedLength; + } + + size_t EncodeSV4(const uint8_t* src, uint8_t* dst, size_t length) + { + // Encode + size_t encodedLength = EncodeChunkRLE(src, dst, length); + + // Append checksum + uint32_t checksum = CalculateChecksum(dst, encodedLength); + *(reinterpret_cast(&dst[encodedLength])) = checksum; + + return encodedLength + 4; + } + + size_t DecodeTD6(const uint8_t* src, uint8_t* dst, size_t length) + { + return DecodeChunkRLE(src, dst, length - 4); + } + + size_t EncodeTD6(const uint8_t* src, uint8_t* dst, size_t length) + { + size_t output_length = EncodeChunkRLE(src, dst, length); + + uint32_t checksum = 0; + for (size_t i = 0; i < output_length; i++) + { + uint8_t new_byte = ((checksum & 0xFF) + dst[i]) & 0xFF; + checksum = (checksum & 0xFFFFFF00) + new_byte; + checksum = Numerics::rol32(checksum, 3); + } + checksum -= 0x1D4C1; + + *(reinterpret_cast(&dst[output_length])) = checksum; + output_length += 4; + return output_length; + } + + /* Based off of rct2: 0x006770C1 */ + int32_t ValidateTrackChecksum(const uint8_t* src, size_t length) + { + if (length < 4) + return 0; + + uint32_t file_checksum = *(reinterpret_cast(&src[length - 4])); + + uint32_t checksum = 0; + for (size_t i = 0; i < length - 4; i++) + { + uint8_t new_byte = ((checksum & 0xFF) + src[i]) & 0xFF; + checksum = (checksum & 0xFFFFFF00) + new_byte; + checksum = Numerics::rol32(checksum, 3); + } + + if (checksum - 0x1D4C1 == file_checksum) + return 1; // .TD6 + else if (checksum - 0x1A67C == file_checksum) + return 1; // .TD4 + else if (checksum - 0x1A650 == file_checksum) + return 1; // .TD4 + else + return 0; + } + +#pragma region Decoding + + /** + * + * rct2: 0x0067693A + */ + static size_t DecodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length) + { + size_t count; + uint8_t *dst, rleCodeByte; + + dst = dst_buffer; + + for (size_t i = 0; i < length; i++) + { + rleCodeByte = src_buffer[i]; + if (rleCodeByte & 128) + { + i++; + count = 257 - rleCodeByte; + std::fill_n(dst, count, src_buffer[i]); + dst = reinterpret_cast(reinterpret_cast(dst) + count); + } + else + { + std::memcpy(dst, src_buffer + i + 1, rleCodeByte + 1); + dst = reinterpret_cast(reinterpret_cast(dst) + rleCodeByte + 1); + i += rleCodeByte + 1; + } + } + + // Return final size + return dst - dst_buffer; + } + + /** + * + * rct2: 0x0067693A + */ + static size_t DecodeChunkRLEWithSize(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length, size_t dstSize) + { + size_t count; + uint8_t *dst, rleCodeByte; + + dst = dst_buffer; + + if (length <= 0 || dstSize <= 0) + throw std::out_of_range("Invalid RLE string!"); + + for (size_t i = 0; i < length; i++) + { + rleCodeByte = src_buffer[i]; + if (rleCodeByte & 128) + { + i++; + count = 257 - rleCodeByte; + assert(dst + count <= dst_buffer + dstSize); + assert(i < length); + std::fill_n(dst, count, src_buffer[i]); + dst = reinterpret_cast(reinterpret_cast(dst) + count); + } + else + { + if ((dst + rleCodeByte + 1 > dst_buffer + dstSize) || (i + 1 >= length)) + throw std::out_of_range("Invalid RLE string!"); + std::memcpy(dst, src_buffer + i + 1, rleCodeByte + 1); + dst = reinterpret_cast(reinterpret_cast(dst) + rleCodeByte + 1); + i += rleCodeByte + 1; + } + } + + // Return final size + return dst - dst_buffer; + } + +#pragma endregion + +#pragma region Encoding + + /** + * Ensure dst_buffer is bigger than src_buffer then resize afterwards + * returns length of dst_buffer + */ + static size_t EncodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length) + { + const uint8_t* src = src_buffer; + uint8_t* dst = dst_buffer; + const uint8_t* end_src = src + length; + uint8_t count = 0; + const uint8_t* src_norm_start = src; + + while (src < end_src - 1) + { + if ((count && *src == src[1]) || count > 125) + { + *dst++ = count - 1; + std::memcpy(dst, src_norm_start, count); + dst += count; + src_norm_start += count; + count = 0; + } + if (*src == src[1]) + { + for (; (count < 125) && ((src + count) < end_src); count++) + { + if (*src != src[count]) + break; + } + *dst++ = 257 - count; + *dst++ = *src; + src += count; + src_norm_start = src; + count = 0; + } + else + { + count++; + src++; + } + } + if (src == end_src - 1) + count++; + if (count) + { + *dst++ = count - 1; + std::memcpy(dst, src_norm_start, count); + dst += count; + } + return dst - dst_buffer; + } + + static size_t EncodeChunkRepeat(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length) + { + if (length == 0) + return 0; + + size_t outLength = 0; + + // Need to emit at least one byte, otherwise there is nothing to repeat + *dst_buffer++ = 255; + *dst_buffer++ = src_buffer[0]; + outLength += 2; + + // Iterate through remainder of the source buffer + for (size_t i = 1; i < length;) + { + size_t searchIndex = (i < 32) ? 0 : (i - 32); + size_t searchEnd = i - 1; + + size_t bestRepeatIndex = 0; + size_t bestRepeatCount = 0; + for (size_t repeatIndex = searchIndex; repeatIndex <= searchEnd; repeatIndex++) + { + size_t repeatCount = 0; + size_t maxRepeatCount = std::min(std::min(static_cast(7), searchEnd - repeatIndex), length - i - 1); + // maxRepeatCount should not exceed length + assert(repeatIndex + maxRepeatCount < length); + assert(i + maxRepeatCount < length); + for (size_t j = 0; j <= maxRepeatCount; j++) + { + if (src_buffer[repeatIndex + j] == src_buffer[i + j]) + { + repeatCount++; + } + else + { + break; + } + } + if (repeatCount > bestRepeatCount) + { + bestRepeatIndex = repeatIndex; + bestRepeatCount = repeatCount; + + // Maximum repeat count is 8 + if (repeatCount == 8) + break; + } + } + + if (bestRepeatCount == 0) + { + *dst_buffer++ = 255; + *dst_buffer++ = src_buffer[i]; + outLength += 2; + i++; + } + else + { + *dst_buffer++ = static_cast((bestRepeatCount - 1) | ((32 - (i - bestRepeatIndex)) << 3)); + outLength++; + i += bestRepeatCount; + } + } + + return outLength; + } + + static void EncodeChunkRotate(uint8_t* buffer, size_t length) + { + size_t i; + uint8_t code = 1; + for (i = 0; i < length; i++) + { + buffer[i] = Numerics::rol8(buffer[i], code); + code = (code + 2) % 8; + } + } + +#pragma endregion + + int32_t DetectFileType(const uint8_t* src, size_t length) + { + if (length < 4) + { + throw std::length_error("Stream is (nearly) empty!"); + } + + size_t i; + + // Currently can't detect TD4, as the checksum is the same as SC4 (need alternative method) + + uint32_t checksum = *(reinterpret_cast(&src[length - 4])); + uint32_t actualChecksum = 0; + for (i = 0; i < length - 4; i++) + { + actualChecksum = (actualChecksum & 0xFFFFFF00) | (((actualChecksum & 0xFF) + static_cast(src[i])) & 0xFF); + actualChecksum = Numerics::rol32(actualChecksum, 3); + } + + return DetectRCT1Version(checksum - actualChecksum); + } + + int32_t DetectRCT1Version(int32_t gameVersion) + { + int32_t fileType = (gameVersion) > 0 ? FILE_TYPE_SV4 : FILE_TYPE_SC4; + gameVersion = abs(gameVersion); + + if (gameVersion >= 108000 && gameVersion < 110000) + return (FILE_VERSION_RCT1 | fileType); + if (gameVersion >= 110000 && gameVersion < 120000) + return (FILE_VERSION_RCT1_AA | fileType); + if (gameVersion >= 120000 && gameVersion < 130000) + return (FILE_VERSION_RCT1_LL | fileType); + // RCTOA Acres sets this, and possibly some other user-created scenarios as well + if (gameVersion == 0) + return (FILE_VERSION_RCT1_LL | fileType); + + return -1; + } +} // namespace OpenRCT2::SawyerCoding diff --git a/src/openrct2/core/SawyerCoding.h b/src/openrct2/core/SawyerCoding.h new file mode 100644 index 0000000000..16f357eb46 --- /dev/null +++ b/src/openrct2/core/SawyerCoding.h @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include +#include + +namespace OpenRCT2 +{ + // TODO: make enum class in SawyerCoding namespace + enum + { + CHUNK_ENCODING_NONE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLECOMPRESSED, + CHUNK_ENCODING_ROTATE + }; + + // TODO: make enum class in SawyerCoding namespace + enum + { + FILE_VERSION_MASK = (3 << 0), + FILE_VERSION_RCT1 = (0 << 0), + FILE_VERSION_RCT1_AA = (1 << 0), + FILE_VERSION_RCT1_LL = (2 << 0), + + FILE_TYPE_MASK = (3 << 2), + FILE_TYPE_TD4 = (0 << 2), + FILE_TYPE_SV4 = (1 << 2), + FILE_TYPE_SC4 = (2 << 2) + }; +} // namespace OpenRCT2 + +namespace OpenRCT2::SawyerCoding +{ +#pragma pack(push, 1) + struct ChunkHeader + { + uint8_t encoding; + uint32_t length; + }; + static_assert(sizeof(ChunkHeader) == 5); +#pragma pack(pop) + + uint32_t CalculateChecksum(const uint8_t* buffer, size_t length); + size_t WriteChunkBuffer(uint8_t* dst_file, const uint8_t* src_buffer, ChunkHeader chunkHeader); + size_t DecodeSV4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength); + size_t DecodeSC4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength); + size_t EncodeSV4(const uint8_t* src, uint8_t* dst, size_t length); + size_t DecodeTD6(const uint8_t* src, uint8_t* dst, size_t length); + size_t EncodeTD6(const uint8_t* src, uint8_t* dst, size_t length); + int32_t ValidateTrackChecksum(const uint8_t* src, size_t length); + + int32_t DetectFileType(const uint8_t* src, size_t length); + int32_t DetectRCT1Version(int32_t gameVersion); +} // namespace OpenRCT2::SawyerCoding diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 95e2371cd2..dcfd4acf7c 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -203,6 +203,8 @@ + + @@ -222,8 +224,7 @@ - - + @@ -595,8 +596,7 @@ - - + @@ -768,6 +768,7 @@ + @@ -1091,7 +1092,6 @@ - diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index d4cb290212..8dc1032cee 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -23,6 +23,7 @@ #include "../core/File.h" #include "../core/Guard.hpp" #include "../core/Json.hpp" +#include "../core/SawyerCoding.h" #include "../entity/EntityList.h" #include "../entity/EntityRegistry.h" #include "../entity/EntityTweener.h" @@ -35,7 +36,6 @@ #include "../scripting/ScriptEngine.h" #include "../ui/UiContext.h" #include "../ui/WindowManager.h" -#include "../util/SawyerCoding.h" #include "../world/Location.hpp" #include "network.h" diff --git a/src/openrct2/object/ObjectList.cpp b/src/openrct2/object/ObjectList.cpp index 59d50d887b..27ebb3c8d9 100644 --- a/src/openrct2/object/ObjectList.cpp +++ b/src/openrct2/object/ObjectList.cpp @@ -11,8 +11,8 @@ #include "../Context.h" #include "../Game.h" +#include "../core/SawyerCoding.h" #include "../object/Object.h" -#include "../util/SawyerCoding.h" #include "../util/Util.h" #include "ObjectLimits.h" #include "ObjectManager.h" diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index 5be0e5eae8..ee90794869 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -23,6 +23,7 @@ #include "../core/MemoryStream.h" #include "../core/Numerics.hpp" #include "../core/Path.hpp" +#include "../core/SawyerCoding.h" #include "../core/String.hpp" #include "../localisation/LocalisationService.h" #include "../object/Object.h" @@ -31,7 +32,6 @@ #include "../rct12/SawyerChunkReader.h" #include "../rct12/SawyerChunkWriter.h" #include "../scenario/ScenarioRepository.h" -#include "../util/SawyerCoding.h" #include "../util/Util.h" #include "Object.h" #include "ObjectFactory.h" @@ -528,11 +528,11 @@ private: // Encode data ObjectType objectType = entry->GetType(); - SawyerCodingChunkHeader chunkHeader; + SawyerCoding::ChunkHeader chunkHeader; chunkHeader.encoding = kLegacyObjectEntryGroupEncoding[EnumValue(objectType)]; chunkHeader.length = static_cast(dataSize); uint8_t* encodedDataBuffer = Memory::Allocate(0x600000); - size_t encodedDataSize = SawyerCodingWriteChunkBuffer( + size_t encodedDataSize = SawyerCoding::WriteChunkBuffer( encodedDataBuffer, reinterpret_cast(data), chunkHeader); // Save to file diff --git a/src/openrct2/platform/Crash.cpp b/src/openrct2/platform/Crash.cpp index b999eeb3de..69734b4377 100644 --- a/src/openrct2/platform/Crash.cpp +++ b/src/openrct2/platform/Crash.cpp @@ -35,6 +35,7 @@ # include "../core/Console.hpp" # include "../core/Guard.hpp" # include "../core/Path.hpp" +# include "../core/SawyerCoding.h" # include "../core/String.hpp" # include "../drawing/IDrawingEngine.h" # include "../interface/Screenshot.h" @@ -42,7 +43,6 @@ # include "../object/ObjectManager.h" # include "../park/ParkFile.h" # include "../scenario/Scenario.h" -# include "../util/SawyerCoding.h" # include "Platform.h" # define WSZ(x) L"" x diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index f9f6362ac2..548241ceb6 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -24,6 +24,7 @@ #include "../core/IStream.hpp" #include "../core/Memory.hpp" #include "../core/Path.hpp" +#include "../core/SawyerCoding.h" #include "../core/String.hpp" #include "../entity/Balloon.h" #include "../entity/Duck.h" @@ -61,7 +62,6 @@ #include "../scenario/Scenario.h" #include "../scenario/ScenarioRepository.h" #include "../scenario/ScenarioSources.h" -#include "../util/SawyerCoding.h" #include "../util/Util.h" #include "../world/Climate.h" #include "../world/Entrance.h" @@ -175,7 +175,7 @@ namespace OpenRCT2::RCT1 _s4 = *ReadAndDecodeS4(stream, isScenario); _s4Path = path; _isScenario = isScenario; - _gameVersion = SawyerCodingDetectRCT1Version(_s4.GameVersion) & FILE_VERSION_MASK; + _gameVersion = SawyerCoding::DetectRCT1Version(_s4.GameVersion) & FILE_VERSION_MASK; // Only determine what objects we required to import this saved game InitialiseEntryMaps(); @@ -309,14 +309,14 @@ namespace OpenRCT2::RCT1 auto decodedData = std::make_unique(sizeof(S4)); size_t decodedSize; - int32_t fileType = SawyerCodingDetectFileType(data.get(), dataSize); + int32_t fileType = SawyerCoding::DetectFileType(data.get(), dataSize); if (isScenario && (fileType & FILE_VERSION_MASK) != FILE_VERSION_RCT1) { - decodedSize = SawyerCodingDecodeSC4(data.get(), decodedData.get(), dataSize, sizeof(S4)); + decodedSize = SawyerCoding::DecodeSC4(data.get(), decodedData.get(), dataSize, sizeof(S4)); } else { - decodedSize = SawyerCodingDecodeSV4(data.get(), decodedData.get(), dataSize, sizeof(S4)); + decodedSize = SawyerCoding::DecodeSV4(data.get(), decodedData.get(), dataSize, sizeof(S4)); } if (decodedSize == sizeof(S4)) diff --git a/src/openrct2/rct12/SawyerChunkReader.cpp b/src/openrct2/rct12/SawyerChunkReader.cpp index 1e93b99298..6af96998f7 100644 --- a/src/openrct2/rct12/SawyerChunkReader.cpp +++ b/src/openrct2/rct12/SawyerChunkReader.cpp @@ -24,7 +24,7 @@ constexpr const char* EXCEPTION_MSG_DESTINATION_TOO_SMALL = "Chunk data larger t constexpr const char* EXCEPTION_MSG_INVALID_CHUNK_ENCODING = "Invalid chunk encoding."; constexpr const char* EXCEPTION_MSG_ZERO_SIZED_CHUNK = "Encountered zero-sized chunk."; -static MemoryStream DecodeChunk(const void* src, const SawyerCodingChunkHeader& header); +static MemoryStream DecodeChunk(const void* src, const SawyerCoding::ChunkHeader& header); SawyerChunkReader::SawyerChunkReader(OpenRCT2::IStream* stream) : _stream(stream) @@ -36,7 +36,7 @@ void SawyerChunkReader::SkipChunk() uint64_t originalPosition = _stream->GetPosition(); try { - auto header = _stream->ReadValue(); + auto header = _stream->ReadValue(); _stream->Seek(header.length, OpenRCT2::STREAM_SEEK_CURRENT); } catch (const std::exception&) @@ -52,7 +52,7 @@ std::shared_ptr SawyerChunkReader::ReadChunk() uint64_t originalPosition = _stream->GetPosition(); try { - auto header = _stream->ReadValue(); + auto header = _stream->ReadValue(); if (header.length >= MAX_UNCOMPRESSED_CHUNK_SIZE) throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_CHUNK_SIZE); @@ -108,7 +108,7 @@ std::shared_ptr SawyerChunkReader::ReadChunkTrack() throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_CHUNK_SIZE); } - SawyerCodingChunkHeader header{ CHUNK_ENCODING_RLE, compressedDataLength }; + SawyerCoding::ChunkHeader header{ CHUNK_ENCODING_RLE, compressedDataLength }; auto buffer = DecodeChunk(compressedData.get(), header); if (buffer.GetLength() == 0) { @@ -261,7 +261,7 @@ static MemoryStream DecodeChunkRotate(const void* src, size_t srcLength) return buf; } -static MemoryStream DecodeChunk(const void* src, const SawyerCodingChunkHeader& header) +static MemoryStream DecodeChunk(const void* src, const SawyerCoding::ChunkHeader& header) { MemoryStream buf; diff --git a/src/openrct2/rct12/SawyerChunkReader.h b/src/openrct2/rct12/SawyerChunkReader.h index 8ca5543e0c..2ebf43dbe7 100644 --- a/src/openrct2/rct12/SawyerChunkReader.h +++ b/src/openrct2/rct12/SawyerChunkReader.h @@ -10,7 +10,7 @@ #pragma once #include "../core/IStream.hpp" -#include "../util/SawyerCoding.h" +#include "../core/SawyerCoding.h" #include "SawyerChunk.h" #include diff --git a/src/openrct2/rct12/SawyerChunkWriter.cpp b/src/openrct2/rct12/SawyerChunkWriter.cpp index 765319666a..96bcc90f04 100644 --- a/src/openrct2/rct12/SawyerChunkWriter.cpp +++ b/src/openrct2/rct12/SawyerChunkWriter.cpp @@ -11,7 +11,7 @@ #include "../core/IStream.hpp" #include "../core/Numerics.hpp" -#include "../util/SawyerCoding.h" +#include "../core/SawyerCoding.h" using namespace OpenRCT2; @@ -30,12 +30,12 @@ void SawyerChunkWriter::WriteChunk(const SawyerChunk* chunk) void SawyerChunkWriter::WriteChunk(const void* src, size_t length, SAWYER_ENCODING encoding) { - SawyerCodingChunkHeader header; + SawyerCoding::ChunkHeader header; header.encoding = static_cast(encoding); header.length = static_cast(length); auto data = std::make_unique(MAX_COMPRESSED_CHUNK_SIZE); - size_t dataLength = SawyerCodingWriteChunkBuffer(data.get(), static_cast(src), header); + size_t dataLength = SawyerCoding::WriteChunkBuffer(data.get(), static_cast(src), header); _stream->Write(data.get(), dataLength); } diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index fc05b5568a..3ba6acb201 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -21,6 +21,7 @@ #include "../core/Numerics.hpp" #include "../core/Path.hpp" #include "../core/Random.hpp" +#include "../core/SawyerCoding.h" #include "../core/String.hpp" #include "../entity/Balloon.h" #include "../entity/Duck.h" @@ -68,7 +69,6 @@ #include "../scenario/Scenario.h" #include "../scenario/ScenarioRepository.h" #include "../scenario/ScenarioSources.h" -#include "../util/SawyerCoding.h" #include "../util/Util.h" #include "../world/Climate.h" #include "../world/Entrance.h" diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index c432f8ca85..78fd353d65 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -15,13 +15,13 @@ #include "../GameState.h" #include "../audio/audio.h" #include "../config/Config.h" +#include "../core/SawyerCoding.h" #include "../interface/Viewport.h" #include "../management/Finance.h" #include "../network/network.h" #include "../platform/Platform.h" #include "../rct1/RCT1.h" #include "../ride/RideColour.h" -#include "../util/SawyerCoding.h" #include "../world/Footpath.h" #include "../world/Map.h" #include "../world/MapAnimation.h" diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 118283752a..817a86ec89 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -34,6 +34,7 @@ #include "../core/DataSerialiser.h" #include "../core/File.h" #include "../core/Numerics.hpp" +#include "../core/SawyerCoding.h" #include "../core/String.hpp" #include "../core/UnitConversion.h" #include "../drawing/X8DrawingEngine.h" @@ -52,7 +53,6 @@ #include "../object/StationObject.h" #include "../rct2/RCT2.h" #include "../ride/RideConstruction.h" -#include "../util/SawyerCoding.h" #include "../util/Util.h" #include "../world/Footpath.h" #include "../world/Park.h" diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 11ea57859a..cef4e8582c 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -11,6 +11,7 @@ #include "../Diagnostic.h" #include "../Game.h" #include "../audio/audio.h" +#include "../core/SawyerCoding.h" #include "../interface/Viewport.h" #include "../localisation/StringIds.h" #include "../object/FootpathObject.h" @@ -20,7 +21,6 @@ #include "../object/ObjectList.h" #include "../object/ObjectManager.h" #include "../rct2/RCT2.h" -#include "../util/SawyerCoding.h" #include "../windows/Intent.h" #include "../world/Footpath.h" #include "../world/Scenery.h" diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index c99959915f..6b6382c9bc 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -24,6 +24,7 @@ #include "../core/Guard.hpp" #include "../core/Path.hpp" #include "../core/Random.hpp" +#include "../core/SawyerCoding.h" #include "../core/UnitConversion.h" #include "../entity/Duck.h" #include "../entity/Guest.h" @@ -47,7 +48,6 @@ #include "../rct12/RCT12.h" #include "../ride/Ride.h" #include "../ride/Track.h" -#include "../util/SawyerCoding.h" #include "../util/Util.h" #include "../windows/Intent.h" #include "../world/Climate.h" diff --git a/src/openrct2/util/SawyerCoding.cpp b/src/openrct2/util/SawyerCoding.cpp deleted file mode 100644 index 76de8d4b0c..0000000000 --- a/src/openrct2/util/SawyerCoding.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2024 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#include "SawyerCoding.h" - -#include "../core/Numerics.hpp" -#include "../platform/Platform.h" -#include "../scenario/Scenario.h" -#include "Util.h" - -#include -#include -#include - -using namespace OpenRCT2; - -static size_t DecodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length); -static size_t DecodeChunkRLEWithSize(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length, size_t dstSize); - -static size_t EncodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length); -static size_t EncodeChunkRepeat(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length); -static void EncodeChunkRotate(uint8_t* buffer, size_t length); - -uint32_t SawyerCodingCalculateChecksum(const uint8_t* buffer, size_t length) -{ - uint32_t checksum = 0; - for (size_t i = 0; i < length; i++) - checksum += buffer[i]; - - return checksum; -} - -/** - * - * rct2: 0x006762E1 - * - */ -size_t SawyerCodingWriteChunkBuffer(uint8_t* dst_file, const uint8_t* buffer, SawyerCodingChunkHeader chunkHeader) -{ - switch (chunkHeader.encoding) - { - case CHUNK_ENCODING_NONE: - std::memcpy(dst_file, &chunkHeader, sizeof(SawyerCodingChunkHeader)); - dst_file += sizeof(SawyerCodingChunkHeader); - std::memcpy(dst_file, buffer, chunkHeader.length); - // fwrite(&chunkHeader, sizeof(SawyerCodingChunkHeader), 1, file); - // fwrite(buffer, 1, chunkHeader.length, file); - break; - case CHUNK_ENCODING_RLE: - { - auto encode_buffer = std::make_unique(0x600000); - chunkHeader.length = static_cast(EncodeChunkRLE(buffer, encode_buffer.get(), chunkHeader.length)); - std::memcpy(dst_file, &chunkHeader, sizeof(SawyerCodingChunkHeader)); - dst_file += sizeof(SawyerCodingChunkHeader); - std::memcpy(dst_file, encode_buffer.get(), chunkHeader.length); - } - break; - case CHUNK_ENCODING_RLECOMPRESSED: - { - auto encode_buffer = std::make_unique(chunkHeader.length * 2); - auto encode_buffer2 = std::make_unique(0x600000); - chunkHeader.length = static_cast(EncodeChunkRepeat(buffer, encode_buffer.get(), chunkHeader.length)); - chunkHeader.length = static_cast( - EncodeChunkRLE(encode_buffer.get(), encode_buffer2.get(), chunkHeader.length)); - std::memcpy(dst_file, &chunkHeader, sizeof(SawyerCodingChunkHeader)); - dst_file += sizeof(SawyerCodingChunkHeader); - std::memcpy(dst_file, encode_buffer2.get(), chunkHeader.length); - } - break; - case CHUNK_ENCODING_ROTATE: - { - auto encode_buffer = std::make_unique(chunkHeader.length); - std::memcpy(encode_buffer.get(), buffer, chunkHeader.length); - EncodeChunkRotate(encode_buffer.get(), chunkHeader.length); - std::memcpy(dst_file, &chunkHeader, sizeof(SawyerCodingChunkHeader)); - dst_file += sizeof(SawyerCodingChunkHeader); - std::memcpy(dst_file, encode_buffer.get(), chunkHeader.length); - } - break; - } - - return chunkHeader.length + sizeof(SawyerCodingChunkHeader); -} - -size_t SawyerCodingDecodeSV4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength) -{ - // (0 to length - 4): RLE chunk - // (length - 4 to length): checksum - return DecodeChunkRLEWithSize(src, dst, length - 4, bufferLength); -} - -size_t SawyerCodingDecodeSC4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength) -{ - // Uncompress - size_t decodedLength = DecodeChunkRLEWithSize(src, dst, length - 4, bufferLength); - - // Decode - for (size_t i = 0x60018; i <= std::min(decodedLength - 1, static_cast(0x1F8353)); i++) - dst[i] = dst[i] ^ 0x9C; - - for (size_t i = 0x60018; i <= std::min(decodedLength - 1, static_cast(0x1F8350)); i += 4) - { - dst[i + 1] = Numerics::ror8(dst[i + 1], 3); - - uint32_t* code = reinterpret_cast(&dst[i]); - *code = Numerics::rol32(*code, 9); - } - - return decodedLength; -} - -size_t SawyerCodingEencodeSV4(const uint8_t* src, uint8_t* dst, size_t length) -{ - // Encode - size_t encodedLength = EncodeChunkRLE(src, dst, length); - - // Append checksum - uint32_t checksum = SawyerCodingCalculateChecksum(dst, encodedLength); - *(reinterpret_cast(&dst[encodedLength])) = checksum; - - return encodedLength + 4; -} - -size_t SawyerCodingDecodeTD6(const uint8_t* src, uint8_t* dst, size_t length) -{ - return DecodeChunkRLE(src, dst, length - 4); -} - -size_t SawyerCodingEncodeTD6(const uint8_t* src, uint8_t* dst, size_t length) -{ - size_t output_length = EncodeChunkRLE(src, dst, length); - - uint32_t checksum = 0; - for (size_t i = 0; i < output_length; i++) - { - uint8_t new_byte = ((checksum & 0xFF) + dst[i]) & 0xFF; - checksum = (checksum & 0xFFFFFF00) + new_byte; - checksum = Numerics::rol32(checksum, 3); - } - checksum -= 0x1D4C1; - - *(reinterpret_cast(&dst[output_length])) = checksum; - output_length += 4; - return output_length; -} - -/* Based off of rct2: 0x006770C1 */ -int32_t SawyerCodingValidateTrackChecksum(const uint8_t* src, size_t length) -{ - if (length < 4) - return 0; - - uint32_t file_checksum = *(reinterpret_cast(&src[length - 4])); - - uint32_t checksum = 0; - for (size_t i = 0; i < length - 4; i++) - { - uint8_t new_byte = ((checksum & 0xFF) + src[i]) & 0xFF; - checksum = (checksum & 0xFFFFFF00) + new_byte; - checksum = Numerics::rol32(checksum, 3); - } - - if (checksum - 0x1D4C1 == file_checksum) - return 1; // .TD6 - else if (checksum - 0x1A67C == file_checksum) - return 1; // .TD4 - else if (checksum - 0x1A650 == file_checksum) - return 1; // .TD4 - else - return 0; -} - -#pragma region Decoding - -/** - * - * rct2: 0x0067693A - */ -static size_t DecodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length) -{ - size_t count; - uint8_t *dst, rleCodeByte; - - dst = dst_buffer; - - for (size_t i = 0; i < length; i++) - { - rleCodeByte = src_buffer[i]; - if (rleCodeByte & 128) - { - i++; - count = 257 - rleCodeByte; - std::fill_n(dst, count, src_buffer[i]); - dst = reinterpret_cast(reinterpret_cast(dst) + count); - } - else - { - std::memcpy(dst, src_buffer + i + 1, rleCodeByte + 1); - dst = reinterpret_cast(reinterpret_cast(dst) + rleCodeByte + 1); - i += rleCodeByte + 1; - } - } - - // Return final size - return dst - dst_buffer; -} - -/** - * - * rct2: 0x0067693A - */ -static size_t DecodeChunkRLEWithSize(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length, size_t dstSize) -{ - size_t count; - uint8_t *dst, rleCodeByte; - - dst = dst_buffer; - - if (length <= 0 || dstSize <= 0) - throw std::out_of_range("Invalid RLE string!"); - - for (size_t i = 0; i < length; i++) - { - rleCodeByte = src_buffer[i]; - if (rleCodeByte & 128) - { - i++; - count = 257 - rleCodeByte; - assert(dst + count <= dst_buffer + dstSize); - assert(i < length); - std::fill_n(dst, count, src_buffer[i]); - dst = reinterpret_cast(reinterpret_cast(dst) + count); - } - else - { - if ((dst + rleCodeByte + 1 > dst_buffer + dstSize) || (i + 1 >= length)) - throw std::out_of_range("Invalid RLE string!"); - std::memcpy(dst, src_buffer + i + 1, rleCodeByte + 1); - dst = reinterpret_cast(reinterpret_cast(dst) + rleCodeByte + 1); - i += rleCodeByte + 1; - } - } - - // Return final size - return dst - dst_buffer; -} - -#pragma endregion - -#pragma region Encoding - -/** - * Ensure dst_buffer is bigger than src_buffer then resize afterwards - * returns length of dst_buffer - */ -static size_t EncodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length) -{ - const uint8_t* src = src_buffer; - uint8_t* dst = dst_buffer; - const uint8_t* end_src = src + length; - uint8_t count = 0; - const uint8_t* src_norm_start = src; - - while (src < end_src - 1) - { - if ((count && *src == src[1]) || count > 125) - { - *dst++ = count - 1; - std::memcpy(dst, src_norm_start, count); - dst += count; - src_norm_start += count; - count = 0; - } - if (*src == src[1]) - { - for (; (count < 125) && ((src + count) < end_src); count++) - { - if (*src != src[count]) - break; - } - *dst++ = 257 - count; - *dst++ = *src; - src += count; - src_norm_start = src; - count = 0; - } - else - { - count++; - src++; - } - } - if (src == end_src - 1) - count++; - if (count) - { - *dst++ = count - 1; - std::memcpy(dst, src_norm_start, count); - dst += count; - } - return dst - dst_buffer; -} - -static size_t EncodeChunkRepeat(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length) -{ - if (length == 0) - return 0; - - size_t outLength = 0; - - // Need to emit at least one byte, otherwise there is nothing to repeat - *dst_buffer++ = 255; - *dst_buffer++ = src_buffer[0]; - outLength += 2; - - // Iterate through remainder of the source buffer - for (size_t i = 1; i < length;) - { - size_t searchIndex = (i < 32) ? 0 : (i - 32); - size_t searchEnd = i - 1; - - size_t bestRepeatIndex = 0; - size_t bestRepeatCount = 0; - for (size_t repeatIndex = searchIndex; repeatIndex <= searchEnd; repeatIndex++) - { - size_t repeatCount = 0; - size_t maxRepeatCount = std::min(std::min(static_cast(7), searchEnd - repeatIndex), length - i - 1); - // maxRepeatCount should not exceed length - assert(repeatIndex + maxRepeatCount < length); - assert(i + maxRepeatCount < length); - for (size_t j = 0; j <= maxRepeatCount; j++) - { - if (src_buffer[repeatIndex + j] == src_buffer[i + j]) - { - repeatCount++; - } - else - { - break; - } - } - if (repeatCount > bestRepeatCount) - { - bestRepeatIndex = repeatIndex; - bestRepeatCount = repeatCount; - - // Maximum repeat count is 8 - if (repeatCount == 8) - break; - } - } - - if (bestRepeatCount == 0) - { - *dst_buffer++ = 255; - *dst_buffer++ = src_buffer[i]; - outLength += 2; - i++; - } - else - { - *dst_buffer++ = static_cast((bestRepeatCount - 1) | ((32 - (i - bestRepeatIndex)) << 3)); - outLength++; - i += bestRepeatCount; - } - } - - return outLength; -} - -static void EncodeChunkRotate(uint8_t* buffer, size_t length) -{ - size_t i; - uint8_t code = 1; - for (i = 0; i < length; i++) - { - buffer[i] = Numerics::rol8(buffer[i], code); - code = (code + 2) % 8; - } -} - -#pragma endregion - -int32_t SawyerCodingDetectFileType(const uint8_t* src, size_t length) -{ - if (length < 4) - { - throw std::length_error("Stream is (nearly) empty!"); - } - - size_t i; - - // Currently can't detect TD4, as the checksum is the same as SC4 (need alternative method) - - uint32_t checksum = *(reinterpret_cast(&src[length - 4])); - uint32_t actualChecksum = 0; - for (i = 0; i < length - 4; i++) - { - actualChecksum = (actualChecksum & 0xFFFFFF00) | (((actualChecksum & 0xFF) + static_cast(src[i])) & 0xFF); - actualChecksum = Numerics::rol32(actualChecksum, 3); - } - - return SawyerCodingDetectRCT1Version(checksum - actualChecksum); -} - -int32_t SawyerCodingDetectRCT1Version(int32_t gameVersion) -{ - int32_t fileType = (gameVersion) > 0 ? FILE_TYPE_SV4 : FILE_TYPE_SC4; - gameVersion = abs(gameVersion); - - if (gameVersion >= 108000 && gameVersion < 110000) - return (FILE_VERSION_RCT1 | fileType); - if (gameVersion >= 110000 && gameVersion < 120000) - return (FILE_VERSION_RCT1_AA | fileType); - if (gameVersion >= 120000 && gameVersion < 130000) - return (FILE_VERSION_RCT1_LL | fileType); - // RCTOA Acres sets this, and possibly some other user-created scenarios as well - if (gameVersion == 0) - return (FILE_VERSION_RCT1_LL | fileType); - - return -1; -} diff --git a/src/openrct2/util/SawyerCoding.h b/src/openrct2/util/SawyerCoding.h deleted file mode 100644 index 2997d587a4..0000000000 --- a/src/openrct2/util/SawyerCoding.h +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2024 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#pragma once - -#include -#include - -#pragma pack(push, 1) -struct SawyerCodingChunkHeader -{ - uint8_t encoding; - uint32_t length; -}; -static_assert(sizeof(SawyerCodingChunkHeader) == 5); -#pragma pack(pop) - -enum -{ - CHUNK_ENCODING_NONE, - CHUNK_ENCODING_RLE, - CHUNK_ENCODING_RLECOMPRESSED, - CHUNK_ENCODING_ROTATE -}; - -enum -{ - FILE_VERSION_MASK = (3 << 0), - FILE_VERSION_RCT1 = (0 << 0), - FILE_VERSION_RCT1_AA = (1 << 0), - FILE_VERSION_RCT1_LL = (2 << 0), - - FILE_TYPE_MASK = (3 << 2), - FILE_TYPE_TD4 = (0 << 2), - FILE_TYPE_SV4 = (1 << 2), - FILE_TYPE_SC4 = (2 << 2) -}; - -uint32_t SawyerCodingCalculateChecksum(const uint8_t* buffer, size_t length); -size_t SawyerCodingWriteChunkBuffer(uint8_t* dst_file, const uint8_t* src_buffer, SawyerCodingChunkHeader chunkHeader); -size_t SawyerCodingDecodeSV4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength); -size_t SawyerCodingDecodeSC4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength); -size_t SawyerCodingEencodeSV4(const uint8_t* src, uint8_t* dst, size_t length); -size_t SawyerCodingDecodeTD6(const uint8_t* src, uint8_t* dst, size_t length); -size_t SawyerCodingEncodeTD6(const uint8_t* src, uint8_t* dst, size_t length); -int32_t SawyerCodingValidateTrackChecksum(const uint8_t* src, size_t length); - -int32_t SawyerCodingDetectFileType(const uint8_t* src, size_t length); -int32_t SawyerCodingDetectRCT1Version(int32_t gameVersion); diff --git a/test/tests/SawyerCodingTest.cpp b/test/tests/SawyerCodingTest.cpp index 4df48d448e..05dff2888a 100644 --- a/test/tests/SawyerCodingTest.cpp +++ b/test/tests/SawyerCodingTest.cpp @@ -9,11 +9,13 @@ #include #include +#include #include -#include constexpr size_t BUFFER_SIZE = 0x600000; +using namespace OpenRCT2; + class SawyerCodingTest : public testing::Test { protected: @@ -34,13 +36,13 @@ protected: void TestEncodeDecode(uint8_t encoding_type) { // Encode - SawyerCodingChunkHeader chdr_in; + SawyerCoding::ChunkHeader chdr_in; chdr_in.encoding = encoding_type; chdr_in.length = sizeof(randomdata); uint8_t* encodedDataBuffer = new uint8_t[BUFFER_SIZE]; - size_t encodedDataSize = SawyerCodingWriteChunkBuffer( + size_t encodedDataSize = SawyerCoding::WriteChunkBuffer( encodedDataBuffer, reinterpret_cast(randomdata), chdr_in); - ASSERT_GT(encodedDataSize, sizeof(SawyerCodingChunkHeader)); + ASSERT_GT(encodedDataSize, sizeof(SawyerCoding::ChunkHeader)); // Decode OpenRCT2::MemoryStream ms(encodedDataBuffer, encodedDataSize); @@ -56,8 +58,8 @@ protected: void TestDecode(const uint8_t* data, size_t size) { - auto expectedLength = size - sizeof(SawyerCodingChunkHeader); - auto chdr_in = reinterpret_cast(data); + auto expectedLength = size - sizeof(SawyerCoding::ChunkHeader); + auto chdr_in = reinterpret_cast(data); ASSERT_EQ(chdr_in->length, expectedLength); OpenRCT2::MemoryStream ms(data, size); From 487886695ea9a86b436fa097148959c283d11b00 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 29 Oct 2024 22:02:41 +0100 Subject: [PATCH 71/97] Move SawyerChunk units into OpenRCT2 namespace --- src/openrct2/rct12/SawyerChunk.cpp | 13 +- src/openrct2/rct12/SawyerChunk.h | 69 +-- src/openrct2/rct12/SawyerChunkReader.cpp | 517 ++++++++++++----------- src/openrct2/rct12/SawyerChunkReader.h | 130 +++--- src/openrct2/rct12/SawyerChunkWriter.cpp | 171 ++++---- src/openrct2/rct12/SawyerChunkWriter.h | 76 ++-- 6 files changed, 491 insertions(+), 485 deletions(-) diff --git a/src/openrct2/rct12/SawyerChunk.cpp b/src/openrct2/rct12/SawyerChunk.cpp index 667821ec6e..07393c8e17 100644 --- a/src/openrct2/rct12/SawyerChunk.cpp +++ b/src/openrct2/rct12/SawyerChunk.cpp @@ -11,10 +11,11 @@ #include "SawyerChunkReader.h" -using namespace OpenRCT2; - -SawyerChunk::SawyerChunk(SAWYER_ENCODING encoding, MemoryStream&& data) - : _data(std::move(data)) - , _encoding(encoding) +namespace OpenRCT2 { -} + SawyerChunk::SawyerChunk(SAWYER_ENCODING encoding, MemoryStream&& data) + : _data(std::move(data)) + , _encoding(encoding) + { + } +} // namespace OpenRCT2 diff --git a/src/openrct2/rct12/SawyerChunk.h b/src/openrct2/rct12/SawyerChunk.h index fb7fa47966..67615ec1d5 100644 --- a/src/openrct2/rct12/SawyerChunk.h +++ b/src/openrct2/rct12/SawyerChunk.h @@ -13,39 +13,42 @@ #include -/** - * The type of encoding / compression for a sawyer encoded chunk. - */ -enum class SAWYER_ENCODING : uint8_t +namespace OpenRCT2 { - NONE, - RLE, - RLECOMPRESSED, - ROTATE, -}; - -/** - * Represents a sawyer encoded chunk. - */ -class SawyerChunk final -{ -private: - OpenRCT2::MemoryStream _data; - SAWYER_ENCODING _encoding = SAWYER_ENCODING::NONE; - -public: - const void* GetData() const + /** + * The type of encoding / compression for a sawyer encoded chunk. + */ + enum class SAWYER_ENCODING : uint8_t { - return _data.GetData(); - } - size_t GetLength() const - { - return _data.GetLength(); - } - SAWYER_ENCODING GetEncoding() const - { - return _encoding; - } + NONE, + RLE, + RLECOMPRESSED, + ROTATE, + }; - SawyerChunk(SAWYER_ENCODING encoding, OpenRCT2::MemoryStream&& data); -}; + /** + * Represents a sawyer encoded chunk. + */ + class SawyerChunk final + { + private: + OpenRCT2::MemoryStream _data; + SAWYER_ENCODING _encoding = SAWYER_ENCODING::NONE; + + public: + const void* GetData() const + { + return _data.GetData(); + } + size_t GetLength() const + { + return _data.GetLength(); + } + SAWYER_ENCODING GetEncoding() const + { + return _encoding; + } + + SawyerChunk(SAWYER_ENCODING encoding, OpenRCT2::MemoryStream&& data); + }; +} // namespace OpenRCT2 diff --git a/src/openrct2/rct12/SawyerChunkReader.cpp b/src/openrct2/rct12/SawyerChunkReader.cpp index 6af96998f7..07d2fd95b4 100644 --- a/src/openrct2/rct12/SawyerChunkReader.cpp +++ b/src/openrct2/rct12/SawyerChunkReader.cpp @@ -13,278 +13,279 @@ #include "../core/MemoryStream.h" #include "../core/Numerics.hpp" -using namespace OpenRCT2; - -// Allow chunks to be uncompressed to a maximum of 16 MiB -constexpr size_t MAX_UNCOMPRESSED_CHUNK_SIZE = 16 * 1024 * 1024; - -constexpr const char* EXCEPTION_MSG_CORRUPT_CHUNK_SIZE = "Corrupt chunk size."; -constexpr const char* EXCEPTION_MSG_CORRUPT_RLE = "Corrupt RLE compression data."; -constexpr const char* EXCEPTION_MSG_DESTINATION_TOO_SMALL = "Chunk data larger than allocated destination capacity."; -constexpr const char* EXCEPTION_MSG_INVALID_CHUNK_ENCODING = "Invalid chunk encoding."; -constexpr const char* EXCEPTION_MSG_ZERO_SIZED_CHUNK = "Encountered zero-sized chunk."; - -static MemoryStream DecodeChunk(const void* src, const SawyerCoding::ChunkHeader& header); - -SawyerChunkReader::SawyerChunkReader(OpenRCT2::IStream* stream) - : _stream(stream) +namespace OpenRCT2 { -} + // Allow chunks to be uncompressed to a maximum of 16 MiB + constexpr size_t MAX_UNCOMPRESSED_CHUNK_SIZE = 16 * 1024 * 1024; -void SawyerChunkReader::SkipChunk() -{ - uint64_t originalPosition = _stream->GetPosition(); - try + constexpr const char* EXCEPTION_MSG_CORRUPT_CHUNK_SIZE = "Corrupt chunk size."; + constexpr const char* EXCEPTION_MSG_CORRUPT_RLE = "Corrupt RLE compression data."; + constexpr const char* EXCEPTION_MSG_DESTINATION_TOO_SMALL = "Chunk data larger than allocated destination capacity."; + constexpr const char* EXCEPTION_MSG_INVALID_CHUNK_ENCODING = "Invalid chunk encoding."; + constexpr const char* EXCEPTION_MSG_ZERO_SIZED_CHUNK = "Encountered zero-sized chunk."; + + static MemoryStream DecodeChunk(const void* src, const SawyerCoding::ChunkHeader& header); + + SawyerChunkReader::SawyerChunkReader(OpenRCT2::IStream* stream) + : _stream(stream) { - auto header = _stream->ReadValue(); - _stream->Seek(header.length, OpenRCT2::STREAM_SEEK_CURRENT); } - catch (const std::exception&) - { - // Rewind stream back to original position - _stream->SetPosition(originalPosition); - throw; - } -} -std::shared_ptr SawyerChunkReader::ReadChunk() -{ - uint64_t originalPosition = _stream->GetPosition(); - try + void SawyerChunkReader::SkipChunk() { - auto header = _stream->ReadValue(); - if (header.length >= MAX_UNCOMPRESSED_CHUNK_SIZE) - throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_CHUNK_SIZE); + uint64_t originalPosition = _stream->GetPosition(); + try + { + auto header = _stream->ReadValue(); + _stream->Seek(header.length, OpenRCT2::STREAM_SEEK_CURRENT); + } + catch (const std::exception&) + { + // Rewind stream back to original position + _stream->SetPosition(originalPosition); + throw; + } + } + + std::shared_ptr SawyerChunkReader::ReadChunk() + { + uint64_t originalPosition = _stream->GetPosition(); + try + { + auto header = _stream->ReadValue(); + if (header.length >= MAX_UNCOMPRESSED_CHUNK_SIZE) + throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_CHUNK_SIZE); + + switch (header.encoding) + { + case CHUNK_ENCODING_NONE: + case CHUNK_ENCODING_RLE: + case CHUNK_ENCODING_RLECOMPRESSED: + case CHUNK_ENCODING_ROTATE: + { + auto compressedData = std::make_unique(header.length); + if (_stream->TryRead(compressedData.get(), header.length) != header.length) + { + throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_CHUNK_SIZE); + } + + auto buffer = DecodeChunk(compressedData.get(), header); + if (buffer.GetLength() == 0) + { + throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); + } + + return std::make_shared(static_cast(header.encoding), std::move(buffer)); + } + default: + throw SawyerChunkException(EXCEPTION_MSG_INVALID_CHUNK_ENCODING); + } + } + catch (const std::exception&) + { + // Rewind stream back to original position + _stream->SetPosition(originalPosition); + throw; + } + } + + std::shared_ptr SawyerChunkReader::ReadChunkTrack() + { + uint64_t originalPosition = _stream->GetPosition(); + try + { + // Remove 4 as we don't want to touch the checksum at the end of the file + int64_t compressedDataLength64 = _stream->GetLength() - _stream->GetPosition() - 4; + if (compressedDataLength64 < 0 || compressedDataLength64 > std::numeric_limits::max()) + { + throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); + } + uint32_t compressedDataLength = compressedDataLength64; + auto compressedData = std::make_unique(compressedDataLength); + + if (_stream->TryRead(compressedData.get(), compressedDataLength) != compressedDataLength) + { + throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_CHUNK_SIZE); + } + + SawyerCoding::ChunkHeader header{ CHUNK_ENCODING_RLE, compressedDataLength }; + auto buffer = DecodeChunk(compressedData.get(), header); + if (buffer.GetLength() == 0) + { + throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); + } + return std::make_shared(SAWYER_ENCODING::RLE, std::move(buffer)); + } + catch (const std::exception&) + { + // Rewind stream back to original position + _stream->SetPosition(originalPosition); + throw; + } + } + + void SawyerChunkReader::ReadChunk(void* dst, size_t length) + { + auto chunk = ReadChunk(); + auto chunkData = static_cast(chunk->GetData()); + auto chunkLength = chunk->GetLength(); + if (chunkLength > length) + { + std::memcpy(dst, chunkData, length); + } + else + { + std::memcpy(dst, chunkData, chunkLength); + auto remainingLength = length - chunkLength; + if (remainingLength > 0) + { + auto offset = static_cast(dst) + chunkLength; + std::fill_n(offset, remainingLength, 0x00); + } + } + } + + static MemoryStream DecodeChunkRLE(const void* src, size_t srcLength) + { + MemoryStream buf; + + auto src8 = static_cast(src); + for (size_t i = 0; i < srcLength; i++) + { + uint8_t rleCodeByte = src8[i]; + if (rleCodeByte & 128) + { + i++; + size_t count = 257 - rleCodeByte; + + if (i >= srcLength) + { + throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); + } + if (buf.GetLength() + count > MAX_UNCOMPRESSED_CHUNK_SIZE) + { + throw SawyerChunkException(EXCEPTION_MSG_DESTINATION_TOO_SMALL); + } + + for (size_t n = 0; n < count; n++) + { + buf.Write1(src8 + i); + } + } + else + { + const auto len = rleCodeByte + 1; + + if (i + 1 >= srcLength) + { + throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); + } + if (buf.GetLength() + len > MAX_UNCOMPRESSED_CHUNK_SIZE) + { + throw SawyerChunkException(EXCEPTION_MSG_DESTINATION_TOO_SMALL); + } + if (i + 1 + len > srcLength) + { + throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); + } + + const auto* pos = src8 + i + 1; + + buf.Write(pos, len); + i += len; + } + } + + return buf; + } + + static MemoryStream DecodeChunkRepeat(const void* src, size_t srcLength) + { + MemoryStream buf; + + auto src8 = static_cast(src); + for (size_t i = 0; i < srcLength; i++) + { + if (src8[i] == 0xFF) + { + if (i + 1 >= srcLength) + { + throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); + } + i++; + buf.Write1(src8 + i); + } + else + { + size_t count = (src8[i] & 7) + 1; + int32_t offset = static_cast(src8[i] >> 3) - 32; + const uint8_t* copySrc = static_cast(buf.GetData()) + (buf.GetLength() + offset); + + if (copySrc < static_cast(buf.GetData()) + || copySrc + count > static_cast(buf.GetData()) + buf.GetLength()) + { + throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); + } + + // We need a temporary buffer as the vector might invalidate the pointer. + uint8_t temp[16]; + std::memcpy(temp, copySrc, count); + + buf.Write(temp, count); + } + } + + return buf; + } + + static MemoryStream DecodeChunkRLERepeat(const void* src, size_t srcLength) + { + auto tempBuf = DecodeChunkRLE(src, srcLength); + return DecodeChunkRepeat(tempBuf.GetData(), tempBuf.GetLength()); + } + + static MemoryStream DecodeChunkRotate(const void* src, size_t srcLength) + { + MemoryStream buf; + + auto src8 = static_cast(src); + + uint8_t code = 1; + for (size_t i = 0; i < srcLength; i++) + { + uint8_t temp = Numerics::ror8(src8[i], code); + buf.Write1(&temp); + code = (code + 2) % 8; + } + + return buf; + } + + static MemoryStream DecodeChunk(const void* src, const SawyerCoding::ChunkHeader& header) + { + MemoryStream buf; switch (header.encoding) { case CHUNK_ENCODING_NONE: + buf.Write(src, header.length); + break; case CHUNK_ENCODING_RLE: + buf = DecodeChunkRLE(src, header.length); + break; case CHUNK_ENCODING_RLECOMPRESSED: + buf = DecodeChunkRLERepeat(src, header.length); + break; case CHUNK_ENCODING_ROTATE: - { - auto compressedData = std::make_unique(header.length); - if (_stream->TryRead(compressedData.get(), header.length) != header.length) - { - throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_CHUNK_SIZE); - } - - auto buffer = DecodeChunk(compressedData.get(), header); - if (buffer.GetLength() == 0) - { - throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); - } - - return std::make_shared(static_cast(header.encoding), std::move(buffer)); - } + buf = DecodeChunkRotate(src, header.length); + break; default: throw SawyerChunkException(EXCEPTION_MSG_INVALID_CHUNK_ENCODING); } + + // Return the stream with the position at the beginning. + buf.SetPosition(0); + + return buf; } - catch (const std::exception&) - { - // Rewind stream back to original position - _stream->SetPosition(originalPosition); - throw; - } -} - -std::shared_ptr SawyerChunkReader::ReadChunkTrack() -{ - uint64_t originalPosition = _stream->GetPosition(); - try - { - // Remove 4 as we don't want to touch the checksum at the end of the file - int64_t compressedDataLength64 = _stream->GetLength() - _stream->GetPosition() - 4; - if (compressedDataLength64 < 0 || compressedDataLength64 > std::numeric_limits::max()) - { - throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); - } - uint32_t compressedDataLength = compressedDataLength64; - auto compressedData = std::make_unique(compressedDataLength); - - if (_stream->TryRead(compressedData.get(), compressedDataLength) != compressedDataLength) - { - throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_CHUNK_SIZE); - } - - SawyerCoding::ChunkHeader header{ CHUNK_ENCODING_RLE, compressedDataLength }; - auto buffer = DecodeChunk(compressedData.get(), header); - if (buffer.GetLength() == 0) - { - throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); - } - return std::make_shared(SAWYER_ENCODING::RLE, std::move(buffer)); - } - catch (const std::exception&) - { - // Rewind stream back to original position - _stream->SetPosition(originalPosition); - throw; - } -} - -void SawyerChunkReader::ReadChunk(void* dst, size_t length) -{ - auto chunk = ReadChunk(); - auto chunkData = static_cast(chunk->GetData()); - auto chunkLength = chunk->GetLength(); - if (chunkLength > length) - { - std::memcpy(dst, chunkData, length); - } - else - { - std::memcpy(dst, chunkData, chunkLength); - auto remainingLength = length - chunkLength; - if (remainingLength > 0) - { - auto offset = static_cast(dst) + chunkLength; - std::fill_n(offset, remainingLength, 0x00); - } - } -} - -static MemoryStream DecodeChunkRLE(const void* src, size_t srcLength) -{ - MemoryStream buf; - - auto src8 = static_cast(src); - for (size_t i = 0; i < srcLength; i++) - { - uint8_t rleCodeByte = src8[i]; - if (rleCodeByte & 128) - { - i++; - size_t count = 257 - rleCodeByte; - - if (i >= srcLength) - { - throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); - } - if (buf.GetLength() + count > MAX_UNCOMPRESSED_CHUNK_SIZE) - { - throw SawyerChunkException(EXCEPTION_MSG_DESTINATION_TOO_SMALL); - } - - for (size_t n = 0; n < count; n++) - { - buf.Write1(src8 + i); - } - } - else - { - const auto len = rleCodeByte + 1; - - if (i + 1 >= srcLength) - { - throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); - } - if (buf.GetLength() + len > MAX_UNCOMPRESSED_CHUNK_SIZE) - { - throw SawyerChunkException(EXCEPTION_MSG_DESTINATION_TOO_SMALL); - } - if (i + 1 + len > srcLength) - { - throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); - } - - const auto* pos = src8 + i + 1; - - buf.Write(pos, len); - i += len; - } - } - - return buf; -} - -static MemoryStream DecodeChunkRepeat(const void* src, size_t srcLength) -{ - MemoryStream buf; - - auto src8 = static_cast(src); - for (size_t i = 0; i < srcLength; i++) - { - if (src8[i] == 0xFF) - { - if (i + 1 >= srcLength) - { - throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); - } - i++; - buf.Write1(src8 + i); - } - else - { - size_t count = (src8[i] & 7) + 1; - int32_t offset = static_cast(src8[i] >> 3) - 32; - const uint8_t* copySrc = static_cast(buf.GetData()) + (buf.GetLength() + offset); - - if (copySrc < static_cast(buf.GetData()) - || copySrc + count > static_cast(buf.GetData()) + buf.GetLength()) - { - throw SawyerChunkException(EXCEPTION_MSG_CORRUPT_RLE); - } - - // We need a temporary buffer as the vector might invalidate the pointer. - uint8_t temp[16]; - std::memcpy(temp, copySrc, count); - - buf.Write(temp, count); - } - } - - return buf; -} - -static MemoryStream DecodeChunkRLERepeat(const void* src, size_t srcLength) -{ - auto tempBuf = DecodeChunkRLE(src, srcLength); - return DecodeChunkRepeat(tempBuf.GetData(), tempBuf.GetLength()); -} - -static MemoryStream DecodeChunkRotate(const void* src, size_t srcLength) -{ - MemoryStream buf; - - auto src8 = static_cast(src); - - uint8_t code = 1; - for (size_t i = 0; i < srcLength; i++) - { - uint8_t temp = Numerics::ror8(src8[i], code); - buf.Write1(&temp); - code = (code + 2) % 8; - } - - return buf; -} - -static MemoryStream DecodeChunk(const void* src, const SawyerCoding::ChunkHeader& header) -{ - MemoryStream buf; - - switch (header.encoding) - { - case CHUNK_ENCODING_NONE: - buf.Write(src, header.length); - break; - case CHUNK_ENCODING_RLE: - buf = DecodeChunkRLE(src, header.length); - break; - case CHUNK_ENCODING_RLECOMPRESSED: - buf = DecodeChunkRLERepeat(src, header.length); - break; - case CHUNK_ENCODING_ROTATE: - buf = DecodeChunkRotate(src, header.length); - break; - default: - throw SawyerChunkException(EXCEPTION_MSG_INVALID_CHUNK_ENCODING); - } - - // Return the stream with the position at the beginning. - buf.SetPosition(0); - - return buf; -} +} // namespace OpenRCT2 diff --git a/src/openrct2/rct12/SawyerChunkReader.h b/src/openrct2/rct12/SawyerChunkReader.h index 2ebf43dbe7..e9b51b9029 100644 --- a/src/openrct2/rct12/SawyerChunkReader.h +++ b/src/openrct2/rct12/SawyerChunkReader.h @@ -17,73 +17,73 @@ #include #include -class SawyerChunkException : public IOException -{ -public: - explicit SawyerChunkException(const char* message) - : IOException(message) - { - } - explicit SawyerChunkException(const std::string& message) - : IOException(message) - { - } -}; - namespace OpenRCT2 { struct IStream; -} -/** - * Reads sawyer encoding chunks from a data stream. This can be used to read - * SC6, SV6 and RCT2 objects. persistentChunks is a hint to the reader that the chunk will be preserved, - * and thus the chunk memory should be shrunk. - */ -class SawyerChunkReader final -{ -private: - OpenRCT2::IStream* const _stream = nullptr; - -public: - explicit SawyerChunkReader(OpenRCT2::IStream* stream); - - /** - * Skips the next chunk in the stream without decoding or reading its data - * into RAM. - */ - void SkipChunk(); - - /** - * Reads the next chunk from the stream. - */ - [[nodiscard]] std::shared_ptr ReadChunk(); - - /** - * As above but for chunks without a header - */ - [[nodiscard]] std::shared_ptr ReadChunkTrack(); - - /** - * Reads the next chunk from the stream and copies it directly to the - * destination buffer. If the chunk is larger than length, only length - * is copied. If the chunk is smaller than length, the remaining space - * is padded with zero. - * @param dst The destination buffer. - * @param length The size of the destination buffer. - */ - void ReadChunk(void* dst, size_t length); - - /** - * Reads the next chunk from the stream into a buffer returned as the - * specified type. If the chunk is smaller than the size of the type - * then the remaining space is padded with zero. - */ - template - T ReadChunkAs() + class SawyerChunkException : public IOException { - T result; - ReadChunk(&result, sizeof(result)); - return result; - } -}; + public: + explicit SawyerChunkException(const char* message) + : IOException(message) + { + } + explicit SawyerChunkException(const std::string& message) + : IOException(message) + { + } + }; + + /** + * Reads sawyer encoding chunks from a data stream. This can be used to read + * SC6, SV6 and RCT2 objects. persistentChunks is a hint to the reader that the chunk will be preserved, + * and thus the chunk memory should be shrunk. + */ + class SawyerChunkReader final + { + private: + OpenRCT2::IStream* const _stream = nullptr; + + public: + explicit SawyerChunkReader(OpenRCT2::IStream* stream); + + /** + * Skips the next chunk in the stream without decoding or reading its data + * into RAM. + */ + void SkipChunk(); + + /** + * Reads the next chunk from the stream. + */ + [[nodiscard]] std::shared_ptr ReadChunk(); + + /** + * As above but for chunks without a header + */ + [[nodiscard]] std::shared_ptr ReadChunkTrack(); + + /** + * Reads the next chunk from the stream and copies it directly to the + * destination buffer. If the chunk is larger than length, only length + * is copied. If the chunk is smaller than length, the remaining space + * is padded with zero. + * @param dst The destination buffer. + * @param length The size of the destination buffer. + */ + void ReadChunk(void* dst, size_t length); + + /** + * Reads the next chunk from the stream into a buffer returned as the + * specified type. If the chunk is smaller than the size of the type + * then the remaining space is padded with zero. + */ + template + T ReadChunkAs() + { + T result; + ReadChunk(&result, sizeof(result)); + return result; + } + }; +} // namespace OpenRCT2 diff --git a/src/openrct2/rct12/SawyerChunkWriter.cpp b/src/openrct2/rct12/SawyerChunkWriter.cpp index 96bcc90f04..7589371ab1 100644 --- a/src/openrct2/rct12/SawyerChunkWriter.cpp +++ b/src/openrct2/rct12/SawyerChunkWriter.cpp @@ -13,99 +13,100 @@ #include "../core/Numerics.hpp" #include "../core/SawyerCoding.h" -using namespace OpenRCT2; - -// Maximum buffer size to store compressed data, maximum of 16 MiB -constexpr size_t MAX_COMPRESSED_CHUNK_SIZE = 16 * 1024 * 1024; - -SawyerChunkWriter::SawyerChunkWriter(OpenRCT2::IStream* stream) - : _stream(stream) +namespace OpenRCT2 { -} + // Maximum buffer size to store compressed data, maximum of 16 MiB + constexpr size_t MAX_COMPRESSED_CHUNK_SIZE = 16 * 1024 * 1024; -void SawyerChunkWriter::WriteChunk(const SawyerChunk* chunk) -{ - WriteChunk(chunk->GetData(), chunk->GetLength(), chunk->GetEncoding()); -} - -void SawyerChunkWriter::WriteChunk(const void* src, size_t length, SAWYER_ENCODING encoding) -{ - SawyerCoding::ChunkHeader header; - header.encoding = static_cast(encoding); - header.length = static_cast(length); - - auto data = std::make_unique(MAX_COMPRESSED_CHUNK_SIZE); - size_t dataLength = SawyerCoding::WriteChunkBuffer(data.get(), static_cast(src), header); - - _stream->Write(data.get(), dataLength); -} - -/** - * Ensure dst_buffer is bigger than src_buffer then resize afterwards - * returns length of dst_buffer - */ -static size_t EncodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length) -{ - const uint8_t* src = src_buffer; - uint8_t* dst = dst_buffer; - const uint8_t* end_src = src + length; - uint8_t count = 0; - const uint8_t* src_norm_start = src; - - while (src < end_src - 1) + SawyerChunkWriter::SawyerChunkWriter(OpenRCT2::IStream* stream) + : _stream(stream) { - if ((count && *src == src[1]) || count > 125) + } + + void SawyerChunkWriter::WriteChunk(const SawyerChunk* chunk) + { + WriteChunk(chunk->GetData(), chunk->GetLength(), chunk->GetEncoding()); + } + + void SawyerChunkWriter::WriteChunk(const void* src, size_t length, SAWYER_ENCODING encoding) + { + SawyerCoding::ChunkHeader header; + header.encoding = static_cast(encoding); + header.length = static_cast(length); + + auto data = std::make_unique(MAX_COMPRESSED_CHUNK_SIZE); + size_t dataLength = SawyerCoding::WriteChunkBuffer(data.get(), static_cast(src), header); + + _stream->Write(data.get(), dataLength); + } + + /** + * Ensure dst_buffer is bigger than src_buffer then resize afterwards + * returns length of dst_buffer + */ + static size_t EncodeChunkRLE(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length) + { + const uint8_t* src = src_buffer; + uint8_t* dst = dst_buffer; + const uint8_t* end_src = src + length; + uint8_t count = 0; + const uint8_t* src_norm_start = src; + + while (src < end_src - 1) + { + if ((count && *src == src[1]) || count > 125) + { + *dst++ = count - 1; + std::memcpy(dst, src_norm_start, count); + dst += count; + src_norm_start += count; + count = 0; + } + if (*src == src[1]) + { + for (; (count < 125) && ((src + count) < end_src); count++) + { + if (*src != src[count]) + break; + } + *dst++ = 257 - count; + *dst++ = *src; + src += count; + src_norm_start = src; + count = 0; + } + else + { + count++; + src++; + } + } + if (src == end_src - 1) + count++; + if (count) { *dst++ = count - 1; std::memcpy(dst, src_norm_start, count); dst += count; - src_norm_start += count; - count = 0; - } - if (*src == src[1]) - { - for (; (count < 125) && ((src + count) < end_src); count++) - { - if (*src != src[count]) - break; - } - *dst++ = 257 - count; - *dst++ = *src; - src += count; - src_norm_start = src; - count = 0; - } - else - { - count++; - src++; } + return dst - dst_buffer; } - if (src == end_src - 1) - count++; - if (count) + + void SawyerChunkWriter::WriteChunkTrack(const void* src, size_t length) { - *dst++ = count - 1; - std::memcpy(dst, src_norm_start, count); - dst += count; + auto data = std::make_unique(MAX_COMPRESSED_CHUNK_SIZE); + size_t dataLength = EncodeChunkRLE(static_cast(src), data.get(), length); + + uint32_t checksum = 0; + for (size_t i = 0; i < dataLength; i++) + { + uint8_t newByte = ((checksum & 0xFF) + data[i]) & 0xFF; + checksum = (checksum & 0xFFFFFF00) + newByte; + checksum = Numerics::rol32(checksum, 3); + } + checksum -= 0x1D4C1; + + _stream->Write(data.get(), dataLength); + _stream->WriteValue(checksum); } - return dst - dst_buffer; -} - -void SawyerChunkWriter::WriteChunkTrack(const void* src, size_t length) -{ - auto data = std::make_unique(MAX_COMPRESSED_CHUNK_SIZE); - size_t dataLength = EncodeChunkRLE(static_cast(src), data.get(), length); - - uint32_t checksum = 0; - for (size_t i = 0; i < dataLength; i++) - { - uint8_t newByte = ((checksum & 0xFF) + data[i]) & 0xFF; - checksum = (checksum & 0xFFFFFF00) + newByte; - checksum = Numerics::rol32(checksum, 3); - } - checksum -= 0x1D4C1; - - _stream->Write(data.get(), dataLength); - _stream->WriteValue(checksum); -} +} // namespace OpenRCT2 diff --git a/src/openrct2/rct12/SawyerChunkWriter.h b/src/openrct2/rct12/SawyerChunkWriter.h index 5a31116624..725a08ea48 100644 --- a/src/openrct2/rct12/SawyerChunkWriter.h +++ b/src/openrct2/rct12/SawyerChunkWriter.h @@ -16,45 +16,45 @@ namespace OpenRCT2 { struct IStream; -} - -/** - * Writes sawyer encoding chunks to a data stream. This can be used to write - * SC6 and SV6 files. - */ -class SawyerChunkWriter final -{ -private: - OpenRCT2::IStream* const _stream = nullptr; - -public: - explicit SawyerChunkWriter(OpenRCT2::IStream* stream); /** - * Writes a chunk to the stream. + * Writes sawyer encoding chunks to a data stream. This can be used to write + * SC6 and SV6 files. */ - void WriteChunk(const SawyerChunk* chunk); - - /** - * Writes a chunk to the stream containing the given buffer. - * @param src The source buffer. - * @param length The size of the source buffer. - */ - void WriteChunk(const void* src, size_t length, SAWYER_ENCODING encoding); - - /** - * Writes a track chunk to the stream containing the given buffer. - * @param src The source buffer. - * @param length The size of the source buffer. - */ - void WriteChunkTrack(const void* src, size_t length); - - /** - * Writes a chunk to the stream containing the given type. - */ - template - void WriteChunk(const T* src, SAWYER_ENCODING encoding) + class SawyerChunkWriter final { - WriteChunk(src, sizeof(T), encoding); - } -}; + private: + OpenRCT2::IStream* const _stream = nullptr; + + public: + explicit SawyerChunkWriter(OpenRCT2::IStream* stream); + + /** + * Writes a chunk to the stream. + */ + void WriteChunk(const SawyerChunk* chunk); + + /** + * Writes a chunk to the stream containing the given buffer. + * @param src The source buffer. + * @param length The size of the source buffer. + */ + void WriteChunk(const void* src, size_t length, SAWYER_ENCODING encoding); + + /** + * Writes a track chunk to the stream containing the given buffer. + * @param src The source buffer. + * @param length The size of the source buffer. + */ + void WriteChunkTrack(const void* src, size_t length); + + /** + * Writes a chunk to the stream containing the given type. + */ + template + void WriteChunk(const T* src, SAWYER_ENCODING encoding) + { + WriteChunk(src, sizeof(T), encoding); + } + }; +} // namespace OpenRCT2 From 85bfa10fe3fecba4db46de8d69241a994002b444 Mon Sep 17 00:00:00 2001 From: mix Date: Mon, 28 Oct 2024 22:02:35 +0000 Subject: [PATCH 72/97] Fix LIM Launched RC medium half loops from clipping in to eachother --- distribution/changelog.txt | 1 + .../paint/track/coaster/LimLaunchedRollerCoaster.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 726c729f25..3d08d1bb8d 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -16,6 +16,7 @@ - Fix: [#23044] "remove_unused_objects" command causes blank peep names. - Fix: [#23048] Map generator allows map sizes out of range through text input. - Fix: [#23058] [Plugin] Changing window colours doesn’t trigger the window to be fully redrawn. +- Fix: [#23085] LIM Launched Roller Coaster medium half loops clip into each other when built back-to-back. 0.4.15 (2024-10-06) ------------------------------------------------------------------------ diff --git a/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp b/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp index d911783da7..89ae2d800a 100644 --- a/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/LimLaunchedRollerCoaster.cpp @@ -3346,12 +3346,12 @@ static void LimLaunchedRCTrackLeftMediumHalfLoopUp( case 0: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_LIM_LAUNCHED_TRACK_MEDIUM_HALF_LOOP + 3), - { 0, 0, height }, { { 0, 0, height }, { 0, 32, 160 } }); + { 0, 0, height }, { { 2, 0, height }, { 1, 32, 160 } }); break; case 1: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_LIM_LAUNCHED_TRACK_MEDIUM_HALF_LOOP + 8), - { 0, 0, height }, { { 30, 0, height }, { 0, 32, 160 } }); + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 32, 3 } }); break; case 2: PaintAddImageAsParentRotated( @@ -3506,7 +3506,7 @@ static void LimLaunchedRCTrackRightMediumHalfLoopUp( case 1: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_LIM_LAUNCHED_TRACK_MEDIUM_HALF_LOOP + 27), - { 0, 0, height }, { { 30, 0, height }, { 0, 32, 96 } }); + { 0, 0, height }, { { 30, 16, height }, { 0, 32, 96 } }); MetalBSupportsPaintSetup( session, supportType.metal, MetalSupportPlace::BottomLeftSide, 18, height, session.SupportColours); break; @@ -3541,17 +3541,17 @@ static void LimLaunchedRCTrackRightMediumHalfLoopUp( case 0: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_LIM_LAUNCHED_TRACK_MEDIUM_HALF_LOOP + 23), - { 0, 0, height }, { { -12, 0, height }, { 0, 32, 160 } }); + { 0, 0, height }, { { 0, 0, height }, { 1, 32, 160 } }); break; case 1: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_LIM_LAUNCHED_TRACK_MEDIUM_HALF_LOOP + 28), - { 0, 0, height }, { { 29, 0, height }, { 0, 32, 160 } }); + { 0, 0, height }, { { 29, 16, height }, { 0, 16, 160 } }); break; case 2: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_LIM_LAUNCHED_TRACK_MEDIUM_HALF_LOOP + 33), - { 0, 0, height }, { { 30, 0, height }, { 0, 32, 160 } }); + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 32, 3 } }); break; case 3: PaintAddImageAsParentRotated( From e94ddba5d752e959c0f5f7245bb545c2358785fd Mon Sep 17 00:00:00 2001 From: mix Date: Mon, 28 Oct 2024 22:44:25 +0000 Subject: [PATCH 73/97] Improve LIM train pitch 105 and 120 bounding boxes --- src/openrct2/paint/vehicle/VehiclePaint.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openrct2/paint/vehicle/VehiclePaint.cpp b/src/openrct2/paint/vehicle/VehiclePaint.cpp index 6f7ca3b2c5..ec98713bbb 100644 --- a/src/openrct2/paint/vehicle/VehiclePaint.cpp +++ b/src/openrct2/paint/vehicle/VehiclePaint.cpp @@ -585,8 +585,8 @@ const VehicleBoundBox VehicleBoundboxes[16][224] = { { -6, -12, -7, 12, 10, 14 }, { -6, -12, -7, 12, 10, 14 }, { -6, -12, -7, 12, 10, 14 }, { -6, -12, -7, 12, 10, 14 }, { -12, -6, -7, 10, 12, 14 }, { -12, -6, -7, 10, 12, 14 }, { -12, -6, -7, 10, 12, 14 }, { -12, -6, -7, 10, 12, 14 }, { -6, 0, -7, 12, 10, 14 }, { -6, 0, -7, 12, 10, 14 }, { -6, 0, -7, 12, 10, 14 }, { -6, 0, -7, 12, 10, 14 }, - { -14, -6, -10, 28, 12, 24 }, { -6, -17, -10, 3, 28, 24 }, { -17, -6, -10, 28, 5, 24 }, { -6, -14, -10, 12, 28, 24 }, - { -14, -6, 1, 28, 12, 14 }, { -6, -17, -10, 3, 28, 24 }, { -17, -6, -10, 28, 5, 24 }, { -6, -14, 1, 12, 28, 14 }, + { 0, -6, -10, 14, 12, 14 }, { -6, -17, -10, 3, 14, 14 }, { -17, -6, -10, 14, 5, 14 }, { -6, 0, -10, 12, 14, 14 }, + { 0, -6, -10, 14, 12, 14 }, { -6, -17, -10, 3, 14, 14 }, { -17, -6, -10, 14, 5, 14 }, { -6, 0, -10, 12, 14, 14 }, { -14, -6, -15, 28, 12, 7 }, { -6, -14, -15, 12, 28, 7 }, { -14, -6, -15, 28, 12, 7 }, { -6, -14, -15, 12, 28, 7 }, { -14, -6, -15, 28, 12, 7 }, { -6, -14, -15, 12, 28, 7 }, { -14, -6, -15, 28, 12, 7 }, { -6, -14, -15, 12, 28, 7 }, { -14, -6, -15, 28, 12, 7 }, { -6, -14, -15, 12, 28, 7 }, { -14, -6, -15, 28, 12, 7 }, { -6, -14, -15, 12, 28, 7 }, From d4f34388a6f6e4b06834676b52324f12ede6080d Mon Sep 17 00:00:00 2001 From: mix <167040362+mixiate@users.noreply.github.com> Date: Wed, 30 Oct 2024 08:50:27 +0000 Subject: [PATCH 74/97] Fix Wooden RC medium half loops from clipping into each other --- src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp index 40d2c871f4..af2f92fb46 100644 --- a/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/WoodenRollerCoaster.cpp @@ -16754,7 +16754,7 @@ static void WoodenRCTrackLeftMediumHalfLoopUp( case 0: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 3), - { 0, 0, height }, { { 0, 0, height }, { 0, 32, 160 } }); + { 0, 0, height }, { { 2, 0, height }, { 1, 32, 160 } }); PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 44), { 0, 0, height }, { { 0, 0, height + 144 }, { 32, 20, 0 } }); @@ -16965,7 +16965,7 @@ static void WoodenRCTrackRightMediumHalfLoopUp( case 0: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 23), - { 0, 0, height }, { { -12, 0, height }, { 0, 32, 160 } }); + { 0, 0, height }, { { 0, 0, height }, { 1, 32, 160 } }); break; case 1: PaintAddImageAsParentRotated( @@ -16975,7 +16975,7 @@ static void WoodenRCTrackRightMediumHalfLoopUp( case 2: PaintAddImageAsParentRotated( session, direction, session.TrackColours.WithIndex(SPR_G2_WOODEN_RC_MEDIUM_HALF_LOOP + 33), - { 0, 0, height }, { { 30, 0, height }, { 0, 32, 160 } }); + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 32, 3 } }); break; case 3: PaintAddImageAsParentRotated( From e46f23702d05788bbf3b2b88cf905a73b4170f36 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Wed, 30 Oct 2024 12:17:27 +0100 Subject: [PATCH 75/97] Remove OpenRCT2WriteFullVersionInfo() --- src/openrct2-ui/windows/About.cpp | 8 +++----- src/openrct2/Context.cpp | 5 ----- src/openrct2/OpenRCT2.h | 1 - src/openrct2/command_line/RootCommands.cpp | 10 ++++------ 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/openrct2-ui/windows/About.cpp b/src/openrct2-ui/windows/About.cpp index ef4ff8cbe6..e03aab27f8 100644 --- a/src/openrct2-ui/windows/About.cpp +++ b/src/openrct2-ui/windows/About.cpp @@ -199,12 +199,10 @@ namespace OpenRCT2::Ui::Windows ScreenCoordsXY logoCoords = windowPos + ScreenCoordsXY(widgets[WIDX_OPENRCT2_LOGO].left, widgets[WIDX_OPENRCT2_LOGO].top); GfxDrawSprite(dpi, ImageId(SPR_G2_LOGO), logoCoords); - // Version info - utf8 buffer[256]; - utf8* ch = buffer; - OpenRCT2WriteFullVersionInfo(ch, sizeof(buffer) - (ch - buffer)); + + u8string versionInfo = gVersionInfoFull; auto ft = Formatter(); - ft.Add(buffer); + ft.Add(versionInfo.c_str()); auto const& versionPlaceholder = widgets[WIDX_VERSION]; auto versionPlaceHolderWidth = versionPlaceholder.right - versionPlaceholder.left; diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index d19f79c02c..eac8d2b346 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -1566,11 +1566,6 @@ bool ContextLoadParkFromStream(void* stream) return GetContext()->LoadParkFromStream(static_cast(stream), ""); } -void OpenRCT2WriteFullVersionInfo(utf8* buffer, size_t bufferSize) -{ - String::Set(buffer, bufferSize, gVersionInfoFull); -} - void OpenRCT2Finish() { GetContext()->Finish(); diff --git a/src/openrct2/OpenRCT2.h b/src/openrct2/OpenRCT2.h index 9d72ea7e78..1f8729f611 100644 --- a/src/openrct2/OpenRCT2.h +++ b/src/openrct2/OpenRCT2.h @@ -60,7 +60,6 @@ extern uint8_t gScreenFlags; extern uint32_t gScreenAge; extern PromptMode gSavePromptMode; -void OpenRCT2WriteFullVersionInfo(utf8* buffer, size_t bufferSize); void OpenRCT2Finish(); int32_t CommandLineRun(const char** argv, int32_t argc); diff --git a/src/openrct2/command_line/RootCommands.cpp b/src/openrct2/command_line/RootCommands.cpp index 0092f76002..2fe5c348e0 100644 --- a/src/openrct2/command_line/RootCommands.cpp +++ b/src/openrct2/command_line/RootCommands.cpp @@ -447,9 +447,8 @@ static void PrintAbout() static void PrintVersion() { - char buffer[256]; - OpenRCT2WriteFullVersionInfo(buffer, sizeof(buffer)); - Console::WriteLine(buffer); + u8string versionInfo = gVersionInfoFull; + Console::WriteLine(versionInfo.c_str()); Console::WriteFormat("%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); Console::WriteLine(); Console::WriteFormat("Network version: %s", NetworkGetVersion().c_str()); @@ -481,9 +480,8 @@ static void PrintLaunchInformation() struct tm* tmInfo; // Print name and version information - OpenRCT2WriteFullVersionInfo(buffer, sizeof(buffer)); - Console::WriteFormat("%s", buffer); - Console::WriteLine(); + u8string versionInfo = gVersionInfoFull; + Console::WriteLine(versionInfo.c_str()); Console::WriteFormat("%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); Console::WriteLine(); Console::WriteLine(); From 95178be1b9478f42200cc236deadd0416bc77dae Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Wed, 30 Oct 2024 12:47:38 +0100 Subject: [PATCH 76/97] Remove C strings in ContextOpenCommonFileDialog() --- src/openrct2/Context.cpp | 16 ---------------- src/openrct2/Context.h | 1 - src/openrct2/config/Config.cpp | 8 ++++---- 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index eac8d2b346..4f2684257b 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -1733,22 +1733,6 @@ void ContextQuit() GetContext()->Quit(); } -bool ContextOpenCommonFileDialog(utf8* outFilename, OpenRCT2::Ui::FileDialogDesc& desc, size_t outSize) -{ - try - { - std::string result = GetContext()->GetUiContext()->ShowFileDialog(desc); - String::Set(outFilename, outSize, result.c_str()); - return !result.empty(); - } - catch (const std::exception& ex) - { - LOG_ERROR(ex.what()); - outFilename[0] = '\0'; - return false; - } -} - u8string ContextOpenCommonFileDialog(OpenRCT2::Ui::FileDialogDesc& desc) { try diff --git a/src/openrct2/Context.h b/src/openrct2/Context.h index 2087fee0f4..31e4110bd8 100644 --- a/src/openrct2/Context.h +++ b/src/openrct2/Context.h @@ -232,5 +232,4 @@ void ContextHandleInput(); void ContextInputHandleKeyboard(bool isTitle); void ContextQuit(); bool ContextLoadParkFromStream(void* stream); -bool ContextOpenCommonFileDialog(utf8* outFilename, OpenRCT2::Ui::FileDialogDesc& desc, size_t outSize); u8string ContextOpenCommonFileDialog(OpenRCT2::Ui::FileDialogDesc& desc); diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index c29f8a78be..bf35f11209 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -749,7 +749,7 @@ namespace OpenRCT2::Config return {}; } - static bool SelectGogInstaller(utf8* installerPath) + static u8string SelectGogInstaller() { FileDialogDesc desc{}; desc.Type = FileDialogType::Open; @@ -760,7 +760,7 @@ namespace OpenRCT2::Config const auto userHomePath = Platform::GetFolderPath(SPECIAL_FOLDER::USER_HOME); desc.InitialDirectory = userHomePath; - return ContextOpenCommonFileDialog(installerPath, desc, 4096); + return ContextOpenCommonFileDialog(desc); } static bool ExtractGogInstaller(const u8string& installerPath, const u8string& targetPath) @@ -888,8 +888,8 @@ namespace OpenRCT2::Config while (true) { uiContext->ShowMessageBox(LanguageGetString(STR_PLEASE_SELECT_GOG_INSTALLER)); - utf8 gogPath[4096]; - if (!SelectGogInstaller(gogPath)) + auto gogPath = SelectGogInstaller(); + if (gogPath.empty()) { // The user clicked "Cancel", so stop trying. return false; From 749b331187399541d9b8a9ec49b9ec655c7b469d Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Wed, 30 Oct 2024 14:06:24 +0100 Subject: [PATCH 77/97] Replace C string in scenario name handling --- src/openrct2/core/String.cpp | 5 -- src/openrct2/core/String.hpp | 5 +- src/openrct2/localisation/Language.cpp | 2 +- src/openrct2/localisation/Language.h | 2 +- src/openrct2/localisation/LanguagePack.cpp | 3 +- src/openrct2/localisation/LanguagePack.h | 2 +- .../localisation/LocalisationService.cpp | 9 ++-- .../localisation/LocalisationService.h | 3 +- src/openrct2/rct2/S6Importer.cpp | 4 +- src/openrct2/scenario/Scenario.cpp | 3 +- src/openrct2/scenario/ScenarioSources.cpp | 49 ++++++++++--------- src/openrct2/scenario/ScenarioSources.h | 2 +- 12 files changed, 42 insertions(+), 47 deletions(-) diff --git a/src/openrct2/core/String.cpp b/src/openrct2/core/String.cpp index ebc599e947..b0b09dca5b 100644 --- a/src/openrct2/core/String.cpp +++ b/src/openrct2/core/String.cpp @@ -525,11 +525,6 @@ namespace OpenRCT2::String return ch; } - utf8* TrimStart(utf8* buffer, size_t bufferSize, const utf8* src) - { - return String::Set(buffer, bufferSize, TrimStart(src)); - } - std::string TrimStart(const std::string& s) { const utf8* trimmed = TrimStart(s.c_str()); diff --git a/src/openrct2/core/String.hpp b/src/openrct2/core/String.hpp index 19ccf5d77b..bdcf2ce5aa 100644 --- a/src/openrct2/core/String.hpp +++ b/src/openrct2/core/String.hpp @@ -84,9 +84,8 @@ namespace OpenRCT2::String bool IsWhiteSpace(codepoint_t codepoint); utf8* Trim(utf8* str); const utf8* TrimStart(const utf8* str); - utf8* TrimStart(utf8* buffer, size_t bufferSize, const utf8* src); - std::string TrimStart(const std::string& s); - std::string Trim(const std::string& s); + [[nodiscard]] std::string TrimStart(const std::string& s); + [[nodiscard]] std::string Trim(const std::string& s); /** * Converts a multi-byte string from one code page to UTF-8. diff --git a/src/openrct2/localisation/Language.cpp b/src/openrct2/localisation/Language.cpp index 0d6100c524..c1dd601cc9 100644 --- a/src/openrct2/localisation/Language.cpp +++ b/src/openrct2/localisation/Language.cpp @@ -96,7 +96,7 @@ bool LanguageOpen(int32_t id) } } -bool LanguageGetLocalisedScenarioStrings(const utf8* scenarioFilename, StringId* outStringIds) +bool LanguageGetLocalisedScenarioStrings(u8string_view scenarioFilename, StringId* outStringIds) { const auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService(); auto result = localisationService.GetLocalisedScenarioStrings(scenarioFilename); diff --git a/src/openrct2/localisation/Language.h b/src/openrct2/localisation/Language.h index c679b5f95b..70703be8d0 100644 --- a/src/openrct2/localisation/Language.h +++ b/src/openrct2/localisation/Language.h @@ -88,6 +88,6 @@ uint8_t LanguageGetIDFromLocale(const char* locale); const char* LanguageGetString(StringId id); bool LanguageOpen(int32_t id); -bool LanguageGetLocalisedScenarioStrings(const utf8* scenarioFilename, StringId* outStringIds); +bool LanguageGetLocalisedScenarioStrings(u8string_view scenarioFilename, StringId* outStringIds); void LanguageFreeObjectString(StringId stringId); StringId LanguageAllocateObjectString(const std::string& target); diff --git a/src/openrct2/localisation/LanguagePack.cpp b/src/openrct2/localisation/LanguagePack.cpp index 0165c03987..2599843860 100644 --- a/src/openrct2/localisation/LanguagePack.cpp +++ b/src/openrct2/localisation/LanguagePack.cpp @@ -155,9 +155,8 @@ public: return nullptr; } - StringId GetScenarioOverrideStringId(const utf8* scenarioFilename, uint8_t index) override + StringId GetScenarioOverrideStringId(u8string_view scenarioFilename, uint8_t index) override { - Guard::ArgumentNotNull(scenarioFilename); Guard::Assert(index < ScenarioOverrideMaxStringCount); int32_t ooIndex = 0; diff --git a/src/openrct2/localisation/LanguagePack.h b/src/openrct2/localisation/LanguagePack.h index c692320f9a..ae510f180b 100644 --- a/src/openrct2/localisation/LanguagePack.h +++ b/src/openrct2/localisation/LanguagePack.h @@ -24,7 +24,7 @@ struct ILanguagePack virtual void RemoveString(StringId stringId) = 0; virtual void SetString(StringId stringId, const std::string& str) = 0; virtual const utf8* GetString(StringId stringId) const = 0; - virtual StringId GetScenarioOverrideStringId(const utf8* scenarioFilename, uint8_t index) = 0; + virtual StringId GetScenarioOverrideStringId(u8string_view scenarioFilename, uint8_t index) = 0; }; namespace OpenRCT2::LanguagePackFactory diff --git a/src/openrct2/localisation/LocalisationService.cpp b/src/openrct2/localisation/LocalisationService.cpp index c1e7692447..daa2a79ce6 100644 --- a/src/openrct2/localisation/LocalisationService.cpp +++ b/src/openrct2/localisation/LocalisationService.cpp @@ -143,13 +143,12 @@ void LocalisationService::CloseLanguages() _currentLanguage = LANGUAGE_UNDEFINED; } -std::tuple LocalisationService::GetLocalisedScenarioStrings( - const std::string& scenarioFilename) const +std::tuple LocalisationService::GetLocalisedScenarioStrings(u8string_view scenarioFilename) const { Guard::Assert(!_loadedLanguages.empty()); - auto result0 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename.c_str(), 0); - auto result1 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename.c_str(), 1); - auto result2 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename.c_str(), 2); + auto result0 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename, 0); + auto result1 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename, 1); + auto result2 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename, 2); return std::make_tuple(result0, result1, result2); } diff --git a/src/openrct2/localisation/LocalisationService.h b/src/openrct2/localisation/LocalisationService.h index a2090e42d2..5f02d00140 100644 --- a/src/openrct2/localisation/LocalisationService.h +++ b/src/openrct2/localisation/LocalisationService.h @@ -9,6 +9,7 @@ #pragma once +#include "../core/StringTypes.h" #include "../localisation/StringIdType.h" #include @@ -58,7 +59,7 @@ namespace OpenRCT2::Localisation ~LocalisationService(); const char* GetString(StringId id) const; - std::tuple GetLocalisedScenarioStrings(const std::string& scenarioFilename) const; + std::tuple GetLocalisedScenarioStrings(u8string_view scenarioFilename) const; std::string GetLanguagePath(uint32_t languageId) const; void OpenLanguage(int32_t id); diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 3ba6acb201..d8050f5a84 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -258,9 +258,9 @@ namespace OpenRCT2::RCT2 } else { - String::Set(dst->Name, sizeof(dst->Name), _s6.Info.Name); // Normalise the name to make the scenario as recognisable as possible. - ScenarioSources::NormaliseName(dst->Name, sizeof(dst->Name), dst->Name); + auto normalisedName = ScenarioSources::NormaliseName(_s6.Info.Name); + String::Set(dst->Name, sizeof(dst->Name), normalisedName.c_str()); } // dst->name will be translated later so keep the untranslated name here diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index 6b6382c9bc..99e4a862c0 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -108,8 +108,7 @@ void ScenarioReset(GameState_t& gameState) gameState.Cash = gameState.InitialCash; { - utf8 normalisedName[64]; - ScenarioSources::NormaliseName(normalisedName, sizeof(normalisedName), gameState.ScenarioName.c_str()); + auto normalisedName = ScenarioSources::NormaliseName(gameState.ScenarioName); StringId localisedStringIds[3]; if (LanguageGetLocalisedScenarioStrings(normalisedName, localisedStringIds)) diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp index 13e2d1b229..00004dde56 100644 --- a/src/openrct2/scenario/ScenarioSources.cpp +++ b/src/openrct2/scenario/ScenarioSources.cpp @@ -421,36 +421,39 @@ namespace OpenRCT2::ScenarioSources return false; } - void NormaliseName(utf8* buffer, size_t bufferSize, const utf8* name) + u8string NormaliseName(u8string_view input) { - size_t nameLength = String::LengthOf(name); - - // Strip "RCT(1|2)?" prefix off scenario names. - if (nameLength >= 3 && (name[0] == 'R' && name[1] == 'C' && name[2] == 'T')) - { - if (nameLength >= 4 && (name[3] == '1' || name[3] == '2')) - { - LOG_VERBOSE("Stripping RCT/1/2 from name: %s", name); - String::Set(buffer, bufferSize, name + 4); - } - else - { - String::Set(buffer, bufferSize, name + 3); - } - } - - // Trim (for the sake of the above and WW / TT scenarios - String::TrimStart(buffer, bufferSize, name); - // American scenario titles should be converted to British name // Don't worry, names will be translated using language packs later for (const ScenarioAlias& alias : ScenarioAliases) { - if (String::Equals(alias.Alternative, name)) + if (String::Equals(alias.Alternative, input)) { - LOG_VERBOSE("Found alias: %s; will treat as: %s", name, alias.Original); - String::Set(buffer, bufferSize, alias.Original); + LOG_VERBOSE("Found alias: %s; will treat as: %s", input, alias.Original); + return u8string(alias.Original); } } + + u8string normalisedName; + // Strip "RCT(1|2)?" prefix off scenario names. + if (input.starts_with("RCT")) + { + LOG_VERBOSE("Stripping RCT/1/2 from name: %s", u8string(input).c_str()); + if (input.length() >= 4 && (input[3] == '1' || input[3] == '2')) + { + normalisedName = input.substr(4); + } + else + { + normalisedName = input.substr(3); + } + } + else + { + normalisedName = input; + } + + // Trim (for the sake of the above and WW / TT scenarios) + return String::TrimStart(normalisedName); } } // namespace OpenRCT2::ScenarioSources diff --git a/src/openrct2/scenario/ScenarioSources.h b/src/openrct2/scenario/ScenarioSources.h index fe3196e96e..2bfddbd1e2 100644 --- a/src/openrct2/scenario/ScenarioSources.h +++ b/src/openrct2/scenario/ScenarioSources.h @@ -24,7 +24,7 @@ namespace OpenRCT2::ScenarioSources { bool TryGetByName(const utf8* name, SourceDescriptor* outDesc); bool TryGetById(uint8_t id, SourceDescriptor* outDesc); - void NormaliseName(utf8* buffer, size_t bufferSize, const utf8* name); + u8string NormaliseName(u8string_view input); } // namespace OpenRCT2::ScenarioSources // RCT1 scenario index map From 4ea3e334f6336f22122a627079d2296d82dc0e7b Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:44:08 +0100 Subject: [PATCH 78/97] Fix #22908: Crash when passing through invalid wall door --- distribution/changelog.txt | 1 + src/openrct2/actions/WallPlaceAction.h | 2 ++ src/openrct2/libopenrct2.vcxproj | 1 + src/openrct2/object/WallSceneryEntry.cpp | 15 ++++++++ src/openrct2/object/WallSceneryEntry.h | 11 +++++- src/openrct2/ride/Vehicle.cpp | 46 ++++++++++++------------ src/openrct2/world/Scenery.cpp | 5 --- src/openrct2/world/Scenery.h | 4 --- 8 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 src/openrct2/object/WallSceneryEntry.cpp diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 3d08d1bb8d..c69bf19bbc 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -5,6 +5,7 @@ - Fix: [#21221] Trains use unbanked sprites on flat to gentle diagonal banked track pieces. - Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. - Fix: [#22633] Crash when drawing loading screen with an outdated g2.dat. +- Fix: [#22908] Crash when passing through a door from an invalid wall type. - Fix: [#22918] Zooming with keyboard moves the view off centre. - Fix: [#22920] Crash when sacking a staff member. - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. diff --git a/src/openrct2/actions/WallPlaceAction.h b/src/openrct2/actions/WallPlaceAction.h index c511e9b307..f8ba664ada 100644 --- a/src/openrct2/actions/WallPlaceAction.h +++ b/src/openrct2/actions/WallPlaceAction.h @@ -15,6 +15,8 @@ #include "../world/Scenery.h" #include "GameAction.h" +struct WallSceneryEntry; + struct WallPlaceActionResult { int32_t BaseHeight{}; diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index dcfd4acf7c..f64c17b5a6 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -886,6 +886,7 @@ + diff --git a/src/openrct2/object/WallSceneryEntry.cpp b/src/openrct2/object/WallSceneryEntry.cpp new file mode 100644 index 0000000000..b66e282e6a --- /dev/null +++ b/src/openrct2/object/WallSceneryEntry.cpp @@ -0,0 +1,15 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "WallSceneryEntry.h" + +DoorSoundType WallSceneryEntry::getDoorSoundType() const +{ + return static_cast((flags2 & WALL_SCENERY_2_DOOR_SOUND_MASK) >> WALL_SCENERY_2_DOOR_SOUND_SHIFT); +} diff --git a/src/openrct2/object/WallSceneryEntry.h b/src/openrct2/object/WallSceneryEntry.h index eb0b07dbb7..7fd9b0f53f 100644 --- a/src/openrct2/object/WallSceneryEntry.h +++ b/src/openrct2/object/WallSceneryEntry.h @@ -30,12 +30,19 @@ enum WALL_SCENERY_FLAGS enum WALL_SCENERY_2_FLAGS { WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR = (1 << 0), // 0x1 - WALL_SCENERY_2_DOOR_SOUND_MASK = 0x6, + WALL_SCENERY_2_DOOR_SOUND_MASK = 0b0110, WALL_SCENERY_2_DOOR_SOUND_SHIFT = 1, WALL_SCENERY_2_IS_OPAQUE = (1 << 3), // 0x8 WALL_SCENERY_2_ANIMATED = (1 << 4), // 0x10 }; +enum class DoorSoundType : uint8_t +{ + none, + door, + portcullis, +}; + struct WallSceneryEntry { static constexpr auto kObjectType = ObjectType::Walls; @@ -49,4 +56,6 @@ struct WallSceneryEntry money64 price; ObjectEntryIndex scenery_tab_id; uint8_t scrolling_mode; + + DoorSoundType getDoorSoundType() const; }; diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 555b73a623..1c98883d50 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -439,13 +439,15 @@ static constexpr CoordsXY AvoidCollisionMoveOffset[] = { }; static constexpr OpenRCT2::Audio::SoundId DoorOpenSoundIds[] = { - OpenRCT2::Audio::SoundId::DoorOpen, - OpenRCT2::Audio::SoundId::Portcullis, + OpenRCT2::Audio::SoundId::Null, // DoorSoundType::none + OpenRCT2::Audio::SoundId::DoorOpen, // DoorSoundType::door + OpenRCT2::Audio::SoundId::Portcullis, // DoorSoundType::portcullis }; static constexpr OpenRCT2::Audio::SoundId DoorCloseSoundIds[] = { - OpenRCT2::Audio::SoundId::DoorClose, - OpenRCT2::Audio::SoundId::Portcullis, + OpenRCT2::Audio::SoundId::Null, // DoorSoundType::none + OpenRCT2::Audio::SoundId::DoorClose, // DoorSoundType::door + OpenRCT2::Audio::SoundId::Portcullis, // DoorSoundType::portcullis }; template<> @@ -6247,15 +6249,15 @@ void Vehicle::UpdateAdditionalAnimation() static void play_scenery_door_open_sound(const CoordsXYZ& loc, WallElement* tileElement) { auto* wallEntry = tileElement->GetEntry(); - int32_t doorSoundType = WallEntryGetDoorSound(wallEntry); - if (doorSoundType != 0) - { - auto soundId = DoorOpenSoundIds[doorSoundType - 1]; - if (soundId != OpenRCT2::Audio::SoundId::Null) - { - OpenRCT2::Audio::Play3D(soundId, loc); - } - } + if (wallEntry == nullptr) + return; + + auto doorSoundType = wallEntry->getDoorSoundType(); + if (doorSoundType == DoorSoundType::none) + return; + + auto soundId = DoorOpenSoundIds[EnumValue(doorSoundType)]; + OpenRCT2::Audio::Play3D(soundId, loc); } /** @@ -6265,15 +6267,15 @@ static void play_scenery_door_open_sound(const CoordsXYZ& loc, WallElement* tile static void play_scenery_door_close_sound(const CoordsXYZ& loc, WallElement* tileElement) { auto* wallEntry = tileElement->GetEntry(); - int32_t doorSoundType = WallEntryGetDoorSound(wallEntry); - if (doorSoundType != 0) - { - auto soundId = DoorCloseSoundIds[doorSoundType - 1]; - if (soundId != OpenRCT2::Audio::SoundId::Null) - { - Play3D(soundId, loc); - } - } + if (wallEntry == nullptr) + return; + + auto doorSoundType = wallEntry->getDoorSoundType(); + if (doorSoundType == DoorSoundType::none) + return; + + auto soundId = DoorCloseSoundIds[EnumValue(doorSoundType)]; + Play3D(soundId, loc); } template diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index d070fd4c79..33caedd22b 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -300,11 +300,6 @@ void SceneryRemoveGhostToolPlacement() } } -int32_t WallEntryGetDoorSound(const WallSceneryEntry* wallEntry) -{ - return (wallEntry->flags2 & WALL_SCENERY_2_DOOR_SOUND_MASK) >> WALL_SCENERY_2_DOOR_SOUND_SHIFT; -} - bool IsSceneryAvailableToBuild(const ScenerySelection& item) { // All scenery can be built when in the scenario editor diff --git a/src/openrct2/world/Scenery.h b/src/openrct2/world/Scenery.h index 2d22ae0c55..5810257525 100644 --- a/src/openrct2/world/Scenery.h +++ b/src/openrct2/world/Scenery.h @@ -69,10 +69,6 @@ extern const CoordsXY SceneryQuadrantOffsets[]; void SceneryUpdateTile(const CoordsXY& sceneryPos); void SceneryRemoveGhostToolPlacement(); -struct WallSceneryEntry; - -int32_t WallEntryGetDoorSound(const WallSceneryEntry* wallEntry); - bool IsSceneryAvailableToBuild(const ScenerySelection& item); bool IsSceneryItemRestricted(const ScenerySelection& item); From f7ae40bac89ab14350c0cd831ca4bb578031356b Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sun, 27 Oct 2024 14:53:27 +0100 Subject: [PATCH 79/97] Re-introduce basic scenario text objects --- src/openrct2/interface/InteractiveConsole.cpp | 2 +- src/openrct2/libopenrct2.vcxproj | 2 + src/openrct2/object/ObjectFactory.cpp | 4 ++ src/openrct2/object/ObjectLimits.h | 2 +- src/openrct2/object/ScenarioTextObject.cpp | 46 +++++++++++++++++++ src/openrct2/object/ScenarioTextObject.h | 29 ++++++++++++ src/openrct2/scenario/Scenario.cpp | 25 +++------- 7 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 src/openrct2/object/ScenarioTextObject.cpp create mode 100644 src/openrct2/object/ScenarioTextObject.h diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index eed0710626..67b5ed1930 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1299,7 +1299,7 @@ constexpr std::array _objectTypeNames = { "Scenery groups", "Park entrances", "Water", - "ScenarioText", + "Scenario Text", "Terrain Surface", "Terrain Edges", "Stations", diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index f64c17b5a6..b88e708d96 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -355,6 +355,7 @@ + @@ -880,6 +881,7 @@ + diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index d4b47fab8a..31a3f58cba 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -38,6 +38,7 @@ #include "PathAdditionObject.h" #include "PeepNamesObject.h" #include "RideObject.h" +#include "ScenarioTextObject.h" #include "SceneryGroupObject.h" #include "SmallSceneryObject.h" #include "StationObject.h" @@ -363,6 +364,7 @@ namespace OpenRCT2::ObjectFactory result = std::make_unique(); break; case ObjectType::ScenarioText: + result = std::make_unique(); break; case ObjectType::TerrainSurface: result = std::make_unique(); @@ -414,6 +416,8 @@ namespace OpenRCT2::ObjectFactory return ObjectType::ParkEntrance; if (s == "water") return ObjectType::Water; + if (s == "scenario_text") + return ObjectType::ScenarioText; if (s == "terrain_surface") return ObjectType::TerrainSurface; if (s == "terrain_edge") diff --git a/src/openrct2/object/ObjectLimits.h b/src/openrct2/object/ObjectLimits.h index d8b9f599e7..5af71860ec 100644 --- a/src/openrct2/object/ObjectLimits.h +++ b/src/openrct2/object/ObjectLimits.h @@ -23,7 +23,7 @@ constexpr uint16_t kMaxPathAdditionObjects = 255; constexpr uint16_t kMaxSceneryGroupObjects = 255; constexpr uint16_t kMaxParkEntranceObjects = 4; constexpr uint16_t kMaxWaterObjects = 1; -constexpr uint16_t kMaxScenarioTextObjects = 0; +constexpr uint16_t kMaxScenarioTextObjects = 1; constexpr uint16_t kMaxTerrainSurfaceObjects = 255; constexpr uint16_t kMaxTerrainEdgeObjects = 255; constexpr uint16_t kMaxStationObjects = 255; diff --git a/src/openrct2/object/ScenarioTextObject.cpp b/src/openrct2/object/ScenarioTextObject.cpp new file mode 100644 index 0000000000..b82e46070d --- /dev/null +++ b/src/openrct2/object/ScenarioTextObject.cpp @@ -0,0 +1,46 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "ScenarioTextObject.h" + +#include "../Context.h" +#include "../PlatformEnvironment.h" +#include "../core/Guard.hpp" +#include "../core/Json.hpp" + +using namespace OpenRCT2; + +void ScenarioTextObject::Load() +{ +} + +void ScenarioTextObject::Unload() +{ +} + +void ScenarioTextObject::ReadJson(IReadObjectContext* context, json_t& root) +{ + Guard::Assert(root.is_object(), "ScenarioTextObject::ReadJson expects parameter root to be an object"); + PopulateTablesFromJson(context, root); +} + +std::string ScenarioTextObject::GetScenarioName() +{ + return GetStringTable().GetString(ObjectStringID::SCENARIO_NAME); +} + +std::string ScenarioTextObject::GetParkName() +{ + return GetStringTable().GetString(ObjectStringID::PARK_NAME); +} + +std::string ScenarioTextObject::GetScenarioDetails() +{ + return GetStringTable().GetString(ObjectStringID::SCENARIO_DETAILS); +} diff --git a/src/openrct2/object/ScenarioTextObject.h b/src/openrct2/object/ScenarioTextObject.h new file mode 100644 index 0000000000..5173ede439 --- /dev/null +++ b/src/openrct2/object/ScenarioTextObject.h @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../core/IStream.hpp" +#include "Object.h" + +#include + +class ScenarioTextObject final : public Object +{ +public: + static constexpr ObjectType kObjectType = ObjectType::ScenarioText; + + void ReadJson(IReadObjectContext* context, json_t& root) override; + void Load() override; + void Unload() override; + + std::string GetScenarioName(); + std::string GetParkName(); + std::string GetScenarioDetails(); +}; diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index 99e4a862c0..d07bcdbc49 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -41,6 +41,7 @@ #include "../object/ObjectEntryManager.h" #include "../object/ObjectList.h" #include "../object/ObjectManager.h" +#include "../object/ScenarioTextObject.h" #include "../object/WaterEntry.h" #include "../platform/Platform.h" #include "../profiling/Profiling.h" @@ -107,25 +108,14 @@ void ScenarioReset(GameState_t& gameState) gameState.HistoricalProfit = gameState.InitialCash - gameState.BankLoan; gameState.Cash = gameState.InitialCash; + auto& objManager = GetContext()->GetObjectManager(); + if (auto* object = objManager.GetLoadedObject(ObjectType::ScenarioText, 0)) { - auto normalisedName = ScenarioSources::NormaliseName(gameState.ScenarioName); + auto* textObject = reinterpret_cast(object); - StringId localisedStringIds[3]; - if (LanguageGetLocalisedScenarioStrings(normalisedName, localisedStringIds)) - { - if (localisedStringIds[0] != STR_NONE) - { - gameState.ScenarioName = LanguageGetString(localisedStringIds[0]); - } - if (localisedStringIds[1] != STR_NONE) - { - gameState.Park.Name = LanguageGetString(localisedStringIds[1]); - } - if (localisedStringIds[2] != STR_NONE) - { - gameState.ScenarioDetails = LanguageGetString(localisedStringIds[2]); - } - } + gameState.ScenarioName = textObject->GetScenarioName(); + gameState.Park.Name = textObject->GetParkName(); + gameState.ScenarioDetails = textObject->GetScenarioDetails(); } // Set the last saved game path @@ -154,7 +144,6 @@ void ScenarioReset(GameState_t& gameState) MapCountRemainingLandRights(); Staff::ResetStats(); - auto& objManager = GetContext()->GetObjectManager(); gameState.LastEntranceStyle = objManager.GetLoadedObjectEntryIndex("rct2.station.plain"); if (gameState.LastEntranceStyle == OBJECT_ENTRY_INDEX_NULL) { From be3ce8e92b0a3e15441f76edc71823a270d065a0 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sun, 27 Oct 2024 15:01:43 +0100 Subject: [PATCH 80/97] ScenarioSources: refactor DEFINE_SCENARIO_TITLE_DESC_GROUP macro --- src/openrct2/scenario/ScenarioSources.cpp | 33 +++++++++++------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp index 00004dde56..3a7a3f3482 100644 --- a/src/openrct2/scenario/ScenarioSources.cpp +++ b/src/openrct2/scenario/ScenarioSources.cpp @@ -16,6 +16,7 @@ #include "ScenarioRepository.h" #include +#include namespace OpenRCT2::ScenarioSources { @@ -340,20 +341,16 @@ namespace OpenRCT2::ScenarioSources { SC_UNIDENTIFIED, "Tycoon Park", SCENARIO_CATEGORY_OTHER }, }; - #define DEFINE_SCENARIO_TITLE_DESC_GROUP(x) { std::size(x), x } - const struct { - size_t count; - const ScenarioTitleDescriptor * const titles; - } ScenarioTitlesBySource[] = { - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1), - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1AA), - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1LL), - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2), - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2WW), - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2TT), - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesUCES), - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRealParks), - DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesExtrasParks), + constexpr std::span ScenarioTitlesBySource[] = { + ScenarioTitlesRCT1, + ScenarioTitlesRCT1AA, + ScenarioTitlesRCT1LL, + ScenarioTitlesRCT2, + ScenarioTitlesRCT2WW, + ScenarioTitlesRCT2TT, + ScenarioTitlesUCES, + ScenarioTitlesRealParks, + ScenarioTitlesExtrasParks, }; // clang-format on @@ -366,9 +363,9 @@ namespace OpenRCT2::ScenarioSources int32_t currentIndex = 0; for (size_t i = 0; i < std::size(ScenarioTitlesBySource); i++) { - for (size_t j = 0; j < ScenarioTitlesBySource[i].count; j++) + for (size_t j = 0; j < std::size(ScenarioTitlesBySource[i]); j++) { - const ScenarioTitleDescriptor* desc = &ScenarioTitlesBySource[i].titles[j]; + const ScenarioTitleDescriptor* desc = &ScenarioTitlesBySource[i][j]; if (String::IEquals(name, desc->Title)) { outDesc->title = desc->Title; @@ -397,9 +394,9 @@ namespace OpenRCT2::ScenarioSources int32_t currentIndex = 0; for (size_t i = 0; i < std::size(ScenarioTitlesBySource); i++) { - for (size_t j = 0; j < ScenarioTitlesBySource[i].count; j++) + for (size_t j = 0; j < std::size(ScenarioTitlesBySource[i]); j++) { - const ScenarioTitleDescriptor* desc = &ScenarioTitlesBySource[i].titles[j]; + const ScenarioTitleDescriptor* desc = &ScenarioTitlesBySource[i][j]; if (id == desc->Id) { outDesc->title = desc->Title; From 7c74d91b7ddce610be1685e26ccaa6981a9dbf16 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sun, 27 Oct 2024 15:27:26 +0100 Subject: [PATCH 81/97] Add scenario text object ids to scenario source tables --- src/openrct2/scenario/ScenarioSources.cpp | 363 +++++++++++----------- src/openrct2/scenario/ScenarioSources.h | 1 + 2 files changed, 185 insertions(+), 179 deletions(-) diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp index 3a7a3f3482..5030ad234b 100644 --- a/src/openrct2/scenario/ScenarioSources.cpp +++ b/src/openrct2/scenario/ScenarioSources.cpp @@ -31,6 +31,7 @@ namespace OpenRCT2::ScenarioSources const uint8_t Id; const utf8* Title; const uint8_t Category; + const char* TextObjectId; }; #pragma region Scenario Data @@ -120,225 +121,225 @@ namespace OpenRCT2::ScenarioSources // RCT static constexpr ScenarioTitleDescriptor ScenarioTitlesRCT1[] = { - { SC_FOREST_FRONTIERS, "Forest Frontiers", SCENARIO_CATEGORY_BEGINNER }, - { SC_DYNAMITE_DUNES, "Dynamite Dunes", SCENARIO_CATEGORY_BEGINNER }, - { SC_LEAFY_LAKE, "Leafy Lake", SCENARIO_CATEGORY_BEGINNER }, - { SC_DIAMOND_HEIGHTS, "Diamond Heights", SCENARIO_CATEGORY_BEGINNER }, - { SC_EVERGREEN_GARDENS, "Evergreen Gardens", SCENARIO_CATEGORY_BEGINNER }, - { SC_BUMBLY_BEACH, "Bumbly Beach", SCENARIO_CATEGORY_BEGINNER }, - { SC_TRINITY_ISLANDS, "Trinity Islands", SCENARIO_CATEGORY_CHALLENGING }, - { SC_KATIES_DREAMLAND, "Katie's Dreamland", SCENARIO_CATEGORY_CHALLENGING }, - { SC_POKEY_PARK, "Pokey Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_WHITE_WATER_PARK, "White Water Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_MILLENNIUM_MINES, "Millennium Mines", SCENARIO_CATEGORY_CHALLENGING }, - { SC_KARTS_COASTERS, "Karts & Coasters", SCENARIO_CATEGORY_CHALLENGING }, - { SC_MELS_WORLD, "Mel's World", SCENARIO_CATEGORY_CHALLENGING }, - { SC_MYSTIC_MOUNTAIN, "Mystic Mountain", SCENARIO_CATEGORY_CHALLENGING }, - { SC_PACIFIC_PYRAMIDS, "Pacific Pyramids", SCENARIO_CATEGORY_CHALLENGING }, - { SC_CRUMBLY_WOODS, "Crumbly Woods", SCENARIO_CATEGORY_CHALLENGING }, - { SC_PARADISE_PIER, "Paradise Pier", SCENARIO_CATEGORY_CHALLENGING }, - { SC_LIGHTNING_PEAKS, "Lightning Peaks", SCENARIO_CATEGORY_EXPERT }, - { SC_IVORY_TOWERS, "Ivory Towers", SCENARIO_CATEGORY_EXPERT }, - { SC_RAINBOW_VALLEY, "Rainbow Valley", SCENARIO_CATEGORY_EXPERT }, - { SC_THUNDER_ROCK, "Thunder Rock", SCENARIO_CATEGORY_EXPERT }, - { SC_MEGA_PARK, "Mega Park", SCENARIO_CATEGORY_OTHER }, + { SC_FOREST_FRONTIERS, "Forest Frontiers", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.forest_frontiers" }, + { SC_DYNAMITE_DUNES, "Dynamite Dunes", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.dynamite_dunes" }, + { SC_LEAFY_LAKE, "Leafy Lake", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.leafy_lake" }, + { SC_DIAMOND_HEIGHTS, "Diamond Heights", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.diamond_heights" }, + { SC_EVERGREEN_GARDENS, "Evergreen Gardens", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.evergreen_gardens" }, + { SC_BUMBLY_BEACH, "Bumbly Beach", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.bumbly_beach" }, + { SC_TRINITY_ISLANDS, "Trinity Islands", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.trinity_islands" }, + { SC_KATIES_DREAMLAND, "Katie's Dreamland", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.katies_dreamland" }, + { SC_POKEY_PARK, "Pokey Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.pokey_park" }, + { SC_WHITE_WATER_PARK, "White Water Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.white_water_park" }, + { SC_MILLENNIUM_MINES, "Millennium Mines", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.millennium_mines" }, + { SC_KARTS_COASTERS, "Karts & Coasters", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.karts_coasters" }, + { SC_MELS_WORLD, "Mel's World", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.mels_world" }, + { SC_MYSTIC_MOUNTAIN, "Mystic Mountain", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.mystic_mountain" }, + { SC_PACIFIC_PYRAMIDS, "Pacific Pyramids", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.pacific_pyramids" }, + { SC_CRUMBLY_WOODS, "Crumbly Woods", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.crumbly_woods" }, + { SC_PARADISE_PIER, "Paradise Pier", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.paradise_pier" }, + { SC_LIGHTNING_PEAKS, "Lightning Peaks", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.lightning_peaks" }, + { SC_IVORY_TOWERS, "Ivory Towers", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.ivory_towers" }, + { SC_RAINBOW_VALLEY, "Rainbow Valley", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.rainbow_valley" }, + { SC_THUNDER_ROCK, "Thunder Rock", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.thunder_rock" }, + { SC_MEGA_PARK, "Mega Park", SCENARIO_CATEGORY_OTHER, "rct1.scenario_text.mega_park" }, }; // RCT: Added Attractions static constexpr ScenarioTitleDescriptor ScenarioTitlesRCT1AA[] = { - { SC_WHISPERING_CLIFFS, "Whispering Cliffs", SCENARIO_CATEGORY_BEGINNER }, - { SC_THREE_MONKEYS_PARK, "Three Monkeys Park", SCENARIO_CATEGORY_BEGINNER }, - { SC_CANARY_MINES, "Canary Mines", SCENARIO_CATEGORY_BEGINNER }, - { SC_BARONY_BRIDGE, "Barony Bridge", SCENARIO_CATEGORY_BEGINNER }, - { SC_FUNTOPIA, "Funtopia", SCENARIO_CATEGORY_BEGINNER }, - { SC_HAUNTED_HARBOUR, "Haunted Harbour", SCENARIO_CATEGORY_BEGINNER }, - { SC_FUN_FORTRESS, "Fun Fortress", SCENARIO_CATEGORY_BEGINNER }, - { SC_FUTURE_WORLD, "Future World", SCENARIO_CATEGORY_BEGINNER }, - { SC_GENTLE_GLEN, "Gentle Glen", SCENARIO_CATEGORY_BEGINNER }, - { SC_JOLLY_JUNGLE, "Jolly Jungle", SCENARIO_CATEGORY_CHALLENGING }, - { SC_HYDRO_HILLS, "Hydro Hills", SCENARIO_CATEGORY_CHALLENGING }, - { SC_SPRIGHTLY_PARK, "Sprightly Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_MAGIC_QUARTERS, "Magic Quarters", SCENARIO_CATEGORY_CHALLENGING }, - { SC_FRUIT_FARM, "Fruit Farm", SCENARIO_CATEGORY_CHALLENGING }, - { SC_BUTTERFLY_DAM, "Butterfly Dam", SCENARIO_CATEGORY_CHALLENGING }, - { SC_COASTER_CANYON, "Coaster Canyon", SCENARIO_CATEGORY_CHALLENGING }, - { SC_THUNDERSTORM_PARK, "Thunderstorm Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_HARMONIC_HILLS, "Harmonic Hills", SCENARIO_CATEGORY_CHALLENGING }, - { SC_ROMAN_VILLAGE, "Roman Village", SCENARIO_CATEGORY_CHALLENGING }, - { SC_SWAMP_COVE, "Swamp Cove", SCENARIO_CATEGORY_CHALLENGING }, - { SC_ADRENALINE_HEIGHTS, "Adrenaline Heights", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UTOPIA_PARK, "Utopia Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_ROTTING_HEIGHTS, "Rotting Heights", SCENARIO_CATEGORY_EXPERT }, - { SC_FIASCO_FOREST, "Fiasco Forest", SCENARIO_CATEGORY_EXPERT }, - { SC_PICKLE_PARK, "Pickle Park", SCENARIO_CATEGORY_EXPERT }, - { SC_GIGGLE_DOWNS, "Giggle Downs", SCENARIO_CATEGORY_EXPERT }, - { SC_MINERAL_PARK, "Mineral Park", SCENARIO_CATEGORY_EXPERT }, - { SC_COASTER_CRAZY, "Coaster Crazy", SCENARIO_CATEGORY_EXPERT }, - { SC_URBAN_PARK, "Urban Park", SCENARIO_CATEGORY_EXPERT }, - { SC_GEOFFREY_GARDENS, "Geoffrey Gardens", SCENARIO_CATEGORY_EXPERT }, + { SC_WHISPERING_CLIFFS, "Whispering Cliffs", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.whispering_cliffs" }, + { SC_THREE_MONKEYS_PARK, "Three Monkeys Park", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.three_monkeys_park" }, + { SC_CANARY_MINES, "Canary Mines", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.canary_mines" }, + { SC_BARONY_BRIDGE, "Barony Bridge", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.barony_bridge" }, + { SC_FUNTOPIA, "Funtopia", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.funtopia" }, + { SC_HAUNTED_HARBOUR, "Haunted Harbour", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.haunted_harbour" }, + { SC_FUN_FORTRESS, "Fun Fortress", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.fun_fortress" }, + { SC_FUTURE_WORLD, "Future World", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.future_world" }, + { SC_GENTLE_GLEN, "Gentle Glen", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.gentle_glen" }, + { SC_JOLLY_JUNGLE, "Jolly Jungle", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.jolly_jungle" }, + { SC_HYDRO_HILLS, "Hydro Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.hydro_hills" }, + { SC_SPRIGHTLY_PARK, "Sprightly Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.sprightly_park" }, + { SC_MAGIC_QUARTERS, "Magic Quarters", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.magic_quarters" }, + { SC_FRUIT_FARM, "Fruit Farm", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.fruit_farm" }, + { SC_BUTTERFLY_DAM, "Butterfly Dam", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.butterfly_dam" }, + { SC_COASTER_CANYON, "Coaster Canyon", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.coaster_canyon" }, + { SC_THUNDERSTORM_PARK, "Thunderstorm Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.thunderstorm_park" }, + { SC_HARMONIC_HILLS, "Harmonic Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.harmonic_hills" }, + { SC_ROMAN_VILLAGE, "Roman Village", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.roman_village" }, + { SC_SWAMP_COVE, "Swamp Cove", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.swamp_cove" }, + { SC_ADRENALINE_HEIGHTS, "Adrenaline Heights", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.adrenaline_heights" }, + { SC_UTOPIA_PARK, "Utopia Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.utopia_park" }, + { SC_ROTTING_HEIGHTS, "Rotting Heights", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.rotting_heights" }, + { SC_FIASCO_FOREST, "Fiasco Forest", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.fiasco_forest" }, + { SC_PICKLE_PARK, "Pickle Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.pickle_park" }, + { SC_GIGGLE_DOWNS, "Giggle Downs", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.giggle_downs" }, + { SC_MINERAL_PARK, "Mineral Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.mineral_park" }, + { SC_COASTER_CRAZY, "Coaster Crazy", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.coaster_crazy" }, + { SC_URBAN_PARK, "Urban Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.urban_park" }, + { SC_GEOFFREY_GARDENS, "Geoffrey Gardens", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.geoffrey_gardens" }, }; // RCT: Loopy Landscapes static constexpr ScenarioTitleDescriptor ScenarioTitlesRCT1LL[] = { - { SC_ICEBERG_ISLANDS, "Iceberg Islands", SCENARIO_CATEGORY_BEGINNER }, - { SC_VOLCANIA, "Volcania", SCENARIO_CATEGORY_BEGINNER }, - { SC_ARID_HEIGHTS, "Arid Heights", SCENARIO_CATEGORY_BEGINNER }, - { SC_RAZOR_ROCKS, "Razor Rocks", SCENARIO_CATEGORY_BEGINNER }, - { SC_CRATER_LAKE, "Crater Lake", SCENARIO_CATEGORY_BEGINNER }, - { SC_VERTIGO_VIEWS, "Vertigo Views", SCENARIO_CATEGORY_BEGINNER }, - { SC_PARADISE_PIER_2, "Paradise Pier 2", SCENARIO_CATEGORY_CHALLENGING }, - { SC_DRAGONS_COVE, "Dragon's Cove", SCENARIO_CATEGORY_CHALLENGING }, - { SC_GOOD_KNIGHT_PARK, "Good Knight Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_WACKY_WARREN, "Wacky Warren", SCENARIO_CATEGORY_CHALLENGING }, - { SC_GRAND_GLACIER, "Grand Glacier", SCENARIO_CATEGORY_CHALLENGING }, - { SC_CRAZY_CRATERS, "Crazy Craters", SCENARIO_CATEGORY_CHALLENGING }, - { SC_DUSTY_DESERT, "Dusty Desert", SCENARIO_CATEGORY_CHALLENGING }, - { SC_WOODWORM_PARK, "Woodworm Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_ICARUS_PARK, "Icarus Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_SUNNY_SWAMPS, "Sunny Swamps", SCENARIO_CATEGORY_CHALLENGING }, - { SC_FRIGHTMARE_HILLS, "Frightmare Hills", SCENARIO_CATEGORY_CHALLENGING }, - { SC_THUNDER_ROCKS, "Thunder Rocks", SCENARIO_CATEGORY_CHALLENGING }, - { SC_OCTAGON_PARK, "Octagon Park", SCENARIO_CATEGORY_CHALLENGING }, - { SC_PLEASURE_ISLAND, "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING }, - { SC_ICICLE_WORLDS, "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING }, - { SC_SOUTHERN_SANDS, "Southern Sands", SCENARIO_CATEGORY_EXPERT }, - { SC_TINY_TOWERS, "Tiny Towers", SCENARIO_CATEGORY_EXPERT }, - { SC_NEVERMORE_PARK, "Nevermore Park", SCENARIO_CATEGORY_EXPERT }, - { SC_PACIFICA, "Pacifica", SCENARIO_CATEGORY_EXPERT }, - { SC_URBAN_JUNGLE, "Urban Jungle", SCENARIO_CATEGORY_EXPERT }, - { SC_TERROR_TOWN, "Terror Town", SCENARIO_CATEGORY_EXPERT }, - { SC_MEGAWORLD_PARK, "Megaworld Park", SCENARIO_CATEGORY_EXPERT }, - { SC_VENUS_PONDS, "Venus Ponds", SCENARIO_CATEGORY_EXPERT }, - { SC_MICRO_PARK, "Micro Park", SCENARIO_CATEGORY_EXPERT }, + { SC_ICEBERG_ISLANDS, "Iceberg Islands", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.iceberg_islands" }, + { SC_VOLCANIA, "Volcania", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.volcania" }, + { SC_ARID_HEIGHTS, "Arid Heights", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.arid_heights" }, + { SC_RAZOR_ROCKS, "Razor Rocks", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.razor_rocks" }, + { SC_CRATER_LAKE, "Crater Lake", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.crater_lake" }, + { SC_VERTIGO_VIEWS, "Vertigo Views", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.vertigo_views" }, + { SC_PARADISE_PIER_2, "Paradise Pier 2", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.paradise_pier_2" }, + { SC_DRAGONS_COVE, "Dragon's Cove", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.dragons_cove" }, + { SC_GOOD_KNIGHT_PARK, "Good Knight Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.good_knight_park" }, + { SC_WACKY_WARREN, "Wacky Warren", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.wacky_warren" }, + { SC_GRAND_GLACIER, "Grand Glacier", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.grand_glacier" }, + { SC_CRAZY_CRATERS, "Crazy Craters", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.crazy_craters" }, + { SC_DUSTY_DESERT, "Dusty Desert", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.dusty_desert" }, + { SC_WOODWORM_PARK, "Woodworm Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.woodworm_park" }, + { SC_ICARUS_PARK, "Icarus Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.icarus_park" }, + { SC_SUNNY_SWAMPS, "Sunny Swamps", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.sunny_swamps" }, + { SC_FRIGHTMARE_HILLS, "Frightmare Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.frightmare_hills" }, + { SC_THUNDER_ROCKS, "Thunder Rocks", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.thunder_rocks" }, + { SC_OCTAGON_PARK, "Octagon Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.octagon_park" }, + { SC_PLEASURE_ISLAND, "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.pleasure_island" }, + { SC_ICICLE_WORLDS, "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.icicle_worlds" }, + { SC_SOUTHERN_SANDS, "Southern Sands", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.southern_sands" }, + { SC_TINY_TOWERS, "Tiny Towers", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.tiny_towers" }, + { SC_NEVERMORE_PARK, "Nevermore Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.nevermore_park" }, + { SC_PACIFICA, "Pacifica", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.pacifica" }, + { SC_URBAN_JUNGLE, "Urban Jungle", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.urban_jungle" }, + { SC_TERROR_TOWN, "Terror Town", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.terror_town" }, + { SC_MEGAWORLD_PARK, "Megaworld Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.megaworld_park" }, + { SC_VENUS_PONDS, "Venus Ponds", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.venus_ponds" }, + { SC_MICRO_PARK, "Micro Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.micro_park" }, }; // RCT2 static constexpr ScenarioTitleDescriptor ScenarioTitlesRCT2[] = { - { SC_UNIDENTIFIED, "Electric Fields", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Factory Capers", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Crazy Castle", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Dusty Greens", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Bumbly Bazaar", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Infernal Views", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Lucky Lake", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Botany Breakers", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Alpine Adventures", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Gravity Gardens", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Extreme Heights", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Amity Airfield", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Ghost Town", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Fungus Woods", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Rainbow Summit", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Electric Fields", SCENARIO_CATEGORY_BEGINNER, "rct2.scenario_text.electric_fields" }, + { SC_UNIDENTIFIED, "Factory Capers", SCENARIO_CATEGORY_BEGINNER, "rct2.scenario_text.factory_capers" }, + { SC_UNIDENTIFIED, "Crazy Castle", SCENARIO_CATEGORY_BEGINNER, "rct2.scenario_text.crazy_castle" }, + { SC_UNIDENTIFIED, "Dusty Greens", SCENARIO_CATEGORY_BEGINNER, "rct2.scenario_text.dusty_greens" }, + { SC_UNIDENTIFIED, "Bumbly Bazaar", SCENARIO_CATEGORY_BEGINNER, "rct2.scenario_text.bumbly_bazaar" }, + { SC_UNIDENTIFIED, "Infernal Views", SCENARIO_CATEGORY_CHALLENGING, "rct2.scenario_text.infernal_views" }, + { SC_UNIDENTIFIED, "Lucky Lake", SCENARIO_CATEGORY_CHALLENGING, "rct2.scenario_text.lucky_lake" }, + { SC_UNIDENTIFIED, "Botany Breakers", SCENARIO_CATEGORY_CHALLENGING, "rct2.scenario_text.botany_breakers" }, + { SC_UNIDENTIFIED, "Alpine Adventures", SCENARIO_CATEGORY_CHALLENGING, "rct2.scenario_text.alpine_adventures" }, + { SC_UNIDENTIFIED, "Gravity Gardens", SCENARIO_CATEGORY_EXPERT, "rct2.scenario_text.gravity_gardens" }, + { SC_UNIDENTIFIED, "Extreme Heights", SCENARIO_CATEGORY_EXPERT, "rct2.scenario_text.extreme_heights" }, + { SC_UNIDENTIFIED, "Amity Airfield", SCENARIO_CATEGORY_EXPERT, "rct2.scenario_text.amity_airfield" }, + { SC_UNIDENTIFIED, "Ghost Town", SCENARIO_CATEGORY_EXPERT, "rct2.scenario_text.ghost_town" }, + { SC_UNIDENTIFIED, "Fungus Woods", SCENARIO_CATEGORY_EXPERT, "rct2.scenario_text.fungus_woods" }, + { SC_UNIDENTIFIED, "Rainbow Summit", SCENARIO_CATEGORY_EXPERT, "rct2.scenario_text.rainbow_summit" }, }; // RCT2: Wacky Worlds static constexpr ScenarioTitleDescriptor ScenarioTitlesRCT2WW[] = { - { SC_UNIDENTIFIED, "North America - Grand Canyon", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Asia - Great Wall of China Tourism Enhancement", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Africa - African Diamond Mine", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Australasia - Ayers Rock", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "North America - Rollercoaster Heaven", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Africa - Oasis", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "South America - Rio Carnival", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Asia - Maharaja Palace", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Africa - Victoria Falls", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "N. America - Extreme Hawaiian Island", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "South America - Rain Forest Plateau", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Europe - Renovation", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Antarctic - Ecological Salvage", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Europe - European Cultural Festival", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Australasia - Fun at the Beach", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "South America - Inca Lost City", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Asia - Japanese Coastal Reclaim", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "North America - Grand Canyon", SCENARIO_CATEGORY_BEGINNER, "rct2ww.scenario_text.canyon_calamities" }, + { SC_UNIDENTIFIED, "Asia - Great Wall of China Tourism Enhancement", SCENARIO_CATEGORY_BEGINNER, "rct2ww.scenario_text.great_wall_of_china" }, + { SC_UNIDENTIFIED, "Africa - African Diamond Mine", SCENARIO_CATEGORY_BEGINNER, "rct2ww.scenario_text.mines_of_africa" }, + { SC_UNIDENTIFIED, "Australasia - Ayers Rock", SCENARIO_CATEGORY_BEGINNER, "rct2ww.scenario_text.ayers_adventure" }, + { SC_UNIDENTIFIED, "North America - Rollercoaster Heaven", SCENARIO_CATEGORY_BEGINNER, "rct2ww.scenario_text.rollercoaster_heaven" }, + { SC_UNIDENTIFIED, "Africa - Oasis", SCENARIO_CATEGORY_CHALLENGING, "rct2ww.scenario_text.mirage_madness" }, + { SC_UNIDENTIFIED, "South America - Rio Carnival", SCENARIO_CATEGORY_CHALLENGING, "rct2ww.scenario_text.sugarloaf_shores" }, + { SC_UNIDENTIFIED, "Asia - Maharaja Palace", SCENARIO_CATEGORY_CHALLENGING, "rct2ww.scenario_text.park_maharaja" }, + { SC_UNIDENTIFIED, "Africa - Victoria Falls", SCENARIO_CATEGORY_CHALLENGING, "rct2ww.scenario_text.over_the_edge" }, + { SC_UNIDENTIFIED, "N. America - Extreme Hawaiian Island", SCENARIO_CATEGORY_CHALLENGING, "rct2ww.scenario_text.wacky_waikiki" }, + { SC_UNIDENTIFIED, "South America - Rain Forest Plateau", SCENARIO_CATEGORY_CHALLENGING, "rct2ww.scenario_text.rainforest_romp" }, + { SC_UNIDENTIFIED, "Europe - Renovation", SCENARIO_CATEGORY_CHALLENGING, "rct2ww.scenario_text.from_the_ashes" }, + { SC_UNIDENTIFIED, "Antarctic - Ecological Salvage", SCENARIO_CATEGORY_EXPERT, "rct2ww.scenario_text.icy_adventures" }, + { SC_UNIDENTIFIED, "Europe - European Cultural Festival", SCENARIO_CATEGORY_EXPERT, "rct2ww.scenario_text.european_extravaganza" }, + { SC_UNIDENTIFIED, "Australasia - Fun at the Beach", SCENARIO_CATEGORY_EXPERT, "rct2ww.scenario_text.beach_barbecue_blast" }, + { SC_UNIDENTIFIED, "South America - Inca Lost City", SCENARIO_CATEGORY_EXPERT, "rct2ww.scenario_text.lost_city_founder" }, + { SC_UNIDENTIFIED, "Asia - Japanese Coastal Reclaim", SCENARIO_CATEGORY_EXPERT, "rct2ww.scenario_text.okinawa_coast" }, }; // RCT2: Time Twister static constexpr ScenarioTitleDescriptor ScenarioTitlesRCT2TT[] = { - { SC_UNIDENTIFIED, "Dark Age - Robin Hood", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Prehistoric - After the Asteroid", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Roaring Twenties - Prison Island", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Future - First Encounters", SCENARIO_CATEGORY_BEGINNER }, - { SC_UNIDENTIFIED, "Roaring Twenties - Schneider Cup", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Prehistoric - Stone Age", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Mythological - Cradle of Civilisation", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Rock 'n' Roll - Rock 'n' Roll", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Future - Future World", SCENARIO_CATEGORY_CHALLENGING }, - { SC_UNIDENTIFIED, "Roaring Twenties - Skyscrapers", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Rock 'n' Roll - Flower Power", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Dark Age - Castle", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Mythological - Animatronic Film Set", SCENARIO_CATEGORY_EXPERT }, - { SC_UNIDENTIFIED, "Prehistoric - Jurassic Safari", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Dark Age - Robin Hood", SCENARIO_CATEGORY_BEGINNER, "rct2tt.scenario_text.sherwood_forest" }, + { SC_UNIDENTIFIED, "Prehistoric - After the Asteroid", SCENARIO_CATEGORY_BEGINNER, "rct2tt.scenario_text.crater_carnage" }, + { SC_UNIDENTIFIED, "Roaring Twenties - Prison Island", SCENARIO_CATEGORY_BEGINNER, "rct2tt.scenario_text.alcatraz" }, + { SC_UNIDENTIFIED, "Future - First Encounters", SCENARIO_CATEGORY_BEGINNER, "rct2tt.scenario_text.extraterrestrial_extravaganza" }, + { SC_UNIDENTIFIED, "Roaring Twenties - Schneider Cup", SCENARIO_CATEGORY_CHALLENGING, "rct2tt.scenario_text.schneider_shores" }, + { SC_UNIDENTIFIED, "Prehistoric - Stone Age", SCENARIO_CATEGORY_CHALLENGING, "rct2tt.scenario_text.rocky_rambles" }, + { SC_UNIDENTIFIED, "Mythological - Cradle of Civilisation", SCENARIO_CATEGORY_CHALLENGING, "rct2tt.scenario_text.mythological_madness" }, + { SC_UNIDENTIFIED, "Rock 'n' Roll - Rock 'n' Roll", SCENARIO_CATEGORY_CHALLENGING, "rct2tt.scenario_text.rock_n_roll_revival" }, + { SC_UNIDENTIFIED, "Future - Future World", SCENARIO_CATEGORY_CHALLENGING, "rct2tt.scenario_text.gemini_city" }, + { SC_UNIDENTIFIED, "Roaring Twenties - Skyscrapers", SCENARIO_CATEGORY_EXPERT, "rct2tt.scenario_text.metropolis" }, + { SC_UNIDENTIFIED, "Rock 'n' Roll - Flower Power", SCENARIO_CATEGORY_EXPERT, "rct2tt.scenario_text.woodstock" }, + { SC_UNIDENTIFIED, "Dark Age - Castle", SCENARIO_CATEGORY_EXPERT, "rct2tt.scenario_text.cliffside_castle" }, + { SC_UNIDENTIFIED, "Mythological - Animatronic Film Set", SCENARIO_CATEGORY_EXPERT, "rct2tt.scenario_text.animatronic_antics" }, + { SC_UNIDENTIFIED, "Prehistoric - Jurassic Safari", SCENARIO_CATEGORY_EXPERT, "rct2tt.scenario_text.coastersaurus" }, }; // User Created Expansion Sets static constexpr ScenarioTitleDescriptor ScenarioTitlesUCES[] = { - { SC_UNIDENTIFIED, "Lighthouse of Alexandria by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "Cleveland's Luna Park", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "Mount Vesuvius 1700 A.D. by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "The Sandbox by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "Niagara Falls & Gorge by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "Rocky Mountain Miners", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "The Time Machine by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "Tower of Babel", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "Transformation", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "Urbis Incognitus", SCENARIO_CATEGORY_TIME_MACHINE }, - { SC_UNIDENTIFIED, "Beneath the Christmas Tree by Katatude for UCES", SCENARIO_CATEGORY_KATYS_DREAMWORLD }, - { SC_UNIDENTIFIED, "Bigrock Blast", SCENARIO_CATEGORY_KATYS_DREAMWORLD }, - { SC_UNIDENTIFIED, "Camp Mockingbird for UCES by Katatude", SCENARIO_CATEGORY_KATYS_DREAMWORLD }, - { SC_UNIDENTIFIED, "Choo Choo Town", SCENARIO_CATEGORY_KATYS_DREAMWORLD }, - { SC_UNIDENTIFIED, "Dragon Islands", SCENARIO_CATEGORY_KATYS_DREAMWORLD }, - { SC_UNIDENTIFIED, "Kiddy Karnival II", SCENARIO_CATEGORY_KATYS_DREAMWORLD }, - { SC_UNIDENTIFIED, "Sand Dune", SCENARIO_CATEGORY_KATYS_DREAMWORLD }, - { SC_UNIDENTIFIED, "UCES Halloween", SCENARIO_CATEGORY_OTHER }, + { SC_UNIDENTIFIED, "Lighthouse of Alexandria by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.the_lighthouse_of_alexandria" }, + { SC_UNIDENTIFIED, "Cleveland's Luna Park", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.luna_park_cleveland" }, + { SC_UNIDENTIFIED, "Mount Vesuvius 1700 A.D. by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.mount_vesuvius" }, + { SC_UNIDENTIFIED, "The Sandbox by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.the_sandbox" }, + { SC_UNIDENTIFIED, "Niagara Falls & Gorge by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.niagara_falls_gorge" }, + { SC_UNIDENTIFIED, "Rocky Mountain Miners", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.rocky_mountain_miners" }, + { SC_UNIDENTIFIED, "The Time Machine by Katatude for UCES", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.the_time_machine" }, + { SC_UNIDENTIFIED, "Tower of Babel", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.tower_of_babel" }, + { SC_UNIDENTIFIED, "Transformation", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.transformation" }, + { SC_UNIDENTIFIED, "Urbis Incognitus", SCENARIO_CATEGORY_TIME_MACHINE, "uces.scenario_text.urbis_incognitus" }, + { SC_UNIDENTIFIED, "Beneath the Christmas Tree by Katatude for UCES", SCENARIO_CATEGORY_KATYS_DREAMWORLD, "uces.scenario_text.beneath_the_christmas_tree" }, + { SC_UNIDENTIFIED, "Bigrock Blast", SCENARIO_CATEGORY_KATYS_DREAMWORLD, "uces.scenario_text.bigrock_blast" }, + { SC_UNIDENTIFIED, "Camp Mockingbird for UCES by Katatude", SCENARIO_CATEGORY_KATYS_DREAMWORLD, "uces.scenario_text.camp_mockingbird" }, + { SC_UNIDENTIFIED, "Choo Choo Town", SCENARIO_CATEGORY_KATYS_DREAMWORLD, "uces.scenario_text.choochoo_town" }, + { SC_UNIDENTIFIED, "Dragon Islands", SCENARIO_CATEGORY_KATYS_DREAMWORLD, "uces.scenario_text.dragon_islands" }, + { SC_UNIDENTIFIED, "Kiddy Karnival II", SCENARIO_CATEGORY_KATYS_DREAMWORLD, "uces.scenario_text.kiddie_karnival_ii" }, + { SC_UNIDENTIFIED, "Sand Dune", SCENARIO_CATEGORY_KATYS_DREAMWORLD, "uces.scenario_text.sand_dune" }, + { SC_UNIDENTIFIED, "UCES Halloween", SCENARIO_CATEGORY_OTHER, "uces.scenario_text.cemetery_ridge" }, }; // Real parks static constexpr ScenarioTitleDescriptor ScenarioTitlesRealParks[] = { - { SC_ALTON_TOWERS, "Alton Towers", SCENARIO_CATEGORY_REAL }, - { SC_HEIDE_PARK, "Heide-Park", SCENARIO_CATEGORY_REAL }, - { SC_BLACKPOOL_PLEASURE_BEACH, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags Belgium", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags Holland", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags Magic Mountain", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags over Texas", SCENARIO_CATEGORY_REAL }, + { SC_ALTON_TOWERS, "Alton Towers", SCENARIO_CATEGORY_REAL, "rct1.scenario_text.alton_towers" }, + { SC_HEIDE_PARK, "Heide-Park", SCENARIO_CATEGORY_REAL, "rct1.scenario_text.heidepark" }, + { SC_BLACKPOOL_PLEASURE_BEACH, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL, "rct1.scenario_text.blackpool_pleasure_beach" }, + { SC_UNIDENTIFIED, "Six Flags Belgium", SCENARIO_CATEGORY_REAL, "rct2.scenario_text.six_flags_belgium" }, + { SC_UNIDENTIFIED, "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL, "rct2.scenario_text.six_flags_great_adventure" }, + { SC_UNIDENTIFIED, "Six Flags Holland", SCENARIO_CATEGORY_REAL, "rct2.scenario_text.six_flags_holland" }, + { SC_UNIDENTIFIED, "Six Flags Magic Mountain", SCENARIO_CATEGORY_REAL, "rct2.scenario_text.six_flags_magic_mountain" }, + { SC_UNIDENTIFIED, "Six Flags over Texas", SCENARIO_CATEGORY_REAL, "rct2.scenario_text.six_flags_over_texas" }, }; // Other parks static constexpr ScenarioTitleDescriptor ScenarioTitlesExtrasParks[] = { - { SC_FORT_ANACHRONISM, "Fort Anachronism", SCENARIO_CATEGORY_DLC }, - { SC_PCPLAYER, "PC Player", SCENARIO_CATEGORY_DLC }, - { SC_PCGW, "PC Gaming World", SCENARIO_CATEGORY_DLC }, - { SC_GAMEPLAY, "gameplay", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "Panda World", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags Park", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags over Texas", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Competition Land 1", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_UNIDENTIFIED, "Competition Land 2", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_BOBSLED_COMPETITION, "Bobsled Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_GO_KARTS_COMPETITION, "Go Karts Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_INVERTED_ROLLER_COASTER_COMPETITION, "Inverted Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_MINE_TRAIN_COMPETITION, "Mine Train Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_STAND_UP_STEEL_ROLLER_COASTER_COMPETITION, "Stand-Up Steel Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_STEEL_CORKSCREW_COMPETITION, "Steel Corkscrew Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_STEEL_MINI_ROLLER_COASTER_COMPETITION, "Steel Mini Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_STEEL_ROLLER_COASTER_COMPETITION, "Steel Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_STEEL_TWISTER_COMPETITION, "Steel Twister Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_SUSPENDED_ROLLER_COASTER_COMPETITION, "Suspended Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_WOODEN_ROLLER_COASTER_COMPETITION, "Wooden Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS }, - { SC_UNIDENTIFIED, "Tycoon Park", SCENARIO_CATEGORY_OTHER }, + { SC_FORT_ANACHRONISM, "Fort Anachronism", SCENARIO_CATEGORY_DLC, "rct1.scenario_text.fort_anachronism" }, + { SC_PCPLAYER, "PC Player", SCENARIO_CATEGORY_DLC, {} }, + { SC_PCGW, "PC Gaming World", SCENARIO_CATEGORY_DLC, {} }, + { SC_GAMEPLAY, "gameplay", SCENARIO_CATEGORY_DLC, {} }, + { SC_UNIDENTIFIED, "Panda World", SCENARIO_CATEGORY_DLC, "rct2.scenario_text.panda_world" }, + { SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_belgium" }, + { SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_great_adventure" }, + { SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_holland" }, + { SC_UNIDENTIFIED, "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_magic_mountain" }, + { SC_UNIDENTIFIED, "Build your own Six Flags Park", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_park" }, + { SC_UNIDENTIFIED, "Build your own Six Flags over Texas", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_over_texas" }, + { SC_UNIDENTIFIED, "Competition Land 1", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_UNIDENTIFIED, "Competition Land 2", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_BOBSLED_COMPETITION, "Bobsled Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_GO_KARTS_COMPETITION, "Go Karts Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_INVERTED_ROLLER_COASTER_COMPETITION, "Inverted Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_MINE_TRAIN_COMPETITION, "Mine Train Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_STAND_UP_STEEL_ROLLER_COASTER_COMPETITION, "Stand-Up Steel Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_STEEL_CORKSCREW_COMPETITION, "Steel Corkscrew Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_STEEL_MINI_ROLLER_COASTER_COMPETITION, "Steel Mini Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_STEEL_ROLLER_COASTER_COMPETITION, "Steel Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_STEEL_TWISTER_COMPETITION, "Steel Twister Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_SUSPENDED_ROLLER_COASTER_COMPETITION, "Suspended Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_WOODEN_ROLLER_COASTER_COMPETITION, "Wooden Roller Coaster Competition", SCENARIO_CATEGORY_COMPETITIONS, {} }, + { SC_UNIDENTIFIED, "Tycoon Park", SCENARIO_CATEGORY_OTHER, "rct2.scenario_text.tycoon_park" }, }; constexpr std::span ScenarioTitlesBySource[] = { @@ -373,6 +374,7 @@ namespace OpenRCT2::ScenarioSources outDesc->source = static_cast(i); outDesc->index = currentIndex; outDesc->category = desc->Category; + outDesc->textObjectId = desc->TextObjectId; return true; } currentIndex++; @@ -384,6 +386,7 @@ namespace OpenRCT2::ScenarioSources outDesc->source = static_cast(ScenarioSource::Other); outDesc->index = -1; outDesc->category = SCENARIO_CATEGORY_OTHER; + outDesc->textObjectId = nullptr; return false; } @@ -404,6 +407,7 @@ namespace OpenRCT2::ScenarioSources outDesc->source = static_cast(i); outDesc->index = currentIndex; outDesc->category = desc->Category; + outDesc->textObjectId = desc->TextObjectId; return true; } currentIndex++; @@ -415,6 +419,7 @@ namespace OpenRCT2::ScenarioSources outDesc->source = static_cast(ScenarioSource::Other); outDesc->index = -1; outDesc->category = SCENARIO_CATEGORY_OTHER; + outDesc->textObjectId = nullptr; return false; } diff --git a/src/openrct2/scenario/ScenarioSources.h b/src/openrct2/scenario/ScenarioSources.h index 2bfddbd1e2..e3a77d8bcf 100644 --- a/src/openrct2/scenario/ScenarioSources.h +++ b/src/openrct2/scenario/ScenarioSources.h @@ -18,6 +18,7 @@ struct SourceDescriptor uint8_t source; int32_t index; uint8_t category; + const char* textObjectId; }; namespace OpenRCT2::ScenarioSources From 263b73cb3170c1ccfc41d33e779010c3d8700f15 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sun, 27 Oct 2024 19:23:12 +0100 Subject: [PATCH 82/97] Use ScenarioTextObject for indexing scenarios --- src/openrct2/object/ScenarioTextObject.cpp | 2 +- src/openrct2/object/StringTable.cpp | 4 ++ src/openrct2/rct1/S4Importer.cpp | 56 ++++++++++++---------- src/openrct2/rct2/S6Importer.cpp | 34 +++++++------ 4 files changed, 56 insertions(+), 40 deletions(-) diff --git a/src/openrct2/object/ScenarioTextObject.cpp b/src/openrct2/object/ScenarioTextObject.cpp index b82e46070d..93c5c1aca1 100644 --- a/src/openrct2/object/ScenarioTextObject.cpp +++ b/src/openrct2/object/ScenarioTextObject.cpp @@ -32,7 +32,7 @@ void ScenarioTextObject::ReadJson(IReadObjectContext* context, json_t& root) std::string ScenarioTextObject::GetScenarioName() { - return GetStringTable().GetString(ObjectStringID::SCENARIO_NAME); + return GetStringTable().GetString(ObjectStringID::NAME); // SCENARIO_NAME } std::string ScenarioTextObject::GetParkName() diff --git a/src/openrct2/object/StringTable.cpp b/src/openrct2/object/StringTable.cpp index db3c6310d5..d507b4430c 100644 --- a/src/openrct2/object/StringTable.cpp +++ b/src/openrct2/object/StringTable.cpp @@ -88,6 +88,10 @@ ObjectStringID StringTable::ParseStringId(const std::string& s) return ObjectStringID::NAME; if (s == "description") return ObjectStringID::DESCRIPTION; + if (s == "park_name") + return ObjectStringID::PARK_NAME; + if (s == "details") + return ObjectStringID::SCENARIO_DETAILS; if (s == "capacity") return ObjectStringID::CAPACITY; if (s == "vehicleName") diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 548241ceb6..17b373cde1 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -48,6 +48,7 @@ #include "../object/ObjectList.h" #include "../object/ObjectManager.h" #include "../object/ObjectRepository.h" +#include "../object/ScenarioTextObject.h" #include "../park/Legacy.h" #include "../peep/PeepAnimationData.h" #include "../peep/RideUseSystem.h" @@ -244,7 +245,7 @@ namespace OpenRCT2::RCT1 dst->ObjectiveArg3 = GetBuildTheBestRideId(); } - auto name = RCT2StringToUTF8(_s4.ScenarioName, RCT2LanguageId::EnglishUK); + std::string name = RCT2StringToUTF8(_s4.ScenarioName, RCT2LanguageId::EnglishUK); std::string details; // TryGetById won't set this property if the scenario is not recognised, @@ -256,16 +257,20 @@ namespace OpenRCT2::RCT1 String::Set(dst->InternalName, sizeof(dst->InternalName), desc.title); - StringId localisedStringIds[3]; - if (LanguageGetLocalisedScenarioStrings(desc.title, localisedStringIds)) + if (desc.textObjectId != nullptr) { - if (localisedStringIds[0] != STR_NONE) + auto& objManager = GetContext()->GetObjectManager(); + + // Unload loaded scenario text object, if any. + if (auto* obj = objManager.GetLoadedObject(ObjectType::ScenarioText, 0); obj != nullptr) + objManager.UnloadObjects({ obj->GetDescriptor() }); + + // Load the one specified + if (auto* obj = objManager.LoadObject(desc.textObjectId); obj != nullptr) { - name = String::ToStd(LanguageGetString(localisedStringIds[0])); - } - if (localisedStringIds[2] != STR_NONE) - { - details = String::ToStd(LanguageGetString(localisedStringIds[2])); + auto* textObject = reinterpret_cast(obj); + name = textObject->GetScenarioName(); + details = textObject->GetScenarioDetails(); } } @@ -2324,24 +2329,25 @@ namespace OpenRCT2::RCT1 int32_t scNumber = _s4.ScenarioSlotIndex; if (scNumber != -1) { - SourceDescriptor sourceDesc; - if (ScenarioSources::TryGetById(scNumber, &sourceDesc)) + SourceDescriptor desc; + if (ScenarioSources::TryGetById(scNumber, &desc) && desc.textObjectId != nullptr) { - StringId localisedStringIds[3]; - if (LanguageGetLocalisedScenarioStrings(sourceDesc.title, localisedStringIds)) + auto& objManager = GetContext()->GetObjectManager(); + + // Ensure only one thread talks to the object manager at a time + std::lock_guard lock(mtx); + + // Unload loaded scenario text object, if any. + if (auto* obj = objManager.GetLoadedObject(ObjectType::ScenarioText, 0); obj != nullptr) + objManager.UnloadObjects({ obj->GetDescriptor() }); + + // Load the one specified + if (auto* obj = objManager.LoadObject(desc.textObjectId); obj != nullptr) { - if (localisedStringIds[0] != STR_NONE) - { - name = String::ToStd(LanguageGetString(localisedStringIds[0])); - } - if (localisedStringIds[1] != STR_NONE) - { - parkName = String::ToStd(LanguageGetString(localisedStringIds[1])); - } - if (localisedStringIds[2] != STR_NONE) - { - details = String::ToStd(LanguageGetString(localisedStringIds[2])); - } + auto* textObject = reinterpret_cast(obj); + name = textObject->GetScenarioName(); + parkName = textObject->GetParkName(); + details = textObject->GetScenarioDetails(); } } } diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index d8050f5a84..e70d48d58c 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -49,6 +49,7 @@ #include "../object/ObjectList.h" #include "../object/ObjectManager.h" #include "../object/ObjectRepository.h" +#include "../object/ScenarioTextObject.h" #include "../object/WallSceneryEntry.h" #include "../park/Legacy.h" #include "../peep/RideUseSystem.h" @@ -263,11 +264,6 @@ namespace OpenRCT2::RCT2 String::Set(dst->Name, sizeof(dst->Name), normalisedName.c_str()); } - // dst->name will be translated later so keep the untranslated name here - String::Set(dst->InternalName, sizeof(dst->InternalName), dst->Name); - - String::Set(dst->Details, sizeof(dst->Details), _s6.Info.Details); - // Look up and store information regarding the origins of this scenario. SourceDescriptor desc; if (ScenarioSources::TryGetByName(dst->Name, &desc)) @@ -291,17 +287,27 @@ namespace OpenRCT2::RCT2 } } - // Localise the park name and description - StringId localisedStringIds[3]; - if (LanguageGetLocalisedScenarioStrings(dst->Name, localisedStringIds)) + // dst->name will be translated later so keep the untranslated name here + String::Set(dst->InternalName, sizeof(dst->InternalName), dst->Name); + String::Set(dst->Details, sizeof(dst->Details), _s6.Info.Details); + + if (desc.textObjectId != nullptr) { - if (localisedStringIds[0] != STR_NONE) + auto& objManager = GetContext()->GetObjectManager(); + + // Unload loaded scenario text object, if any. + if (auto* obj = objManager.GetLoadedObject(ObjectType::ScenarioText, 0); obj != nullptr) + objManager.UnloadObjects({ obj->GetDescriptor() }); + + // Load the one specified + if (auto* obj = objManager.LoadObject(desc.textObjectId); obj != nullptr) { - String::Set(dst->Name, sizeof(dst->Name), LanguageGetString(localisedStringIds[0])); - } - if (localisedStringIds[2] != STR_NONE) - { - String::Set(dst->Details, sizeof(dst->Details), LanguageGetString(localisedStringIds[2])); + auto* textObject = reinterpret_cast(obj); + auto name = textObject->GetScenarioName(); + auto details = textObject->GetScenarioDetails(); + + String::Set(dst->Name, sizeof(dst->Name), name.c_str()); + String::Set(dst->Details, sizeof(dst->Details), details.c_str()); } } From e13dfc174194a2e31f7267a5cf47d11a7eaf9075 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Oct 2024 18:45:34 +0100 Subject: [PATCH 83/97] Append scenario text object on S4/S6 park load --- src/openrct2/rct1/S4Importer.cpp | 9 +++++++++ src/openrct2/rct2/S6Importer.cpp | 9 +++++++++ src/openrct2/scenario/Scenario.cpp | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 17b373cde1..4b8d941f7d 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1516,6 +1516,15 @@ namespace OpenRCT2::RCT1 AppendRequiredObjects(result, ObjectType::FootpathRailings, _footpathRailingsEntries); AppendRequiredObjects(result, ObjectType::PeepNames, std::vector({ "rct2.peep_names.original" })); RCT12AddDefaultObjects(result); + + // Normalise the name to make the scenario as recognisable as possible + auto normalisedName = ScenarioSources::NormaliseName(_s4.ScenarioName); + + // Infer what scenario text object to use, if any + SourceDescriptor desc; + if (ScenarioSources::TryGetByName(normalisedName.c_str(), &desc) && desc.textObjectId != nullptr) + AppendRequiredObjects(result, ObjectType::ScenarioText, std::vector({ desc.textObjectId })); + return result; } diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index e70d48d58c..48784211a9 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1883,6 +1883,15 @@ namespace OpenRCT2::RCT2 AppendRequiredObjects(objectList, ObjectType::TerrainEdge, _terrainEdgeEntries); AppendRequiredObjects(objectList, ObjectType::PeepNames, std::vector({ "rct2.peep_names.original" })); RCT12AddDefaultObjects(objectList); + + // Normalise the name to make the scenario as recognisable as possible + auto normalisedName = ScenarioSources::NormaliseName(_s6.Info.Name); + + // Infer what scenario text object to use, if any + SourceDescriptor desc; + if (ScenarioSources::TryGetByName(normalisedName.c_str(), &desc) && desc.textObjectId != nullptr) + AppendRequiredObjects(objectList, ObjectType::ScenarioText, std::vector({ desc.textObjectId })); + return objectList; } }; diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index d07bcdbc49..575811d918 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -109,7 +109,7 @@ void ScenarioReset(GameState_t& gameState) gameState.Cash = gameState.InitialCash; auto& objManager = GetContext()->GetObjectManager(); - if (auto* object = objManager.GetLoadedObject(ObjectType::ScenarioText, 0)) + if (auto* object = objManager.GetLoadedObject(ObjectType::ScenarioText, 0); object != nullptr) { auto* textObject = reinterpret_cast(object); From 17b3b664b0e4e39ce224a3e176d919e7a96a965f Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Oct 2024 23:43:50 +0100 Subject: [PATCH 84/97] Ensure exclusive object manager access when rebuilding scenario index --- src/openrct2/rct1/S4Importer.cpp | 6 ++++++ src/openrct2/rct2/S6Importer.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 4b8d941f7d..993599ddc4 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -86,6 +86,7 @@ #include #include #include +#include #include using namespace OpenRCT2; @@ -94,6 +95,8 @@ static constexpr ObjectEntryIndex ObjectEntryIndexIgnore = 254; namespace OpenRCT2::RCT1 { + static std::mutex mtx; + class S4Importer final : public IParkImporter { private: @@ -261,6 +264,9 @@ namespace OpenRCT2::RCT1 { auto& objManager = GetContext()->GetObjectManager(); + // Ensure only one thread talks to the object manager at a time + std::lock_guard lock(mtx); + // Unload loaded scenario text object, if any. if (auto* obj = objManager.GetLoadedObject(ObjectType::ScenarioText, 0); obj != nullptr) objManager.UnloadObjects({ obj->GetDescriptor() }); diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 48784211a9..3bdf808a7c 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -88,6 +88,7 @@ #include "../world/tile_element/WallElement.h" #include +#include using namespace OpenRCT2; @@ -95,6 +96,8 @@ namespace OpenRCT2::RCT2 { #define DECRYPT_MONEY(money) (static_cast(Numerics::rol32((money) ^ 0xF4EC9621, 13))) + static std::mutex mtx; + /** * Class to import RollerCoaster Tycoon 2 scenarios (*.SC6) and saved games (*.SV6). */ @@ -295,6 +298,9 @@ namespace OpenRCT2::RCT2 { auto& objManager = GetContext()->GetObjectManager(); + // Ensure only one thread talks to the object manager at a time + std::lock_guard lock(mtx); + // Unload loaded scenario text object, if any. if (auto* obj = objManager.GetLoadedObject(ObjectType::ScenarioText, 0); obj != nullptr) objManager.UnloadObjects({ obj->GetDescriptor() }); From d803647bd3b23ccad1165a6636aea5b0a2302d25 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 30 Oct 2024 18:50:16 +0100 Subject: [PATCH 85/97] Update objects bundle to v1.4.9 --- CMakeLists.txt | 4 ++-- openrct2.proj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ff2d55734..030ad0d81b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,9 +68,9 @@ set(TITLE_SEQUENCE_VERSION "0.4.14") set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v${TITLE_SEQUENCE_VERSION}/title-sequences.zip") set(TITLE_SEQUENCE_SHA1 "6c04781b959b468e1f65ec2d2f21f5aaa5e5724d") -set(OBJECTS_VERSION "1.4.8") +set(OBJECTS_VERSION "1.4.9") set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip") -set(OBJECTS_SHA1 "405aef518945e617b2750be9128796daa70dba19") +set(OBJECTS_SHA1 "5e50b33ab556e7bf8ed80484b8ba05b593c191c2") set(OPENSFX_VERSION "1.0.5") set(OPENSFX_URL "https://github.com/OpenRCT2/OpenSoundEffects/releases/download/v${OPENSFX_VERSION}/opensound.zip") diff --git a/openrct2.proj b/openrct2.proj index 6d9bf56efd..8ca15283c4 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -45,8 +45,8 @@ 9984c1e317dcfb3aaf8e17f1db2ebb0f771e2373 https://github.com/OpenRCT2/title-sequences/releases/download/v0.4.14/title-sequences.zip 6c04781b959b468e1f65ec2d2f21f5aaa5e5724d - https://github.com/OpenRCT2/objects/releases/download/v1.4.8/objects.zip - 405aef518945e617b2750be9128796daa70dba19 + https://github.com/OpenRCT2/objects/releases/download/v1.4.9/objects.zip + 5e50b33ab556e7bf8ed80484b8ba05b593c191c2 https://github.com/OpenRCT2/OpenSoundEffects/releases/download/v1.0.5/opensound.zip b1b1f1b241d2cbff63a1889c4dc5a09bdf769bfb https://github.com/OpenRCT2/OpenMusic/releases/download/v1.6/openmusic.zip From 9257a9d62d438296ffc706551aad6dc2b1f0eaf6 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 30 Oct 2024 19:49:29 +0100 Subject: [PATCH 86/97] Remove support for scenario overrides from language files --- data/language/en-GB.txt | 847 ------------------ src/openrct2/localisation/Language.cpp | 10 - src/openrct2/localisation/Language.h | 1 - src/openrct2/localisation/LanguagePack.cpp | 128 --- src/openrct2/localisation/LanguagePack.h | 1 - .../localisation/LocalisationService.cpp | 9 - .../localisation/LocalisationService.h | 1 - test/tests/LanguagePackTest.cpp | 12 - 8 files changed, 1009 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index cc572a5de9..15cf329813 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3781,850 +3781,3 @@ STR_6706 :{WINDOW_COLOUR_2}Current image file: {BLACK}{STRING} STR_6707 :(none selected) STR_6708 :Smooth Strength STR_6709 :Enter Smooth Strength between {COMMA16} and {COMMA16} - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Starting from scratch, build a theme park around a large lake - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Develop Bumbly Beach’s small amusement park into a thriving theme park - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Several islands form the basis for this new park - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :A small theme park with a few rides and room for expansion. Your aim is to double the park value. - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :A small, cramped amusement park which requires major expansion - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :A park with some excellent water-based rides requires expansion - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :In the hilly forests of Mystic Mountain, build a theme park from scratch - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :A large park with well-designed but rather old rides. Replace the old rides or add new rides to make the park more popular. - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Convert this sleepy town’s pier into a thriving attraction - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers. Use the available land to attract a new thrill-seeking clientele. - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :A well-established park, which has a few problems - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Rainbow Valley’s local authority won’t allow any landscape changes or large tree removal, but you must develop the area into a large theme park - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists. Use the available space to build rides to attract more people. - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Just for fun! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Develop the seaside cliffs into a thriving amusement park - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Central to this large developing park is a giant triple-track racing/duelling steel coaster - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its miniature railway and a pair of vertical drop roller coasters - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :An old redundant bridge is yours to develop into an amusement park - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Covering land both sides of a highway, this park has several rides already operating - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :This castle is all yours to turn into a theme park - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :A series of stepped lakes form the basis for this new park - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :This elderly park has many historical rides but is badly in debt - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :A large area of land has been cleared and partially themed ready for you to develop into a landscaped theme park - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :A thriving fruit farm has built a railroad to boost its income, your job is to develop it into a full-blown amusement park - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :The area around a dam is available for you to develop into an amusement park - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :A vast canyon is yours to turn into a theme park - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :The local authority won’t allow you to build above tree height in this park - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centrepiece - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :A four lane steeplechase ride is the centrepiece of this expanding park - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :A large garden park needs turning into a thriving theme park - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :A dormant volcano is the setting of this coaster-building challenge - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :A large lake in an ancient crater is the setting for this park - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :This sea-side cove is the setting for this coaster-building challenge - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :A park which has much of its footpaths and coasters underground - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :A glacier-filled valley is yours to develop into a theme park - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Five coasters require completion in this desert park - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :This historical park is only allowed to build older-styled rides - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Develop this alien park to maximise its profit - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :A scary park with a giant centrepiece coaster - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :In this large park you must design and build ten large coasters - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :An icy landscape needs turning into a thriving theme park - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :A desert park with some cleverly designed coasters is yours to expand - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :In this tiny park you must finish building the five existing coasters - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :A large park with a novel transportation system around its edge - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :This large island is all yours to develop as an amusement park - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :This urban area is all yours to develop into an amusement park - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :A giant park already packed full of rides needs improving - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :On a far-away planet this area of land needs turning into a theme park - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Try to create the world’s smallest profitable park - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Convert a small mountain ski resort into a snow-themed amusement park - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Build a flying-themed amusement park in this abandoned airport - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Your challenge is to build a high-profit park on this paradise island - - -STR_SCNR :Build your own Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Build your own version of this European Six Flags park - - -STR_SCNR :Build your own Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Use your design skills to recreate this Six Flags park - - -STR_SCNR :Build your own Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Build this European Six Flags park the way you want to - - -STR_SCNR :Build your own Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Create your own version of this massive Six Flags park - - -STR_SCNR :Build your own Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Starting from scratch, build the rides in this Six Flags park - - -STR_SCNR :Build your own Six Flags Park -STR_PARK :Six Flags -STR_DTLS :Build your own design of Six Flags park - either build rides from other Six Flags parks or design and build your own rides - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Starting with a small market bazaar, your challenge is to increase the profit from shops and stalls by building rides and roller coasters to attract more customers - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :You have inherited a large castle. Your job is to convert it into a small theme park. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Situated near a highway junction in the desert, Dusty Greens is an opportunity to develop a small golf resort into a thriving theme park - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :You have inherited a small farm, and your challenge is to build a small theme park amongst the fields and farm buildings - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Free of financial restrictions, your challenge is to expand this desert park to attract people seeking the ultimate thrills - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :An abandoned factory complex is an opportunity to build a mechanical-themed amusement park - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Restricted to only older-style wooden rides, your challenge is to build a thriving theme park in Fungus Woods - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Hired by a large amusement park chain, your task is to build them a giant roller coaster park around an abandoned mining town - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Your challenge is to build a roller coaster park in the beautiful Gravity Gardens. No other rides, just roller coasters! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :A park nestled precariously on lava rock with streams of magma - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :With unlimited funds but a challenging lake location, this park will be a challenge to expand and manage - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Built on a hillside, this park is forbidden from building anything tall. Can you expand the park and make it successful? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to attract more guests to the park! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to repay your loan while keeping the park value up! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to attract more guests to the park! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :You inherited a disused diamond mine, and find a valuable diamond. You decide to invest that money to build a world-famous theme park. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :A desert Oasis has been discovered and would provide a beautiful location for a park. Transport to the oasis has been provided. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :A dam has been built offering abundant, cheap hydroelectric power with which to run a park. You need to reach a high park value to help repay the loan for the dam. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :The environment agency has turned to you to transform an old oil refinery ecological eyesore into a top tourist attraction. Land is cheap but loan interest is high. You can sell the old buildings for salvage. - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :The authorities have decided to enhance tourism around the Great Wall by building a theme park on the adjacent land. Money is no object! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :An existing park has run out of space. Your only option is to build out into the sea, and so you have taken out a loan. Height restrictions on your building are enforced due to foundations and earthquake risk. - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :You have been commissioned by the Maharaja to bring entertainment to the large local population. Build a park inspired by the Maharaja’s palace. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :You are helping Aboriginal people to build a park as part of a cultural awareness program. You need to get a large number of guests to educate them in the unique heritage of the Aboriginal people. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :A local entrepreneur’s sealife park has gone bust. You already operate a small park and buy the other park from the construction company. Develop a big combined park. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :You have been brought in to take over a European Cultural Visitor Attraction and must increase the number of guests in order to pay back the EU subsidy by the end of the current European parliament term. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :An old park has fallen into disrepair. You gain a European Union grant to return this deprived area to its former glory! You need to renovate the park and repay the grant. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :The people of Hawaii are bored of surfing and are looking for something more intense. You need to build a park with this in mind to keep the area’s tourist attraction rating high. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :You have to build a park on limited land either side of this natural treasure - you do have the opportunity to buy neighbouring land from the Native American Indians. You need to complete the objective to sustain the local town’s population. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :You are a successful business tycoon on long sabbatical who desires to use this time transforming the city park into Rollercoaster Heaven. Money is no object! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :To further boost local tourism you must construct a park that is in tune with its surroundings. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Space is limited in the precious rainforest - you must cram as much as possible into the existing clearing, in order to provide a viable alternative to the local timber industry. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :You run a small park near Rio but the bank has called in your loan. You need to quickly increase your earning capacity to repay this unexpected debt. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Local members of the battle re-enactment society are rather serious about their hobby. They’ve entrusted you with the job of constructing a Dark Age theme park on the grounds of Cliffside Castle. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :To liberate wealth from the rich and distribute it to the needy, you and your Merry Men have decided to build a theme park in Sherwood Forest. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Life has been discovered on a distant planet Build an alien theme park to cash in on the unprecedented wave of interest. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Show off your inventive, utopian vision of the future - come up with a futuristic park design that incorporates state-of-the-art attractions. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :You have been given the task of running and improving an existing theme park, which has been built on an old film set. Build a tribute to the pioneering stop-motion animators who first brought mythical creatures to life on the silver screen. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :You own an island of particular archaeological value. You’ve decided to fund its preservation by constructing a theme park based on the area’s rich Mythological heritage. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :You own a dusty old meteor crater. In the true entrepreneurial spirit, you’ve decided to construct an asteroid theme park and convert your seemingly worthless land into a sizeable fortune. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :You’ve been given the task of constructing a Jurassic era theme park. To optimize your visitors’ access to the exotic plant and animal exhibits, you will need to build rides going over and into the valley. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :To thwart the highway developers and preserve the mysterious ancient stone circles, you will need to construct a Stone Age theme park and turn a profit. However, attracting visitors may pose a challenge, as the terrain is a tad inhospitable. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :The infamous Prison Island - whose population once swelled with bootleggers and racketeers - is now up for sale. You’ve decided to convert it into a top tourist attraction, and money is no object - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :The 75th anniversary of your grandfather’s Schneider Cup victory is coming up in a few years. You’re going to honour his achievement by building a theme park based on the famous seaplane race. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :You own an empty lot near the low-rise part of town. To squeeze the most out of your urban property, build a skyscraper theme park inspired by the soaring art deco architecture of the twenties. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :A large annual music festival takes place on your land. Build a hip theme park to keep the free-spirited audience entertained. - - -STR_SCNR :Rock ‘n’ Roll Revival -STR_PARK :Rock ‘n’ Roll Revival -STR_DTLS :This aging theme park has seen better days. Help the owner give it a retro rock ‘n’ roll makeover and turn the place into a successful venue. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Panda World -STR_PARK :Panda World -STR_DTLS :Add more rides and attract more people to this panda-themed park - - -STR_SCNR :Tycoon Park -STR_PARK :Tycoon Park -STR_DTLS : - -### - -STR_SCNR :Cemetery Ridge -STR_PARK :Cemetery Ridge -STR_DTLS :This is Halloween, UCES Halloween, pumpkins scream in the dead of night! This graveyard is in trouble and it’s up to you to save it, while letting the dead rest in peace! Can you keep the ghosts in their graves and bring chills to your customers?{NEWLINE}Author: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :The Lighthouse of Alexandria -STR_PARK :The Lighthouse of Alexandria -STR_DTLS :Alexander built the city; Greeks, Romans, Egyptians left their mark. But the biggest honor was a Wonder of the Ancient World - the Lighthouse. Visit and make a park!{NEWLINE}Author: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :As it was on its opening day - 18 May 1905.{NEWLINE}Author: Aetherwave - - -STR_SCNR :Mount Vesuvius -STR_PARK :Mount Vesuvius -STR_DTLS :Pompeii and Herculaneum were buried by Mt. Vesuvius in 79 A.D. Visit the excavations and build a park!{NEWLINE}Author: Katatude - - -STR_SCNR :The Sandbox -STR_PARK :The Sandbox -STR_DTLS :What everyone wants - a sandbox! So grab your l’il pail and shovel and build a park!{NEWLINE}Author: Katatude - - -STR_SCNR :Niagara Falls & Gorge -STR_PARK :Niagara Falls -STR_DTLS :American Falls, Bridal Falls & Canadian Horseshoe Falls on the Niagara Frontier, 1850.{NEWLINE}Author: Katatude - - -STR_SCNR :Rocky Mountain Miners -STR_PARK :Rocky Mountain Miners -STR_DTLS :A rockslide damaged your railway. Your workers have gone prospecting. Is there gold in roller coasters?{NEWLINE}Authors: Squid, Buckone, Fossil - - -STR_SCNR :The Time Machine -STR_PARK :The Time Machine -STR_DTLS :The Time Machine. Build to go - when you want, where you want. Eternity awaits. It’s all relative.{NEWLINE}Author: Katatude - - -STR_SCNR :Tower of Babel -STR_PARK :Tower of Babel -STR_DTLS :Whoaa! Look where the time machine took us now! Where did everybody go?{NEWLINE}Author: Fossil - - -STR_SCNR :Transformation -STR_PARK :Transformation -STR_DTLS :We were expecting you…{NEWLINE}Author: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :The Romans are tired of boring gladiator fights. Give them a better thrill, turn a Roman city into the greatest amusement park of all time!{NEWLINE}Author: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Beneath the Christmas Tree -STR_PARK :Winter Wonderland -STR_DTLS :Mum built this scene under our tree. Now she wants a park made in it! Can you help?{NEWLINE}Author: Katatude - - -STR_SCNR :Bigrock Blast -STR_PARK :Bigrock Blast -STR_DTLS :After an explosion at the Bigrock Mining Co., the people of Bigrock have to build an amusement park to keep their town alive.{NEWLINE}Authors: rbarclay & buckone - - -STR_SCNR :Camp Mockingbird -STR_PARK :Camp Mockingbird -STR_DTLS :Only $500/week to this summer camp! Break open your bank and then have fun and build a park.{NEWLINE}Author: Katatude - - -STR_SCNR :Choo-Choo Town -STR_PARK :Choo-Choo Town -STR_DTLS :Mommy! Daddy! I want to go to Choo-Choo Town!{NEWLINE}Author: Fossil - - -STR_SCNR :Dragon Islands -STR_PARK :Dragon Islands -STR_DTLS :Dragon Islands? I’m not sure I want to go there…{NEWLINE}Author: Fossil - - -STR_SCNR :Kiddie Karnival II -STR_PARK :Kiddie Karnival -STR_DTLS :Hey kids! Let’s have fun!{NEWLINE}Authors: Piehead & Fossil - - -STR_SCNR :Sand Dune -STR_PARK :Sand Dune -STR_DTLS :As the owner of a small park, you bought a large piece of land along the beach to expand and attract more guests to visit the beautiful sand dunes, but beware: you cannot disturb those ecologically fragile sand dunes.{NEWLINE}Author: rbarclay diff --git a/src/openrct2/localisation/Language.cpp b/src/openrct2/localisation/Language.cpp index c1dd601cc9..cc4bff6696 100644 --- a/src/openrct2/localisation/Language.cpp +++ b/src/openrct2/localisation/Language.cpp @@ -96,16 +96,6 @@ bool LanguageOpen(int32_t id) } } -bool LanguageGetLocalisedScenarioStrings(u8string_view scenarioFilename, StringId* outStringIds) -{ - const auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService(); - auto result = localisationService.GetLocalisedScenarioStrings(scenarioFilename); - outStringIds[0] = std::get<0>(result); - outStringIds[1] = std::get<1>(result); - outStringIds[2] = std::get<2>(result); - return outStringIds[0] != STR_NONE || outStringIds[1] != STR_NONE || outStringIds[2] != STR_NONE; -} - void LanguageFreeObjectString(StringId stringId) { auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService(); diff --git a/src/openrct2/localisation/Language.h b/src/openrct2/localisation/Language.h index 70703be8d0..505133bd48 100644 --- a/src/openrct2/localisation/Language.h +++ b/src/openrct2/localisation/Language.h @@ -88,6 +88,5 @@ uint8_t LanguageGetIDFromLocale(const char* locale); const char* LanguageGetString(StringId id); bool LanguageOpen(int32_t id); -bool LanguageGetLocalisedScenarioStrings(u8string_view scenarioFilename, StringId* outStringIds); void LanguageFreeObjectString(StringId stringId); StringId LanguageAllocateObjectString(const std::string& target); diff --git a/src/openrct2/localisation/LanguagePack.cpp b/src/openrct2/localisation/LanguagePack.cpp index 2599843860..54eb93e5b7 100644 --- a/src/openrct2/localisation/LanguagePack.cpp +++ b/src/openrct2/localisation/LanguagePack.cpp @@ -29,29 +29,15 @@ using namespace OpenRCT2; // Don't try to load more than language files that exceed 64 MiB constexpr uint64_t MAX_LANGUAGE_SIZE = 64 * 1024 * 1024; -constexpr uint64_t MAX_SCENARIO_OVERRIDES = 4096; - -constexpr StringId ScenarioOverrideBase = 0x7000; -constexpr int32_t ScenarioOverrideMaxStringCount = 3; - -struct ScenarioOverride -{ - std::string filename; - std::string strings[ScenarioOverrideMaxStringCount]; -}; class LanguagePack final : public ILanguagePack { private: uint16_t const _id; std::vector _strings; - std::vector _scenarioOverrides; - /////////////////////////////////////////////////////////////////////////// // Parsing work data - /////////////////////////////////////////////////////////////////////////// std::string _currentGroup; - ScenarioOverride* _currentScenarioOverride = nullptr; public: static std::unique_ptr FromFile(uint16_t id, const utf8* path) @@ -101,7 +87,6 @@ public: // Clean up the parsing work data _currentGroup.clear(); - _currentScenarioOverride = nullptr; } uint16_t GetId() const override @@ -132,21 +117,6 @@ public: const utf8* GetString(StringId stringId) const override { - if (stringId >= ScenarioOverrideBase) - { - int32_t offset = stringId - ScenarioOverrideBase; - int32_t ooIndex = offset / ScenarioOverrideMaxStringCount; - int32_t ooStringIndex = offset % ScenarioOverrideMaxStringCount; - - if (_scenarioOverrides.size() > static_cast(ooIndex) - && !_scenarioOverrides[ooIndex].strings[ooStringIndex].empty()) - { - return _scenarioOverrides[ooIndex].strings[ooStringIndex].c_str(); - } - - return nullptr; - } - if ((_strings.size() > static_cast(stringId)) && !_strings[stringId].empty()) { return _strings[stringId].c_str(); @@ -155,40 +125,7 @@ public: return nullptr; } - StringId GetScenarioOverrideStringId(u8string_view scenarioFilename, uint8_t index) override - { - Guard::Assert(index < ScenarioOverrideMaxStringCount); - - int32_t ooIndex = 0; - for (const ScenarioOverride& scenarioOverride : _scenarioOverrides) - { - if (String::IEquals(scenarioOverride.filename, scenarioFilename)) - { - if (scenarioOverride.strings[index].empty()) - { - return STR_NONE; - } - return ScenarioOverrideBase + (ooIndex * ScenarioOverrideMaxStringCount) + index; - } - ooIndex++; - } - - return STR_NONE; - } - private: - ScenarioOverride* GetScenarioOverride(const std::string& scenarioIdentifier) - { - for (auto& so : _scenarioOverrides) - { - if (String::IEquals(so.strings[0], scenarioIdentifier)) - { - return &so; - } - } - return nullptr; - } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Parsing //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -277,9 +214,6 @@ private: case '[': ParseGroupObject(reader); break; - case '<': - ParseGroupScenario(reader); - break; case '\r': case '\n': break; @@ -315,48 +249,6 @@ private: _currentGroup.clear(); } - void ParseGroupScenario(IStringReader* reader) - { - auto sb = StringBuilder(); - codepoint_t codepoint; - - // Should have already deduced that the next codepoint is a < - reader->Skip(); - - // Read string up to > or line end - bool closedCorrectly = false; - while (reader->TryPeek(&codepoint)) - { - if (IsNewLine(codepoint)) - break; - - reader->Skip(); - if (codepoint == '>') - { - closedCorrectly = true; - break; - } - sb.Append(codepoint); - } - - if (closedCorrectly) - { - _currentGroup = sb.GetStdString(); - _currentScenarioOverride = GetScenarioOverride(_currentGroup); - if (_currentScenarioOverride == nullptr) - { - if (_scenarioOverrides.size() == MAX_SCENARIO_OVERRIDES) - { - LOG_WARNING("Maximum number of scenario strings exceeded."); - } - - _scenarioOverrides.emplace_back(); - _currentScenarioOverride = &_scenarioOverrides[_scenarioOverrides.size() - 1]; - _currentScenarioOverride->filename = std::string(sb.GetBuffer()); - } - } - } - void ParseString(IStringReader* reader) { auto sb = StringBuilder(); @@ -418,19 +310,6 @@ private: { stringId = 2; } - - else if (String::Equals(identifier, "STR_SCNR")) - { - stringId = 0; - } - else if (String::Equals(identifier, "STR_PARK")) - { - stringId = 1; - } - else if (String::Equals(identifier, "STR_DTLS")) - { - stringId = 2; - } else { // Ignore line entirely @@ -466,13 +345,6 @@ private: } _strings[stringId] = s; } - else - { - if (_currentScenarioOverride != nullptr) - { - _currentScenarioOverride->strings[stringId] = std::move(s); - } - } } }; diff --git a/src/openrct2/localisation/LanguagePack.h b/src/openrct2/localisation/LanguagePack.h index ae510f180b..bf1b1b2c14 100644 --- a/src/openrct2/localisation/LanguagePack.h +++ b/src/openrct2/localisation/LanguagePack.h @@ -24,7 +24,6 @@ struct ILanguagePack virtual void RemoveString(StringId stringId) = 0; virtual void SetString(StringId stringId, const std::string& str) = 0; virtual const utf8* GetString(StringId stringId) const = 0; - virtual StringId GetScenarioOverrideStringId(u8string_view scenarioFilename, uint8_t index) = 0; }; namespace OpenRCT2::LanguagePackFactory diff --git a/src/openrct2/localisation/LocalisationService.cpp b/src/openrct2/localisation/LocalisationService.cpp index daa2a79ce6..3ef816dd72 100644 --- a/src/openrct2/localisation/LocalisationService.cpp +++ b/src/openrct2/localisation/LocalisationService.cpp @@ -143,15 +143,6 @@ void LocalisationService::CloseLanguages() _currentLanguage = LANGUAGE_UNDEFINED; } -std::tuple LocalisationService::GetLocalisedScenarioStrings(u8string_view scenarioFilename) const -{ - Guard::Assert(!_loadedLanguages.empty()); - auto result0 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename, 0); - auto result1 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename, 1); - auto result2 = _loadedLanguages[0]->GetScenarioOverrideStringId(scenarioFilename, 2); - return std::make_tuple(result0, result1, result2); -} - StringId LocalisationService::AllocateObjectString(const std::string& target) { if (_availableObjectStringIds.empty()) diff --git a/src/openrct2/localisation/LocalisationService.h b/src/openrct2/localisation/LocalisationService.h index 5f02d00140..87a781bc0a 100644 --- a/src/openrct2/localisation/LocalisationService.h +++ b/src/openrct2/localisation/LocalisationService.h @@ -59,7 +59,6 @@ namespace OpenRCT2::Localisation ~LocalisationService(); const char* GetString(StringId id) const; - std::tuple GetLocalisedScenarioStrings(u8string_view scenarioFilename) const; std::string GetLanguagePath(uint32_t languageId) const; void OpenLanguage(int32_t id); diff --git a/test/tests/LanguagePackTest.cpp b/test/tests/LanguagePackTest.cpp index 4ed9d9153a..c63dd51830 100644 --- a/test/tests/LanguagePackTest.cpp +++ b/test/tests/LanguagePackTest.cpp @@ -47,11 +47,8 @@ TEST_F(LanguagePackTest, language_pack_simple) ASSERT_EQ(lang->GetId(), 0); ASSERT_EQ(lang->GetCount(), 4u); ASSERT_STREQ(lang->GetString(2), "Spiral Roller Coaster"); - ASSERT_EQ(lang->GetScenarioOverrideStringId("Arid Heights", 0), 0x7000); - ASSERT_STREQ(lang->GetString(0x7000), "Arid Heights scenario string"); // Test some negatives too ASSERT_EQ(lang->GetString(1000), nullptr); - ASSERT_EQ(lang->GetScenarioOverrideStringId("No such park", 0), STR_NONE); } TEST_F(LanguagePackTest, language_pack_multibyte) @@ -60,10 +57,6 @@ TEST_F(LanguagePackTest, language_pack_multibyte) ASSERT_EQ(lang->GetId(), 0); ASSERT_EQ(lang->GetCount(), 4u); ASSERT_STREQ(lang->GetString(2), u8"懸吊式雲霄飛車"); - ASSERT_EQ(lang->GetScenarioOverrideStringId("Forest Frontiers", 0), 0x7000); - ASSERT_EQ(lang->GetScenarioOverrideStringId("Forest Frontiers", 2), 0x7002); - ASSERT_STREQ(lang->GetString(0x7000), "Forest Frontiers"); - ASSERT_STREQ(lang->GetString(0x7002), u8"在隱藏於森林深處的清空範圍中, 建造一個很受歡迎的樂園"); } const utf8* LanguagePackTest::LanguageEnGB = "# STR_XXXX part is read and XXXX becomes the string id number.\n" @@ -74,11 +67,6 @@ const utf8* LanguagePackTest::LanguageEnGB = "# STR_XXXX part is read and XXXX b "STR_0001 :{STRINGID} {COMMA16}\n" "STR_0002 :Spiral Roller Coaster\n" "STR_0003 :Stand-up Roller Coaster\n" - "\n" - "STR_SCNR :Arid Heights scenario string\n" - "STR_PARK :Arid Heights park string\n" - "STR_DTLS :Free of any financial limits, your challenge is to develop " - "this desert park while keeping the guests happy\n" "[CONDORRD]\n" "STR_NAME :my test ride\n" "STR_DESC :ride description\n" From f8ea776dba906ff1f4e5a2ad090a15bf243a7f1c Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 30 Oct 2024 21:34:37 +0100 Subject: [PATCH 87/97] Rework AppendRequiredObjects to take a std::string_view instead --- src/openrct2/park/ParkFile.cpp | 2 +- src/openrct2/rct1/S4Importer.cpp | 13 +++++++------ src/openrct2/rct12/EntryList.h | 5 ++--- src/openrct2/rct12/RCT12.cpp | 2 +- src/openrct2/rct12/RCT12.h | 2 +- src/openrct2/rct2/S6Importer.cpp | 10 ++++++---- src/openrct2/scenario/ScenarioSources.cpp | 6 +++--- src/openrct2/scenario/ScenarioSources.h | 2 +- 8 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/openrct2/park/ParkFile.cpp b/src/openrct2/park/ParkFile.cpp index 47b5b92280..cf2c503ec6 100644 --- a/src/openrct2/park/ParkFile.cpp +++ b/src/openrct2/park/ParkFile.cpp @@ -380,7 +380,7 @@ namespace OpenRCT2 if (version < kPeepNamesObjectsVersion) { AppendRequiredObjects( - requiredObjects, ObjectType::PeepNames, std::vector({ "rct2.peep_names.original" })); + requiredObjects, ObjectType::PeepNames, std::vector({ "rct2.peep_names.original" })); } RequiredObjects = std::move(requiredObjects); diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 993599ddc4..c7058a5277 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -260,7 +260,7 @@ namespace OpenRCT2::RCT1 String::Set(dst->InternalName, sizeof(dst->InternalName), desc.title); - if (desc.textObjectId != nullptr) + if (!desc.textObjectId.empty()) { auto& objManager = GetContext()->GetObjectManager(); @@ -1514,13 +1514,14 @@ namespace OpenRCT2::RCT1 AppendRequiredObjects(result, ObjectType::PathAdditions, _pathAdditionEntries); AppendRequiredObjects(result, ObjectType::SceneryGroup, _sceneryGroupEntries); AppendRequiredObjects(result, ObjectType::Banners, _bannerEntries); - AppendRequiredObjects(result, ObjectType::ParkEntrance, std::vector({ "rct2.park_entrance.pkent1" })); + AppendRequiredObjects( + result, ObjectType::ParkEntrance, std::vector({ "rct2.park_entrance.pkent1" })); AppendRequiredObjects(result, ObjectType::Water, _waterEntry); AppendRequiredObjects(result, ObjectType::TerrainSurface, _terrainSurfaceEntries); AppendRequiredObjects(result, ObjectType::TerrainEdge, _terrainEdgeEntries); AppendRequiredObjects(result, ObjectType::FootpathSurface, _footpathSurfaceEntries); AppendRequiredObjects(result, ObjectType::FootpathRailings, _footpathRailingsEntries); - AppendRequiredObjects(result, ObjectType::PeepNames, std::vector({ "rct2.peep_names.original" })); + AppendRequiredObjects(result, ObjectType::PeepNames, std::vector({ "rct2.peep_names.original" })); RCT12AddDefaultObjects(result); // Normalise the name to make the scenario as recognisable as possible @@ -1528,8 +1529,8 @@ namespace OpenRCT2::RCT1 // Infer what scenario text object to use, if any SourceDescriptor desc; - if (ScenarioSources::TryGetByName(normalisedName.c_str(), &desc) && desc.textObjectId != nullptr) - AppendRequiredObjects(result, ObjectType::ScenarioText, std::vector({ desc.textObjectId })); + if (ScenarioSources::TryGetByName(normalisedName.c_str(), &desc) && !desc.textObjectId.empty()) + AppendRequiredObjects(result, ObjectType::ScenarioText, std::vector({ desc.textObjectId })); return result; } @@ -2345,7 +2346,7 @@ namespace OpenRCT2::RCT1 if (scNumber != -1) { SourceDescriptor desc; - if (ScenarioSources::TryGetById(scNumber, &desc) && desc.textObjectId != nullptr) + if (ScenarioSources::TryGetById(scNumber, &desc) && !desc.textObjectId.empty()) { auto& objManager = GetContext()->GetObjectManager(); diff --git a/src/openrct2/rct12/EntryList.h b/src/openrct2/rct12/EntryList.h index 36e2478d27..4efddd8005 100644 --- a/src/openrct2/rct12/EntryList.h +++ b/src/openrct2/rct12/EntryList.h @@ -10,7 +10,6 @@ #pragma once #include -#include #include #include @@ -21,7 +20,7 @@ namespace OpenRCT2::RCT12 class EntryList { private: - std::vector _entries; + std::vector _entries; public: size_t GetCount() const @@ -29,7 +28,7 @@ namespace OpenRCT2::RCT12 return _entries.size(); } - const std::vector& GetEntries() const + const std::vector& GetEntries() const { return _entries; } diff --git a/src/openrct2/rct12/RCT12.cpp b/src/openrct2/rct12/RCT12.cpp index 4cb535081d..d36961380d 100644 --- a/src/openrct2/rct12/RCT12.cpp +++ b/src/openrct2/rct12/RCT12.cpp @@ -818,7 +818,7 @@ void RCT12AddDefaultObjects(ObjectList& objectList) } } -void AppendRequiredObjects(ObjectList& objectList, ObjectType objectType, const std::vector& objectNames) +void AppendRequiredObjects(ObjectList& objectList, ObjectType objectType, const std::vector& objectNames) { for (const auto& objectName : objectNames) { diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h index 42abe290bb..98d169f7f4 100644 --- a/src/openrct2/rct12/RCT12.h +++ b/src/openrct2/rct12/RCT12.h @@ -1197,7 +1197,7 @@ std::string_view GetStationIdentifierFromStyle(uint8_t style); uint8_t GetStationStyleFromIdentifier(u8string_view identifier); std::optional GetStyleFromMusicIdentifier(std::string_view identifier); void RCT12AddDefaultObjects(ObjectList& objectList); -void AppendRequiredObjects(ObjectList& objectList, ObjectType objectType, const std::vector& objectNames); +void AppendRequiredObjects(ObjectList& objectList, ObjectType objectType, const std::vector& objectNames); void AppendRequiredObjects(ObjectList& objectList, ObjectType objectType, const OpenRCT2::RCT12::EntryList& entryList); bool IsUserStringID(StringId stringId); diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 3bdf808a7c..72ad05dd03 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -294,7 +294,7 @@ namespace OpenRCT2::RCT2 String::Set(dst->InternalName, sizeof(dst->InternalName), dst->Name); String::Set(dst->Details, sizeof(dst->Details), _s6.Info.Details); - if (desc.textObjectId != nullptr) + if (!desc.textObjectId.empty()) { auto& objManager = GetContext()->GetObjectManager(); @@ -1887,7 +1887,8 @@ namespace OpenRCT2::RCT2 AppendRequiredObjects(objectList, ObjectType::TerrainSurface, _terrainSurfaceEntries); AppendRequiredObjects(objectList, ObjectType::TerrainEdge, _terrainEdgeEntries); - AppendRequiredObjects(objectList, ObjectType::PeepNames, std::vector({ "rct2.peep_names.original" })); + AppendRequiredObjects( + objectList, ObjectType::PeepNames, std::vector({ "rct2.peep_names.original" })); RCT12AddDefaultObjects(objectList); // Normalise the name to make the scenario as recognisable as possible @@ -1895,8 +1896,9 @@ namespace OpenRCT2::RCT2 // Infer what scenario text object to use, if any SourceDescriptor desc; - if (ScenarioSources::TryGetByName(normalisedName.c_str(), &desc) && desc.textObjectId != nullptr) - AppendRequiredObjects(objectList, ObjectType::ScenarioText, std::vector({ desc.textObjectId })); + if (ScenarioSources::TryGetByName(normalisedName.c_str(), &desc) && !desc.textObjectId.empty()) + AppendRequiredObjects( + objectList, ObjectType::ScenarioText, std::vector({ desc.textObjectId })); return objectList; } diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp index 5030ad234b..e7e8d8287d 100644 --- a/src/openrct2/scenario/ScenarioSources.cpp +++ b/src/openrct2/scenario/ScenarioSources.cpp @@ -31,7 +31,7 @@ namespace OpenRCT2::ScenarioSources const uint8_t Id; const utf8* Title; const uint8_t Category; - const char* TextObjectId; + u8string_view TextObjectId; }; #pragma region Scenario Data @@ -386,7 +386,7 @@ namespace OpenRCT2::ScenarioSources outDesc->source = static_cast(ScenarioSource::Other); outDesc->index = -1; outDesc->category = SCENARIO_CATEGORY_OTHER; - outDesc->textObjectId = nullptr; + outDesc->textObjectId = {}; return false; } @@ -419,7 +419,7 @@ namespace OpenRCT2::ScenarioSources outDesc->source = static_cast(ScenarioSource::Other); outDesc->index = -1; outDesc->category = SCENARIO_CATEGORY_OTHER; - outDesc->textObjectId = nullptr; + outDesc->textObjectId = {}; return false; } diff --git a/src/openrct2/scenario/ScenarioSources.h b/src/openrct2/scenario/ScenarioSources.h index e3a77d8bcf..b6604a2908 100644 --- a/src/openrct2/scenario/ScenarioSources.h +++ b/src/openrct2/scenario/ScenarioSources.h @@ -18,7 +18,7 @@ struct SourceDescriptor uint8_t source; int32_t index; uint8_t category; - const char* textObjectId; + u8string_view textObjectId; }; namespace OpenRCT2::ScenarioSources From 8aeb1d2b980cb183df1850308178dff1e44350ba Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 30 Oct 2024 22:04:51 +0100 Subject: [PATCH 88/97] Remove broken support for object string overrides as well --- src/openrct2/localisation/LanguagePack.cpp | 72 +++------------------- test/tests/LanguagePackTest.cpp | 6 +- 2 files changed, 8 insertions(+), 70 deletions(-) diff --git a/src/openrct2/localisation/LanguagePack.cpp b/src/openrct2/localisation/LanguagePack.cpp index 54eb93e5b7..edbc61ce12 100644 --- a/src/openrct2/localisation/LanguagePack.cpp +++ b/src/openrct2/localisation/LanguagePack.cpp @@ -36,9 +36,6 @@ private: uint16_t const _id; std::vector _strings; - // Parsing work data - std::string _currentGroup; - public: static std::unique_ptr FromFile(uint16_t id, const utf8* path) { @@ -84,9 +81,6 @@ public: { ParseLine(&reader); } - - // Clean up the parsing work data - _currentGroup.clear(); } uint16_t GetId() const override @@ -211,9 +205,6 @@ private: case '#': SkipToEndOfLine(reader); break; - case '[': - ParseGroupObject(reader); - break; case '\r': case '\n': break; @@ -226,29 +217,6 @@ private: } } - void ParseGroupObject(IStringReader* reader) - { - // THIS IS NO LONGER USED SO WE ARE JUST SKIPPING OVER - codepoint_t codepoint; - - // Should have already deduced that the next codepoint is a [ - reader->Skip(); - - // Read string up to ] or line end - while (reader->TryPeek(&codepoint)) - { - if (IsNewLine(codepoint)) - break; - - reader->Skip(); - if (codepoint == ']') - { - break; - } - } - _currentGroup.clear(); - } - void ParseString(IStringReader* reader) { auto sb = StringBuilder(); @@ -288,33 +256,10 @@ private: const utf8* identifier = sb.GetBuffer(); int32_t stringId; - if (_currentGroup.empty()) + if (sscanf(identifier, "STR_%4d", &stringId) != 1) { - if (sscanf(identifier, "STR_%4d", &stringId) != 1) - { - // Ignore line entirely - return; - } - } - else - { - if (String::Equals(identifier, "STR_NAME")) - { - stringId = 0; - } - else if (String::Equals(identifier, "STR_DESC")) - { - stringId = 1; - } - else if (String::Equals(identifier, "STR_CPTY")) - { - stringId = 2; - } - else - { - // Ignore line entirely - return; - } + // Ignore line entirely + return; } // Rest of the line is the actual string @@ -336,15 +281,12 @@ private: s = std::string(sb.GetBuffer(), sb.GetLength()); } - if (_currentGroup.empty()) + // Make sure the list is big enough to contain this string id + if (static_cast(stringId) >= _strings.size()) { - // Make sure the list is big enough to contain this string id - if (static_cast(stringId) >= _strings.size()) - { - _strings.resize(stringId + 1); - } - _strings[stringId] = s; + _strings.resize(stringId + 1); } + _strings[stringId] = s; } }; diff --git a/test/tests/LanguagePackTest.cpp b/test/tests/LanguagePackTest.cpp index c63dd51830..7598ac5210 100644 --- a/test/tests/LanguagePackTest.cpp +++ b/test/tests/LanguagePackTest.cpp @@ -66,11 +66,7 @@ const utf8* LanguagePackTest::LanguageEnGB = "# STR_XXXX part is read and XXXX b "STR_0000 :\n" "STR_0001 :{STRINGID} {COMMA16}\n" "STR_0002 :Spiral Roller Coaster\n" - "STR_0003 :Stand-up Roller Coaster\n" - "[CONDORRD]\n" - "STR_NAME :my test ride\n" - "STR_DESC :ride description\n" - "STR_CPTY :ride capacity\n"; + "STR_0003 :Stand-up Roller Coaster\n"; // This includes a few entries extracted from zh-TW localisation. // It has to be declared as `unsigned char`, or else the values overflow signed byte. From 7c69ba3d6ad586a03b445a8ad1dc32a06deeae36 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 30 Oct 2024 22:18:55 +0100 Subject: [PATCH 89/97] Rewrite Zh-TW language test to use UTF-8 strings, dropping overrides --- test/tests/LanguagePackTest.cpp | 36 ++++++--------------------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/test/tests/LanguagePackTest.cpp b/test/tests/LanguagePackTest.cpp index 7598ac5210..5f19d2e309 100644 --- a/test/tests/LanguagePackTest.cpp +++ b/test/tests/LanguagePackTest.cpp @@ -20,7 +20,7 @@ class LanguagePackTest : public testing::Test { protected: static const utf8* LanguageEnGB; - static const unsigned char LanguageZhTW[]; + static const utf8* LanguageZhTW; }; TEST_F(LanguagePackTest, create_empty) @@ -53,7 +53,7 @@ TEST_F(LanguagePackTest, language_pack_simple) TEST_F(LanguagePackTest, language_pack_multibyte) { - auto lang = LanguagePackFactory::FromText(0, reinterpret_cast(LanguageZhTW)); + auto lang = LanguagePackFactory::FromText(0, LanguageZhTW); ASSERT_EQ(lang->GetId(), 0); ASSERT_EQ(lang->GetCount(), 4u); ASSERT_STREQ(lang->GetString(2), u8"懸吊式雲霄飛車"); @@ -69,31 +69,7 @@ const utf8* LanguagePackTest::LanguageEnGB = "# STR_XXXX part is read and XXXX b "STR_0003 :Stand-up Roller Coaster\n"; // This includes a few entries extracted from zh-TW localisation. -// It has to be declared as `unsigned char`, or else the values overflow signed byte. -const unsigned char LanguagePackTest::LanguageZhTW[] = { - 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe8, 0x9e, 0xba, 0xe6, 0x97, 0x8b, 0xe5, - 0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30, - 0x30, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe7, 0xab, 0x99, 0xe7, 0xab, 0x8b, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2, - 0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x32, 0x20, 0x20, - 0x20, 0x20, 0x3a, 0xe6, 0x87, 0xb8, 0xe5, 0x90, 0x8a, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3, - 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x33, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe5, 0x8f, - 0x8d, 0xe8, 0xbd, 0x89, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, - 0x3c, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x3e, 0x0a, 0x53, - 0x54, 0x52, 0x5f, 0x53, 0x43, 0x4e, 0x52, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46, - 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x50, 0x41, 0x52, 0x4b, 0x20, 0x20, 0x20, - 0x20, 0x3a, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x0a, 0x53, - 0x54, 0x52, 0x5f, 0x44, 0x54, 0x4c, 0x53, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe5, 0x9c, 0xa8, 0xe9, 0x9a, 0xb1, 0xe8, 0x97, - 0x8f, 0xe6, 0x96, 0xbc, 0xe6, 0xa3, 0xae, 0xe6, 0x9e, 0x97, 0xe6, 0xb7, 0xb1, 0xe8, 0x99, 0x95, 0xe7, 0x9a, 0x84, 0xe6, - 0xb8, 0x85, 0xe7, 0xa9, 0xba, 0xe7, 0xaf, 0x84, 0xe5, 0x9c, 0x8d, 0xe4, 0xb8, 0xad, 0x2c, 0x20, 0xe5, 0xbb, 0xba, 0xe9, - 0x80, 0xa0, 0xe4, 0xb8, 0x80, 0xe5, 0x80, 0x8b, 0xe5, 0xbe, 0x88, 0xe5, 0x8f, 0x97, 0xe6, 0xad, 0xa1, 0xe8, 0xbf, 0x8e, - 0xe7, 0x9a, 0x84, 0xe6, 0xa8, 0x82, 0xe5, 0x9c, 0x92, 0x0a, 0x5b, 0x43, 0x4f, 0x4e, 0x44, 0x4f, 0x52, 0x52, 0x44, 0x5d, - 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe7, 0xa5, 0x9e, 0xe9, 0xb7, 0xb9, - 0xe6, 0x9a, 0xa2, 0xe9, 0x81, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x44, 0x45, 0x53, 0x43, 0x20, 0x20, 0x20, 0x20, 0x3a, - 0xe4, 0xb9, 0x98, 0xe5, 0xae, 0xa2, 0xe4, 0xb9, 0x98, 0xe5, 0x9d, 0x90, 0xe6, 0x96, 0xbc, 0xe8, 0xbb, 0x8c, 0xe9, 0x81, - 0x93, 0xe4, 0xb8, 0x8b, 0xe7, 0x9a, 0x84, 0xe7, 0xa5, 0x9e, 0xe9, 0xb7, 0xb9, 0xe9, 0x80, 0xa0, 0xe5, 0x9e, 0x8b, 0xe5, - 0x88, 0x97, 0xe8, 0xbb, 0x8a, 0xe4, 0xb8, 0x8a, 0x2c, 0x20, 0xe5, 0xb0, 0x87, 0xe6, 0x9c, 0x83, 0xe6, 0x96, 0xbc, 0xe9, - 0xa3, 0x9b, 0xe9, 0xa6, 0xb3, 0xe4, 0xb8, 0xad, 0xe9, 0xab, 0x94, 0xe9, 0xa9, 0x97, 0xe9, 0xa3, 0x9b, 0xe4, 0xb8, 0x80, - 0xe8, 0x88, 0xac, 0xe7, 0x9a, 0x84, 0xe5, 0xbf, 0xab, 0xe6, 0x84, 0x9f, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x43, 0x50, 0x54, - 0x59, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe6, 0xaf, 0x8f, 0xe8, 0xbb, 0x8a, 0xe5, 0x8d, 0xa1, 0x34, 0xe4, 0xbd, 0x8d, 0xe4, - 0xb9, 0x98, 0xe5, 0xae, 0xa2, 0x0a, 0x00, -}; +const utf8* LanguagePackTest::LanguageZhTW = u8"STR_0000 :螺旋式雲霄飛車\n" + u8"STR_0001 :站立式雲霄飛車\n" + u8"STR_0002 :懸吊式雲霄飛車\n" + u8"STR_0003 :反轉式雲霄飛車\n"; From d722eddd90d9f5f932e8c3d8a4ba841b91f7bbfe Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Wed, 30 Oct 2024 22:42:09 +0100 Subject: [PATCH 90/97] Handle missing STEX without crashing --- src/openrct2/object/ObjectManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index 4c1f202ba4..9fc779581a 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -539,7 +539,12 @@ private: if (entry.HasValue()) { const auto* ori = _objectRepository.FindObject(entry); - if (ori == nullptr && entry.GetType() != ObjectType::ScenarioText) + if (ori == nullptr && entry.GetType() == ObjectType::ScenarioText) + { + continue; + } + + if (ori == nullptr) { missingObjects.push_back(entry); ReportMissingObject(entry); From 225c7ab3762c65b70cbf39cc372fcbb85710bebf Mon Sep 17 00:00:00 2001 From: OpenRCT2 git bot Date: Thu, 31 Oct 2024 04:02:22 +0000 Subject: [PATCH 91/97] Merge Localisation/master into OpenRCT2/develop --- data/language/ar-EG.txt | 858 ------------------------------------- data/language/ca-ES.txt | 855 ------------------------------------- data/language/cs-CZ.txt | 299 ------------- data/language/da-DK.txt | 847 ------------------------------------ data/language/de-DE.txt | 857 ------------------------------------- data/language/en-US.txt | 735 -------------------------------- data/language/eo-ZZ.txt | 856 ------------------------------------- data/language/es-ES.txt | 860 ------------------------------------- data/language/fi-FI.txt | 858 ------------------------------------- data/language/fr-FR.txt | 858 ------------------------------------- data/language/hu-HU.txt | 847 ------------------------------------ data/language/it-IT.txt | 855 ------------------------------------- data/language/ja-JP.txt | 746 -------------------------------- data/language/ko-KR.txt | 855 ------------------------------------- data/language/nb-NO.txt | 847 ------------------------------------ data/language/nl-NL.txt | 922 ---------------------------------------- data/language/pl-PL.txt | 755 -------------------------------- data/language/pt-BR.txt | 856 ------------------------------------- data/language/ru-RU.txt | 300 ------------- data/language/sv-SE.txt | 758 --------------------------------- data/language/tr-TR.txt | 745 -------------------------------- data/language/uk-UA.txt | 833 ------------------------------------ data/language/vi-VN.txt | 754 -------------------------------- data/language/zh-CN.txt | 859 ------------------------------------- data/language/zh-TW.txt | 745 -------------------------------- 25 files changed, 19560 deletions(-) diff --git a/data/language/ar-EG.txt b/data/language/ar-EG.txt index 4cbebf7c6f..b280c760da 100644 --- a/data/language/ar-EG.txt +++ b/data/language/ar-EG.txt @@ -3604,861 +3604,3 @@ STR_6533 :{WINDOW_COLOUR_2}عامل الاثارة: {BLACK}-{COMMA16}% STR_6534 :{WINDOW_COLOUR_2}عامل الشدة: {BLACK}-{COMMA16}% STR_6535 :{WINDOW_COLOUR_2}عامل الغثيان: {BLACK}-{COMMA16}% STR_6536 :حٌفظت الحديقة بنسخة احدث من اللعبة. حٌفظت الحديقة بنسخة v{INT32}, أنت حاليا تستخدم النسخة v{INT32}. -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :حدود الغابات -STR_PARK :حدود الغابات -STR_DTLS :عميقًا في الغابة، أبني حديقة مزدهرة في منطقة خالية كبيرة - - -STR_SCNR :كثبان الديناميت -STR_PARK :كثبان الديناميت -STR_DTLS :بُني في وسط الصحراء، هذا المتنزه يحتوي على أفعوانية دوارة واحدة فقط ولكن لديه مساحة للتوسع - - -STR_SCNR :بحيرة ليفي -STR_PARK :بحيرة ليفي -STR_DTLS :إبدء من لاشئ، إبني حديقة مزدهرة حول بركة كبيرة - - -STR_SCNR :المرتفعات الألماسية -STR_PARK :المرتفعات الألماسية -STR_DTLS :المرتفعات الألماسية هي بالفعل حديقة ترفيهية ناجحة مع رحلات رائعة - قم بتطويرها لمضاعفة قيمتها - - -STR_SCNR :الحدائق الخضراء دائماً -STR_PARK :الحدائق الخضراء دائماً -STR_DTLS :حول الحدائق الخضراء دائماً إلى مدينة ترفيهية مزدهرة - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Develop Bumbly Beach’s small amusement park into a thriving theme park - - -STR_SCNR :الجزيرة الثلاثية -STR_PARK :الجزيرة الثلاثية -STR_DTLS :عدة جزر تشكل الأساس لهذه الحديقة - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :A small theme park with a few rides and room for expansion - Your aim is to double the park value - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :A small, cramped amusement park which requires major expansion - - -STR_SCNR :حديقة المياه البيضاء -STR_PARK :حديقة المياه البيضاء -STR_DTLS :حديقة مع أفعوانيات بحرية ممتازة تتطلب التوسيع - - -STR_SCNR :منجم الألفية -STR_PARK :منجم الألفية -STR_DTLS :حول منجم مهجور كبير من جازب للسياح إلي حديقة ترفيهية - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion - - -STR_SCNR :الجبل السحري -STR_PARK :الجبل السحري -STR_DTLS :في غابات الجبل السحري، قم ببناء مدينة ملاهي من الصفر - - -STR_SCNR :أهرامات المحيط الهادئ -STR_PARK :أهرامات المحيط الهادئ -STR_DTLS :تحويل المعالم السياحية المصرية الأثرية إلى مدينة ترفيهية مزدهرة - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :A large park with well-designed but rather old rides - Replace the old rides or add new rides to make the park more popular - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Convert this sleepy town’s pier into a thriving attraction - - -STR_SCNR :قمم الضوء -STR_PARK :قمم الضوء -STR_DTLS :تحظى جبال "قمم الضوء" الجميلة بشعبية كبيرة بين المشاة والمتنزهين - استخدم الأرض المتاحة لجذب زوار جدد يبحثون عن الإثارة - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :A well-established park, which has a few problems - - -STR_SCNR :وادي قوس القزح -STR_PARK :وادي قوس القزح -STR_DTLS :لن تسمح السلطة المحلية في "وادي قوس القزح" بأي تغييرات في المناظر الطبيعية أو إزالة الأشجار الكبيرة، ولكن يجب عليك تطوير المنطقة لتصبح حديقة ملاهي كبيرة - - -STR_SCNR :صخرة الرعد -STR_PARK :صخرة الرعد -STR_DTLS :تقف "صخرة الرعد" في وسط الصحراء وتجذب العديد من السياح - استخدم المساحة المتاحة لبناء رحلات ركوب لجذب المزيد من الزوار - - -STR_SCNR :الحديقة العملاقة -STR_PARK :الحدبقة العملاقة -STR_DTLS :فقط للمتعة! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Develop the seaside cliffs into a thriving amusement park - - -STR_SCNR :حديقة القرود الثلاثة -STR_PARK :حديقة القرود الثلاثة -STR_DTLS :في قلب هذه الحديقة النامية الكبيرة توجد سفينة فولاذية عملاقة ثلاثية الحلقات للسباقات أو المبارزات - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its miniature railway and a pair of vertical drop roller coasters - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :An old redundant bridge is yours to develop into an amusement park - - -STR_SCNR :فينتوبيا -STR_PARK :فينتوبيا -STR_DTLS :تغطي هذه الحديقة جانبي الطريق السريع، ولديها العديد من الرحلات التي تعمل بالفعل - - -STR_SCNR :الميناء المسكون -STR_PARK :الميناء المسكون -STR_DTLS :وافقت السلطة المحلية على بيع الأراضي المجاورة بسعر رخيص لهذه الحديقة الساحلية الصغيرة، بشرط الحفاظ على بعض الرحلات. - - -STR_SCNR :قلعة المرح -STR_PARK :قلعة المرح -STR_DTLS :هذه الحديقة كلها لك لكي تحولها إلي حديقة ترفيهية - - -STR_SCNR :عالم المستقبل -STR_PARK :عالم المستقبل -STR_DTLS :هذه الحديقة المستقبلية لديها الكثير من المساحة لتبني العديد من الإفعوانيات علي أرضها الفضائية - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :A series of stepped lakes form the basis for this new park - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :This elderly park has many historical rides but is badly in debt - - -STR_SCNR :مقر السحر الرئيسي -STR_PARK :مقر السحر الرئيسي -STR_DTLS :تم تنظيف مساحة كبيرة من الأرض وأصبحت جاهزة جُزئيًا لتحويلها إلى مدينة ملاهي ذات مناظر طبيعية - - -STR_SCNR :مزرعة الفواكه -STR_PARK :مزرعة الفواكه -STR_DTLS :قامت مزرعة فواكه مزدهرة ببناء خط سكة حديد لزيادة ربحها، وظيفتك هي تطويرها إلى مدينة ملاهي كاملة - - -STR_SCNR :سد الفراشات -STR_PARK :سد الفراشات -STR_DTLS :المنطقة حول السد متوفرة لكي تطورها إلي حديقة ترفيهية - - -STR_SCNR :وادي الإفعوانيات -STR_PARK :وادي الإفعوانيات -STR_DTLS :وادي كبير متوفر لك لكي تطورة إلي حديقة أفعوانيات - - -STR_SCNR :حديقة العاصفة البرقية -STR_PARK :حديقة العاصفة البرقية -STR_DTLS :الجو رطب للغاية هنا لدرجة أنه تم بناء هرم عملاق للسماح ببناء بعض الألعاب تحته - - -STR_SCNR :السهول المتناغمة -STR_PARK :السهول المتناغمة -STR_DTLS :لن تسمح لك السلطة المحلية بالبناء فوق ارتفاع الشجر في هذه الحديقة - - -STR_SCNR :القرية الرومانية -STR_PARK :القرية الرومانية -STR_DTLS :طور هذه الحديقة المثيرة علي النمط اليوناني، بالمزيد من الأفعوانيات والرحلات - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centrepiece - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people - - -STR_SCNR :حديقة يوتوبيا -STR_PARK :يوتوبيا -STR_DTLS :واحة في وسط الصحراء تُعطي فرصة غير عادية لبناء حديقة ترفيهية - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :A four lane steeplechase ride is the centrepiece of this expanding park - - -STR_SCNR :حديقة المعادن -STR_PARK :حديقة المعادن -STR_DTLS :حوّل هذا المحجر المهجور إلى مكان يجذب السياح الباحثين عن الإثارة - - -STR_SCNR :جنون الأفعوانيات -STR_PARK :جنون الأفعوانيات -STR_DTLS :لديك أموال محدودة ولكن لديك وقت غير محدود لتحويل هذه المنطقة الجبلية إلى حديقة أفعوانيات شاسعة - - -STR_SCNR :الحديقة الحضرية -STR_PARK :الحديقة الحضرية -STR_DTLS :حديقة صغيرة قد عقدت عقداً مع المدينة القريبة لكي تتوسع في المدينة نفسها - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :A large garden park needs turning into a thriving theme park - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :A dormant volcano is the setting of this coaster-building challenge - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :A large lake in an ancient crater is the setting for this park - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :This sea-side cove is the setting for this coaster-building challenge - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :A park which has much of its footpaths and coasters underground - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :A glacier-filled valley is yours to develop into a theme park - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy - - -STR_SCNR :الصحراء المغبرة -STR_PARK :الصحراء المغبرة -STR_DTLS :خمسة أفعوانيات تحتاج الإكمال - - -STR_SCNR :حديقة دودة الخشب -STR_PARK :حديقة دودة الخشب -STR_DTLS :هذه الحديقة التاريخية يُسمح فيها فقط ببناء الرحلات القديمة - - -STR_SCNR :حديقة إيكاروس -STR_PARK :حديقة إيكاروس -STR_DTLS :يجب تطوير هذه الحديقة الغريبة لتعظيم ربحها - - -STR_SCNR :المستنقع المُشمس -STR_PARK :المستنقع المُشمس -STR_DTLS :هذا المنتزه الترفيهي يحتوي على العديد من الألعاب، لكنه يحتوي على الكثير من المساحة للتوسع - - -STR_SCNR :سهول الرعب -STR_PARK :سهول الرعب -STR_DTLS :حديقة مرعبة مع الأفعوانية المركزية العملاقة - - -STR_SCNR :صخور الرعد -STR_PARK :صخور الرعد -STR_DTLS :اثنين من الكتل الكبيرة من الصخور تبرز من الرمال، والتي يتم بناء عليها بدايات حديقة الملاهي - - -STR_SCNR :الحديقة الثمانية -STR_PARK :الحديقة الثمانية -STR_DTLS :في هذه الحديقة الكبيرة، يجب تصميم وبناء عشرة أفعوانيات كبيرة - - -STR_SCNR :جزيرة المتعة -STR_PARK :جزيرة المتعة -STR_DTLS :جزيرة رفيعة طويلة تشكل بيئة صعبة لبناء مجموعة من الأفعوانيات - - -STR_SCNR :العالم الجليدي -STR_PARK :العالم الجليدي -STR_DTLS :قطعة أرض جليدية تحتاج إلي من يحولها إلي حديقة ملاهي ممتعة - - -STR_SCNR :الرمال الجنوبية -STR_PARK :الرمال الجنوبية -STR_DTLS :حديقة صحراوية مع بعض الملاهي مصممة بذكاء لك الحرية في التوسع - - -STR_SCNR :الأبراج الصغيرة -STR_PARK :الأبراج الصغيرة -STR_DTLS :في هذه الحديقة الصغيرة يجب الانتهاء من بناء الدوامات الخمسة الموجودة - - -STR_SCNR :نيفرمور بارك -STR_PARK :نيفرمور بارك -STR_DTLS :حديقة كبيرة مع نظام نقل جديد حول حافتها - - -STR_SCNR :باسيفيكا -STR_PARK :باسيفيكا -STR_DTLS :هذه الحديقة العملاقة هي كلياً لك لتطور حديقة ملاهي للمتعة - - -STR_SCNR :الغابة الحضرية -STR_PARK :الغابة الحضرية -STR_DTLS :ناطحة سحاب مهجورة عملاقة هي فرصة فريدة لمطور متنزه ملاهي - - -STR_SCNR :مدينة الرعب -STR_PARK :مدينة الرعب -STR_DTLS :هذه المنطقة الحضارية هي لك كلياً لتحولها إلي حديقة للمتعة - - -STR_SCNR :حديقة عملاقة -STR_PARK :حديقة عملاقة -STR_DTLS :حديقة عملاقة مليئة بالرحلات تحتاج فقط إلي التحسين - - -STR_SCNR :برك فينوس -STR_PARK :برك فينوس -STR_DTLS :علي كوكب بعيد جداً، قطعة الأرض هذه تحتاج أن تحول إلي حديقة ملاهي - - -STR_SCNR :ميكرو بارك -STR_PARK :ميكرو بارك -STR_DTLS :حاول أن تبني أصغر حديقة ملاهي ربحية - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :أبراج ألتون -STR_PARK :أبراج ألتون -STR_DTLS : - - -STR_SCNR :هايد بارك -STR_PARK :هايد بارك -STR_DTLS : - - -STR_SCNR :بلاكبول شاطئ المتعة -STR_PARK :بلاكبول شاطئ المتعة -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :حصن المفارقة تاريخية -STR_PARK :حصن المفارقة تاريخية -STR_DTLS : - - - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :سقف - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :مغامرات جبال الألب -STR_PARK :مغامرات جبال الألب -STR_DTLS :قم بتحويل منتجع تزلج جبلي صغير إلى متنزه ترفيهي ذا طابع ثلجي - - -STR_SCNR :مطار أميتي -STR_PARK :مطار أميتي -STR_DTLS :قم ببناء متنزه ترفيهي ذا طابع الطيران بهذا المطار المهجور - - -STR_SCNR :قاطع النباتات -STR_PARK :قاطع النباتات -STR_DTLS :التحدي الخاص بك هو بناء حديقة عالية الربح في جزيرة الفردوس هذه - - -STR_SCNR :قم ببناء ستة أعلام بلجيكا الخاصة بك -STR_PARK :ستة أعلام بلجيكا -STR_DTLS :قم ببناء نسختك الخاصة من هذه حديقة الأعلام الستة الأوروبية - - -STR_SCNR :قم ببناء مغامرتك الرائعة ذات الأعلام الستة -STR_PARK :مغامرات الستة أعلام العظيمة -STR_DTLS :استخدم مهارات التصميم الخاصة بك لإعادة إنشاء حديقة الأعلام الستة - - -STR_SCNR :قم ببناء ستة أعلام هولندا الخاصة بك -STR_PARK :ستة أعلام هولندا -STR_DTLS :قم ببناء حديقة الأعلام الستة الأوروبية بالطريقة التي تريدها - - -STR_SCNR :قم ببناء جبل سحر الستةأعلام الخاص بك -STR_PARK :جبل سحر الستةأعلام -STR_DTLS :قم بإنشاء نسختك الخاصة من حديقة الستة أعلام الضخمة هذه - - -STR_SCNR :قم ببناء الأعلام الستة الخاصة بولاية تكساس -STR_PARK :الأعلام الستة الخاصة بولاية تكساس -STR_DTLS :بدءاً من الصفر ، قم ببناء الرحلات في حديقة الأعلام الستة - - -STR_SCNR :قم ببناء حديقة الستةأعلام الخاص بك -STR_PARK :الستة أعلام -STR_DTLS :قم ببناء التصميم الخاص بك لحديقة الأعلام الستة - أو قم ببناء الرحلات من حدائق الأعلام الستة الأخرى أو قم بتصميم وبناء ألعابك الخاصة - - -STR_SCNR :بازار بومبلي -STR_PARK :بازار بومبلي -STR_DTLS :بدءًا من بازار صغير، يتمثل التحدي الذي تواجهه في زيادة أرباح المتاجر والأكشاك عن طريق بناء الرحلات والأفعوانيات لجذب المزيد من الزوار - - -STR_SCNR :القصر المجنون -STR_PARK :القصر المجنون -STR_DTLS :لقد وَرثت قلعة كبيرة. مهمتك هي تحويلها إلى حديقة صغيرة. - - -STR_SCNR :الخضار المُغبر -STR_PARK :الخضار المُغبر -STR_DTLS :يقع الخضار المُغبر بالقرب من تقاطع طريق سريع في الصحراء، وهو فرصة لتطوير منتجع الغولف الصغير إلى حديقة ترفيهية مزدهرة - - -STR_SCNR :الحقول الكهربائية -STR_PARK :الحقول الكهربائية -STR_DTLS :لقد ورثت مزرعة صغيرة، والتحدي الذي تواجهه هو بناء حديقة صغيرة بين الحقول والمباني الزراعية - - -STR_SCNR :الأرتفاعات القصوي -STR_PARK :الأرتفاعات القصوي -STR_DTLS :Free of financial restrictions, your challenge is to expand this desert park to attract people seeking the ultimate thrills - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :An abandoned factory complex is an opportunity to build a mechanical-themed amusement park - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Restricted to only older-style wooden rides, your challenge is to build a thriving theme park in Fungus Woods - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Hired by a large amusement park chain, your task is to build them a giant roller coaster park around an abandoned mining town - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Your challenge is to build a roller coaster park in the beautiful Gravity Gardens. No other rides, just roller coasters! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :A park nestled precariously on lava rock with streams of magma - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :With unlimited funds but a challenging lake location, this park will be a challenge to expand and manage - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Built on a hillside, this park is forbidden from building anything tall. Can you expand the park and make it successful? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to attract more guests to the park! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to repay your loan while keeping the park value up! - - -STR_SCNR :ستة أعلام فوق تكساس -STR_PARK :ستة أعلام فوق تكساس -STR_DTLS :قم ببناء جولات الأعلام الستة المفقودة، أو قم بإنشاء تصميماتك الخاصة لتحسين الحديقة! لكن لا تنس هدفك النهائي: جذب المزيد من الضيوف إلى الحديقة! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :مناجم أفريقيا -STR_PARK :مناجم أفريقيا -STR_DTLS :لقد ورثت منجم ألماس مهجور ووجدت ألماسة ثمينة. قررت استثمار هذه الأموال لبناء مدينة ملاهي مشهورة عالميًا. - - -STR_SCNR :جنون السراب -STR_PARK :جنون السراب -STR_DTLS :تم اكتشاف واحة صحراوية والتي ستوفر موقعًا جميلًا للحديقة. تم توفير المواصلات من وإلى الواحة. - - -STR_SCNR :على الحافة -STR_PARK :على الحافة -STR_DTLS :تم بناء سد يوفر طاقة كهرومائية وفيرة ورخيصة لتشغيل الحديقة. أنت بحاجة للوصول إلى قيمة عالية للحديقة للمساعدة في سداد قرض السد. - - -STR_SCNR :المغامرات الثلجية -STR_PARK :المغامرات الثلجية -STR_DTLS :لقد لجأت إليك وكالة البيئة لتحويل مصفاة نفط قديمة صديقة للبيئة إلى منطقة جذب سياحي كبرى. الأرض رخيصة لكن الفائدة على القرض مرتفعة. يمكنك بيع المباني القديمة من أجل بعض النقود. - - -STR_SCNR :سور الصين العظيم -STR_PARK :سور الصين العظيم -STR_DTLS :قررت السلطات تعزيز السياحة حول السور العظيم من خلال بناء مدينة ترفيهية على الأرض المجاورة. المال ليس مُعضلة! - - -STR_SCNR :شاطئ أوكيناوا -STR_PARK :شاطئ أوكيناوا -STR_DTLS :نفدت مساحة الحديقة الموجودة. خيارك الوحيد هو البناء في البحر، وهكذا حصلت على قرض. يتم فرض قيود الارتفاع على المباني الخاصة بك بسبب الأساسات ومخاطر الزلازل. - - -STR_SCNR :حديقة المهراجا -STR_PARK :حديقة المهراجا -STR_DTLS :لقد تم تكليفك من قبل المهراجا لإحضار الترفيه لعدد كبير من السكان المحليين. حيث يتعين عليك بناء حديقة مستوحاة من قصر المهراجا. - - -STR_SCNR :مغامرات أولورو -STR_PARK :مغامرات أولورو -STR_DTLS :أنت تساعد السكان الأصليين في بناء حديقة كجزء من برنامج التوعية الثقافية. تحتاج إلى الوصول إلى عدد كبير من الزوار لتثقيفهم حول التراث الفريد للسكان الأصليين. - - -STR_SCNR :حفلة شواء على الشاطئ -STR_PARK :حفلة شواء على الشاطئ -STR_DTLS :تعرضت حديقة الفقمة الخاصة برجل أعمال محلي للإفلاس. أنت حاليًا تدير حديقة صغيرة، قُمت بشراء الحديقة الأخرى من شركة البناء. ويتعين عليك الأن تطوير حديقة مشتركة كبيرة. - - -STR_SCNR :الروعة الأوروبية -STR_PARK :الروعة الأوروبية -STR_DTLS :لقد تم إحضارك لتولي مركز جذب الزوار الثقافيين الأوروبيين ويجب عليك زيادة عدد الضيوف من أجل سداد دعم الاتحاد الأوروبي بحلول نهاية الدورة الحالية للبرلمان الأوروبي. - - -STR_SCNR :من الرماد -STR_PARK :من الرماد -STR_DTLS :لقد أصبحت هذه الحديقة القديمة بحالة يرثى لها. حَصلت على منحة من الاتحاد الأوروبي لإعادة هذه المنطقة المحرومة إلى مجدها السابق! تحتاج إلى تجديد الحديقة وسداد المنحة. - - -STR_SCNR :واكي وايكيكي -STR_PARK :واكي وايكيكي -STR_DTLS :يشعر سكان هاواي بالملل من ركوب الأمواج ويبحثون عن شيء أكثر إثارة. تحتاج إلى بناء حديقة مع وضع ذلك في الاعتبار للحفاظ على التصنيف المرتفع لمناطق الجذب السياحي في المنطقة. - - -STR_SCNR :أحداث الوادي -STR_PARK :أحداث الوادي -STR_DTLS :عليك بناء حديقة على أرض محدودة على جانبي هذا الكنز الطبيعي - لديك الفرصة لشراء الأراضي المجاورة من الهنود الأمريكيين الأصليين. تحتاج إلى إكمال الهدف للحفاظ على سكان المدينة المحلية. - - -STR_SCNR :جنة الأفعوانيات -STR_PARK :جنة الأفعوانيات -STR_DTLS :أنت رجل أعمال ناجح في إجازة طويلة وترغب في استغلال هذا الوقت في تحويل حديقة المدينة إلى جنة أفعوانيات. المال ليس عائقًا! - - -STR_SCNR :مؤسس المدينة المفقودة -STR_PARK :مؤسس المدينة المفقودة -STR_DTLS :لتعزيز السياحة المحلية، يجب عليك إنشاء حديقة تتماشى مع محيطها، ولها قيود على الارتفاع. - - -STR_SCNR :العاب الغابات المطيرة -STR_PARK :العاب الغابات المطيرة -STR_DTLS :المساحة محدودة في الغابات المطيرة الثمينة - حيث يجب عليك ضم أكبر قدر ممكن في المساحة المخلية الحالية، من أجل توفير بديل قابل للتطبيق لصناعة الأخشاب المحليةالمساحة محدودة في الغابات المطيرة الثمينة - يجب حشر أكبر قدر ممكن في المساحة المخلية الحالية، من أجل توفير بديل قابل للتطبيق لصناعة الأخشاب المحلية. - - -STR_SCNR :شواطئ باو دي أسوكار -STR_PARK :شواطئ باو دي أسوكار -STR_DTLS :انت تُدير حديقة صغيرة بالقرب من مدينة ريو لكن البنك طالبك بالقرض. تحتاج إلى زيادة ربحك بسرعة لتسديد هذا الدين غير المتوقع. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :قلعة كليفسايد -STR_PARK :قلعة كليفسايد -STR_DTLS :الأعضاء المحليون في مجتمع إعادة تمثيل المعركة جادون إلى حد ما بشأن هوايتهم. لقد عهدوا إليك بمهمة بناء مدينة ملاهي بطابع العصور المظلمة على أراضي قلعة كليفسايد. - - -STR_SCNR :غابة شيروود -STR_PARK :غابة شيروود -STR_DTLS :لتحرير الثروة من الأثرياء وتوزيعها على المحتاجين، قررت أنت ورجالك التابعين بناء مدينة ملاهي في غابة شيروود. - - -STR_SCNR :الروعة خارج الأرض -STR_PARK :الروعة خارج الأرض -STR_DTLS :تم اكتشاف الحياة على كوكب بعيد، قم ببناء متنزه غريب للاستفادة من موجة الاهتمام غير المسبوقة. - - -STR_SCNR :مدينة الجوزاء -STR_PARK :مدينة الجوزاء -STR_DTLS :أظهر رؤيتك المبتكرة والمثالية للمستقبل - ابتكر تصميمًا مستقبليًا للحديقة يتضمن أحدث عوامل الجذب. - - -STR_SCNR :تحفيات أنيماترونكس -STR_PARK :تحفيات أنيماترونكس -STR_DTLS :لقد تم تكليفك بمهمة تشغيل وتحسين مدينة ملاهي موجودة، والتي تم إنشاؤها على مجموعة أفلام قديمة. أنشئ تكريمًا لرسامي تقنية إيقاف الحركة الرائدين الذين قاموا بإحياء الكائنات الأسطورية على الشاشة الفضية لأول مرة. - - -STR_SCNR :جنون الأساطير -STR_PARK :جنون الأساطير -STR_DTLS :أنت تمتلك جزيرة ذات قيمة أثرية معينة. لقد قررت تمويل الحفاظ عليها من خلال بناء مدينة ملاهي على أساس التراث الأسطوري الغني للمنطقة. - - -STR_SCNR :المذبحة الحفرة -STR_PARK :المذبحة الحفرة -STR_DTLS :أنت تمتلك حفرة نيزك قديمة متربة. بروح ريادة الأعمال الحقيقية، قررت إنشاء مدينة ملاهي ذات طابع نايزك وكويكبات وتحويل أرضك التي تبدو بلا قيمة إلى ثروة كبيرة. - - -STR_SCNR :كوسترسورس -STR_PARK :كوسترسورس -STR_DTLS :لقد تم تكليفك بمهمة بناء مدينة ملاهي ذات طابع من العصر الجوراسي. لتحسين وصول الزائرين إلى المعروضات النباتية والحيوانية الغريبة، ستحتاج إلى إنشاء رحلات تجول في الوادي وداخله. - - -STR_SCNR :الرحلات الحجرية -STR_PARK :الرحلات الحجرية -STR_DTLS :لإحباط مطوري الطرق السريعة والحفاظ على الدوائر الحجرية القديمة الغامضة، ستحتاج إلى إنشاء مدينة ملاهي ذا طابع العصر الحجري وزيادة الأرباح. ومع ذلك، قد يشكل جذب الزوار تحديًا، حيث أن التضاريس غير مضيافة. - - -STR_SCNR :ألكتراز -STR_PARK :ألكتراز -STR_DTLS :جزيرة السجن سيئة السمعة - التي زاد عدد سكانها ذات يوم بالمهربين والمبتزين - معروضة للبيع الآن. لقد قررت تحويلها إلى منطقة جذب سياحي كبرى، والمال ليس مُعضلة - - -STR_SCNR :شواطئ شنايدر -STR_PARK :شواطئ شنايدر -STR_DTLS :تقترب الذكرى 75 لفوز جدك بكأس شنايدر في غضون بضع سنوات. سوف تكرم إنجازه من خلال بناء مدينة ملاهي على أساس سباق الطائرات المائية الشهير. - - -STR_SCNR :متروبوليس -STR_PARK :متروبوليس -STR_DTLS :أنت تمتلك قطعة أرض فارغة بالقرب من الجزء المنخفض من المدينة. لتحقيق أقصى استفادة من الممتلكات الحضرية الخاصة بك ، قم ببناء مدينة ملاهي مع ناطحات سحاب مستوحاة من العمارة الشاهقة على طراز فن الآرت ديكو في العشرينات. - - -STR_SCNR :وودستوك -STR_PARK :وودستوك -STR_DTLS :يُقام مهرجان موسيقي سنوي كبير على أرضك. أنشئ متنزهًا عصريًا للترفيه عن الجمهور المفعم بالحيوية. - - -STR_SCNR :إحياء الروك أند رول -STR_PARK :إحياء الروك أند رول -STR_DTLS :شهدت مدينة ملاهي القديمة هذه أيامًا أفضل. ساعد المالك على إضفاء مظهر روك أند رول وحول المكان إلى مكان ناجح. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :عالم الباندا -STR_PARK :عالم الباندا -STR_DTLS :أضف رحلات أكثر وقم بجذب مزيد من الناس إلى الحديقة بطابع الباندا - - -STR_SCNR :حديقة تايكون -STR_PARK :حديقة تايكون -STR_DTLS : - -##### - -STR_SCNR :مقبرة التلال -STR_PARK :مقبرة التلال -STR_DTLS :هذا عيد الهالوين ،UCES هالوين، القرع يصرخ في جوف الليل! هذه المقبرة في ورطة والأمر متروك لك لإنقاذها مع ترك الموتى يرقدون بسلام! هل يمكنك إبقاء الأشباح في قبورهم وتجلب القشعريرة لعملائك؟{NEWLINE}المؤلف: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :منارة الأسكندرية -STR_PARK :منارة الأسكندرية -STR_DTLS :بنى الإسكندر هذه المدينة. ترك الإغريق والرومان والمصريون بصماتهم. ولكن كان التكريم الأكبر هو أعجوبة العالم القديم - المنارة. قم بزيارتها وإنشئ حديقة ترفيهية!{NEWLINE}المؤلف: Katatude - - -STR_SCNR :حديقة لونا، كليفلاند -STR_PARK :حديقة لونا -STR_DTLS :كما كانت في يوم أفتتاحها - 18 مايو 1905.{NEWLINE}المؤلف: Aetherwave - - -STR_SCNR :جبل فيزوف -STR_PARK :جبل فيزوف -STR_DTLS :بومبي وهيركولانيوم دفنهم جبل فيزوف في 79 قبل الميلاد. قم بزيارة الحفريات وقم ببناء حديقة!{NEWLINE}المؤلف: Katatude - - -STR_SCNR :صندوق التجارب -STR_PARK :صندوق التجارب -STR_DTLS :ما يريده الجميع - صندوق تجارب! لذا خذ سطلًا صغيرًا ومجرفة وأستعد لبناء الحديقة!{NEWLINE}المؤلف: Katatude - - -STR_SCNR :شلالات نياجرا والمضيق -STR_PARK :شلالات نياجرا -STR_DTLS :الشلالات الأمريكية، وشلالات برايدل، وشلالات حدوة الحصان الكندية على حدود نياجرا فرونتير، 1850.{NEWLINE}المؤلف: Katatude - - -STR_SCNR :منقبي الصخور الجبلية -STR_PARK :منقبي الصخور الجبلية -STR_DTLS :تسبب الانهيار الصخري في إتلاف السكك الحديدية الخاصة بك. لقد ذهب عمالك للتنقيب. هل يوجد ذهب في الأفوانيات?{NEWLINE}المؤلفون: Squid, Buckone, Fossil - - -STR_SCNR :آلة السفر عبر الزمن -STR_PARK :آلة السفر عبر الزمن -STR_DTLS :آلة السفر عبر الزمن. صمم لتذهب - عندما تريد، أينما تريد. الأبدية تنتظر. انها كلها نسبية.{NEWLINE}المؤلف: Katatude - - -STR_SCNR :برج بابل -STR_PARK :برج بابل -STR_DTLS :قف! انظر أين أخذتنا آلة الزمن الآن! أين ذهب الجميع?{NEWLINE}المؤلف: Fossil - - -STR_SCNR :التحول -STR_PARK :التحول -STR_DTLS :كنا نتوقع ظهورك…{NEWLINE}المؤلف: Fossil - - -STR_SCNR :المدينة المجهولة -STR_PARK :المدينة المجهولة -STR_DTLS :سئم الرومان من معارك المصارع المملة. امنحهم الإثارة الأفضل، وحوّل هذه المدينة الرومانية إلى أعظم مدينة ملاهي على الإطلاق!{NEWLINE}المؤلف: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :تحت شجرة عيد الميلاد -STR_PARK :أرض عجائب الشتاء -STR_DTLS :قامت أمي ببناء هذا المشهد تحت شجرتنا. الآن تريد إنشاء حديقة فيها! هل يمكنك المساعدة?{NEWLINE}المؤلف: Katatude - - -STR_SCNR :انفجار بيجروك -STR_PARK :انفجار بيجروك -STR_DTLS :بعد انفجار في شركة شركة بيجروك للتعدين، يتعين على سكان بيجروك بناء مدينة ملاهي للحفاظ على حياة بلدتهم.{NEWLINE}المؤلفان: rbarclay & buckone - - -STR_SCNR :معسكر الطائر المحاكي -STR_PARK :معسكر الطائر المحاكي -STR_DTLS :500 دولار فقط في الأسبوع لهذا المخيم الصيفي! أسترح وإفتح البنك الخاص بك ثم استمتع وقم ببناء حديقة.{NEWLINE}المؤلف: Katatude - - -STR_SCNR :مدينة تشو تشو -STR_PARK :مدينة تشو تشو -STR_DTLS :ماما! بابا! أريد الذهاب لمدينة تشو تشو!{NEWLINE}المؤلف: Fossil - - -STR_SCNR :جزر التنين -STR_PARK :جزر التنين -STR_DTLS :جزر التنين? لست متأكدًا من أنني أريد الذهاب إلى هناك…{NEWLINE}المؤلف: Fossil - - -STR_SCNR :كرنفال الأطفال 2 -STR_PARK :كرنفال الأطفال -STR_DTLS :يا أطفال! هيا نمرح!{NEWLINE}المؤلفان: Piehead & Fossil - - -STR_SCNR :الكثبان الرملية -STR_PARK :الكثبان الرملية -STR_DTLS :باعتبارك مالكًا لمتنزه صغير، فقد اشتريت قطعة أرض كبيرة على طول الشاطئ للتوسع وجذب المزيد من الضيوف لزيارة الكثبان الرملية الجميلة، ولكن احذر: لا يمكنك إزعاج تلك الكثبان الرملية الهشة بيئيًا.{NEWLINE}المؤلف: rbarclay diff --git a/data/language/ca-ES.txt b/data/language/ca-ES.txt index 0875744f3c..a8bbdb9dfd 100644 --- a/data/language/ca-ES.txt +++ b/data/language/ca-ES.txt @@ -3736,858 +3736,3 @@ STR_6659 :Els visitants ignoren els preus STR_6660 :Els visitants ignoraran els preus de les atraccions i paradetes. STR_6661 :Aleatoritza’ls tots STR_6662 :Aleatoritza els colors de cada cotxe o vehicle. - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Les fronteres forestals -STR_PARK :Les fronteres forestals -STR_DTLS :Construïu un parc pròsper a l’àrea que s’ha netejat ben endins del bosc. - - -STR_SCNR :Les dunes Dinamita -STR_PARK :Les dunes Dinamita -STR_DTLS :Construït al bell mig del desert, aquest parc temàtic només té una muntanya russa però disposa d’espai per a expandir-se. - - -STR_SCNR :El llac frondós -STR_PARK :El llac frondós -STR_DTLS :Construïu un parc temàtic des de l’inici al voltant d’un llac. - - -STR_SCNR :Els cims diamantins -STR_PARK :Els cims diamantins -STR_DTLS :«Els cims diamantins» ja és un parc exitós amb grans atraccions. Desenvolupeu-lo i dobleu-ne el valor. - - -STR_SCNR :Els jardins perennes -STR_PARK :Els jardins perennes -STR_DTLS :Convertiu aquests preciosos jardins perennes en un parc temàtic pròsper. - - -STR_SCNR :La platja Bumbly -STR_PARK :La platja Bumbly -STR_DTLS :Desenvolupeu aquest parc d’atraccions i convertiu-lo en un parc temàtic pròsper. - - -STR_SCNR :Les illes Trinitat -STR_PARK :Les illes Trinitat -STR_DTLS :La base d’aquest parc la formen diverses illes. - - -STR_SCNR :El món de fantasia de la Katie -STR_PARK :El món de fantasia de la Katie -STR_DTLS :Un parc temàtic petit amb unes quantes atraccions i espai per a expandir-lo. El vostre objectiu és duplicar-ne el valor. - - -STR_SCNR :El parc diminut -STR_PARK :El parc diminut -STR_DTLS :Un parc d’atraccions petit i atapeït que requereix una expansió important. - - -STR_SCNR :El parc Aiguablanca -STR_PARK :El parc Aiguablanca -STR_DTLS :Un parc amb algunes atraccions aquàtiques excel·lents necessita que se’n dissenyi una expansió. - - -STR_SCNR :Les mines Mil·lennium -STR_PARK :Les mines Mil·lennium -STR_DTLS :Convertiu aquestes enormes mines abandonades que actualment són una mera atracció turística en un parc temàtic. - - -STR_SCNR :Kàrting i muntanyes russes -STR_PARK :Kàrting i muntanyes russes -STR_DTLS :Un parc gran amagat al bell mig dels boscos. Només té vies de kàrting i muntanyes russes de fusta. - - -STR_SCNR :El món d’en Mel -STR_PARK :El món d’en Mel -STR_DTLS :Aquest parc temàtic té algunes atraccions modernes molt ben dissenyades i molt d’espai per a expandir-se. - - -STR_SCNR :La muntanya mística -STR_PARK :La muntanya mística -STR_DTLS :Construïu un parc temàtic des de zero en els boscos i turons de la muntanya mística. - - -STR_SCNR :Les piràmides pacífiques -STR_PARK :Les piràmides pacífiques -STR_DTLS :Convertiu l’atracció turística d’aquestes ruïnes egípcies en un parc temàtic pròsper. - - -STR_SCNR :Els boscos llangorosos -STR_PARK :Els boscos llangorosos -STR_DTLS :Un parc enorme amb atraccions ben dissenyades però que comencen a ser velles. Substituïu-les o afegiu-hi atraccions noves per a fer que el parc sigui més popular. - - -STR_SCNR :El moll paradisíac -STR_PARK :El moll paradisíac -STR_DTLS :Convertiu aquest petit moll fantasma en una atracció pròspera. - - -STR_SCNR :Els cims llampeguejants -STR_PARK :Els cims llampeguejants -STR_DTLS :Els excursionistes ja coneixen aquestes magnífiques muntanyes. Useu el terreny disponible per a atreure més clientela, especialment aquells que busquin emocions fortes. - - -STR_SCNR :Les torres de vori -STR_PARK :Les torres de vori -STR_DTLS :Un parc ben establert que té alguns problemes. - - -STR_SCNR :La vall de l’arc iris -STR_PARK :La vall de l’arc iris -STR_DTLS :Les autoritats locals de la vall no permetran canvis en el terreny ni que es treguin arbres centenaris. L’haureu de desenvolupar amb molt de compte per a convertir-la en un parc temàtic. - - -STR_SCNR :La roca del tro -STR_PARK :La roca del tro -STR_DTLS :La roca del tro està al mig d’un desert i atrau molts turistes. Useu l’espai disponible per a construir-hi atraccions i atreure més visitants. - - -STR_SCNR :Megaparc -STR_PARK :Megaparc -STR_DTLS :Només per a divertir-se! - -## Added Attractions - -STR_SCNR :Els penya-segats murmuriosos -STR_PARK :Els penya-segats murmuriosos -STR_DTLS :Desenvolupeu els penya-segats i convertiu-los en un parc d’atraccions pròsper. - - -STR_SCNR :El parc de les tres mones -STR_PARK :El parc de les tres mones -STR_DTLS :Al bell mig d’aquest gran parc en desenvolupament i hi ha una muntanya russa d’acer amb triple carril per a fer competicions. - - -STR_SCNR :Les mines Canàries -STR_PARK :Les mines Canàries -STR_DTLS :Aquestes mines abandonades ja són una atracció turística amb el seu tren en miniatura i una parella de muntanyes russes amb caigudes verticals. - - -STR_SCNR :El pont de la baronia -STR_PARK :El pont de la baronia -STR_DTLS :Disposeu d’un pont antic que actualment és redundant. Convertiu-lo en un parc temàtic. - - -STR_SCNR :Diversiotopia -STR_PARK :Diversiotopia -STR_DTLS :Cobrint ambdues bandes d’una autopista, aquest parc ja opera amb algunes atraccions. - - -STR_SCNR :El port embruixat -STR_PARK :El port embruixat -STR_DTLS :Les autoritats locals han acordat vendre barat el terreny proper d’aquest parc coster amb la condició que es preservin algunes atraccions. - - -STR_SCNR :La fortalesa de la diversió -STR_PARK :La fortalesa de la diversió -STR_DTLS :Aquest castell és tot vostre per a convertir-lo en un parc temàtic. - - -STR_SCNR :El món del futur -STR_PARK :El món del futur -STR_DTLS :Aquest parc futurístic disposa de molt d’espai lliure per a noves atraccions en terreny alienígena. - - -STR_SCNR :La vall tranquil·la -STR_PARK :La vall tranquil·la -STR_DTLS :La població local prefereix atraccions suaus i relaxants. Així que la vostra feina és expandir aquest parc per a satisfer els seus desitjos. - - -STR_SCNR :La selva alegre -STR_PARK :La selva alegre -STR_DTLS :Ben endins de la selva hi ha una gran àrea de terreny preparada per a convertir-la en un parc temàtic. - - -STR_SCNR :Els turons Hydro -STR_PARK :Els turons Hydro -STR_DTLS :Una sèrie de llacs escalonats formen la base per a aquest parc nou. - - -STR_SCNR :El parc alegre -STR_PARK :El parc alegre -STR_DTLS :Aquest parc envellit té moltes atraccions històriques però està massa endeutat. - - -STR_SCNR :Els barris màgics -STR_PARK :Els barris màgics -STR_DTLS :S’ha netejat una gran àrea de terreny i s’ha tematitzat parcialment per a convertir-la en un parc temàtic paisatgístic. - - -STR_SCNR :La granja de la fruita -STR_PARK :La granja de la fruita -STR_DTLS :Una granja de fruites pròspera ha construït el ferrocarril per a augmentar-ne els ingressos. La vostra feina és convertir-la en un parc d’atraccions plenament desenvolupat. - - -STR_SCNR :La presa Papallona -STR_PARK :La presa Papallona -STR_DTLS :L’àrea del voltant de la presa està disponible perquè hi desenvolupeu un parc d’atraccions. - - -STR_SCNR :Atraccions al canyó -STR_PARK :Atraccions al canyó -STR_DTLS :Teniu un vast canyó per a convertir-lo en un parc temàtic. - - -STR_SCNR :Parc Tempesta -STR_PARK :Parc Tempesta -STR_DTLS :El clima és tan humit que s’ha construït una piràmide gegant per a construir-hi algunes atraccions a cobert. - - -STR_SCNR :Turons harmònics -STR_PARK :Turons harmònics -STR_DTLS :Les autoritats pertinents no permeten que es construeixi per damunt de l’alçada dels arbres en aquest parc. - - -STR_SCNR :La vila romana -STR_PARK :La vila romana -STR_DTLS :Desenvolupeu aquest parc temàtic romà afegint-hi atraccions i muntanyes russes. - - -STR_SCNR :La cova del pantà -STR_PARK :La cova del pantà -STR_DTLS :Construït parcialment en illes petites, aquest parc ja disposa d’un parell de muntanyes russes enormes com a peces centrals. - - -STR_SCNR :Els cims d’Adrenalina -STR_PARK :Els cims d’Adrenalina -STR_DTLS :Construeix un parc per a atreure a la gent dels voltants que busqui emocions d’alt voltatge. - - -STR_SCNR :Parc Utopia -STR_PARK :Parc Utopia -STR_DTLS :Un oasi al mig del desert ofereix una oportunitat poc usual per a construir un parc d’atraccions. - - -STR_SCNR :Els cims Mig-Podrits -STR_PARK :Els cims Mig-Podrits -STR_DTLS :Descuidat i dilapidat, podreu ressuscitar aquest parc d’atraccions que fa temps era un dels millors? - - -STR_SCNR :El bosc Fiasco -STR_PARK :El bosc Fiasco -STR_DTLS :Ple d’atraccions perilloses i mal dissenyades, teniu un pressupost i temps molt limitat per a solucionar-ne els problemes i tirar endavant el parc. - - -STR_SCNR :Parc dels cogombrets -STR_PARK :Parc dels cogombrets -STR_DTLS :L’autoritat local no permetrà campanyes de màrqueting. El parc haurà d’aconseguir tirar endavant només amb la seva reputació. - - -STR_SCNR :Baixades de riure -STR_PARK :Baixades de riure -STR_DTLS :Un «steeplechase» de quatre carrils és la peça centra d’aquest parc en expansió. - - -STR_SCNR :Parc mineral -STR_PARK :Parc mineral -STR_DTLS :Convertiu aquesta pedrera abandonada en un lloc on atreure als turistes que busquin emocions fortes. - - -STR_SCNR :Vessants boges -STR_PARK :Vessants boges -STR_DTLS :Disposeu de fons financers limitats però temps il·limitat per a convertir aquesta àrea de muntanyes en un gran parc de muntanyes russes. - - -STR_SCNR :Parc urbà -STR_PARK :Parc urbà -STR_DTLS :Un petit parc ha arribat a un acord amb una població propera per a expandir-se pel mig de la mateixa població. - - -STR_SCNR :Jardins Geoffrey -STR_PARK :Jardins Geoffrey -STR_DTLS :Un gran parc de jardins necessita reformar-se i convertir-se en un parc temàtic pròsper. - -## Loopy Landscapes - -STR_SCNR :Illes Iceberg -STR_PARK :Illes Iceberg -STR_DTLS :L’entorn d’aquest gèlid i ambiciós parc temàtic és un grup d’icebergs. - - -STR_SCNR :Volcània -STR_PARK :Volcània -STR_DTLS :L’entorn d’aquest repte de construcció de muntanyes russes és un inquietant volcà adormit. - - -STR_SCNR :Els cims àrids -STR_PARK :Els cims àrids -STR_DTLS :Sense límits financers, el repte és desenvolupar aquest parc desèrtic mantenint feliços als visitants. - - -STR_SCNR :Roques afilades -STR_PARK :Roques afilades -STR_DTLS :La vostra tasca és construir un parc ple de muntanyes russes gegantines entre roques afilades. - - -STR_SCNR :El llac del cràter -STR_PARK :El llac del cràter -STR_DTLS :Aquest parc està situat en un llac molt gran al mig d’un antic cràter. - - -STR_SCNR :Vistes vertiginoses -STR_PARK :Vistes vertiginoses -STR_DTLS :Aquest parc enorme ja té una hipermuntanya russa, però la vostra tasca és incrementar-ne massivament els beneficis. - - -STR_SCNR :El moll paradisíac II -STR_PARK :El moll paradisíac II -STR_DTLS :El moll paradisíac ha expandit la seva xarxa de camins pel mar i la vostra tasca és ampliar el parc i fer servir aquest espai extra. - - -STR_SCNR :La cova del drac -STR_PARK :La cova del drac -STR_DTLS :Aquesta cova al costat del mar és el lloc d’aquest repte de construcció de muntanyes russes. - - -STR_SCNR :Parc del bon cavaller -STR_PARK :Parc del bon cavaller -STR_DTLS :Un castell amb un parell de muntanyes russes que s’ha de convertir en un parc temàtic més gran. - - -STR_SCNR :Madrigueres boges -STR_PARK :Madrigueres boges -STR_DTLS :Un parc que té molts dels camins i muntanyes russes sota terra. - - -STR_SCNR :La gran glacera -STR_PARK :La gran glacera -STR_DTLS :Teniu aquesta vall ocupada per una glacera. Hi heu de desenvolupar un parc temàtic. - - -STR_SCNR :Cràters bojos -STR_PARK :Cràters bojos -STR_DTLS :En un món llunyà on els diners no fan falta, heu de construir un centre d’entreteniment per a mantenir feliç a la gent. - - -STR_SCNR :Desert polsegós -STR_PARK :Desert polsegós -STR_DTLS :Cal completar 5 muntanyes russes en aquest parc situat al desert. - - -STR_SCNR :Parc dels corcs -STR_PARK :Parc dels corcs -STR_DTLS :Aquest parc històric només té permís per a construir atraccions d’estil antic. - - -STR_SCNR :Parc Ícar -STR_PARK :Parc Ícar -STR_DTLS :Desenvolupeu aquest parc alienígena per tal de maximitzar-ne els beneficis. - - -STR_SCNR :Pantans solejats -STR_PARK :Pantans solejats -STR_DTLS :Aquest parc d’atraccions ben tematitzat ja disposa d’unes quantes atraccions, però encara es pot expandir molt més. - - -STR_SCNR :Els turons de la por -STR_PARK :Els turons de la por -STR_DTLS :Un parc sinistre amb una muntanya russa gegant que atrau totes les mirades. - - -STR_SCNR :Les roques del tro -STR_PARK :Les roques del tro -STR_DTLS :De la sorra sobresurten dos trossos de roca, justament on comença el vostre parc temàtic. - - -STR_SCNR :Parc octagonal -STR_PARK :Parc octagonal -STR_DTLS :En aquest parc gran heu de dissenyar i construir 10 muntanyes russes grans. - - -STR_SCNR :L’illa Delícia -STR_PARK :L’illa Delícia -STR_DTLS :Una illa llarga i estreta que fa difícil triar i construir una bona selecció de muntanyes russes. - - -STR_SCNR :Els mons de les estalactites i estalagmites -STR_PARK :Els mons de les estalactites i estalagmites -STR_DTLS :Un paisatge gèlid que demana que el converteixin en un parc temàtic pròsper. - - -STR_SCNR :Les arenes del sud -STR_PARK :Les arenes del sud -STR_DTLS :Un parc al desert amb algunes muntanyes russes enginyosament dissenyades és tot vostre per a expandir-lo. - - -STR_SCNR :Les torres petites -STR_PARK :Les torres petites -STR_DTLS :S’ha de completar la construcció de 5 muntanyes russes en aquest petit parc. - - -STR_SCNR :Parc Nevermore -STR_PARK :Parc Nevermore -STR_DTLS :Un parc gran amb un sistema de transport nou que el voreja. - - -STR_SCNR :L’illa Pacífica -STR_PARK :L’illa Pacífica -STR_DTLS :Aquesta enorme illa és tota vostra per a desenvolupar-la com a parc d’atraccions. - - -STR_SCNR :La jungla urbana -STR_PARK :La jungla urbana -STR_DTLS :Un gratacels gegant abandonat és l’única opció per a desenvolupar un parc temàtic. - - -STR_SCNR :El poble Terror -STR_PARK :El poble Terror -STR_DTLS :Aquesta àrea urbana és tota vostra per a desenvolupar-la com a parc d’atraccions. - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :Un parc gegantí que ja té moltes atraccions necessita millores urgents. - - -STR_SCNR :Estanys de Venus -STR_PARK :Estanys de Venus -STR_DTLS :Aquesta àrea d’un planeta llunyà necessita que la converteixin en un parc temàtic. - - -STR_SCNR :Microparc -STR_PARK :Microparc -STR_DTLS :Es pot crear aquí el parc més petit del món i que tingui beneficis? - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers (Regne Unit) -STR_PARK :Alton Towers (Regne Unit) -STR_DTLS : - - -STR_SCNR :Heide-Park (Alemanya) -STR_PARK :Heide-Park (Alemanya) -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach (Regne Unit) -STR_PARK :Blackpool Pleasure Beach (Regne Unit) -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :El castell «Fort Anachronism» -STR_PARK :El castell «Fort Anachronism» -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Sostre - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Aventures alpines -STR_PARK :Aventures alpines -STR_DTLS :Convertiu una estació d’esquí en un parc d’atraccions cobert de neu. - - -STR_SCNR :Aeròdrom de la concòrdia -STR_PARK :Aeròdrom de la concòrdia -STR_DTLS :Construïu un parc d’atraccions de temàtica aeronàutica en un aeroport abandonat. - - -STR_SCNR :El factor botànic -STR_PARK :El factor botànic -STR_DTLS :El repte és construir un parc que generi molts beneficis en aquesta illa paradisíaca. - - -STR_SCNR :El vostre Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Construïu la vostra versió d’aquest parc Six Flag europeu. - - -STR_SCNR :El vostre Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Empreu les vostres tècniques de disseny per tal de recrear aquest parc Six Flag. - - -STR_SCNR :El vostre Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Construïu aquest parc Six Flags europeu a la vostra manera. - - -STR_SCNR :El vostre Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Creeu la vostra versió d’aquest gegantesc parc Six Flags. - - -STR_SCNR :El vostre Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Començant des del principi, construïu atraccions en aquest parc Six Flags. - - -STR_SCNR :El vostre Six Flags -STR_PARK :Six Flags -STR_DTLS :Construïu el vostre disseny del parc Six Flags. Construïu atraccions d’altres Six Flags o bé dissenyeu-ne de noves. - - -STR_SCNR :El basar atrafegat -STR_PARK :El basar atrafegat -STR_DTLS :Començant amb un petit basar, el repte consisteix en incrementar els beneficis de les paradetes construint atraccions i muntanyes russes per a atreure més clients. - - -STR_SCNR :Castell esbojarrat -STR_PARK :Castell esbojarrat -STR_DTLS :Heu heretat aquest enorme castell. La vostra feina consisteix en convertir-lo en un parc temàtic petit. - - -STR_SCNR :Verds polsosos -STR_PARK :Verds polsosos -STR_DTLS :Situat prop d’una sortida d’autopista al mig del desert, «Verds polsosos» és una oportunitat per tal de desenvolupar un petit complex amb un camp de golf i convertir-lo en un parc temàtic pròsper. - - -STR_SCNR :Camps elèctrics -STR_PARK :Camps elèctrics -STR_DTLS :Heu heretat una petita masoveria i teniu el repte de construir un petit parc temàtic entre els camps i les granges. - - -STR_SCNR :Alçades extremes -STR_PARK :Alçades extremes -STR_DTLS :Sense restriccions financeres, el repte és expandir aquest parc desèrtic per a atreure gent que busqui emocions fortes. - - -STR_SCNR :Aventures de la fàbrica -STR_PARK :Aventures de la fàbrica -STR_DTLS :Un complex abandonat és una oportunitat per a construir un parc d’atraccions de temàtica industrial. - - -STR_SCNR :Boscos rancis -STR_PARK :Boscos rancis -STR_DTLS :Amb només atraccions de fusta i d’estil antic, el repte consisteix en construir un parc temàtic pròsper als «Boscos rancis». - - -STR_SCNR :El poble fantasma -STR_PARK :El poble fantasma -STR_DTLS :Contractat per una cadena de parcs temàtics gran, la vostra tasca consisteix en construir-los una muntanya russa gegant al voltant d’un poble miner abandonat. - - -STR_SCNR :Jardins de la gravetat -STR_PARK :Jardins de la gravetat -STR_DTLS :El repte és construir un parc de muntanyes russes en aquests jardins. Només muntanyes russes, sense altres atraccions! - - -STR_SCNR :Paisatges infernals -STR_PARK :Paisatges infernals -STR_DTLS :Un parc construït precàriament en roques volcàniques amb rius de magma. - - -STR_SCNR :Llac de la sort -STR_PARK :Llac de la sort -STR_DTLS :Amb fons il·limitats però en un entorn exigent, expandir i dirigir aquest parc serà tot un repte. - - -STR_SCNR :La cima de l’arc de San Martí -STR_PARK :La cima de l’arc de San Martí -STR_DTLS :Construït en una vessant, aquest parc té prohibit construir-hi res gaire alt. Podeu expandir-lo i fer que tingui èxit? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Proveu a dirigir i millorar aquest parc Six Flags. - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Construïu les atraccions que li falten a aquest Six Flags, o creeu els vostres dissenys per a millorar el parc! Però no oblideu el vostre objectiu final: atreure més clients al parc. - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Proveu a dirigir i millorar aquest parc Six Flags. - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Construïu les atraccions Six Flags que falten, o creeu els vostres dissenys per a millorar el parc! Però no oblideu el vostre objectiu final: retornar el préstec mentre el parc manté una valoració alta. - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Construïu les atraccions Six Flags que falten, o creeu els vostres dissenys per a millorar el parc! Però no oblideu el vostre objectiu final: atreure més clients al parc. - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines d’Àfrica -STR_PARK :Mines d’Àfrica -STR_DTLS :Heu heretat una mina de diamants que ja no s’explota, on hi heu trobat un diamant valuós. Voleu invertir els diners del diamant per tal de construir un parc temàtic conegut a tot el món. - - -STR_SCNR :La follia dels miratges -STR_PARK :La follia dels miratges -STR_DTLS :S’ha descobert un oasi que seria una bona localització per a fer-hi un parc. El transport fins l’oasi ja està preparat. - - -STR_SCNR :A la vora -STR_PARK :A la vora -STR_DTLS :S’ha construït una presa que ofereix energia hidroelèctrica barata i abundant per a fer funcionar un parc. Haureu d’obtenir una valoració del parc prou alta per a poder retornar el préstec de la presa. - - -STR_SCNR :Aventures gèlides -STR_PARK :Aventures gèlides -STR_DTLS :L’agència mediambiental us ha delegat la tasca de transformar aquesta monstruositat ecològica en forma de refineria de petroli en una atracció turística capdavantera. El terreny és barat però el tipus d’interès del préstec és alt. Podeu vendre els vells edificis per a treure’n profit. - - -STR_SCNR :La Gran Muralla xinesa -STR_PARK :La Gran Muralla xinesa -STR_DTLS :Les autoritats han decidit millorar les instal·lacions turístiques al voltant de la Gran Muralla construint-hi un parc temàtic. I no us preocupeu pels diners! - - -STR_SCNR :Costa d’Okinawa -STR_PARK :Costa d’Okinawa -STR_DTLS :Un parc s’ha quedat sense espai. L’única opció és construir mar endins, i per això heu demanat un préstec. Les restriccions d’alçada dels edificis es deuen al tipus de fonaments i el risc de terratrèmols. - - -STR_SCNR :Parc del maharajà -STR_PARK :Parc del maharajà -STR_DTLS :El maharajà us ha destinat aquí per tal que proporcioneu entreteniment a l’enorme població local. Construïu un parc inspirat pel palau del maharajà. - - -STR_SCNR :L’aventura Uluru -STR_PARK :L’aventura Uluru -STR_DTLS :Esteu ajudant els aborígens a construir un parc dins del programa de conscienciació cultural. Necessiteu un gran nombre de visitants per a instruir-los en l’herència cultural única de la població indígena. - - -STR_SCNR :L’explosió de la barbacoa de la platja -STR_PARK :L’explosió de la barbacoa de la platja -STR_DTLS :El parc marítim d’un emprenedor local ha fet fallida. Ja teniu un parc petit que funciona, però ara acabeu de comprar l’altre parc. Desenvolupeu un únic parc combinat. - - -STR_SCNR :Extravagància europea -STR_PARK :Extravagància europea -STR_DTLS :Us han dut per a dirigir una atracció cultural europea per als turistes i heu d’augmentar el nombre de visitants per tal de poder retornar la subvenció de la UE a finals de l’actual mandat del parlament europeu. - - -STR_SCNR :Des de les cendres -STR_PARK :Des de les cendres -STR_DTLS :Aquest parc vell està en mal estat. Heu guanyat una subvenció per a retornar aquesta àrea desafavorida a la seva antiga glòria! Heu de renovar el parc i retornar la subvenció. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :La gent de Hawaii s’avorreixen només fent surf i busquen alguna cosa més intensa. Heu de construir un parc amb això al cap per tal de mantenir un interès turístic a la zona prou elevat. - - -STR_SCNR :Calamitats del Canyó -STR_PARK :Calamitats del Canyó -STR_DTLS :Heu de construir un parc en el terreny limitat en les dues bandes d’aquest tresor natural. Teniu l’oportunitat de comprar terrenys adjacents dels nadius indis americans. Heu de completar l’objectiu per a alimentar els habitants de la població local. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :Sou un magnat de les finances competent en període sabàtic que desitja usar el seu temps en transformar el parc de la ciutat en el «Rollercoaster Heaven». I els diners no importen! - - -STR_SCNR :La fundació de la ciutat perduda -STR_PARK :La fundació de la ciutat perduda -STR_DTLS :Per a augmentar el turisme local heu de construir un parc que s’adigui amb els seus voltants. - - -STR_SCNR :Diversió a la selva -STR_PARK :Diversió a la selva -STR_DTLS :En aquesta preciosa selva tropical, l’espai està limitat. Heu d’amuntegar tot el que pugueu en els llocs sense arbres, per tal de que la indústria local de la fusta continuï sent una alternativa viable al turisme. - - -STR_SCNR :Costes del Pão de Açúcar -STR_PARK :Costes del Pão de Açúcar -STR_DTLS :Dirigiu un petit parc prop de Rio, però el banc demana que se li pagui el préstec. Necessiteu augmentar ràpidament la vostra capacitat recaptatòria per a retornar aquest deute inesperat. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Castell del penya-segat -STR_PARK :Castell del penya-segat -STR_DTLS :Els membres locals de la societat de representacions de batalles es prenen la seva afició seriosament. Us han confiat la tasca de construir un parc temàtic de l’edat mitjana on hi ha el castell de Cliffside. - - -STR_SCNR :El bosc de Sherwood -STR_PARK :El bosc de Sherwood -STR_DTLS :Amb la intenció de robar als rics i repartir el que aconseguiu entre els pobres, heu decidit que, amb l’ajuda dels vostres «homes feliços», construireu un parc temàtic al bosc de Sherwood. - - -STR_SCNR :Extravagància Extraterrestre -STR_PARK :Extravagància Extraterrestre -STR_DTLS :S’ha descobert vida en un planeta llunyà. Construïu un parc de temàtica alienígena per a recaptar els diners d’aquesta onada d’interès sense precedent. - - -STR_SCNR :Ciutat Gèmini -STR_PARK :Ciutat Gèmini -STR_DTLS :Mostreu la vostra inventiva visió utòpica del futur. Aixequeu un parc amb dissenys futurístics que incorpori atraccions avantguardistes. - - -STR_SCNR :Relíquies animatròniques -STR_PARK :Relíquies animatròniques -STR_DTLS :Us han encomanat la tasca de fer funcionar i millorar un parc temàtic ja existent que s’ha construït en un vell plató de cinema. Construïu un tribut als animadors pioners de l’stop-motion que van portar per primer cop criatures mítiques a la vida a la gran pantalla. - - -STR_SCNR :Bogeria mitològica -STR_PARK :Bogeria mitològica -STR_DTLS :Sou el propietari d’una illa amb un important valor arqueològic. Heu decidit finançar la seva preservació construint-hi un parc temàtic basat en la rica herència mitològica de l’àrea. - - -STR_SCNR :La matança del cràter -STR_PARK :La matança del cràter -STR_DTLS :Sou el propietari d’un vell cràter polsegós causat per un meteorit. Amb el vertader esperit emprenedor, heu decidit construir un parc amb la temàtica de l’asteroide i convertir aquestes terres aparentment poc valuoses en una fortuna considerable. - - -STR_SCNR :Atracciósaurus -STR_PARK :Atracciósaurus -STR_DTLS :Us han assignat la tasca de construir un parc de l’era juràssica. Per tal d’optimitzar l’accés dels visitants a les exhibicions de plantes i animals exòtics, haureu de construir atraccions per tota la vall. - - -STR_SCNR :Passeig rocós -STR_PARK :Passeig rocós -STR_DTLS :Per a frustrar els plans dels constructors d’una autopista i per a ajudar a preservar els misteriosos i antics cercles de pedra, haureu de construir un parc temàtic amb l’edat de pedra com a principal motiu i aconseguir treure’n beneficis. No obstant, atreure visitants pot suposar un repte, ja que el terreny és un poc inhòspit. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :La infame Illa Presó, la població de la qual fa molt temps creixia gràcies a contrabandistes i estafadors, està en venda. Heu decidit convertir-la en una atracció turística de primer ordre, i no us preocupeu pels diners. - - -STR_SCNR :Costa Schneider -STR_PARK :Costa Schneider -STR_DTLS :El 25è aniversari de la victòria del vostre avi a la Copa Schneider serà d’aquí pocs anys. L’honorareu construint un parc on la temàtica serà la famosa cursa d’hidroavions. - - -STR_SCNR :Metròpoli -STR_PARK :Metròpoli -STR_DTLS :Disposeu d’un solar buit prop de la zona pobra de la població. Per a treure profit d’aquests terrenys urbans, construïu un parc en forma de gratacels inspirat en el desorbitat art decó dels anys vint. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Hi ha un gran festival anual de música als teus terrenys. Construïu-hi un parc temàtic a la moda per a mantenir els esperits lliures entretinguts. - - -STR_SCNR :Revival del Rock ’n’ Roll -STR_PARK :Revival del Rock ’n’ Roll -STR_DTLS :Aquest parc temàtic ha vist millors dies. Ajudeu al propietari a donar-li un toc rock ’n’ roll retro i convertiu el lloc en un lloc pròsper. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Món Panda -STR_PARK :Món Panda -STR_DTLS :Afegiu més atraccions i atraieu més visitants a aquest parc temàtic inspirat en els pandes. - - -STR_SCNR :Parc Tycoon -STR_PARK :Parc Tycoon -STR_DTLS : - - -STR_SCNR :La cresta del cementiri -STR_PARK :La cresta del cementiri -STR_DTLS :Aquest Halloween, el Halloween UCES, les carabasses cridaran durant les hores més fosques de la nit! Aquest cementiri té problemes i l’heu de salvar, al mateix temps que heu de permetre que els morts descansin en pau. Podeu deixar tranquils els fantasmes a les seves tombes i fer que els visitants s’estremeixin?{NEWLINE}Autor: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :El Far d’Alexandria -STR_PARK :El Far d’Alexandria -STR_DTLS :Alexandre el Gran construí la ciutat; els grecs, els romans i els egipcis hi van deixar la seva petjada. Però l’honor més gran és una meravella del món antic: el Far d’Alexandria. Visiteu-lo i construïu-hi un parc!{NEWLINE}Autor: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Tal i com era el dia de la seva inauguració, el dia 18 de maig de 1.905.{NEWLINE}Autor: Aetherwave - - -STR_SCNR :El Mont Vesuvi -STR_PARK :El Mont Vesuvi -STR_DTLS :Pompeia i Herculà van quedar soterrades pel mont Vesuvi l’any 79 dC. Visiteu les excavacions i construïu-hi un parc!{NEWLINE}Autor: Katatude - - -STR_SCNR :The Sandbox -STR_PARK :The Sandbox -STR_DTLS :Tot el que tothom desitja: una caixa d’arena. Així que agafeu la vostra petita pala i a construir-hi un parc!{NEWLINE}Autor: Katatude - - -STR_SCNR :Niagara Falls & Gorge -STR_PARK :Niagara Falls -STR_DTLS :Les Cascades Americanes, les del Vel de la Núvia i les cataractes Horseshoe canadenques a la frontera del Niàgara, 1850.{NEWLINE}Autor: Katatude - - -STR_SCNR :Els miners de les Muntanyes Rocoses -STR_PARK :Els miners de les Muntanyes Rocoses -STR_DTLS :Un despreniment ha fet malbé el ferrocarril. Els treballadors ara mateix no hi són. Hi ha or a les muntanyes russes?{NEWLINE}Autors: Squid, Buckone, Fossil - - -STR_SCNR :La màquina del temps -STR_PARK :La màquina del temps -STR_DTLS :La màquina del temps. Construïda per a anar on vulgueu quan vulgueu. L’eternitat us espera. Tot és relatiu.{NEWLINE}Autor: Katatude - - -STR_SCNR :La Torre de Babel -STR_PARK :La Torre de Babel -STR_DTLS :Ua! Mireu on ens ha dut la màquina del temps! On ha anat tothom?{NEWLINE}Autor: Fossil - - -STR_SCNR :Transformació -STR_PARK :Transformació -STR_DTLS :Us estàvem esperant…{NEWLINE}Autor: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :Els romans estan cansats de lluites avorrides de gladiadors. Doneu-los altres entreteniments i convertiu la ciutat romana en el parc d’atraccions més gran de tots els temps!{NEWLINE}Autor: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Sota l’arbre de Nadal -STR_PARK :El món de fantasia hivernal -STR_DTLS :La meva mare ha construït aquesta escena a sota de l’arbre de Nadal. Ara vol que hi construïm un parc a dins! Ens podeu ajudar?{NEWLINE}Autor: Katatude - - -STR_SCNR :Explosió a Rocagrossa -STR_PARK :Explosió a Rocagrossa -STR_DTLS :Després de l’explosió de la Companyia Minera Rocagrossa, la gent de Rocagrossa han de construir un parc d’atraccions per a mantenir el seu poble amb vida.{NEWLINE}Autors: rbarclay & buckone - - -STR_SCNR :Camp Rossinyol -STR_PARK :Camp Rossinyol -STR_DTLS :Només 500 $ per setmana per aquest campament d’estiu! Obriu el banc, divertiu-vos i construïu-hi un parc.{NEWLINE}Autor: Katatude - - -STR_SCNR :Poblet Xu-xu-xú -STR_PARK :Poblet Xu-xu-xú -STR_DTLS :Mamà! Papa! Vull anar al Poblet Xu-xu-xú!{NEWLINE}Autor: Fossil - - -STR_SCNR :Arxipèlag del Drac -STR_PARK :Arxipèlag del Drac -STR_DTLS :Illes del Drac? No estic segur que hi vulgui anar…{NEWLINE}Autor: Fossil - - -STR_SCNR :Carnaval infantil II -STR_PARK :Carnaval infantil -STR_DTLS :Ei, nens! Divertiu-vos!{NEWLINE}Autors: Piehead & Fossil - - -STR_SCNR :Les dunes d’arena -STR_PARK :Les dunes d’arena -STR_DTLS :Com a propietari d’un parc petit, heu comprat una parcel·la enorme al costat de la platja per a expandir i atraure més visitants a les dunes de sorra precioses. Però, aneu amb compte: no podeu pertorbar l’ecologia fràgil de les dunes d’arena.{NEWLINE}Autor: rbarclay diff --git a/data/language/cs-CZ.txt b/data/language/cs-CZ.txt index 22960e6f86..ab04e6905e 100644 --- a/data/language/cs-CZ.txt +++ b/data/language/cs-CZ.txt @@ -3597,302 +3597,3 @@ STR_6524 :Zvýšit prioritu zvoleného balíčku doplňků. STR_6525 :Znovu načítat všechny doplňky ve hře se zapnutými balíčkami doplňků. STR_6526 :(základní grafika, hudba a zvukové efekty) STR_6527 :Soutěže - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Přestavte malý horský ski-resort na sněžný zábavní park - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Postavte letecky-orientovaný zábavní park na tomto opuštěném letišti - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Vaším úkolem je postavit vysoce výnosný zábavní park na tomto rajském ostrově - - -STR_SCNR :Postavte si svůj vlastní Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Postavte si svou vlastní verzi tohoto evropského Six Flags zábavního parku - - -STR_SCNR :Postavte si svůj vlastní Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Využijte svých návrhářských dovedností a vytvořte tento Six Flags zábavní park - - -STR_SCNR :Postavte si svůj vlastní Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Postavte tento evropský Six Flags zábavní park tak, jak jen budete chtít - - -STR_SCNR :Postavte si svůj vlastní Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Postavte si svou vlastní verzi tohoto masivního Six Flags zábavního parku - - -STR_SCNR :Postavte si svůj vlastní Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Postavte atrakce tohoto Six Flags zábavního parku na zelené louce - - -STR_SCNR :Postavte si svůj vlastní Six Flags Park -STR_PARK :Six Flags -STR_DTLS :Postavte si svůj vlastní návrh Six Flags zábavního parku - použijte buď atrakce z jiných Six Flags parků, nebo si navrhněte vlastní - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Začínáte s malým bazarem, přičemž vaším úkolem je zvýšit zisky z obchodů a stánků stavbou nových atrakcí k přilákání nových zákazníků - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :Zdědili jste velký hrad - a vaším úkolem je přeměnit ho na malý zábavní park - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Poblíž pouštního dálničního křížení představuje Dusty Greens možnost přestavět malý golfový resort na vzkvétající zábavní park - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :Zdědili jste malou farmu - a vaším úkolem je postavit malý zábavní park mezi poli a farmářskými budovami - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Bez finančních omezení - vaším úkolem je rozšířit tento pouštní zábavní park pro přilákání většího počtu návštěvníků, vyhledávajících pořádnou dávku adrenalinu - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Opuštěný tovární komplex nabízí možnost postavit mechanicky-zaměřený zábavní park - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Omezeni pouze na starší, dřevěné, dráhy, postavte vzkvétající zábavní park ve Fungus Woods - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Velký řetěze zábavních parků si vás najal, abyste postavili obrovský zábavní park plný horských drah v okolí opuštěného důlního městečka - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Postavte zábavní park s horskými drahami v nádherných Gravity Gardens - Jen horské dráhy, nic jiného! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :Zábavní park, postavený na úpatní neklidné sopky - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :S neomezenými financemi v nesnadném terénu okolo jezera - bude obtížné zábavní park dále rozšiřovat - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Zábavní park vybudovaný na straně kopce má zakázány výškové stavby. Dokážete i přes to park rozšířit a dosáhnout úspěchu? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Vyzkoušejte si provoz a vylepšování tohoto Six Flags zábavního parku - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Postavte chybějící Six Flags atrakce, nebo vytvořte své vlastní! Nezapomeňte ale na hlavní cíl - přilákat co nejvíce návštěvníků! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Vyzkoušejte si provoz a vylepšování tohoto Six Flags zábavního parku - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Postavte chybějící Six Flags atrakce, nebo vytvořte své vlastní! Nezapomeňte ale na hlavní cíl - vyrovnat dluhy bez propadu hodnoty parku! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Postavte chybějící Six Flags atrakce, nebo vytvořte své vlastní! Nezapomeňte ale na hlavní cíl - přilákat co nejvíce návštěvníků! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :Zdědili jste diamantový důl mimo provoz a nalezli hodnotný diamant. Rozhodli jste se tedy investovat peníze do stavby světoznámého zábavního parku. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :Byla objevena pouštní oáza, která nabízí nádherné místo pro zábavní park. Přeprava do oázy zajištěna. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :Postavená přehrada zajišťuje velké množství levné hydroelektrické energie pro váš zábavní park. Dosáhněte vysokého hodnocení parku, abyste snáze splatili půjčku na přehradu. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :Obrátili se na vás ochranáři životního prostředí s prosbou, abyste přeměnili neekologickou rafinerii na vysoce navštěvovanou turistickou destinací. Pozemky jsou levné, ale úrok z půjčky vysoký. Zkuste prodat staré budovy. - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :Místní správa se rozhodla podpořit cestovní ruch a vytvořit Velkou zeď stavbou přilehlého zábavního parku. Peníze nehrají roli. - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :Současnému zábavnímu parku došlo místo. Jedinou možností je začít stavět na moři, takže budete potřebovat velkou půjčku. V této oblasti jsou častá zemětřesení, proto nesmíte stavět vysoké budovy. - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :Mahárádža vás vybral, abyste přinesli zábavu pro místní velkou populaci. Postavte zábavní park inspirovaný Mahárádžovým palácem - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :Pomáháte domorodcům postavit zábavní park pro upozornění na jejich kulturu. Musíte poučit co nejvíce lidí o unikátní kultuře domorodých obyvatel. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :Místní mořský svět bankrotoval a vy jste ho odkoupili. Vám už ale jeden malý park patří - postavte tedy ze dvou malých parků jeden obrovský! - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :Byli jste přizváni, abyste převzali kontrolu nad Evropskou Kulturní Návštěvnickou Atrakcí a musíte zajistit nárůst návštěvnosti, jinak nebudete moci zaplatit za EU dotaci do konce vládního období. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :Evropská Unie vám dala grant, abyste zajistil obnovu starého, neudržovaného zábavního parku a přinesl zpět jeho tehdejší slávu. Musíte celý park renovovat a splatit grant. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :Havajané jsou znudění ze surfování a chtějí zažít něco adrenalinovějšího. Postavte zábavní park a nezapomeňte na to - pomůže vám to s dosažením dobrého hodnocení parku. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :Omezený terén vás nutí vybudovat zábavní park po stranách národní památky. Můžete ale od Indiánů nakupovat pozemky. Abyste si udrželi hodnocení místní správy, splňte cíl! - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :Jste úspěšný obchodní magnát, který si přeje přetvořit městský park v místo nebeských horských drah. Peníze nehrají žádnou roli! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :Abyste zvýšili počet místních turistů, musíte postavit zábavní park, který zapadá do okolí a nemá žádné výškové budovy. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Prostor je limitovaný drahocenným deštným pralesem - musíte toho namáčknout co nejvíce do dosavadních pozemků, abyste mohli konkurovat místním dřevorubeckým společnostem. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :Provozujete malý zábavní park poblíž Ria, ale banka chce vrátit půjčku. Musíte rychle zvýšit vaše příjmy, abyste mohli dluh splatit. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Členové místní skupiny pro rekonstrukci historických bitev berou své hobby trochu moc vážně. Svěřili vám stavbu starověkého zábavního parku na území Cliffside Castle. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :Abyste mohli brát bohatým a dávat chudým, rozhodli jste se postavit zábavní park v Sherwood Forest. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Byl objeven život na vzdálené planetě. Postavte mimozemsky zaměřený zábavní park, abyste se svezli na vlně nového nepředvídaného zájmu. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Ukažte svou vynalézavou, utopickou vizi budoucnosti - přijďte s futuristickým zábavním parkem, který zahrnuje ty nejnovější atrakce. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :Byl vám zadán úkol správy a vylepšování stávajícího zábavního parku, který byl postaven na starém filmařském místě. Vybudujte odkaz průkopníkům-animátorům, kteří poprvé přinesli mýtické postavy k životu na stříbrném plátně. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :Vlastníte ostrov velké archeologické hodnoty. Rozhodli jste se podpořit jeho zachování vybudováním zábavního parku založeném na mytologii tohoto místa. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :Vlastníte velký kráter a jakožto opravdový průkopník jste se rozhodl vybudovat zábavní park ve stylu asteroidů a přeměnit tuto zdánlivě bezcennou půdu v profitující a vyhledávanou oblast. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :Byli jste zaúkolováni stavbou zábavního parku ve stylu období Jura. Pro zlepšení přístupu návštěvníků k exotickým rostlinám a zvířatům budete muset postavit mosty do a přes údolí. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :Abyste se vyhnuli stavbě dálnice a zachovali mysteriózní prehistorické kamenné kruhy, budete muset postavit zábavní park ve stylu doby kamenné a začít vydělávat. Nicméně přilákat návštěvníky bude těžké, protože terén je opravdu nehostinný. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :Nechvalně proslavená ostrovní věznice - jejíž populace jednou překypovala pašeráky a vyděrači - je nyní na prodej. Rozhodli jste se jí přetvořit na velkou turistickou atrakci - na peníze berte ohled! - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :75. leté výročí výhry Schneider Cup vašeho dědečka se blíží a zbývá už jen pár let. Poctíte jeho úspěch stavbou zábavního parku založeném na proslulém závodu hydroplánů. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :Vlastníte volný pozemek v městské oblasti téměř bez růstu. Abyste vymačkali co nejvíce z vaší nemovitosti, postavíte mrakodrap-zábavní park inspirovaný architekturou dvacátých let. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Obrovský každoroční hudební festival se bude konat na vašem pozemku. Postavte pořádný park, abyste zabavili návštěvníky. - - -STR_SCNR :Rock ’n’ Roll Revival -STR_PARK :Rock ’n’ Roll Revival -STR_DTLS :Tento stárnoucí zábavní park už viděl lepší dny. Pomozte majiteli dát parku retro rock ’n’ roll vzhled a udělat z něho vyhledávané místo. - - -STR_SCNR :Panda World -STR_PARK :Panda World -STR_DTLS :Přidejte další atrakce a přilákejte více lidí do pandího zábavního parku. diff --git a/data/language/da-DK.txt b/data/language/da-DK.txt index cd64327029..70876baf36 100644 --- a/data/language/da-DK.txt +++ b/data/language/da-DK.txt @@ -3690,850 +3690,3 @@ STR_6619 :Objekttype kan ikke begrænses! STR_6620 :Objektet blev ikke fundet! STR_6621 :Begræns STR_6622 :Begræns objekt til scenarieeditoren og sandkassetilstanden. - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Dybt inde i skoven, Byg en blomstrende forlystelsespark i et stort ryddet område - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :BDenne forlystelsespark, der er bygget midt i ørkenen, indeholder kun en rutschebane, men har plads til udvidelser - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Start fra bunden, Byg en forlystelsespark omkring en stor sø - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights er allerede en succesfuld forlystelsespark med store forlystelser. Forbedre den til at fordoble sin værdi - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Konverter den smukke ‘Evergreen Gardens’ om til en blomstrende forlystelsespark - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Udvikl Bumbly Beach’s lille park i en blomstrende forlystelsespark - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Flere øer danner grundlag for denne nye forlystelsespark - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :En lille forlystelsespark med et par forlystelser og plads til udvidelser - Dit mål er at fordoble parkens værdi - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :En lille, trang forlystelsespark, som kræver større udvidelse - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :En park med nogle fremragende vand-baserede forlystelser, kræver udvidelse - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Konverter en stor forladt mine fra en turistattraktion i en forlystelsespark - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :En stor park skjult i skoven, med kun Go-Kart bane og træ rutschebaner - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :Denne forlystelsespark har nogle godt designede moderne forlystelser, men masser af plads til udvidelse - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :I de bjergrige skove i Mystic Mountain, Byg en forlystelsespark fra bunden - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Konverter turistattraktion, egyptiske ruiner til en blomstrende forlystelsespark - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :En stor park med godt designet, men med gamle forlystelser - Erstat de gamle forlystelser eller tilføj nye forlystelser, for at gøre parken mere populær - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Konverter denne søvnige bys mole til en blomstrende attraktion - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :De smukke bjerge ‘Lightning Peaks’ er populære hos vandrere og turister - brug de tilgængelige jord til at tiltrække nyt spændings-søgende klientel - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :En veletableret Park, som har et par problemer - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Rainbow Valley lokale myndighed vil ikke tillade nogen landskabsændringer eller store træ rydninger, men du skal udvikle området til en stor forlystelsespark - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder rock står i midten af en ørken og tiltrækker mange turister - Brug den tilgængelige plads til at bygge forlystelser, for at tiltrække flere mennesker - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Kun for sjov! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Udvikel denne klippe ud mod havet, til en blomstrende forlystelsespark - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Centralt i denne store udviklingspark, er en kæmpe tredobbelt-Track Racing/Duelling stål rutchebane - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Denne forladte mine er allerede en turistattraktion med sin miniature jernbane og et par lodrette fald rutschebaner - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :Få denne gamle udtjente bro, til at udvikle sig til en forlystelsespark - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Med land begge sider af en motorvej, har denne park allerede flere fungerende forlystelser - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :De lokale myndigheder har indvilliget i at sælge nærliggende land billigt, til denne lille kystpark, på betingelse af, at visse forlystelser bliver bevaret - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Denne borg, kan du forvandle til en forlystelspark - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Denne futuristiske forlystelsespark, har masser af plads til nye forlystelser på sit fremmede landskab - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :Den lokale befolkning foretrækker blide og afslappende forlystelser, så det er dit job at udvide denne forlystelsespark, så den passer til deres smag - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Dybt inde i junglen ligger et stort landområde, klar til at blive omdannet til en forlystelsespark - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :En række forskudte søer, danner grundlaget for denne nye forlystelsespark - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Denne aldrene Park har mange historiske forlystelser, men er forgældet - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Et stort område af jord er blevet ryddet og delvist tematiseret, klar til at udvikle sig til en anlagt forlystelsespark - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :En blomstrende frugt gård har bygget en jernbane for at øge sin indkomst, dit job er at udvikle det til en lækker forlystelsespark - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Området omkring en dæmning er til rådighed for dig, til at udvikle en forlystelsespark - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :En stor kløft er din, til at forvandle den til en forlystelsespark - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :Vejret er så vådt her, at der er bygget en gigantisk pyramide, for at nogle forlystelser kan blive bygget under den. - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :Den lokale myndighed vil ikke tillade dig at bygge over træ højde i denne forlystelsespark - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Udvikl denne forlystelsespark med et romersk tema, ved at tilføje forlystelser og rutschebaner - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Bygget delvist på en række små øer, har denne forlystelsespark allerede et par store rutschebaner som sit centrum - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Byg en Park for at appellere til den højintensive, gys-søgende, lokale folk - - -STR_SCNR :Utopia Park -STR_PARK :Utopia Park -STR_DTLS :En oase midt i ørkenen giver en usædvanlig mulighed for at bygge en forlystelsespark - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Overgroet og nedslidt, kan du genoplive denne en gang store forlystelsespark? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Fuld af dårligt designede og farlige forlystelser, har du et meget begrænset budget og tid, til at løse problemerne og vende parken rundt - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :De lokale myndigheder vil ikke tillade nogen form for reklame eller forfremmelse, så denne forlystelsespark skal lykkes udelukkende på omdømme - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :En fire sporet hestevæddeløbs bane er kernen i denne ekspanderende forlystelsespark - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Forvandel dette forladte stenbrud, til et sted til at tiltrække gys-søgende turister - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Du har begrænsede midler, men ubegrænset tid til at vende dette bjergområde til en stor rutschebane forlystelsespark - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :En lille forlystelsespark har lavet en aftale, med den nærliggende by, for at tillade ekspansion, gennem selve byen - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :En stor have park skal forvandles til en blomstrende forlystelsespark - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :En samling af isbjerge udgør en kold ramme for denne ambitiøse forlystelsespark - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :En sovende vulkan er hovedtemaet af denne coaster-bygning udfordring - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Fri for eventuelle finansielle grænser, din udfordring er at udvikle denne ørken park og samtidig holde gæsterne glade - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Din opgave er at bygge en massiv coaster-fyldt park i blandt Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :En stor sø i et gammelt krater er hovedtemaet denne park - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Denne store park har allerede en fremragende hyper-coaster, men din opgave er at øge fortjenesten massivt - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier har udvidet sit netværk af gangbroer ud over havet, og din opgave er at udvide parken, for at udnytte den ekstra plads - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :Denne bugt ved havet udgør rammen om denne coaster-bygning udfordring - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Et slot med et par rutschebaner har behov udvikle sig til en større forlystelsespark - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :En park, der har mange af sine stier og rutchebaner under jorden - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :En gletscherfyldt dal er din, til at udvikle sig til en forlystelsespark - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :I en fjern verden, hvor der ikke er brug for penge, skal du bygge et underholdningscenter for at holde folk glade - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Fem rutchebaner skal laves færdig, i denne ørkenpark - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :I denne historiske park er kun tilladt at bygge gammeldags forlystelser - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Udvikel denne rumvæsen park til at maksimere fortjenesten - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :Denne velusmykket forlystelsespark har allerede adskillige forlystelser, men der er masser af plads til udvidelse - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :En skræmmende park, med en gigantisk rutchebane i centrum - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :To store klipper stikker frem fra sandet, hvorpå der er påbegyndt en forlystelsespark - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :I denne store park skal du designe og bygge ti store rutchebaner - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :En lang tynd ø uggør en udfordrende ramme til at konstruere et udvalg af rutchebaner - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Et iskoldt landskab, skal blive til en blomstrende forlystelsespark - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :En ørkenpark med nogle smart designede rutchebaner, er klar til at du udvikler den - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :I denne lille forlystelsespark skal du færdigbygge de fem eksisterende rutschebaner - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :En stor park med et gammelt transportsystem langs kanten - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Denne store ø er klar til at du udvikler den til en forlystelsespark - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :En kæmpe forladt skyskraber er en enestående mulighed for en forlystelsespark udvikler - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Dette byområde er klar til at udvikle sig til en forlystelsespark - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :En kæmpe forlystelses som allerede er fuld af forlystelser, med et behov for forbedringer - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :På en planet langt væk, har dette landområde har brug for at blive til en forlystelsespark - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Prøv at skabe verdens mindste rentable Park - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS :Forlystelsespark der ligger i Alton, Staffordshire i England - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS :Stor park der ligger i det nordlige Tyskland - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS :Forlystelsespark der ligger i Blackpool, Lancashire i England - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Konverter et lille bjerg ski ressort, til en park med sne som tema - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Byg en forlystelsespark med luftfart som tema, i en forladt lufthavn. - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Din udfordring, er at bygge en højt profitabel forlystelsespark, på denne paradisø - - -STR_SCNR :Build your own Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Byg din egen version af denne europæiske ‘Six Flags’ park - - -STR_SCNR :Build your own Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Brug dine designer evner, til at genopbygge denne ‘Six Flags’ forlystelsespark - - -STR_SCNR :Build your own Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Byg denne europæiske ‘Six Flags’ forlystelsespark på din helt egen måde - - -STR_SCNR :Build your own Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Lav din egen version af denne enorme Six Flags park - - -STR_SCNR :Build your own Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Start fra bunden, byg forlystelserne i denne Six Flags park - - -STR_SCNR :Build your own Six Flags Park -STR_PARK :Six Flags -STR_DTLS :Byg dit eget Six Flags park design - Enten ved at bygge forlystelser fra andre Six Flags parker eller ved at designe og bygge dine egne forlystelser - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Du starter med en lille markeds bazaar, din udfordring er at forøge indtjeningen fra butikker og boder, ved at bygge forlystelser og rutschebaner for at tiltrække flere kunder - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :Du har arvet et kæmpe stort slot - Din opgave er at udvikle det til en lille forlystelsespark - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Dusty Greens ligger i nærheden af et motorvejskryds i ørkenen, og har mulighed for at udvikle sig, fra et lille golfresort, til en blomstrende forlystelsespark - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :Du har arvet en lille gård, og din udfordring er at bygge en lille forlystelsespark, blandt marker og landbrugsbygninger - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Fri for økonomiske begrænsninger, din udfordring er at udvide denne ørkenpark for at tiltrække folk, der søger den ultimative spænding - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Et forladt fabrikskompleks, er en mulighed for at bygge en forlystelsespark med mekanisk tema - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Begrænset til kun ældre træ forlystelser, er din udfordring at bygge en blomstrende forlystelsespark, i Fungus Woods - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Hyret af en stor forlystelsespark kæde, din opgave er at bygge dem en kæmpe rutschebane park omkring en forladt mineby - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Din udfordring er at bygge en rutschebanepark i den smukke Gravity Gardens - Ingen andre forlystelser, udelukkende rutschebaner! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :En park beliggende usikkert på lava sten med strømme af magma - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :Med ubegrænsede midler, men en udfordrende søplacering, vil denne park være en udfordring at udvide og administrere - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Bygget på en bjergskråning, er denne park forbudt at bygge noget højt. Kan du udvide parken og gøre den vellykket? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Prøv på egen hånd, at drive og forbedre denne Six Flags park - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Byg de manglende Six Flags, eller opret dine egne designs for at forbedre parken! Men glem ikke dit ultimative mål - At tiltrække flere gæster til parken! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Prøv på egen hånd at drive og forbedre denne Six Flags park - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Byg de manglende Six Flags forlystelser, eller opret dine egne designs for at forbedre parken! Men glem ikke dit ultimative mål - At tilbagebetale dit lån og samtidig holde parkens værdi oppe! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Byg de manglende Six Flags forlystelser, eller opret dine egne designs for at forbedre parken! Men glem ikke dit ultimative mål - Tiltrække flere gæster til parken! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :Du arvede en nedlagt diamantmine og fandt en værdifuld diamant. Du beslutter dig for at investere de penge til at bygge en verdensberømt forlystelsespark. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :En ørken oase er blevet opdaget og ville være en smuk beliggenhed for en park. Der er sørget for transport til oasen. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :En dæmning er blevet bygget, som tilbyder rigelige, billige vandkraft til at drive en park. Du er nødt til at nå en høj park værdi for at hjælpe med tilbagebetalingen af lånet til dæmningen. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :Miljøagenturet har henvendt sig til dig for at omdanne et gammelt olieraffinaderi økologisk ‘øjebæ’ til en top turistattraktion. Jord er billigt, men lånerenterne er høje. Du kan sælge de gamle bygninger til genanvendelse. - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :Myndighederne har besluttet at forbedre turismen omkring Den Kinesiske Mur ved at bygge en forlystelsespark på den tilstødende jord. Penge er ikke noget problem! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :En eksisterende park er løbet tør for plads. Din eneste mulighed er at bygge ud i havet, og så har du taget et lån. Højdebegrænsninger på din bygning håndhæves på grund af fundamenter og jordskælvsrisiko. - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :Du er blevet bestilt af Maharajaen til at bringe underholdning til den store lokale befolkning. Byg en park inspireret af Maharajas palads. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :Du hjælper aboriginal folk, til at bygge en park, som en del af en kulturel bevidsthed program. Du skal få et stort antal gæster, til at uddanne dem i den unikke arv af det oprindelige folk. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :En lokal iværksætters havlivs park er gået fallit. Du driver allerede en lille park og køber den anden park fra byggefirmaet. Udvikl den til en stor kombineret park. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :De er blevet hentet ind for at overtage, en europæisk kulturel turistattraktion, og skal øge antallet af gæster, for at kunne betale EU-tilskuddet tilbage, inden udgangen af den nuværende valgperiode i Europa-Parlamentet. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :En gammel park er gået i forfald. De får et EU-tilskud til at bringe dette ugunstigt stillede område, tilbage til sin tidligere herlighed! Du er nødt til at renovere parken, og tilbagebetale tilskuddet. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :Befolkningen i Hawaii er træt af surfing, og er på udkig efter noget mere intenst. Du skal bygge en park, med dette i tankerne for at holde områdets turistattraktion rating i top. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :Du er nødt til at bygge en park på begrænset jord, på hver side af denne naturlige skat - du har mulighed for at købe nabojord fra indianerne. Du er nødt til at fuldføre målet om at opretholde den lokale bys befolkning. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :Du er en succesfuld forretningsmagnat igang med flere sabbatår, der ønsker at bruge denne tid på at omdanne byparken til Rollercoaster Heaven. Penge er ikke noget problem! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :For yderligere at øge den lokale turisme skal du konstruere en park, der er i harmoni med sine omgivelser. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Pladsen er begrænset i den dyrebare regnskov - du skal proppe så meget som muligt ind i den eksisterende rydning for at give et levedygtigt alternativ til den lokale træindustri. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :Du driver en lille park nær Rio, men banken har indkaldt dit lån. Du er nødt til hurtigt at øge din indtjeningsevne, til at tilbagebetale denne uventede gæld. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Lokale medlemmer af kamp re-enactment samfundet er temmelig alvorligt om deres hobby. De har betroet dig opgaven med at bygge en mørk tidsalder forlystelsespark på grunden ved Cliffside Castle. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :For at befri rigdom fra de rige og distribuere den til de trængende, har du og dine lystige svende besluttet at bygge en forlystelsespark i Sherwood Skoven. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Der er fundet liv på en fjern planet. Byg en Rumalien forlystelsespark til at lave penge på den hidtil usete bølge af interesse. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Vis din opfindsomme, utopiske vision om fremtiden - kom op med et futuristisk parkdesign, der inkorporerer state-of-the-art attraktioner. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :Du har fået til opgave at drive og forbedre en eksisterende forlystelsespark, som er bygget på et gammelt filmsæt. Byg en hyldest til de banebrydende stop-motion animatorer, der først bragte mytiske væsner til live på biograflærredet. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :Du ejer en ø af særlig arkæologisk værdi. Du har besluttet at finansiere dens bevarelse, ved at bygge en forlystelsespark baseret på områdets rige mytologiske arv. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :Du ejer et støvet gammelt meteorkrater. I den sande iværksætterånd har du besluttet at konstruere en asteroide forlystelsespark og konvertere dit tilsyneladende værdiløse land til en betydelig formue. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :Du har fået til opgave at bygge en Jurassic æra forlystelsespark. For at optimere dine besøgendes adgang til de eksotiske plante- og dyreudstillinger skal du bygge en bygning, der går over og ind i dalen. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :For at forpurre motorvejsudviklerne og bevare de mystiske gamle stencirkler skal du konstruere en stenalder forlystelsespark og lave en fortjeneste. Det kan dog være en udfordring at tiltrække besøgende, da terrænet er en smule ugæstfrit. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :Den berygtede Prison Island - hvis befolkning engang husede organiseret kriminalitet og hjemmebrændere - er nu til salg. Du har besluttet at konvertere det til en top turistattraktion, og penge er ikke noget problem. - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :T75-årsdagen for din bedstefars Schneider Cup-sejr kommer op om et par år. Du vil ære hans præstation ved at bygge en forlystelsespark baseret på den berømte vandflyver racer. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :Du ejer en tom grund i nærheden af den lave del af byen. For at presse mest muligt ud af din byejendom skal du bygge en skyskraber forlystelsespark inspireret af den skyhøje art deco arkitektur i tyverne. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :En stor årlig musikfestival finder sted på dit land. Byg en hip forlystelsespark for at holde det frisindede publikum underholdt. - - -STR_SCNR :Rock ’n’ Roll Revival -STR_PARK :Rock ’n’ Roll Revival -STR_DTLS :Denne aldrende forlystelsespark har set bedre dage. Hjælp ejeren med at give det en retro rock ’n’ roll makeover og gøre stedet til et vellykket sted. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Panda World -STR_PARK :Panda World -STR_DTLS :Tilføj flere forlystelser, og tiltræk flere besøgende til denne panda-tema park - - -STR_SCNR :Tycoon Park -STR_PARK :Tycoon Park -STR_DTLS : - -### - -STR_SCNR :Cemetery Ridge -STR_PARK :Cemetery Ridge -STR_DTLS :Dette er Halloween, UCES Halloween, græskar skriger i nattens mulm og mørke! Denne kirkegård er i problemer, og det er op til dig at redde den, mens du lader de døde hvile i fred! Kan du holde spøgelserne i deres grave og give de besøgende kuldegysninger?{NEWLINE}Forfatter: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :The Lighthouse of Alexandria -STR_PARK :The Lighthouse of Alexandria -STR_DTLS :Alexander byggede byen; Grækere, romere, egyptere satte deres præg. Men den største ære var et vidunder i den antikke verden - fyret. Besøg og lav en park!{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Som den var på åbningsdagen - 18. Maj 1905.{NEWLINE}Forfatter: Aetherwave - - -STR_SCNR :Mount Vesuvius -STR_PARK :Mount Vesuvius -STR_DTLS :Pompeji og Herculaneum blev begravet af Mt. Vesuvius i 79 e.Kr. Besøg udgravningerne og byg en park!{NEWLINE}Forfatter: Katatude - - -STR_SCNR :The Sandbox -STR_PARK :The Sandbox -STR_DTLS :Hvad alle vil have - en sandkasse! Så grib din lille spand og skovl og byg en park!{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Niagara Falls & Gorge -STR_PARK :Niagara Falls -STR_DTLS :American Falls, Bridal Falls & Canadian Horseshoe Falls på Niagara Frontier, 1850.{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Rocky Mountain Miners -STR_PARK :Rocky Mountain Miners -STR_DTLS :Et stenskred beskadigede din jernbane. Dine arbejdere er gået på guldjagt. Er der guld i rutsjebaner?{NEWLINE}Forfattere: Squid, Buckone, Fossil - - -STR_SCNR :The Time Machine -STR_PARK :The Time Machine -STR_DTLS :Tidsmaskinen. Byg med på farten – når du vil, hvor du vil. Evigheden venter. Alt er relativt.{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Tower of Babel -STR_PARK :Tower of Babel -STR_DTLS :Hovsa! Se, hvor tidsmaskinen tog os til nu! Hvor forsvandt alle hen?{NEWLINE}Forfatter: Fossil - - -STR_SCNR :Transformation -STR_PARK :Transformation -STR_DTLS :Vi har ventet dig…{NEWLINE}Forfatter: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :Romerne er trætte af kedelige gladiatorkampe. Giv dem mere spænding, lav en romersk by om til den største forlystelsespark nogensinde!{NEWLINE}Forfatter: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Beneath the Christmas Tree -STR_PARK :Winter Wonderland -STR_DTLS :Mor byggede denne scene under vores træ. Nu vil hun have lavet en park i den! Kan du hjælpe?{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Bigrock Blast -STR_PARK :Bigrock Blast -STR_DTLS :Efter en eksplosion på Bigrock Mining Co. er befolkningen i Bigrock nødt til at bygge en forlystelsespark for at holde deres by i live.{NEWLINE}Forfattere: rbarclay & buckone - - -STR_SCNR :Camp Mockingbird -STR_PARK :Camp Mockingbird -STR_DTLS :Kun 500$ om ugen til denne sommerlejr! Bryd din sparegris op, og hav det derefter sjovt og byg en park.{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Choo-Choo Town -STR_PARK :Choo-Choo Town -STR_DTLS :Mor! Far! Jeg vil til Fut-Fut by!{NEWLINE}Forfatter: Fossil - - -STR_SCNR :Dragon Islands -STR_PARK :Dragon Islands -STR_DTLS :Drageøen? Jeg er ikke sikker på at jeg vil derhen…{NEWLINE}Forfatter: Fossil - - -STR_SCNR :Kiddie Karnival II -STR_PARK :Kiddie Karnival -STR_DTLS :Hej Unger, Lad os have det sjovt!{NEWLINE}Forfattere: Piehead & Fossil - - -STR_SCNR :Sand Dune -STR_PARK :Sand Dune -STR_DTLS :Som ejer af en lille park, købte du et stort stykke jord langs stranden for at udvide og tiltrække flere gæster til at besøge de smukke klitter, men pas på, du må ikke forstyrre de økologisk skrøbelige klitter.{NEWLINE}Forfatter: rbarclay diff --git a/data/language/de-DE.txt b/data/language/de-DE.txt index c3e87031fa..a7a99efc9d 100644 --- a/data/language/de-DE.txt +++ b/data/language/de-DE.txt @@ -3775,860 +3775,3 @@ STR_6706 :{WINDOW_COLOUR_2}Aktuelle Bilddatei: {BLACK}{STRING} STR_6707 :(keine ausgewählt) STR_6708 :Weiche Stärke STR_6709 :Weiche Stärke zwischen {COMMA16} und {COMMA16} eingeben - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Bauen Sie tief im Wald auf einem großen freigelegten Gelände einen erfolgreichen Freizeitpark. - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Dieser Freizeitpark inmitten der Wüste besitzt nur eine Achterbahn, hat aber genug Platz für Erweiterungen. - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Fangen Sie bei Null an und bauen Sie einen Freizeitpark um einen großen See herum. - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights ist bereits ein erfolgreicher Freizeitpark mit tollen Attraktionen. Entwickeln Sie ihn weiter und verdoppeln Sie seinen Verkehrswert. - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Wandeln Sie die schönen Evergreen Gardens in einen gut besuchten Freizeitpark um. - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Machen Sie aus dem kleinen Vergnügungspark Bumbly Beach einen florierenden Freizeitpark. - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Mehrere Inseln bilden den Ausgangspunkt für diesen neuen Park. - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :Ein kleiner Freizeitpark mit wenigen Attraktionen, aber genug Gelände zur Erweiterung. Ihr Ziel ist es, den Verkehrswert des Parks zu verdoppeln. - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :Ein kleiner, eng zusammengedrängter Vergnügungspark, bei dem eine Erweiterung in großem Ausmaß erforderlich ist. - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :Dieser Park mit verschiedenen hervorragenden Wasser-Attraktionen hat einen Ausbau nötig. - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Machen Sie einen Freizeitpark aus dieser weitläufigen, verlassenen Mine, die zur Zeit nur von Touristen besichtigt wird. - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :Ein großer Park, versteckt im Wald gelegen, der nur Gokartbahnen und Holzachterbahnen aufzuweisen hat. - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :Dieser Freizeitpark verfügt über ein paar ausgezeichnete moderne Attraktionen und jede Menge Platz für Erweiterungen. - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :Bauen Sie in den bergigen Wäldern der Mystic Mountains einen neuen Freizeitpark. - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Verwandeln Sie die Touristenattraktion mit ägyptischen Ruinen in einen erfolgreichen Freizeitpark. - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :Ein großer Park mit guten, aber ziemlich alten Attraktionen. Ersetzen Sie die alten Attraktionen oder fügen Sie neue hinzu, damit der Park mehr Leute anzieht. - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Verwandeln Sie die Anlegestelle dieser verschlafenen Stadt in einen wohlbekannten und gutgehenden Anziehungspunkt. - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :Die herrlichen Berge von Lightning Peaks sind beliebt bei Wanderern und Leuten, die gern interessante Orte besichtigen. Nutzen Sie das zur Verfügung stehende Gelände, um jene Besucher anzulocken, die auf der Suche nach einem aufregenden Kick sind. - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :Ein gut geführter Park, der jedoch ein paar Probleme hat. - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Die örtlichen Behörden von Rainbow Valley werden landschaftliche Veränderungen oder größere Baumrodungen nicht erlauben, aber Sie sollen in dem Gebiet einen großen Freizeitpark entstehen lassen. - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock befindet sich mitten in einer Wüste und zieht viele Touristen an. Bauen Sie auf dem verfügbaren Platz Attraktionen, die noch mehr Leute herlocken. - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Nur zum Spaß! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Lassen Sie in diesen Klippen am Meer einen florierenden Vergnügungspark entstehen. - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Mitten in diesem großen, aufstrebenden Park steht eine riesige Dreispur-Achterbahn, in der die Fahrt wie ein Kopf-an-Kopf-Rennen abläuft. - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Dieses verlassene Bergwerk bietet mit der Miniatureisenbahn und den Sturzachterbahnen bereits gute Voraussetzungen, eine Touristenattraktion zu werden. - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :Wandeln Sie eine alte, nicht mehr benutzte Brücke in einen attraktiven Park um. - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :In diesem Park zu beiden Seiten einer Autobahn sind bereits verschiedene Attraktionen in Betrieb. - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :Die örtlichen Behörden haben zugestimmt, dem kleinen Park an der Küste umliegendes Gelände günstig zu verkaufen, unter der Bedingung, dass bestimmte Attraktionen erhalten werden. - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Sie können Ihrer Fantasie freien Lauf lassen, damit ein Themenpark aus diesem Schloss entsteht. - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Dieser futuristische Park bietet auf seinem fremdartigen Gelände viel Platz für neue Attraktionen. - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :Die Bevölkerung in der Umgebung bevorzugt gemäßigte Attraktionen, auf denen man sich erholen kann. Ihre Aufgabe ist es, diesen Ansprüchen gerecht zu werden. - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Ein riesiges Gelände tief im Dschungel wartet darauf, von Ihnen in einen Themenpark umgewandelt zu werden. - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :Eine Reihe terrassenförmig angeordneter Seen sind der Ausgangsort für den neuen Park. - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Dieser ältere Park besitzt viele historisch interessante Attraktionen, ist aber hoch verschuldet. - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Ein großes Gelände wurde freigeräumt und teilweise thematisch gestaltet. Sie sollen daraus einen interessante Themenlandschaft machen. - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :Eine gutgehende Obstplantage hat eine Miniatureisenbahn bauen lassen, um die Einnahmen zu steigern. Entwickeln Sie jetzt daraus einen Vergnügungspark mit allem Drum und Dran. - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Das Gebiet rings um einen Damm steht Ihnen zur Verfügung, damit daraus ein Vergnügungspark entsteht. - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :Ein weitläufiger Canyon steht Ihnen zur Verfügung, um in einen Themenpark verwandelt zu werden. - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :Das Wetter in dieser Gegend ist so feucht, dass bereits eine riesengroße Pyramide gebaut wurde, damit wenigstens einige Attraktionen überdacht sind. - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :Die Baubehörde dieser Gegend erlaubt in diesem Park keine Konstruktionen über Baumhöhe. - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Entwickeln Sie diesen römisch gestalteten Park weiter, indem Sie Achterbahnen und andere Attraktionen hinzufügen. - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Dieser Park, der sich über eine Reihe kleiner Inseln erstreckt, besitzt ein Paar einer großen Achterbahn als Hauptattraktion. - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Bauen Sie einen Park für die Menschen dieser Gegend, die hohe Intensität und Nervenkitzel bevorzugen. - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :Eine Oase inmitten der Wüste ist sicher eine ungewöhnliche Herausforderung für Planer eines Vergnügungsparks. - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Überwuchert und verfallen. Können Sie diesen einst großartigen Vergnügungspark wieder zum Leben erwecken? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Hier gibt es fast nur gefährliche und schlecht geplante Attraktionen. Sie haben nur sehr begrenzte finanzielle Mittel und wenig Zeit, die Probleme zu beheben und den Park umzukrempeln. - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :Die strengen örtlichen Ämter erlauben keinerlei Werbung oder Propaganda. Dieser Park kann also nur durch seinen Ruf zum Erfolg gelangen. - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :Eine vierspurige Bahn mit Renncharakter ist das Herzstück dieses aufstrebenden Parks. - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Verwandeln Sie diesen verlassenen Steinbruch in einen Ort, der Touristen anzieht, die den besonderen Kick suchen. - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Sie haben nur begrenzt Geld, aber jede Menge Zeit, aus diesem Berggelände einen riesigen Achterbahn-Park zu machen. - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :Ein winzig kleiner Park hat mit der nahe gelegenen Stadt vereinbart, dass er sich durch die Stadt hindurch ausbreiten darf. - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :Eine große gepflegte Parkanlage soll in einen erfolgreichen Themenpark umgestaltet werden. - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :Eine Anzahl Eisberge bilden die kalte Umgebung dieses anspruchsvollen Parkprojekts. - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :Ein untätiger Vulkan fordert geradezu heraus, an ihm eine Achterbahnanlage zu bauen. - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Ohne jegliche finanzielle Einschränkungen sollen Sie diesen Wüstenpark ausbauen und dabei die Besucher bei Laune halten. - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Ihre Aufgabe ist es, zwischen den zerklüfteten Felsen einen Park mit dicht gedrängten Achterbahnen zu bauen. - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :Ein großer See in einem alten Krater ist Ausgangspunkt für diesen Park. - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Dieser große Park besitzt bereits eine ausgezeichnete Hyper-Achterbahn, aber Ihre Aufgabe ist es, die Erträge beträchtlich zu steigern. - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier hat sein Netz von Spazierwegen über dem Meer erweitert. Sie sollen den Park erweitern, indem Sie den neu gewonnenen Platz nutzen. - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :Eine Meeresbucht ist der Rahmen für dieses anspruchsvolle Achterbahn-Bauvorhaben. - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Ein Schloss mit ein paar Achterbahnen soll zu einem großen Vergnügungspark entwickelt werden. - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :Ein Park, dessen Gehwege und Achterbahnen größtenteils unterirdisch angelegt sind. - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :Es steht Ihnen ein Gletschertal zur Verfügung, das in einen Vergnügungspark zu verwandeln ist. - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :In einer weit entfernten Welt, wo man Geld nicht braucht, sollen Sie ein Unterhaltungszentrum bauen, damit die Leute glücklich und zufrieden bleiben. - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Fünf Achterbahnen müssen in diesem Wüstenpark fertiggestellt werden. - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :In diesem historischen Park dürfen nur Attraktionen im altmodischen Stil gebaut werden. - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Verbessern Sie diesen außerirdischen Park, damit höchste Erträge erzielt werden. - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :In diesem nach Themen angelegten Park gibt es zwar verschiedene Attraktionen, aber noch viel Platz für Erweiterungen. - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :Ein Gruselpark mit einer Riesenachterbahn als Herzstück. - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Zwei enorme Gesteinsbrocken ragen aus dem Wüstensand, auf denen mit den ersten Bauten für einen Vergnügungspark bereits begonnen wurde. - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :In diesem weitläufigen Park sollen Sie zehn große Achterbahnen entwerfen und konstruieren. - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :Diese lange, schmale Insel ist Anreiz genug, eine Auswahl an Achterbahnen zu errichten. - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Eine Eislandschaft soll in einen florierenden Vergnügungspark verwandelt werden. - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :Ein Park in der Wüste mit ein paar durchdachten Achterbahnen steht Ihnen zur Verfügung und soll erweitert werden. - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :In diesem winzigen Park sollten Sie die fünf angefangenen Achterbahnen fertigstellen. - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :Ein großer Park mit einem neuartigen Transportsystem, das durch die Randbereiche führt. - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Diese große Insel steht zu Ihrer Verfügung, machen Sie einen Vergnügungspark daraus. - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :Ein gigantischer, verlassener Wolkenkratzer ist eine einmalige Gelegenheit für einen Vergnügungsparkbetreiber. - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Aus diesem Stadtgebiet können Sie einen Vergnügungspark zaubern. - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :Ein ausgedehnter Park, der bereits mit Attraktionen vollgepackt ist, bedarf der Verbesserung. - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :Auf einem weit entfernten Planeten soll dieses Stück Land in einen Vergnügungspark umgewandelt werden. - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Versuchen Sie, den kleinsten Park der Welt anzulegen und dabei möglichst viel Gewinn zu erzielen. - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Dach - -## End of OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Bergabenteuer -STR_PARK :Bergabenteuer -STR_DTLS :Verwandeln Sie einen kleinen Bergskiort in einen Schnee-Themenpark - - -STR_SCNR :Amity-Flugplatz -STR_PARK :Amity-Flugplatz -STR_DTLS :Bauen Sie einen Vergnügungspark mit dem Thema „Fliegen“ auf diesem verlassenen Flughafen - - -STR_SCNR :Kahlschlag -STR_PARK :Kahlschlag -STR_DTLS :Ihre Aufgabe besteht darin, einen gewinnträchtigen Park auf dieser paradiesischen Insel zu errichten - - -STR_SCNR :Bauen Sie Ihren eigenen Six Flags Belgien -STR_PARK :Six Flags Belgien -STR_DTLS :Bauen Sie Ihre eigene Version dieses europäischen Six-Flags-Parks - - -STR_SCNR :Bauen Sie Ihr eigenes Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Nutzen Sie Ihre Entwurfsfähigkeiten, um diesen Six-Flags-Park nachzubauen - - -STR_SCNR :Bauen Sie Ihren eigenen Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Bauen Sie diesen europäischen Six-Flags-Park nach Ihren Wünschen - - -STR_SCNR :Bauen Sie Ihren eigenen Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Bauen Sie Ihre eigene Version dieses riesigen Six-Flags-Parks - - -STR_SCNR :Bauen Sie Ihren eigenen Six-Flags-Park -STR_PARK :Six Flags -STR_DTLS :Setzen Sie Ihren eigenen Entwurf eines Six-Flags-Park um. Bauen Sie entweder Bahnen aus anderen Six-Flags-Parks oder entwerfen und bauen Sie Ihre eigenen Bahnen - - -STR_SCNR :Bauen Sie Ihren eigenen Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Sie fangen von vorne an, diesen Six-Flags-Park zu bauen - - -STR_SCNR :Kleinbasar -STR_PARK :Kleinbasar -STR_DTLS :Sie fangen mit einem kleinen Basar an und müssen die Gewinne aus Läden und Ständen steigern, damit Sie Attraktionen und Achterbahnen bauen können, um weitere Kunden anzuziehen - - -STR_SCNR :Verrückte Burg -STR_PARK :Verrückte Burg -STR_DTLS :Sie haben eine große Burg geerbt - Ihr Ziel besteht darin, sie in einen kleinen Themenpark umzubauen. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Dusty Greens liegt in der Nähe eines Autobahnkreuzes in der Wüste und bietet somit die Gelegenheit, einen kleinen Golfort in einen expandierenden Themenpark umzuwandeln - - -STR_SCNR :Elektrische Felder -STR_PARK :Elektrische Felder -STR_DTLS :Sie haben eine kleine Farm geerbt, und Ihre Aufgabe besteht darin, einen kleinen Themenpark zwischen den Feldern und Farmgebäuden zu bauen - - -STR_SCNR :Extreme Höhen -STR_PARK :Extreme Höhen -STR_DTLS :Sie sind frei von finanziellen Einschränkungen und müssen diesen Wüstenpark erweitern, um Menschen anzuziehen, die den ultimativen Kick suchen - - -STR_SCNR :Fabrikkapriolen -STR_PARK :Fabrikkapriolen -STR_DTLS :Ein verlassener Fabrikkomplex bietet die Gelegenheit, einen Vergnügungspark mit einem Maschinenthema zu bauen - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Sie sind ausschließlich auf ältere Holzbahnen beschränkt und müssen einen expandierenden Themenpark in Fungus Woods errichten - - -STR_SCNR :Geisterstadt -STR_PARK :Geisterstadt -STR_DTLS :Sie wurden von einer großen Vergnügungsparkkette angeheuert und müssen für sie einen riesigen Achterbahnpark rings um eine verlassene Minenstadt bauen - - -STR_SCNR :Schwerkraftgärten -STR_PARK :Schwerkraftgärten -STR_DTLS :Ihre Aufgabe besteht darin, einen Achterbahnpark in die schönen Schwerkraftgärten zu bauen. Keine anderen Attraktionen - nur Achterbahnen! - - -STR_SCNR :Höllenaussicht -STR_PARK :Höllenaussicht -STR_DTLS :Ein Park, der sich auf einem gefährlichen Lavafelsen mit Magmaströmen befindet - - -STR_SCNR :Glückssee -STR_PARK :Glückssee -STR_DTLS :Bei den unbegrenzten Geldmitteln aber der herausfordernden Seelage wird es eine große Aufgabe sein, diesen Park zu erweitern und verwalten - - -STR_SCNR :Regenbogen-Gipfel -STR_PARK :Regenbogen-Gipfel -STR_DTLS :Dieser Park wurde auf einem Hügel errichtet, und es darf nichts Hohes darauf gebaut werden. Können Sie den Park vergrößern und ihn zu einem Erfolg machen? - - -STR_SCNR :Six Flags Belgien -STR_PARK :Six Flags Belgien -STR_DTLS :Versuchen Sie sich an der Verwaltung und Verbesserung dieses Six-Flags-Parks - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Bauen Sie die fehlenden Six-Flags-Bahnen, oder erstellen Sie Ihre eigenen Entwürfe, um den Park zu verbessern! Aber vergessen Sie nicht Ihr endgültiges Ziel - mehr Besucher in den Park zu bekommen! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Versuchen Sie sich an der Verwaltung und Verbesserung dieses Six-Flags-Parks - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Bauen Sie die fehlenden Six-Flags-Bahnen, oder erstellen Sie Ihre eigenen Entwürfe, um den Park zu verbessern! Aber vergessen Sie nicht Ihr endgültiges Ziel - das Darlehen zurückzuzahlen und dabei den Verkehrswert hoch zu halten! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Bauen Sie die fehlenden Six-Flags-Bahnen, oder erstellen Sie Ihre eigenen Entwürfe, um den Park zu verbessern! Aber vergessen Sie nicht Ihr endgültiges Ziel - mehr Besucher in den Park zu bekommen! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Die Minen Afrikas -STR_PARK :Die Minen Afrikas -STR_DTLS :Sie haben eine aufgegebene Diamantenmine geerbt und finden einen wertvollen Diamanten. Sie beschließen, das Geld in einen weltberühmten Themenpark zu investieren. - - -STR_SCNR :Fata Morgana -STR_PARK :Fata Morgana -STR_DTLS :In der Wüste wurde eine Oase entdeckt, die der ideale Standort für einen Vergnügungspark wäre. Transportmittel zur Oase wurden zur Verfügung gestellt. - - -STR_SCNR :Über die Kante -STR_PARK :Über die Kante -STR_DTLS :Ein Damm wurde gebaut und erzeugt große Mengen an billigem Strom, mit dem Sie einen Park betreiben können. Sie müssen allerdings einen hohen Park-Verkehrswert erreichen, um das Darlehen für den Damm zurückzahlen zu können. - - -STR_SCNR :Abenteuer im Eis -STR_PARK :Abenteuer im Eis -STR_DTLS :Sie sollen eine alte Ölraffinerie, die den Umweltschützern ein Dorn im Auge ist, in eine erstklassige Touristenattraktion verwandeln. Das Land ist günstig, doch die Darlehenszinsen sind hoch. Sie können aber die alten Gebäude verkaufen. - - -STR_SCNR :Große Mauer von China -STR_PARK :Große Mauer von China -STR_DTLS :Die Behörden haben entschieden, noch mehr Touristen zur Großen Mauer zu locken, und wollen auf einem angrenzenden Gebiet einen Themenpark errichten. Geld spielt keine Rolle - - -STR_SCNR :Okinawa-Küste -STR_PARK :Okinawa-Küste -STR_DTLS :In einem vorhandenen Park herrscht Platzmangel, Sie müssen also dem Meer neues Land abringen. Dafür haben Sie ein Darlehen aufgenommen. Die maximale Bauhöhe ist aufgrund des instabilen Untergrunds und der Erdbeben beschränkt. - - -STR_SCNR :Maharadscha-Park -STR_PARK :Maharadscha-Park -STR_DTLS :Der Maharadscha hat Sie damit beauftragt, die örtlichen Massen zu unterhalten. Errichten Sie einen Park, der seine Inspiration aus dem Palast des Maharadschas bezieht. - - -STR_SCNR :Ayers-Abenteuer -STR_PARK :Ayers-Abenteuer -STR_DTLS :Sie helfen den Aborigines, im Rahmen eines Programms zur Kulturförderung einen Vergnügungspark zu bauen. Sie müssen eine große Besucherzahl erreichen, um den Leuten das einzigartige kulturelle Erbe der Aborigines nahe zu bringen. - - -STR_SCNR :Strand-Party -STR_PARK :Strand-Party -STR_DTLS :Der Meerespark eines örtlichen Unternehmers hat Bankrott gemacht. Sie besitzen bereits einen kleinen Park und möchten den anderen dazukaufen. Um die benötigten Gelder aufzutreiben, müssen Sie zunächst Ihren kleinen Park ausbauen. - - -STR_SCNR :Europäisches Happening -STR_PARK :Europäisches Happening -STR_DTLS :Sie wurden engagiert, um eine kulturelle Besucherattraktion in Europa zu leiten, und müssen die Anzahl der Gäste steigern, um die EU-Subventionen bis zum Ende der Amtsperiode des aktuellen Europäischen Parlaments zurückzahlen zu können. - - -STR_SCNR :Wie Phönix aus der Asche -STR_PARK :Wie Phönix aus der Asche -STR_DTLS :Ein alter Vergnügungspark befindet sich in desolatem Zustand. Sie erhalten EU-Fördermittel, um dem verwahrlosten Gebiet wieder zu seinem früheren Glanz zu verhelfen. Sie müssen den Park renovieren und die Fördermittel zurückzahlen. - - -STR_SCNR :Verrücktes Waikiki -STR_PARK :Verrücktes Waikiki -STR_DTLS :Die Bevölkerung von Hawaii hat das Surfen satt und sehnt sich nach etwas Abwechslung. Sie müssen einen Park bauen, um sie bei Laune zu halten und gleichzeitig dafür sorgen, dass die Insel für Touristen attraktiv bleibt. - - -STR_SCNR :Canyon-Katastrophen -STR_PARK :Canyon-Katastrophen -STR_DTLS :Sie müssen neben diesem Naturwunder einen Vergnügungspark errichten. Es herrscht Platzmangel, Sie können aber Land von den Indianern kaufen. Haben Sie Erfolg, sichern Sie damit der örtlichen Bevölkerung den Lebensunterhalt. - - -STR_SCNR :Achterbahnhimmel -STR_PARK :Achterbahnhimmel -STR_DTLS :Sie sind ein erfolgreicher Geschäftsmann, der sich eine vierjährige Auszeit genommen hat und nun einen Vergnügungspark errichten möchte, bei dem Geld keine Rolle spielt. - - -STR_SCNR :Gründer der Verlorenen Stadt -STR_PARK :Gründer der Verlorenen Stadt -STR_DTLS :Um der örtlichen Tourismusindustrie den Rücken zu stärken, müssen Sie einen Vergnügungspark konstruieren, der sich harmonisch in die Umgebung einfügt. - - -STR_SCNR :Rummel im Regenwald -STR_PARK :Rummel im Regenwald -STR_DTLS :Platz ist Mangelware im kostbaren Regenwald - Sie müssen so viele Attraktionen wie möglich auf der existierenden Lichtung unterbringen, um eine rentable Alternative zur örtlichen Holzindustrie zu schaffen. - - -STR_SCNR :Zauberei am Zuckerhut -STR_PARK :Zauberei am Zuckerhut -STR_DTLS :Sie leiten einen kleinen Vergnügungspark in der Nähe von Rio. Als die Bank plötzlich das Ihnen gewährte Darlehen zurückfordert, müssen Sie einen Weg finden, Ihre Einnahmen rasch zu steigern, um diese unerwarteten Schulden zurückzuzahlen. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Felsenschloss -STR_PARK :Felsenschloss -STR_DTLS :Einige Mitglieder der Gesellschaft zur Nachstellung von Schlachten nehmen ihr Hobby ziemlich ernst. Sie haben Sie damit beauftragt, einen Freizeitpark Finsteres Mittelalter auf den Gründen des Felsenschlosses zu bauen. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :Um die Reichen finanziell zu erleichtern und das Geld den Bedürftigen zukommen zu lassen, haben Sie und Ihre Gespielen beschlossen, im Sherwood Forest einen Freizeitpark zu bauen. - - -STR_SCNR :Außerirdische Extravaganz -STR_PARK :Außerirdische Extravaganz -STR_DTLS :Auf einem fernen Planeten ist Leben entdeckt worden. Bauen Sie einen außerirdischen Freizeitpark, um die unerwartet heftige Hysterie in bare Münze umzuwandeln. - - -STR_SCNR :Zwillingsstadt -STR_PARK :Zwillingsstadt -STR_DTLS :Beweisen Sie Ihre innovative, utopische Vision der Zukunft - errichten Sie einen futuristischen Freizeitpark mit topmodernen Attraktionen. - - -STR_SCNR :Animatronic-Possen -STR_PARK :Animatronic-Possen -STR_DTLS :Ihre Aufgabe ist, einen bestehenden Freizeitpark zu verbessern, der auf einem alten Filmgelände gebaut wurde. Bauen Sie eine Gedenkstätte für die Pioniere der Stop-Motion, die die Mystikwesen als Erste ins Kino brachten. - - -STR_SCNR :Mythologischer Wahnsinn -STR_PARK :Mythologischer Wahnsinn -STR_DTLS :Sie besitzen eine Insel von besonderem architektonischen Wert. Sie haben beschlossen, ihre Erhaltung durch einen Freizeitpark zu finanzieren, der sich mit dem reichen mythologischen Erbe der Gegend befasst. - - -STR_SCNR :Kratergemetzel -STR_PARK :Kratergemetzel -STR_DTLS :Sie besitzen einen alten, verstaubten Meteoritenkrater. In Ihrem unternehmerischen Geist haben Sie beschlossen, einen Asteroiden-Freizeitpark zu bauen und Ihr scheinbar wertloses Land in eine Geldanlage umzuwandeln. - - -STR_SCNR :Achtersaurus -STR_PARK :Achtersaurus -STR_DTLS :Sie haben die Aufgabe, einen Jurassic-Freizeitpark zu bauen. Damit Ihre Besucher optimalen Zugang zu den exotischen Pflanzen und Tieren haben, müssen Sie Attraktionen errichten, die über und in die Täler führen. - - -STR_SCNR :Felswanderungen -STR_PARK :Felswanderungen -STR_DTLS :Um den Autobahnbauern ein Schnippchen zu schlagen und die alten Steinkreise zu erhalten, müssen Sie einen Steinzeitpark bauen und ihn profitabel machen. Besucher anzulocken wird schwer, weil das Gelände unwirtlich ist. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :Die berüchtigte Gefängnisinsel - die einst überquoll vor Schwarzhändlern und Gaunern - steht jetzt zum Verkauf. Sie haben beschlossen, sie in eine 1A-Touristenattraktion zu verwandeln. Geld spielt keine Rolle - - -STR_SCNR :Schneider-Ufer -STR_PARK :Schneider-Ufer -STR_DTLS :In ein paar Jahren ist das 75. Jubiläum des Sieges Ihres Großvaters im Schneider-Cup. Ihm zu Ehren bauen Sie einen Freizeitpark auf der berühmten Wasserflugzeug-Rennstrecke. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :Sie besitzen ein Gelände in der Nähe des flach gebauten Teils der Stadt. Um aus Ihrem Besitz das Beste zu machen, bauen Sie einen Wolkenkratzer-Freizeitpark im hochragenden Stil der Art Déco-Architektur der Zwanziger Jahre. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Auf Ihrem Land findet jährlich ein großes Musikfestival statt. Bauen Sie einen hippen Freizeitpark, um das freidenkende Publikum bei Laune zu halten. - - -STR_SCNR :Rock-’n’-Roll-Revival -STR_PARK :Rock-’n’-Roll-Revival -STR_DTLS :Dieser Freizeitpark ist ein wenig in die Jahre gekommen. Helfen Sie dem Besitzer, ihm einen Rock-’n’-Roll-Anstrich zu geben und ihn zu einem beliebten Ausflugsziel zu machen. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Pandawelt -STR_PARK :Pandawelt -STR_DTLS :Bauen Sie weitere Fahrgeschäfte und ziehen Sie neue Gäste in diesem Park im Pandastil an - - -STR_SCNR :Tycoon Park -STR_PARK :Tycoon Park -STR_DTLS : - -### - -STR_SCNR :Cemetery Ridge -STR_PARK :Cemetery Ridge -STR_DTLS :Es ist Halloween, UCES-Halloween. Kürbisse kreischen in der kalten toten Nacht! Dieser Friedhof ist in Gefahr, und es liegt an Ihnen, ihn zu retten, während Sie die Toten in Frieden ruhen lassen. Können Sie die Geister in ihren Gräbern halten und Ihren Kunden das Fürchten lehren?{NEWLINE}Autor: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :Der Leuchtturm von Alexandria -STR_PARK :Der Leuchtturm von Alexandria -STR_DTLS :Alexander erbaute die Stadt; Griechen, Römer, Ägypter hinterließen ihre Spuren. Aber die größte Ehre war ein Wunder der Antiken Welt - der Leuchtturm. Statten Sie ihm einen Besuch ab und bauen Sie einen Park.{NEWLINE}Autor: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :So, wie er am Eröffnungstag war, den 18. Mai 1905.{NEWLINE}Autor: Aetherwave - - -STR_SCNR :Vesuv -STR_PARK :Vesuv -STR_DTLS :Pompeji and Herculaneum wurden vom Vesuv in 79 v. Chr. zerstört. Besuchen Sie die Ausgrabungen und bauen Sie einen Park!{NEWLINE}Autor: Katatude - - -STR_SCNR :Der Sandkasten -STR_PARK :Der Sandkasten -STR_DTLS :Was alle wollen - ein Sandkasten! Also schnappen Sie sich Eimer und Schaufel und bauen Sie einen Park!{NEWLINE}Autor: Katatude - - -STR_SCNR :Niagarafälle u. Schlucht -STR_PARK :Niagarafälle -STR_DTLS :Die American Falls, Bridal Falls und die kanadischen Horseshoe Falls am Niagara, 1850.{NEWLINE}Autor: Katatude - - -STR_SCNR :Rocky Mountain Miners -STR_PARK :Rocky Mountain Miners -STR_DTLS :Ein Steinschlag hat Ihre Eisenbahnstrecke beschädigt. Ihre Arbeiter sind auf die Suche nach Bodenschätzen gegangen. Gibt es Gold in Achterbahnen?{NEWLINE}Autoren: Squid, Buckone, Fossil - - -STR_SCNR :Die Zeitmaschine -STR_PARK :Die Zeitmaschine -STR_DTLS :Die Zeitmaschine. Bauen Sie, wann Sie wollen, wo Sie wollen. Die Ewigkeit wartet. Alles ist relativ.{NEWLINE}Autor: Katatude - - -STR_SCNR :Turmbau zu Babel -STR_PARK :Turmbau zu Babel -STR_DTLS :Wow! Schauen Sie, wohin uns die Zeitmaschine jetzt befördert hat! Wo sind alle hin?{NEWLINE}Autor: Fossil - - -STR_SCNR :Transformation -STR_PARK :Transformation -STR_DTLS :Wir haben auf Sie gewartet …{NEWLINE}Autor: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :Die Römer haben keine Lust mehr auf langweilige Gladiatorenkämpfe. Geben Sie ihnen etwas aufregenderes; verwandeln Sie eine römische Stadt zum großartigsten Vergnügungspark aller Zeiten!{NEWLINE}Autor: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Unter dem Weihnachtsbaum -STR_PARK :Winterwunderland -STR_DTLS :Mama hat diese Szenerie unter unserem Baum gebaut. Jetzt möchte sie darin einen Park gebaut haben! Können Sie helfen?{NEWLINE}Autor: Katatude - - -STR_SCNR :Bigrock Blast -STR_PARK :Bigrock Blast -STR_DTLS :Nach einer Explosion bei der Bigrock Mining Co. haben die Einwohner von Bigrock einen Vergnügungspark gebaut, um ihre Stadt am Leben zu halten.{NEWLINE}Autoren: rbarclay u. buckone - - -STR_SCNR :Camp Mockingbird -STR_PARK :Camp Mockingbird -STR_DTLS :Nur $500/Woche in diesem Sommercamp! Ziehen Sie Ihre Spendierhosen an, haben Sie Spaß und bauen Sie einen Park.{NEWLINE}Autor: Katatude - - -STR_SCNR :Töff-Töff-Land -STR_PARK :Töff-Töff-Land -STR_DTLS :Mama! Papa! Ich will ins Töff-Töff-Land!{NEWLINE}Autor: Fossil - - -STR_SCNR :Dracheninseln -STR_PARK :Dracheninseln -STR_DTLS :Dracheninseln? Ich bin mir nicht sicher, wie man da hinkommt …{NEWLINE}Autor: Fossil - - -STR_SCNR :Kiddie Karnival II -STR_PARK :Kiddie Karnival -STR_DTLS :Hallo Kinder! Lasst uns Spaß haben!{NEWLINE}Autoren: Piehead u. Fossil - - -STR_SCNR :Sanddüne -STR_PARK :Sanddüne -STR_DTLS :Als der Eigentümer eines kleinen Parks haben Sie sich ein größes Grundstück am Strand gekauft, um den Park zu erweitern, um mehr Gäste anzulocken, die schönen Sanddünen zu besuchen. Aber vorsicht: Sie dürfen die ökologisch fragilen Sanddünen nicht zerstören.{NEWLINE}Autor: rbarclay diff --git a/data/language/en-US.txt b/data/language/en-US.txt index 3311077f75..7ac4ef8a73 100644 --- a/data/language/en-US.txt +++ b/data/language/en-US.txt @@ -235,738 +235,3 @@ STR_6625 :Invalid color STR_6629 :Align toolbar buttons horizontally centered STR_6630 :This setting will align the toolbar buttons horizontally in the center of the screen. The traditional way of aligning them is in the left and right corner. - -############# -# Scenarios # -############# - -## RCT Original - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Starting from scratch, build a theme park around a large lake - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Develop Bumbly Beach’s small amusement park into a thriving theme park - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Several islands form the basis for this new park - - -STR_SCNR :Katie’s World -STR_PARK :Katie’s World -STR_DTLS :A small theme park with a few rides and room for expansion - Your aim is to double the park value - - -STR_SCNR :Dinky Park -STR_PARK :Dinky Park -STR_DTLS :A small, cramped amusement park which requires major expansion - - -STR_SCNR :Aqua Park -STR_PARK :Aqua Park -STR_DTLS :A park with some excellent water-based rides requires expansion - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion - - -STR_SCNR :Mothball Mountain -STR_PARK :Mothball Mountain -STR_DTLS :In the hilly forests of Mothball Mountain, build a theme park from scratch - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :A large park with well-designed but rather old rides - Replace the old rides or add new rides to make the park more popular - - -STR_SCNR :Big Pier -STR_PARK :Big Pier -STR_DTLS :Convert this sleepy town’s pier into a thriving attraction - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers - Use the available land to attract a new thrill-seeking clientele - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :A well-established park, which has a few problems - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Rainbow Valley’s local authority won’t allow any landscape changes or large tree removal, but you must develop the area into a large theme park - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists - Use the available space to build rides to attract more people - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Just for fun! - -## Corkscrew Follies - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Develop the seaside cliffs into a thriving amusement park - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Central to this large developing park is a giant triple-track racing/dueling steel coaster - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its minature railway and a pair of vertical drop roller coasters - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :An old redundant bridge is yours to develop into an amusement park - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Covering land both sides of a highway, this park has several rides already operating - - -STR_SCNR :Haunted Harbor -STR_PARK :Haunted Harbor -STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :This castle is all yours to turn into a theme park - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :A series of stepped lakes form the basis for this new park - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :This elderly park has many historical rides but is badly in debt - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :A large area of land has been cleared and partially themed ready for you to develop into a landscaped theme park - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :A thriving fruit farm has built a railroad to boost its income, your job is to develop it into a full-blown amusement park - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :The area around a dam is available for you to develop into an amusement park - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :A vast canyon is yours to turn into a theme park - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :The local authority won’t allow you to build above tree height in this park - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centerpiece - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :A large garden park needs turning into a thriving theme park - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :A dormant volcano is the setting of this coaster-building challenge - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :A large lake in an ancient crater is the setting for this park - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit - - -STR_SCNR :Big Pier 2 -STR_PARK :Big Pier 2 -STR_DTLS :Big Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :This sea-side cove is the setting for this coaster-building challenge - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :A park which has much of its footpaths and coasters underground - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :A glacier-filled valley is yours to develop into a theme park - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :In a far-off world where money is not needed, you must build an entertainment center to keep the people happy - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Five coasters require completion in this desert park - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :This historical park is only allowed to build older-styled rides - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Develop this alien park to maximize its profit - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :A scary park with a giant centerpiece coaster - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :In this large park you must design and build ten large coasters - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :An icy landscape needs turning into a thriving theme park - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :A desert park with some cleverly designed coasters is yours to expand - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :In this tiny park you must finish building the five existing coasters - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :A large park with a novel transportation system around its edge - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :This large island is all yours to develop as an amusement park - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :This urban area is all yours to develop into an amusement park - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :A giant park already packed full of rides needs improving - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :On a far-away planet this area of land needs turning into a theme park - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Try to create the world’s smallest profitable park - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Convert a small mountain ski resort into a snow-themed amusement park - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Build a flying-themed amusement park in this abandoned airport - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Your challenge is to build a high-profit park on this paradise island - - -STR_SCNR :Build your own Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Build your own version of this European Six Flags park - - -STR_SCNR :Build your own Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Use your design skills to recreate this Six Flags park - - -STR_SCNR :Build your own Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Build this European Six Flags park the way you want to - - -STR_SCNR :Build your own Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Create your own version of this massive Six Flags park - - -STR_SCNR :Build your own Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Starting from scratch, build the rides in this Six Flags park - - -STR_SCNR :Build your own Six Flags Park -STR_PARK :Six Flags -STR_DTLS :Build your own design of Six Flags park - Either build rides from other Six Flags parks or design and build your own rides - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Starting with a small market bazaar, your challenge is to increase the profit from shops and stalls by building rides and roller coasters to attract more customers - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :You have inherited a large castle - Your job is to convert it into a small theme park. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Situated near a highway junction in the desert, Dusty Greens is an opportunity to develop a small golf resort into a thriving theme park - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :You have inherited a small farm, and your challenge is to build a small theme park amongst the fields and farm buildings - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Free of financial restrictions, your challenge is to expand this desert park to attract people seeking the ultimate thrills - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :An abandoned factory complex is an opportunity to build a mechanical-themed amusement park - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Restricted to only older-style wooden rides, your challenge is to build a thriving theme park in Fungus Woods - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Hired by a large amusement park chain, your task is to build them a giant roller coaster park around an abandoned mining town - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Your challenge is to build a roller coaster park in the beautiful Gravity Gardens - No other rides, just roller coasters! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :A park nestled precariously on lava rock with streams of magma - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :With unlimited funds but a challenging lake location, this park will be a challenge to expand and manage - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Built on a hillside, this park is forbidden from building anything tall. Can you expand the park and make it successful? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim - To attract more guests to the park! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim - To repay your loan while keeping the park value up! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim - To attract more guests to the park! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :You inherited a disused diamond mine, and find a valuable diamond. You decide to invest that money to build a world-famous theme park. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :A desert Oasis has been discovered and would provide a beautiful location for a park. Transport to the oasis has been provided. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :A dam has been built offering abundant, cheap hydroelectric power with which to run a park. You need to reach a high park value to help repay the loan for the dam. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :The environment agency has turned to you to transform an old oil refinery ecological eyesore into a top tourist attraction. Land is cheap but loan interest is high. You can sell the old buildings for salvage. - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :The authorities have decided to enhance tourism around the Great Wall by building a theme park on the adjacent land. Money is no object! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :An existing park has run out of space. Your only option is to build out into the sea, and so you have taken out a loan. Height restrictions on your building are enforced due to foundations and earthquake risk. - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :You have been commissioned by the Maharaja to bring entertainment to the large local population. Build a park inspired by the Maharaja’s palace. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :You are helping Aboriginal people to build a park as part of a cultural awareness program. You need to get a large number of guests to educate them in the unique heritage of the Aboriginal people. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :A local entrepreneur’s sealife park has gone bust. You already operate a small park and buy the other park from the construction company. Develop a big combined park. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :You have been brought in to take over a European Cultural Visitor Attraction and must increase the number of guests in order to pay back the EU subsidy by the end of the current European parliament term. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :An old park has fallen into disrepair. You gain a European Union grant to return this deprived area to its former glory! You need to renovate the park and repay the grant. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :The people of Hawaii are bored of surfing and are looking for something more intense. You need to build a park with this in mind to keep the area’s tourist attraction rating high. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :You have to build a park on limited land either side of this natural treasure - you do have the opportunity to buy neighboring land from the Native American Indians. You need to complete the objective to sustain the local town’s population. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :You are a successful business tycoon on long sabbatical who desires to use this time transforming the city park into Rollercoaster Heaven. Money is no object! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :To further boost local tourism you must construct a park that is in tune with its surroundings. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Space is limited in the precious rainforest - you must cram as much as possible into the existing clearing, in order to provide a viable alternative to the local timber industry. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :You run a small park near Rio but the bank has called in your loan. You need to quickly increase your earning capacity to repay this unexpected debt. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Local members of the battle re-enactment society are rather serious about their hobby. They’ve entrusted you with the job of constructing a Dark Age theme park on the grounds of Cliffside Castle. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :To liberate wealth from the rich and distribute it to the needy, you and your Merry Men have decided to build a theme park in Sherwood Forest. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Life has been discovered on a distant planet. Build an alien theme park to cash in on the unprecedented wave of interest. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Show off your inventive, utopian vision of the future - come up with a futuristic park design that incorporates state-of-the-art attractions. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :You have been given the task of running and improving an existing theme park, which has been built on an old film set. Build a tribute to the pioneering stop-motion animators who first brought mythical creatures to life on the silver screen. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :You own an island of particular archaeological value. You’ve decided to fund its preservation by constructing a theme park based on the area’s rich Mythological heritage. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :You own a dusty old meteor crater. In the true entrepreneurial spirit, you’ve decided to construct an asteroid theme park and convert your seemingly worthless land into a sizeable fortune. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :You’ve been given the task of constructing a Jurassic era theme park. To optimize your visitors’ access to the exotic plant and animal exhibits, you will need to build rides going over and into the valley. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :To thwart the highway developers and preserve the mysterious ancient stone circles, you will need to construct a Stone Age theme park and turn a profit. However, attracting visitors may pose a challenge, as the terrain is a tad inhospitable. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :The infamous Prison Island - whose population once swelled with bootleggers and racketeers - is now up for sale. You’ve decided to convert it into a top tourist attraction, and money is no object. - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :The 75th anniversary of your grandfather’s Schneider Cup victory is coming up in a few years. You’re going to honor his achievement by building a theme park based on the famous seaplane race. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :You own an empty lot near the low-rise part of town. To squeeze the most out of your urban property, build a skyscraper theme park inspired by the soaring art deco architecture of the twenties. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :A large annual music festival takes place on your land. Build a hip theme park to keep the free-spirited audience entertained. - - -STR_SCNR :Rock ‘n’ Roll Revival -STR_PARK :Rock ‘n’ Roll Revival -STR_DTLS :This aging theme park has seen better days. Help the owner give it a retro rock ‘n’ roll makeover and turn the place into a successful venue. diff --git a/data/language/eo-ZZ.txt b/data/language/eo-ZZ.txt index 73694e8de9..e7781e3c11 100644 --- a/data/language/eo-ZZ.txt +++ b/data/language/eo-ZZ.txt @@ -3778,859 +3778,3 @@ STR_6706 :{WINDOW_COLOUR_2}Nuna bildodosiero: {BLACK}{STRING} STR_6707 :(neniu elektita) STR_6708 :Glata forteco STR_6709 :Entajpu glatan fortecon inter {COMMA16} kaj {COMMA16} - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Arbaro-Limoj -STR_PARK :Arbaro-Limoj -STR_DTLS :En profunda arbaro, konstruu prosperan amuzparkon en granda vakigita areo - - -STR_SCNR :Dinamito-Dunoj -STR_PARK :Dinamito-Dunoj -STR_DTLS :Konstruita en la mezo de la dezerto, ĉi tiu amuzparko enhavas nur unu ondan fervojon, sed ankaŭ enhavas spacon por kreski - - -STR_SCNR :Folia Lago -STR_PARK :Folia Lago -STR_DTLS :Komencante de nulo, konstruu amuzparkon ĉirkaŭ granda lago - - -STR_SCNR :Diamanto-Altaĵoj -STR_PARK :Diamanto-Altaĵoj -STR_DTLS :Diamanto-Altaĵoj jam estas sukcesa amuzparko kun bonegaj atrakcioj - ellaboru la parkon por duobligi sian valoron - - -STR_SCNR :Ĉiamverdaj Ĝardenoj -STR_PARK :Ĉiamverdaj Ĝardenoj -STR_DTLS :Konvertu la belajn Ĉiamverdajn Ĝardenojn en prosperan amuzparkon - - -STR_SCNR :Burda Plaĝo -STR_PARK :Burda Plaĝo -STR_DTLS :Ellaboru la malgrandan amuzparkon de Burda Plaĝo en prosperan amuzparkon - - -STR_SCNR :Triunuaj Insuloj -STR_PARK :Triunuaj Insuloj -STR_DTLS :Multaj insuloj formas la bazon de ĉi tiu nova parko - - -STR_SCNR :La Revolando de Kejta -STR_PARK :La Revolando de Kejta -STR_DTLS :Malgranda amuzparko kun kelkaj atrakcioj kaj spaco por kreski. Via celo estas duobligi la parkvaloron. - - -STR_SCNR :Poki-Parko -STR_PARK :Poki-Parko -STR_DTLS :Malgranda kaj malvasta amuzparko, kiu bezonas grandan kreskadon - - -STR_SCNR :Rapidfluo-Parko -STR_PARK :Rapidfluo-Parko -STR_DTLS :Ĉi tiu parko, kun kelkaj bonegaj akvo-atrakcioj, bezonas kreskadon - - -STR_SCNR :Miljaraj Minoj -STR_PARK :Miljaraj Minoj -STR_DTLS :Konvertu grandan forlasitan minon de vidindaĵo en amuzparkon - - -STR_SCNR :Gokartoj k Ondaj Fervojoj -STR_PARK :Gokartoj k Ondaj Fervojoj -STR_DTLS :Granda parko kaŝita en la arbaro, kiu enhavas nur trakojn de gokartoj kaj lignajn ondajn fervojojn - - -STR_SCNR :Melmondo -STR_PARK :Melmondo -STR_DTLS :Ĉi tiu amuzparko enhavas kelkajn bone-desegnitajn modernajn atrakciojn, sed ankaŭ multe da spaco por kreski - - -STR_SCNR :Mistika Monto -STR_PARK :Mistika Monto -STR_DTLS :En la ondaj arbaroj de Mistika Monto, konstruu amuzparkon komencante de nulo - - -STR_SCNR :Pacifikaj Piramidoj -STR_PARK :Pacifikaj Piramidoj -STR_DTLS :Konvertu la vidindaĵon de Egiptaj Restaĵoj en prosperan amuzparkon - - -STR_SCNR :Ĉifaj Arbaroj -STR_PARK :Ĉifaj Arbaroj -STR_DTLS :Granda parko kun bone-desegnitaj sed iomete malnovaj atrakcioj. Anstataŭigu la malnovajn atrakciojn aŭ alkonstruu novajn atrakciojn, por farigi la parkon pli populara. - - -STR_SCNR :Paradizo-Enŝipigejo -STR_PARK :Paradizo-Enŝipigejo -STR_DTLS :Konvertu la enŝipigejon de ĉi tiu dormema urbeto en prosperan atrakcion - - -STR_SCNR :Fulmo-Montopintoj -STR_PARK :Fulmo-Montopintoj -STR_DTLS :La belaj montoj de Fulmo-Montopintoj estas populara por marŝantoj kaj rigardantoj. Uzu la disponeblan teron por allogi novan klientaron, kiu volas ekscitaĵojn. - - -STR_SCNR :Eburo-Turoj -STR_PARK :Eburo-Turoj -STR_DTLS :Bone-establita parko, kiu havas kelkajn problemojn - - -STR_SCNR :Ĉielarko-Valo -STR_PARK :Ĉielarko-Valo -STR_DTLS :La loka aŭtoritato de Ĉielarko-Valo ne permesos iun ajn ŝanĝadon de tero aŭ forigadon de grandaj arboj, sed vi devas ellabori la areon en grandan amuzparkon - - -STR_SCNR :Tondro-Ŝtonego -STR_PARK :Tondro-Ŝtonego -STR_DTLS :Tondro-Ŝtonego troviĝas en la mezo de dezerto, kaj allogas multajn turistojn. Uzu la spacon disponeblan por konstrui atrakciojn por allogi pli da homoj. - - -STR_SCNR :Mega-Parko -STR_PARK :Mega-Parko -STR_DTLS :Nur por amuziĝi! - -## Added Attractions - -STR_SCNR :Flustrantaj Klifoj -STR_PARK :Flustrantaj Klifoj -STR_DTLS :Ellaboru la apudmarajn klifojn en prosperan amuzparkon - - -STR_SCNR :Tri-Simioj-Parko -STR_PARK :Tri-Simioj-Parko -STR_DTLS :La ĉefa atrakcio de ĉi tiu granda ellaborata parko estas giganta triopa-traka vetkuranta ŝtala onda fervojo - - -STR_SCNR :Kanario-Minoj -STR_PARK :Kanario-Minoj -STR_DTLS :Ĉi tiu forlasita mino jam havas la potencialon de vidindaĵo, kun ĝia miniatura fervojo kaj paro da ondaj fervojoj kun vertikalaj malleviĝoj - - -STR_SCNR :Baronlando-Ponto -STR_PARK :Baronlando-Ponto -STR_DTLS :Malnova senutila ponto estas via por ellabori en amuzparkon - - -STR_SCNR :Amuzutopio -STR_PARK :Amuzutopio -STR_DTLS :Sur bieno ambaŭflanke de aŭtovojo, ĉi tiu parko jam havas plurajn funkciantajn atrakciojn - - -STR_SCNR :Fantoma Haveno -STR_PARK :Fantoma Haveno -STR_DTLS :La loka aŭtoritato permesis la malmultekostan vendadon de proksima bieno al ĉi tiu malgranda apudmara parko, sed certaj atrakcioj devas esti konservataj - - -STR_SCNR :Amuza Fortreso -STR_PARK :Amuza Fortreso -STR_DTLS :Ĉi tiu fortreso estas tute via por ŝanĝiĝi al amuzparko - - -STR_SCNR :Estonto-Mondo -STR_PARK :Estonto-Mondo -STR_DTLS :Ĉi tiu estonteca parko havas multe da spaco por novaj atrakcioj sur ĝia ekstertera pejzaĝo - - -STR_SCNR :Milda Valeto -STR_PARK :Milda Valeto -STR_DTLS :La lokaj homoj preferas mildajn atrakciojn, do via celo estas ellabori ĉi tiun parkon por plaĉi ilin - - -STR_SCNR :Gajega Ĝangalo -STR_PARK :Gajega Ĝangalo -STR_DTLS :Profunde en la ĝangalo estas granda areo de tero preta por esti transformita en amuzparkon - - -STR_SCNR :Akvo-Montetoj -STR_PARK :Akvo-Montetoj -STR_DTLS :Serio de lagoj fariĝas la bazo de ĉi tiu nova parko - - -STR_SCNR :Vigla Parko -STR_PARK :Vigla Parko -STR_DTLS :Ĉi tiu malnova parko havas multajn historiajn atrakciojn, sed ankaŭ dronas en ŝuldoj - - -STR_SCNR :Magiaj Kvartaloj -STR_PARK :Magiaj Kvartaloj -STR_DTLS :Granda areo de tero vakigita kaj parte temita estas preta, por ke vi ellaboru ĝin en belan amuzparkon - - -STR_SCNR :Frukto-Farmo -STR_PARK :Frukto-Farmo -STR_DTLS :Prospera fruktofarmo konstruis fervojon por gajni pli da enspezo. Via celo estas ellabori ĝin en kompletan amuzparkon. - - -STR_SCNR :Papilio-Akvobaraĵo -STR_PARK :Papilio-Akvobaraĵo -STR_DTLS :La areo ĉirkaŭ akvobaraĵo estas disponebla, por ke vi ellaboru ĝin en amuzparkon - - -STR_SCNR :Onda-Fervojo-Kanjono -STR_PARK :Onda-Fervojo-Kanjono -STR_DTLS :Vasta kanjono estas via por ŝanĝiĝi al amuzparko - - -STR_SCNR :Fulmotondro-Parko -STR_PARK :Fulmotondro-Parko -STR_DTLS :La vetero estas tiel malseka ĉi tie, ke giganta piramido estis konstruita por permesi kelkajn atrakciojn konstruatajn subtere - - -STR_SCNR :Harmonaj Montetoj -STR_PARK :Harmonaj Montetoj -STR_DTLS :La loka aŭtoritato ne permesos la konstruadon super la arbalteco en ĉi tiu parko - - -STR_SCNR :Romana Vilaĝo -STR_PARK :Romana Vilaĝo -STR_DTLS :Ellaboru ĉi tiun parkon kun romana temo, per aldoni atrakciojn kaj ondajn fervojojn - - -STR_SCNR :Marĉejo-Golfeto -STR_PARK :Marĉejo-Golfeto -STR_DTLS :Konstruita parte sur serio de malgrandaj insuloj, ĉi tiu parko jam havas paron da grandaj ondaj fervojoj kiel ĝiaj ĉefaĵo - - -STR_SCNR :Adrenalino-Altaĵoj -STR_PARK :Adrenalino-Altaĵoj -STR_DTLS :Konstruu parkon por allogi lokajn homojn, kiuj volas altajn-intensajn ekscitaĵojn - - -STR_SCNR :Utopio-Parko -STR_PARK :Utopio -STR_DTLS :Oazo en la mezo de la dezerto provizas nekutiman okazon por konstrui amuzparkon - - -STR_SCNR :Putradaj Altaĵoj -STR_PARK :Putradaj Altaĵoj -STR_DTLS :Surkreskata kaj kaduka, ĉu vi povas relevigi ĉi tiun bonintan amuzparkon? - - -STR_SCNR :Fiasko-Arbaro -STR_PARK :Fiasko-Arbaro -STR_DTLS :Plene je malbone-desegnitaj kaj danĝeraj atrakcioj, vi havas tre limigitan buĝeton kaj tempon por ripari la problemojn kaj rebonigi la parkon - - -STR_SCNR :Peklaĵo-Parko -STR_PARK :Peklaĵo-Parko -STR_DTLS :La loka aŭtoritato ne permesos ian ajn reklamadon aŭ kampanjojn de vendado, do ĉi tiu parko devas sukcesi nur per reputacio. - - -STR_SCNR :Subrido-Malaltaĵoj -STR_PARK :Subrido-Malaltaĵoj -STR_DTLS :Kvaropa-traka stipoĉejso estas la ĉefaĵo de ĉi tiu ellaborata parko - - -STR_SCNR :Minerala Parko -STR_PARK :Minerala Parko -STR_DTLS :Ŝanĝu ĉi tiun forlasitan ŝtonejon al loko por allogi ekscitovolajn turistojn - - -STR_SCNR :Onda-Fervojo-Frenezo -STR_PARK :Onda-Fervojo-Frenezo -STR_DTLS :Vi havas limigitan monon, sed senliman tempon, por ellabori ĉi tiun montoflankan areon en gigantan parkon de ondaj fervojoj - - -STR_SCNR :Urba Parko -STR_PARK :Urba Parko -STR_DTLS :Eta parko negocis kun la proksima urbeto, por permesi ellaboradon tra la urbeto sin mem - - -STR_SCNR :Geoffrey-Ĝardenoj -STR_PARK :Geoffrey-Ĝardenoj -STR_DTLS :Vi devas ŝanĝi grandan ĝardenoparkon al prospera amuzparko - - -## Loopy Landscapes - -STR_SCNR :Glacimonto-Insuloj -STR_PARK :Glacimonto-Insuloj -STR_DTLS :Aro da glacimontoj fariĝas malvarma okazejo por ĉi tiu ambicia amuzparko - - -STR_SCNR :Vulkanlando -STR_PARK :Vulkanlando -STR_DTLS :Dormanta vulkano estas la okazejo de ĉi tiu defio de la konstruado de ondaj fervojoj - - -STR_SCNR :Aridaj Altaĵoj -STR_PARK :Aridaj Altaĵoj -STR_DTLS :Sen financaj limigoj, via defio estas ellabori ĉi tiun dezertparkon, kaj samtempe restigi la gastojn feliĉaj - - -STR_SCNR :Razilecaj Rokoj -STR_PARK :Razilecaj Rokoj -STR_DTLS :Via celo estas konstrui grandegan parkon da ondaj fervojoj ĉe Razilecaj Rokoj - - -STR_SCNR :Kratero-Lago -STR_PARK :Kratero-Lago -STR_DTLS :Granda lago en praa kratero estas la okazejo de ĉi tiu parko - - -STR_SCNR :Kapturnigaj Vidoj -STR_PARK :Kapturnigaj Vidoj -STR_DTLS :Ĉi tiu granda parko jam havas bonegan hiperan ondan fervojon, sed via celo estas pliigi ĝian profiton - - -STR_SCNR :Paradizo-Enŝipigejo 2 -STR_PARK :Paradizo-Enŝipigejo 2 -STR_DTLS :Paradizo-Enŝipigejo etendis sian reton de troturaroj super la maro, kaj via celo estas ellabori la parkon por uzi la ekstran spacon - - -STR_SCNR :Golfeto de Drako -STR_PARK :Golfeto de Drako -STR_DTLS :Apudmara golfeto estas la okazejo de ĉi tiu defio de la konstruado de ondaj fervojoj - - -STR_SCNR :Bona-Kavaliro-Parko -STR_PARK :Bona-Kavaliro-Parko -STR_DTLS :Vi devas ellabori kastelon, kun paro da ondaj fervojoj, en pli grandan amuzparkon - - -STR_SCNR :Komika Kuniklejo -STR_PARK :Komika Kuniklejo -STR_DTLS :Parko, kiu havas plejparton da siaj trotuaroj kaj ondaj fervojoj subtere - - -STR_SCNR :Granda Glaĉero -STR_PARK :Granda Glaĉero -STR_DTLS :Valo kun glaĉero estas via por ellabori en amuzparkon - - -STR_SCNR :Frenezaj Krateroj -STR_PARK :Frenezaj Krateroj -STR_DTLS :En mondo for, kie mono ne necesas, vi devas konstrui centron de amuzaĵo por teni la homojn feliĉaj - - -STR_SCNR :Polva Dezerto -STR_PARK :Polva Dezerto -STR_DTLS :Kvin ondaj fervojoj bezonas kompletadon en ĉi tiu dezertparko - - -STR_SCNR :Anobio-Parko -STR_PARK :Anobio-Parko -STR_DTLS :Eblas konstrui nur malmodernajn atrakciojn en ĉi tiu historia parko - - -STR_SCNR :Ikaro-Parko -STR_PARK :Ikaro-Parko -STR_DTLS :Ellaboru ĉi tiun eksterteran parkon por maksimumigi sian profiton - - -STR_SCNR :Sunplenaj Marĉejoj -STR_PARK :Sunplenaj Marĉejoj -STR_DTLS :Ĉi tiu bone-temita amuzparko jam havas multajn atrakciojn, sed ankoraŭ havas multe da spaco por ellabori - - -STR_SCNR :Inkubo-Montetoj -STR_PARK :Inkubo-Montetoj -STR_DTLS :Timiga parko, kun giganta ĉefa onda fervojo - - -STR_SCNR :Tondro-Rokoj -STR_PARK :Tondro-Rokoj -STR_DTLS :La komenco de ĉi tiu amuzparko estas sur du grandaj eroj da ŝtonego, kiuj elstaras el la sablo - - -STR_SCNR :Okangulo-Parko -STR_PARK :Okangulo-Parko -STR_DTLS :En ĉi tiu granda parko, vi devas desegni kaj konstrui dek grandajn ondajn fervojojn - - -STR_SCNR :Plezuro-Insulo -STR_PARK :Plezuro-Insulo -STR_DTLS :Longa mallarĝa insulo fariĝas defia okazejo por konstrui elektaron da ondaj fervojoj - - -STR_SCNR :Glacikonuso-Mondoj -STR_PARK :Glacikonuso-Mondoj -STR_DTLS :Vi devas ŝanĝi glacian pejzaĝon al prospera amuzparko - - -STR_SCNR :Sudaj Sablaĵoj -STR_PARK :Sudaj Sablaĵoj -STR_DTLS :Dezertparko, kun iuj ondaj fervojoj lerte desegnitaj, estas via por ellabori - - -STR_SCNR :Etaj Turoj -STR_PARK :Etaj Turoj -STR_DTLS :En ĉi tiu eta parko, vi devas fini la konstruadon de la kvin ekzistantaj ondaj fervojoj - - -STR_SCNR :Neniam-Parko -STR_PARK :Neniam-Parko -STR_DTLS :Granda parko, kun nova sistemo de transportado ĉirkaŭ ĝia rando - - -STR_SCNR :Pacifiko -STR_PARK :Pacifiko -STR_DTLS :Ĉi tiu granda insulo estas tute via por ellabori en amuzparkon - - -STR_SCNR :Urba Ĝangalo -STR_PARK :Urba Ĝangalo -STR_DTLS :Giganta forlasita ĉielskrapanto estas unika okazo por amuzparko-ellaboranto - - -STR_SCNR :Teruro-Urbo -STR_PARK :Teruro-Urbo -STR_DTLS :Ĉi tiu urba areo estas tute via por ellabori en amuzparkon - - -STR_SCNR :Mondego-Parko -STR_PARK :Mondego-Parko -STR_DTLS :Ĉi tiu giganta parko, kiu jam estas plena je atrakcioj, bezonas plibonigon - - -STR_SCNR :Venuso-Lagetoj -STR_PARK :Venuso-Lagetoj -STR_DTLS :Sur malproksima planedo, vi bezonas ŝanĝi ĉi tiun bienoareon al amuzparko - - -STR_SCNR :Mikro-Parko -STR_PARK :Mikro-Parko -STR_DTLS :Provu krei la plej malgrandan profiteblan parkon de la mondo - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fuort-Anakronismo -STR_PARK :Fuort-Anakronismo -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Tegmento -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpaj Aventuroj -STR_PARK :Alpaj Aventuroj -STR_DTLS :Konvertu skiejon ĉe malgranda monto en neĝo-temitan amuzparkon - - -STR_SCNR :Amikeco-Aerodromo -STR_PARK :Amikeco-Aerodromo -STR_DTLS :Konstruu amuzparkon kun flugado-temo en ĉi tiu forlasita flughaveno - - -STR_SCNR :Botaniko-Rompiloj -STR_PARK :Botaniko-Rompiloj -STR_DTLS :Via defio estas konstrui tre profitan parkon sur ĉi tiu paradiza insulo - - -STR_SCNR :Konstrui je via propra Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Konstruu vian propran version de ĉi tiu Eŭropa parko de Six Flags - - -STR_SCNR :Konstrui je via propra Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Uzu viajn kapablojn de desegnado por rekrei ĉi tiun parkon de Six Flags - - -STR_SCNR :Konstrui je via propra Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Konstruu ĉi tiun Eŭropan parkon de Six Flags kiel vi volas - - -STR_SCNR :Konstrui je via propra Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Kreu vian propran version de ĉi tiu grandega parko de Six Flags - - -STR_SCNR :Konstrui je via propra Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Komencante de nulo, konstruu la atrakciojn en ĉi tiu parko de Six Flags - - -STR_SCNR :Konstrui vian propran parkon de Six Flags -STR_PARK :Six Flags -STR_DTLS :Konstruu vian propran desegnaĵon de parko de Six Flags - aŭ konstruu atrakciojn de aliaj parkoj de Six Flags, aŭ desegnu kaj konstruu viajn proprajn atrakciojn - - -STR_SCNR :Burda Bazaro -STR_PARK :Burda Bazaro -STR_DTLS :Komencante kun malgranda bazaro, via defio estas pliigi la profitan de vendejoj kaj budoj per konstrui atrakciojn kaj ondajn fervojojn por allogi pli da klientoj - - -STR_SCNR :Freneza Kastelo -STR_PARK :Freneza Kastelo -STR_DTLS :Vi heredis grandan kastelon. Via celo estas konverti ĝin en malgrandan amuzparkon. - - -STR_SCNR :Polvaj Verdejoj -STR_PARK :Polvaj Verdejoj -STR_DTLS :Troviĝas proksime de aŭtovojo en dezerto, Polvaj Verdejoj estas okazo por ellabori malgrandan golfejon en prosperan amuzparkon - - -STR_SCNR :Elektraj Kampoj -STR_PARK :Elektraj Kampoj -STR_DTLS :Vi heredis malgrandan farmon, kaj via defio estas konstrui malgrandan amuzparkon inter la kampoj kaj aliaj farmokonstruaĵoj - - -STR_SCNR :Ekstremaj Altaĵoj -STR_PARK :Ekstremaj Altaĵoj -STR_DTLS :Sen financaj limigoj, via defio estas ellabori ĉi tiun dezertparkon por allogi homojn, kiuj volas la plejajn ekscitaĵojn - - -STR_SCNR :Fabriko-Kaprioloj -STR_PARK :Fabriko-Kaprioloj -STR_DTLS :Ĉi tiu forlasita fabriko-konstruaĵaro estas okazo por konstrui amuzparkon kun mekanika temo - - -STR_SCNR :Fungo-Arbaro -STR_PARK :Fungo-Arbaro -STR_DTLS :Via defio estas konstrui prosperan amuzparkon en Fungo-Arbaro, sed vi povas konstrui nur malnovecajn lignajn atrakciojn - - -STR_SCNR :Fantoma Urbeto -STR_PARK :Fantoma Urbeto -STR_DTLS :Dungita de granda amuzparkofirmo, via celo estas konstrui por ĝi gigantan amuzparkon de ondaj fervojoj ĉe forlasita minurbeto - - -STR_SCNR :Gravito-Ĝardenoj -STR_PARK :Gravito-Ĝardenoj -STR_DTLS :Via celo estas konstrui amuzparkon de ondaj fervojoj en la belaj Gravito-Ĝardenoj. Neniuj aliaj atrakciotipoj, nur ondaj fervojoj! - - -STR_SCNR :Inferaj Vidoj -STR_PARK :Inferaj Vidoj -STR_DTLS :Parko troviĝanta malfirme sur lafoŝtonego kun riveroj de magmo - - -STR_SCNR :Bonŝanca Lago -STR_PARK :Bonŝanca Lago -STR_DTLS :Kun senlima mono, sed malfacila lagoloko, ĉi tiu parko estos defio por ellabori kaj administri - - -STR_SCNR :Ĉielarko-Supraĵo -STR_PARK :Ĉielarko-Supraĵo -STR_DTLS :Konstruita ĉe montetoflanko, la aŭtoritato malpermesas altajn konstruaĵojn. Ĉu vi povas ellabori la parkon kaj farigi ĝin sukcesa? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Provu administri kaj plibonigi ĉi tiun parkon de Six Flags - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Konstruu la mankantajn atrakciojn de Six Flags, aŭ kreu viajn proprajn desegnaĵojn por plibonigi la parkon! Sed ne forgesu vian ĉefan celon: por allogi pli da gastoj al la parko! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Provu administri kaj plibonigi ĉi tiun parkon de Six Flags - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Konstruu la mankantajn atrakciojn de Six Flags, aŭ kreu viajn proprajn desegnaĵojn por plibonigi la parkon! Sed ne forgesu vian ĉefan celon: por repagi vian prunton, konservante la parkvaloron! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Konstruu la mankantajn atrakciojn de Six Flags, aŭ kreu viajn proprajn desegnaĵojn por plibonigi la parkon! Sed ne forgesu vian ĉefan celon: por allogi pli da gastoj al la parko! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Minoj de Afriko -STR_PARK :Minoj de Afriko -STR_DTLS :Vi heredis ne plu uzitan diamanto-minejon, kaj trovis valoran diamanton. Vi decidas investi tiun monon por konstrui mondfaman amuzparkon. - - -STR_SCNR :Miraĝo-Frenezo -STR_PARK :Miraĝo-Frenezo -STR_DTLS :Dezerta oazo estis malkovrita kaj provizus belan lokon por parko. Transporto al la oazo estis provizita. - - -STR_SCNR :Super La Rando -STR_PARK :Super La Rando -STR_DTLS :Digo konstruita oferas abundan malmultekostan hidroelektran potencon por administri parkon. Vi devas atingi altan parkvaloron por helpi repagi la prunton de la digo. - - -STR_SCNR :Glaciaj Aventuroj -STR_PARK :Glaciaj Aventuroj -STR_DTLS :La biomedia agentejo komisiis vin por transformi malnovan nafto-rafinejon, ekologian malbelaĵon, en supran turismo-vidindaĵon. Tereno estas malmultekosta sed pruntinterezo estas alta. Vi povas vendi la malnovajn konstruaĵojn por savado. - - -STR_SCNR :La Granda Ĉina Muro -STR_PARK :La Granda Ĉina Muro -STR_DTLS :La aŭtoritatoj decidis plibonigi turismon ĉirkaŭ la Granda Muro per konstrui amuzparkon sur la apuda tereno. Mono estas neniu problemo! - - -STR_SCNR :Okinavo-Marbordo -STR_PARK :Okinavo-Marbordo -STR_DTLS :Ekzistanta parko elĉerpiĝis de spaco. Via sola eblo estas konstrui sur la maron, kaj tial vi elprenis prunton. Alteco-limigoj de viaj konstruaĵoj estas observigitaj pro fondaĵoj kaj tertremo-risko. - - -STR_SCNR :Parko-Maharaĝo -STR_PARK :Parko-Maharaĝo -STR_DTLS :Vi estis komisiita de la Maharaĝo por alporti amuzadon al la granda loka loĝantaro. Konstruu parkon inspiritan de la palaco de Maharaĝo. - - -STR_SCNR :Uluru-Aventuro -STR_PARK :Uluru-Aventuro -STR_DTLS :Vi helpas aborigenojn per konstrui parkon kiel parto de programo de kultura konscio. Vi bezonas akiri multajn gastojn por eduki ilin pri la unika heredaĵo de la aborigenoj. - - -STR_SCNR :Kradostado-Festo ĉe la Plaĝo -STR_PARK :Kradostado-Festo ĉe la Plaĝo -STR_DTLS :La marvivo-parko de loka entreprenisto eksenmoniĝis. Vi jam funkciigas malgrandan parkon, kaj aĉetas la alian parkon de la konstruo-kompanio. Ellaboru grandan kombinitan parkon. - - -STR_SCNR :Eŭropa Ekstravagancaĵo -STR_PARK :Eŭropa Ekstravagancaĵo -STR_DTLS :Vi estis alportita por transpreni Eŭropan Kulturan Vizitanto-Vidindaĵon kaj devas pliigi la nombron de gastoj por repagi la EU-subvencion antaŭ la fino de la aktuala Eŭropa parlamento-oficdaŭro. - - -STR_SCNR :El La Cindroj -STR_PARK :El La Cindroj -STR_DTLS :Malnova parko falis je kadukiĝo. Vi akiras subvencion de Eŭropa Unio por redoni ĉi tiun senigitan areon al sia iama gloro! Vi bezonas renovigi la parkon kaj repagi la subvencion. - - -STR_SCNR :Komika Waikiki -STR_PARK :Komika Waikiki -STR_DTLS :La homoj de Havajo estas enuigitaj de surfado kaj serĉas ion pli intensan. Vi devas konstrui parkon ĉi-rilate por subteni la vidindaĵo-valoron de la areo alta. - - -STR_SCNR :Kanjono-Katastrofoj -STR_PARK :Kanjono-Katastrofoj -STR_DTLS :Vi devas konstrui parkon sur limigita tereno ambaŭflanke de ĉi tiu natura trezoro - vi havas la oportunecon por aĉeti najbaran terenon de la Indiĝenaj Amerikanoj. Vi devas kompletigi la celon por daŭrigi la loĝantaron de la loka vilaĝo. - - -STR_SCNR :Paradizo de Ondaj Fervojoj -STR_PARK :Paradizo de Ondaj Fervojoj -STR_DTLS :Vi estas sukcesa komerca magnato prenanta longan libertempon, kiu deziras uzi ĉi tiun tempon per transformi la urban parkon en Onda-Fervojo-Paradizon. Mono estas neniu problemo! - - -STR_SCNR :Fondinto de la Perdita Urbo -STR_PARK :Fondinto de la Perdita Urbo -STR_DTLS :Por plue akceli lokan turismon, vi devas konstrui parkon, kiu akordas kun sia ĉirkaŭaĵo. - - -STR_SCNR :Pluvarbaro-Kapriolo -STR_PARK :Pluvarbaro-Kapriolo -STR_DTLS :Spaco estas limigita en la altvalora pluvarbaro - vi devas plenegigi kiel eble plej multe en la ekzistantan senarbejon, por havigi vivipovan alternativon je la loka ligno-industrio. - - -STR_SCNR :Sukerpano-Marbordoj -STR_PARK :Sukerpano-Marbordoj -STR_DTLS :Vi administras malgrandan parkon proksime de Rio-de-Ĵanejro, sed la banko alvokis vian prunton. Vi devas rapide pliigi vian enspezado-kapablon por repagi ĉi tiun neatenditan ŝuldon. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Klifoflanko-Kastelo -STR_PARK :Klifoflanko-Kastelo -STR_DTLS :Lokaj anoj de la socio de batalo-rekonstruoj estas sufiĉe seriozaj pri ilia ŝatokupo. Ili konfidis al vi la laboron de konstrui amuzparkon kun temo de Malluma Epoko sur la tereno de Klifoflanko-Kastelo. - - -STR_SCNR :Arbaro Sherwood -STR_PARK :Arbaro Sherwood -STR_DTLS :Por liberigi la riĉaĵon de riĉuloj kaj disdoni ĝin al senhavuloj, vi kaj viaj Gajaj Viroj decidis konstrui amuzparkon en Arbaro Sherwood. - - -STR_SCNR :Ekstertera Ekstravagancaĵo -STR_PARK :Ekstertera Ekstravagancaĵo -STR_DTLS :Vivo estis malkovrita ĉe malproksima planedo. Konstruu eksterteran parkon por profiti de la senprecedenca ondo de intereso. - - -STR_SCNR :Ĝemeloj-Urbo -STR_PARK :Ĝemeloj-Urbo -STR_DTLS :Montru vian inventeman, utopian konceptadon de la estonteco - kreu futurisman parko-dezegnaĵon, kiu enkorpigas la plej modernajn atrakciojn. - - -STR_SCNR :Animatronikaj Burleskaĵoj -STR_PARK :Animatronikaj Burleskaĵoj -STR_DTLS :Vi ricevis la taskon de funkciigi kaj plibonigi ekzistantan amuzparkon, kiu estis konstruita ĉe malnova filmado-loko. Konstruu tributon al la pioniraj haltmovado-animistoj, kiuj unue vivigis mitajn kreitojn sur la film-ekranon. - - -STR_SCNR :Mitologia Frenezo -STR_PARK :Mitologia Frenezo -STR_DTLS :Vi posedas insulon de aparta arkeologia valoro. Vi decidis financi ĝian konservadon per konstrui amuzparkon surbaze de la riĉa Mitologia heredaĵo de la areo. - - -STR_SCNR :Kratero-Buĉado -STR_PARK :Kratero-Buĉado -STR_DTLS :Vi posedas polvan malnovan meteor-krateron. Per vera entreprenema vigleco, vi decidis konstrui asteroidan amuzparkon kaj konverti vian ŝajne senvaloran bienon en konsiderindan riĉaĵon. - - -STR_SCNR :Onda-Fervojo-Dinosaŭro -STR_PARK :Onda-Fervojo-Dinosaŭro -STR_DTLS :Vi ricevis la taskon de konstrui Ĵurasa-epokan amuzparkon. Por optimumigi la aliron de viaj vizitantoj al la ekzotikaj ekspoziciaĵoj da kreskaĵoj kaj bestoj, vi bezonos konstrui atrakciojn irantajn super kaj en la valon. - - -STR_SCNR :Rokaj Vagaĵoj -STR_PARK :Rokaj Vagaĵoj -STR_DTLS :Por malhelpi la ŝoseo-ellaborantojn kaj konservi la misterajn antikvajn ŝtono-rondojn, vi bezonos konstrui Ŝtonepokan amuzparkon kaj gajni profiton. Tamen, eble estos defio por allogi vizitantojn, ĉar la tereno estas iom negastema. - - -STR_SCNR :Alkatrazo -STR_PARK :Alkatrazo -STR_DTLS :La fifama Mallibereja Insulo - kies loĝantaro iam ŝveliĝis per piratistoj kaj eldevigantoj - nun estas aĉetebla. Vi decidis transformi ĝin en supran turisman vidindaĵon, kaj mono estas neniu problemo. - - -STR_SCNR :Schneider-Marbordoj -STR_PARK :Schneider-Marbordoj -STR_DTLS :La 75-a datreveno de la Schneider-Trofeo-venko de via avo venas en kelkaj jaroj. Vi honoros lian atingon per konstrui amuzparkon surbaze de la fama hidroplano-vetkuro. - - -STR_SCNR :Metropolo -STR_PARK :Metropolo -STR_DTLS :Vi posedas malplenan teron proksime de la malaltaĵo-parto de la urbo. Por akiri la plej grandan parton de via urba propraĵo, konstruu ĉielskrapanto-temitan amuzparkon inspiritan de la altegiĝia artodekora arkitekturo de la dudekaj. - - -STR_SCNR :Woodstock-Festivalo -STR_PARK :Woodstock-Festivalo -STR_DTLS :Granda jara muzikfestivalo okazas sur via tereno. Konstruu mojosan amuzparkon por teni la liberaniman spektantaron amuzita. - - -STR_SCNR :La Revivigo de Rokenrolo -STR_PARK :La Revivigo de Rokenrolo -STR_DTLS :Ĉi tiu maljuniĝa amuzparko vidis pli bonajn tagojn. Helpu la posedanton doni al ĝi eksmodan rokenrolan renovigon, kaj transformi la lokon en sukcesan ejon. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Pando-Mondo -STR_PARK :Pando-Mondo -STR_DTLS :Aldonu pli da atrakcioj kaj allogu pli da homoj al ĉi tiu pando-temita amuzparko - - -STR_SCNR :Magnata Parko -STR_PARK :Magnata Parko -STR_DTLS : - -### - -STR_SCNR :Tombeja Kresto -STR_PARK :Tombeja Kresto -STR_DTLS :Ĉi Tio estas Haloveno, UCES Haloveno, kukurboj kriegas en la plena nokto! Ĉi tiu tombejo havas problemon kaj ĝi dependas de vi por savi ĝin, dum lasinte la mortinton ripozi en paco! Ĉu vi povas teni la fantomojn en iliaj tomboj kaj alporti frostotremojn al viaj klientoj?{NEWLINE}Aŭtoro: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :La Lumturo de Aleksandrio -STR_PARK :La Lumturo de Aleksandrio -STR_DTLS :Aleksandrio konstruis la urbon; Grekoj, romianoj, kaj egiptoj lasis siajn markojn. Sed la plej granda honoro estis Mirindaĵo de la Antikva Mondo - la Lumturo. Vizitu kaj farigu parkon!{NEWLINE}Aŭtoro: Katatude - - -STR_SCNR :Luna Parko, Klevlando -STR_PARK :Luna Parko -STR_DTLS :Kiel ĝi estis en ĝia inaŭgura tago - 18 Majo 1905.{NEWLINE}Aŭtoro: Aetherwave - - -STR_SCNR :Monto Vezuvio -STR_PARK :Monto Vezuvio -STR_DTLS :Pompejo kaj Herkulano estis enterigita de Monto Vezuvio en 79 p.K. Vizitu la elfosaĵojn kaj konstruu parkon!{NEWLINE}Aŭtoro: Katatude - - -STR_SCNR :La Sablokesto -STR_PARK :La Sablokesto -STR_DTLS :Kion ĉiuj volas - sablokesto! Do prenu vian etan sitelon kaj fosilon kaj konstruu parkon!{NEWLINE}Aŭtoro: Katatude - - -STR_SCNR :Niagara Akvofalaro & Valego -STR_PARK :Niagara Akvofalaro -STR_DTLS :Usona Akvofalo, Luna Akvofalo & Huffera Akvofalo sur la Niagara Limo, 1850.{NEWLINE}Aŭtoro: Katatude - - -STR_SCNR :Ministoj de Roka Montaro -STR_PARK :Ministoj de Roka Montaro -STR_DTLS :Terŝoviĝo damaĝis vian fervojon. Viaj laboristoj foriris por esplori. Ĉu estas oro en onda-fervojojn?{NEWLINE}Aŭtoroj: Squid, Buckone, Fossil - - -STR_SCNR :La Tempomaŝino -STR_PARK :La Tempomaŝino -STR_DTLS :La Tempomaŝino. Konstruu por iri - kiam vi volas, kien vi volas. Eterneco atendas. Ĉio estas relativa.{NEWLINE}Aŭtoro: Katatude - - -STR_SCNR :Babela Turo -STR_PARK :Babela Turo -STR_DTLS :Ho! Rigardu kien la tempomaŝino kondukis nin nun! Kien ĉiuj iris?{NEWLINE}Aŭtoro: Fossil - - -STR_SCNR :Transformiĝo -STR_PARK :Transformiĝo -STR_DTLS :Ni atendis vin…{NEWLINE}Aŭtoro: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :La romianoj lacas enuigajn gladiatorajn batalojn. Donu al ili pli bonajn ravojn, transformu roman urbon en la plej bonan amuzparkon de ĉiuj tempoj!{NEWLINE}Aŭtoro: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Sub la Kristnaska Arbo -STR_PARK :Vintra Mirlando -STR_DTLS :Panjo konstruis ĉi tiun scenon sub nia arbo. Nun ŝi volas parkon farigitan en ĝi! Ĉu vi povas helpi?{NEWLINE}Aŭtoro: Katatude - - -STR_SCNR :Rokega Eksplodo -STR_PARK :Rokega Eksplodo -STR_DTLS :Post eksplodo ĉe la Rokega Minada Kompanio, la homoj de Rokego devas konstrui amuzparkon por konservi ilian urbeton viva.{NEWLINE}Aŭtoroj: rbarclay & buckone - - -STR_SCNR :Mokbirdo-Kampejo -STR_PARK :Mokbirdo-Kampejo -STR_DTLS :Nur 500 dolaroj semajne por ĉi tiu somera kampejo! Disrompu vian ŝparmonujon kaj tiam amuziĝu kaj konstruu parkon.{NEWLINE}Aŭtoro: Katatude - - -STR_SCNR :Ĉu-Ĉu-Urbeto -STR_PARK :Ĉu-Ĉu-Urbeto -STR_DTLS :Panjo! Paĉjo! Mi volas iri al Ĉu-Ĉu-Urbeto!{NEWLINE}Aŭtoro: Fossil - - -STR_SCNR :Drakaj Insuloj -STR_PARK :Drakaj Insuloj -STR_DTLS :Ĉu Drakaj Insuloj? Mi ne estas certa, ke mi volas iri tien…{NEWLINE}Aŭtoro: Fossil - - -STR_SCNR :Infana Karnavalo 2 -STR_PARK :Infana Karnavalo -STR_DTLS :He infanoj! Ni amuziĝu!{NEWLINE}Aŭtoroj: Piehead & Fossil - - -STR_SCNR :Sabla Duno -STR_PARK :Sabla Duno -STR_DTLS :Kiel posedanto de malgranda parko, vi aĉetis grandan terpecon laŭ la marbordo por vastigi kaj allogi pli da gastoj viziti la belajn sablajn dunojn, sed singardu: vi ne povas perturbi tiujn ekologie delikatajn sablajn dunojn.{NEWLINE}Aŭtoro: rbarclay diff --git a/data/language/es-ES.txt b/data/language/es-ES.txt index a57cd979ce..e9a814ebf3 100644 --- a/data/language/es-ES.txt +++ b/data/language/es-ES.txt @@ -3747,863 +3747,3 @@ STR_6671 :Mostrar nombres ‘reales’ de empleados STR_6672 :Alternar entre mostrar nombres ‘reales’ y números de empleados STR_6673 :Translúcido STR_6674 :{MONTH}, Año {COMMA16} - -############## -# Escenarios # -############## - -## RCT Original - -STR_SCNR :Fronteras Forestales -STR_PARK :Fronteras Forestales -STR_DTLS :Construye un próspero parque temático en una amplia zona deforestada de un espeso bosque. - - -STR_SCNR :Dunas Dinamita -STR_PARK :Dunas Dinamita -STR_DTLS :Construido en pleno desierto, este parque temático contiene únicamente una montaña rusa, pero tiene espacio para crecer. - - -STR_SCNR :Lago Frondoso -STR_PARK :Lago Frondoso -STR_DTLS :Empezando desde cero, construye un parque temático alrededor de un gran lago. - - -STR_SCNR :Cumbres Diamantinas -STR_PARK :Cumbres Diamantinas -STR_DTLS :Cumbres Diamantinas es ya un parque temático de éxito con magníficas atracciones. Desarróllalo hasta duplicar su valor. - - -STR_SCNR :Jardines Perennes -STR_PARK :Jardines Perennes -STR_DTLS :Convierte los hermosos Jardines Perennes en un próspero parque temático. - - -STR_SCNR :Playa Coqueta -STR_PARK :Playa Coqueta -STR_DTLS :Convierte el pequeño parque de atracciones de Playa Coqueta en un próspero parque temático. - - -STR_SCNR :Islas de la Trinidad -STR_PARK :Islas de la Trinidad -STR_DTLS :Varias islas forman la base de este nuevo parque. - - -STR_SCNR :Mundo de Katie -STR_PARK :Mundo de Katie -STR_DTLS :Un pequeño parque temático con unas cuantas atracciones y posibilidades de expansión. Tu objetivo será duplicar el valor del parque. - - -STR_SCNR :Parque Pequeño -STR_PARK :Parque Pequeño -STR_DTLS :Un pequeño y abarrotado parque de atracciones que necesita una gran expansión. - - -STR_SCNR :Parque Acuático -STR_PARK :Parque Acuático -STR_DTLS :Un parque con unas cuantas atracciones acuáticas, y que necesita expansión. - - -STR_SCNR :Minas del Milenio -STR_PARK :Minas del Milenio -STR_DTLS :Convierte una gran mina abandonada que es en la actualidad una atracción turística, en un parque temático. - - -STR_SCNR :Go-Karts & Montañas Rusas -STR_PARK :Karts & Coasters -STR_DTLS :Un gran parque oculto en el bosque, que sólo contiene pistas de Go-karts y montañas rusas de madera. - - -STR_SCNR :Mundo de Mel -STR_PARK :Mundo de Mel -STR_DTLS :Este parque temático tiene algunas atracciones modernas y bien diseñadas, pero aún hay mucho espacio libre para ampliarlo. - - -STR_SCNR :Montaña Mística -STR_PARK :Montaña Mística -STR_DTLS :Construye un parque temático a partir de cero en las boscosas colinas de la Montaña Mística. - - -STR_SCNR :Pirámides Pacíficas -STR_PARK :Pirámides Pacíficas -STR_DTLS :Convierte la atracción turística de las ruinas egipcias en un próspero parque temático. - - -STR_SCNR :Maderas Viejas -STR_PARK :Maderas Viejas -STR_DTLS :Un gran parque con atracciones bien diseñadas, pero más bien anticuadas. Sustituye las viejas atracciones o añade atracciones nuevas para hacer el parque más popular. - - -STR_SCNR :Gran Muelle -STR_PARK :Gran Muelle -STR_DTLS :Convierte el muelle de esta mortecina ciudad en una próspera atracción. - - -STR_SCNR :Picos del Rayo -STR_PARK :Picos del Rayo -STR_DTLS :Las hermosas montañas de los Picos del Rayo son muy populares entre excursionistas y turistas. Utiliza el terreno disponible para atraer a una nueva clientela en busca de atracciones de riesgo. - - -STR_SCNR :Torres de marfil -STR_PARK :Torres de marfil -STR_DTLS :Un parque bien establecido, con algunos problemas. - - -STR_SCNR :Valle del Arcoíris -STR_PARK :Valle del Arcoíris -STR_DTLS :Las autoridades del Valle del Arcoíris no te dejarán introducir cambios paisajísticos ni eliminar árboles grandes; Aún así, debes convertir el área en un gran parque temático. - - -STR_SCNR :La Roca del Trueno -STR_PARK :La Roca del Trueno -STR_DTLS :La Roca del Trueno se encuentra en pleno desierto y atrae muchos turistas. Utiliza el espacio disponible para construir atracciones y captar más clientes. - - -STR_SCNR :Mega Parque -STR_PARK :Mega Parque -STR_DTLS :¡Por pasarlo bien! - -## Corkscrew Follies - -STR_SCNR :Colinas susurrantes -STR_PARK :Colinas susurrantes -STR_DTLS :Convierte los acantilados en un próspero parque de atracciones. - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :En el centro de este gran parque en desarrollo hay una montaña rusa de tres vías para carreras y duelos. - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Esta mina abandonada tiene posibilidades para ser convertida en atracción turística, con un ferrocarril en miniatura y un par de montañas rusas de caída en picado. - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :Dispones de un viejo puente inutilizado para convertirlo en un parque de atracciones. - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Este parque, que ocupa unos terrenos a ambos lados de una autopista, cuenta con muchas atracciones que ya están en funcionamiento. - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :Las autoridades locales han accedido a vender a este pequeño parque costero unos terrenos contiguos por un precio barato, con la condición de que se conserven determinadas atracciones. - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Este castillo queda a tu entera disposición para que lo conviertas en un parque temático. - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Este parque futurista tiene sitio de sobra para nuevas atracciones en la zona de paisajes extraterrestres. - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :La población local prefiere atracciones tranquilas y relajantes. Debes expandir el parque para satisfacer sus gustos. - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :En las profundidades de la selva hay unos grandes terrenos listos para ser convertidos en un parque temático. - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :La atracción principal de este nuevo parque la constituyen los lagos escalonados. - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Este antiguo parque cuenta con numerosas atracciones históricas, pero en la actualidad se encuentra en quiebra. - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Se ha despejado y tematizado parcialmente un gran terreno que está listo para que lo conviertas en un parque con temática de paisajes. - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :Una prospera compañía frutícola ha construido un ferrocarril en miniatura para aumentar sus ingresos. Tu misión es convertirlo en un verdadero parque de atracciones. - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Dispones del área que rodea una presa para convertirla en un parque de atracciones. - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :Posees un cañón inmenso para convertirlo en parque temático. - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :El clima es tan húmedo que se ha construido una pirámide gigante para poder colocar algunas atracciones a cubierto. - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :Las autoridades locales no permitirán que se construya por encima de la altura de los árboles del parque. - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Desarrolla este parque temático romano añadiendo atracciones y montañas rusas. - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Construye parcialmente sobre una serie de islas pequeñas; este parque cuenta ya con un par de montañas rusas de gran tamaño como atracción central. - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Construye un parque que atraiga a la población local en busca de emociones fuertes. - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :El oasis situado en el centro del parque constituye una oportunidad única para construir un parque de atracciones. - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :¿Puedes devolver la vida a este antiguo parque, ahora abandonado y en ruinas? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Cuentas con un presupuesto y un tiempo limitados para reformar este parque, que esta lleno de atracciones defectuosas y peligrosas. - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :Las autoridades locales prohíben todo tipo de publicidad o propaganda de este parque, de modo que este deberá salir adelante por si mismo. - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :Una atracción de carreras de obstáculos de cuatro calles es el núcleo principal de este parque en crecimiento. - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Convierte esta cantera abandonada en un lugar que atraiga a turistas en busca de emociones fuertes. - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Tienes a tu disposición todo el tiempo necesario para convertir esta área montañosa en un enorme parque de atracciones, pero no olvides que el presupuesto con el que cuentas es limitado. - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :Un pequeño parque ha establecido un acuerdo con la ciudad vecina con el fin de ampliar su territorio. - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :Deberás convertir un gran parque con jardines en un próspero parque de atracciones. - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :Una colección de icebergs dan un gélido entorno a este ambicioso parque temático. - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :Un volcán en estado latente es el entorno para este proyecto de montaña rusa en construcción. - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Libre de cualquier límite financiero, tu reto es desarrollar este desértico parque mientras mantienes contentos a los invitados. - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Tu cometido es construir un gran parque lleno de montañas rusas en medio de Razor Rocks. - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :Un gran lago en un viejo cráter es el entorno para este parque. - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Este gran parque ya cuenta con una excelente hyper-montaña rusa, aunque tu cometido es el de aumentar significantemente sus beneficios. - - -STR_SCNR :Big Pier 2 -STR_PARK :Big Pier 2 -STR_DTLS :Muelle Paraiso ha aumentado su red de pasarelas sobre el mar, y tu cometido es el de agrandar el parque para utilizar el espacio extra. - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :Una cala frente al mar es el entorno para este proyecto de montaña rusa en construcción. - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Hay que desarrollar un castillo con un par de montañas rusas dentro de un gran parque temático. - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :Un parque que tiene gran parte de sus aceras y montañas rusas bajo tierra. - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :Tienes a tu disposición un valle lleno de glaciares para desarrollar en el un parque temático. - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :En un mundo lejano en el que el dinero no es necesario, debes construir un complejo de entretenimiento en el que tener a la gente contenta. - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Necesitan terminarse cinco montañas rusas en este desértico parque. - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :En este parque histórico solo está permitido construir atracciones al viejo estilo. - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Desarrolla este parque ajeno para maximizar sus beneficios. - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :Este buen parque de atracciones temático ya cuenta con numerosas atracciones, aunque tiene espacio suficiente para ampliarlo. - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :Un parque espeluznante con una montaña rusa gigante como atracción principal. - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Dos grandes pedazos de roca sacados de la arena del desierto, sobre los cuales se construyen los principios de este parque temático. - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :En este gran parque debes diseñar y construir diez grandes montañas rusas. - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :Una larga y estrecha isla será el desafiante entorno en el que debes construir una selección de montañas rusas. - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Un paisaje helado que tiene que convertirse en un próspero parque temático. - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :Tienes a tu disposición un desértico parque con algunas montañas rusas ingeniosamente diseñadas, para ampliarlo. - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :En este diminuto parque debes terminar de construir las cinco montañas rusas existentes. - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :Un gran parque con un novedoso sistema de transporte alrededor de su perímetro. - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Esta gran isla es toda tuya para que desarrolles en ella un parque de atracciones. - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :Un rascacielos gigante abandonado es una oportunidad única para un desarrollador de parques temáticos. - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Esta área urbana es toda tuya para que la desarrolles como parque de atracciones. - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :Un parque gigante completamente equipado con atracciones, necesita mejoras. - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :En un planeta lejano, esta zona de terreno debe convertirse en un parque temático. - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Intenta crear el parque rentable más pequeño del mundo. - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official - -[TTPIRF05] -STR_NAME :Techo - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Convierte un pequeño centro de esquí en un parque temático en la nieve. - - -STR_SCNR :Aeroparque Amity -STR_PARK :Aeroparque Amity -STR_DTLS :Construye un parque de alto vuelo en este aeropuerto abandonado. - - -STR_SCNR :Barrenas Botánicas -STR_PARK :Barrenas Botánicas -STR_DTLS :Tú desafío es construir un parque lucrativo en esta isla paradisíaca - - -STR_SCNR :Construye tu propio Six Flags Bélgica -STR_PARK :Six Flags Bélgica -STR_DTLS :Construye tu propia versión de este parque Six Flags europeo. - - -STR_SCNR :Construye tu propio Six Flags Gran Aventura -STR_PARK :Six Flags Gran Aventura -STR_DTLS :Usa tus habilidades de diseño para recrear este parque de Six Flags - - -STR_SCNR :Construye tu propio Six Flags Holanda -STR_PARK :Six Flags Holanda -STR_DTLS :Haz de este Six Flags europeo tu propio mundo de atracciones. - - -STR_SCNR :Construye tu propio Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Crea tu propia versión de este parque Six Flags de gran envergadura. - - -STR_SCNR :Contruye tu propio Six Flags sobe Tejas -STR_PARK :Six Flags sobre Tejas -STR_DTLS :Comenzando desde cero, construye las atracciones de este Six Flags tan caluroso. - - -STR_SCNR :Construye tu propio parque Six Flags -STR_PARK :Six Flags -STR_DTLS :Construye tu propio diseño de un parque Six Flags. Ya sea incluyendo atracciones de otros parques Six Flags, o poniendo tu propia impronta. - - -STR_SCNR :Bazar Ruidoso -STR_PARK :Bazar Ruidoso -STR_DTLS :Comenzando desde un pequeño mercado, tu desafío es aumentar los ingresos de los negocios y puestos mediante la construcción de atracciones y montañas rusas para atraer a más clientes. - - -STR_SCNR :Castillo Loco -STR_PARK :Castillo Loco -STR_DTLS :Has heredado un gran castillo. Tu trabajo es convertirlo en un pequeño parque temático. - - -STR_SCNR :Greens polvorientos -STR_PARK :Greens polvorientos -STR_DTLS :Situado cerca de una unión de autopistas en el desierto, los Greens polvorientos es una oportunidad para llevar a un pequeño complejo de Golf a un pujante parque temático. - - -STR_SCNR :Campos Eléctricos -STR_PARK :Campos Eléctricos -STR_DTLS :Has heredado una pequeña granja, y tu desafío es construir un pequeño parque temático entre los maices y graneros. - - -STR_SCNR :Alturas Extremas -STR_PARK :Alturas Extremas -STR_DTLS :Libre de restricciones financieras, el desafío será expandir este parque del desierto para atraer gente que busca la emoción definitiva. - - -STR_SCNR :Tope de Fábrica -STR_PARK :Tope de Fábrica -STR_DTLS :Un complejo fabril abandonado es la oportunidad perfecta para construir un parque temático mecanizado. - - -STR_SCNR :Maderas Fungosas -STR_PARK :Maderas Fungosas -STR_DTLS :Restringido a solo construir atracciones de madera del viejo estilo, tú desafío será construir un próspero parque temático en Maderas Fungosas - - -STR_SCNR :Pueblo Fantasma -STR_PARK :Pueblo Fantasma -STR_DTLS :Constratado por una gran cadena de parque de atracciones, tu tarea será construir para ellos un gigantesco parque alrededor de una ciudad minera abandonada. - - -STR_SCNR :Jardines Gravitacionales -STR_PARK :Jardines Gravitacionales -STR_DTLS :Tu desafío es construir un parque de montañas rusas en los bellos Jardines Gravitacionales. ¡Ninguna otra atracción, sólo Montañas Rusas! - - -STR_SCNR :Vistas Infernales -STR_PARK :Vistas Infernales -STR_DTLS :Un parque colocado precariamente sobre roca volcánica (principalmente basalto) con ríos de lava. - - -STR_SCNR :Lago Suerte -STR_PARK :Lago Suerte -STR_DTLS :Con fondos ilimitados pero una ubicación desafiante, este parque será difícil de expandir y administrar. - - -STR_SCNR :Cresta Arcoíris -STR_PARK :Cresta Arcoíris -STR_DTLS :Construido en una ladera, este parque la tiene difícil para construir algo alto. ¿Podrás expandir este parque y hacerlo exitoso? - - -STR_SCNR :Six Flags Bélgica -STR_PARK :Six Flags Bélgica -STR_DTLS :Prueba tu capacidad para administrar y mejorar este parque Six Flags. - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Construye las atracciones Six Flags faltantes, o crea tus propios diseños para mejorar el parque. Sólo no te olvides el objetivo principal. ¡Atraer más visitantes al parque! - - -STR_SCNR :Six Flags Holanda -STR_PARK :Six Flags Holanda -STR_DTLS :Prueba tu capacidad para administrar y mejorar este parque Six Flags. - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Construye las atracciones Six Flags faltantes, o crea tus propios diseños para mejorar el parque. Sólo no te olvides el objetivo principal. ¡Pagar el préstamo y mantener el valor del parque! - - -STR_SCNR :Six Flags sobre Tejas -STR_PARK :Six Flags sobre Tejas -STR_DTLS :Construye las atracciones Six Flags faltantes, o crea tus propios diseños para mejorar el parque. Sólo no te olvides el objetivo principal. ¡Atraer más visitantes al parque! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Minas de África -STR_PARK :Minas de África -STR_DTLS :Has heredado una mina de diamantes en desuso, y has encontrado un valioso diamante. Has decidido invertir ese dinero en construir un parque temático de fama mundial. - - -STR_SCNR :Locura de espejismo -STR_PARK :Locura de espejismo -STR_DTLS :Se ha descubierto un oasis en el desierto, y constituye un hermoso lugar para un parque. También se han proporcionado los medios de transporte hasta el oasis. - - -STR_SCNR :Sobre el borde -STR_PARK :Sobre el borde -STR_DTLS :Se ha construido una presa que ofrece abundante y barata energía hidroeléctrica con la que suministrar a un parque. Tendrás que alcanzar un alto valor de parque para poder devolver el dinero del préstamo para la presa. - - -STR_SCNR :Aventuras heladas -STR_PARK :Aventuras heladas -STR_DTLS :La agencia de medio ambiente recurre a ti para transformar una vieja refinería, en una atracción turística de primera. El terreno es barato, pero los intereses son elevados. Puedes vender los viejos edificios como chatarra. - - -STR_SCNR :Gran Muralla China -STR_PARK :Gran Muralla China -STR_DTLS :Las autoridades han decidido mejorar el turismo en torno a la Gran Muralla construyendo un parque temático en el terreno adyacente. ¡El dinero no es un problema - - -STR_SCNR :Costa Okinawa -STR_PARK :Costa Okinawa -STR_DTLS :Un parque ya existente se ha quedado sin espacio. Tu única opción para seguir construyendo es ganarle terreno al mar, así que has pedido un préstamo. Las restricciones de altura de los edificios son obligatorias debido a los cimientos/rie… - - -STR_SCNR :Parque Maharajá -STR_PARK :Parque Maharajá -STR_DTLS :Has sido designado por el Maharajá para traer un poco de entretenimiento a la gran población local. Construye un parque inspirado en el palacio del Maharajá. - - -STR_SCNR :Aventura en Ayers -STR_PARK :Aventura en Ayers -STR_DTLS :Estás ayudando al pueblo aborigen a construir un parque como parte de un programa de concienciación cultural. Necesitas a un gran número de visitantes para instruirles acerca de la herencia única del pueblo aborigen. - - -STR_SCNR :Bárbara barbacoa playera -STR_PARK :Bárbara barbacoa playera -STR_DTLS :El parque marino de un empresario local se ha arruinado. Tú ya tienes un pequeño parque y tienes que ganar suficiente dinero para comprar el otro parque a la compañía de construcción. Tendrás que desarrollar tu propio parque para crea… - - -STR_SCNR :Extravagancia europea -STR_PARK :Extravagancia europea -STR_DTLS :Te han traído aquí para que te ocupes de una atracción europea cultural para visitantes, y tienes que aumentar el número de asistentes para poder devolver el subsidio de la UE al final del periodo parlamentario europeo actual. - - -STR_SCNR :Desde las cenizas -STR_PARK :Desde las cenizas -STR_DTLS :Un viejo parque se encuentra en mal estado. Has recibido una subvención de la Unión Europea para devolver a esta depauperada área a su antigua gloria. Tendrás que renovar el parque y ganar lo suficiente para pagar la subvención. - - - -STR_SCNR :Waikiki Guay -STR_PARK :Waikiki Guay -STR_DTLS :Las gentes de Hawai se han aburrido de practicar surf y ahora buscan algo más intenso. Tienes que construir un parque para satisfacerlos, y conservar alto el índice de atractivo turístico del área. - - -STR_SCNR :Calamidades en el cañon -STR_PARK :Calamidades en el cañon -STR_DTLS :Debes construir un parque en el terreno que hay a ambos lados de este tesoro natural, aunque tienes la oportunidad de comprar las tierras vecinas a los indios nativos americanos. Tendrás que cumplir el objetivo de mantener a la población … - - -STR_SCNR :Paraíso de montañas rusas -STR_PARK :Paraíso de montañas rusas -STR_DTLS :Eres un exitoso magnate de los negocios que se ha tomado cuatro años sabáticos. Tu deseo es construir un parque sin limitaciones de dinero. - - - -STR_SCNR :Fundador de la ciudad perdida -STR_PARK :Fundador de la ciudad perdida -STR_DTLS :Para impulsar aún más el turismo local, tienes que construir un parque que esté en sintonía con el entorno que lo rodea. - - -STR_SCNR :Aventuras en la selva -STR_PARK :Aventuras en la selva -STR_DTLS :En esta valiosa selva el espacio es limitado, tendrás que apretujarte tanto como puedas en el claro existente, con el fin de proporcionar una alternativa viable para la industria maderera local. - - -STR_SCNR :Costas de Sugarloaf -STR_PARK :Costas de Sugarloaf -STR_DTLS :Gestionas un pequeño parque cerca de Río, pero el banco te ha retirado su préstamo. Tendrás que aumentar rápidamente tu capacidad de ganancias para pagar esta deuda inesperada. - - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :El castillo en el risco -STR_PARK :El castillo en el risco -STR_DTLS :Los miembros de una asociación local de recreación de batallas históricas se toman su afición muy en serio. Te han confiado la construcción de un parque temático de la edad media en los terrenos del Castillo del risco. - - -STR_SCNR :El bosque de Sherwood -STR_PARK :El bosque de Sherwood -STR_DTLS :Para quitarles el dinero a los ricos y dárselo a los pobres, tus alegres compañeros y tú habéis decidido construir un parque temático en el bosque de Sherwood. - - -STR_SCNR :Exceso extraterrestre -STR_PARK :Exceso extraterrestre -STR_DTLS :¡Se ha descubierto vida en un planeta distante Construye un parque temático basado en los extraterrestres para sacar dinero del interés sin precedentes que ha despertado el tema. - - -STR_SCNR :Ciudad Géminis -STR_PARK :Ciudad Géminis -STR_DTLS :Demuestra tu inventiva y utópica visión del futuro, crea un parque de diseño futurista que incorpore atracciones de última tecnología. - - -STR_SCNR :Animatrónica de los antiguos -STR_PARK :Animatrónica de los antiguos -STR_DTLS :Se te ha encargado dirigir y mejorar un parque temático ya existente sobre unos antiguos estudios de cine. Rinde tributo a los pioneros de las animaciones que fueron los primeros en llevar a la gran pantalla las criaturas míticas. - - -STR_SCNR :Locura mitológica -STR_PARK :Locura mitológica -STR_DTLS :Posees una isla de cierto valor arqueológico. Has decidido financiar su conservación construyendo un parque temático basado en la riqueza de la tradición mitológica de la zona. - - -STR_SCNR :Carnicería en el cráter -STR_PARK :Carnicería en el cráter -STR_DTLS :Posees un antiguo cráter de meteorito. Siguiendo una clara vocación industrial, has decidido construir un parque temático de asteroides y convertir tus tierras aparentemente sin valor en una considerable fortuna. - - -STR_SCNR :Montañasauro -STR_PARK :Montañasauro -STR_DTLS :Tu misión es construir un parque de atracciones basado en el jurásico. Para optimizar el acceso de los visitantes a las exóticas exhibiciones de plantas y animales, tendrás que construir atracciones que suban y bajen del valle. - - -STR_SCNR :Un paseo por las piedras -STR_PARK :Un paseo por las piedras -STR_DTLS :Para combatir a los promotores de una autopista y preservar los antiguos círculos de piedra, debes construir un parque temático de la edad de piedra y hacerlo rentable. Pero atraer visitantes no es fácil por el terreno poco acogedor. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :La infame isla prisión, antes habitada por contrabandistas y estafadores, ahora está a la venta. Has decidido convertirla en una atracción turística de primer orden ¡y el dinero no es un problema - - -STR_SCNR :Las costas de Schneider -STR_PARK :Las costas de Schneider -STR_DTLS :En pocos años se cumplirá el 75 aniversario de la victoria de tu abuelo en la copa Schneider. Vas a honrar su logro construyendo un parque temático basado en la famosa carrera de hidroaviones. - - -STR_SCNR :Metrópolis -STR_PARK :Metrópolis -STR_DTLS :Posees una parcela vacía en la parte baja de la ciudad. Para exprimir al máximo tu propiedad, decides construir un parque temático basado en los rascacielos y la arquitectura Art Decó de los años veinte. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :En tus tierras se desarrolla todos los años un gran festival musical. Construye un parque temático para mantener a la audiencia entretenida. - - -STR_SCNR :La resurrección del Rock & Roll -STR_PARK :La resurrección del Rock & Roll -STR_DTLS :Este antiguo parque temático ha visto tiempos mejores. Ayuda al propietario a darle un aspecto más rockanrolero y convierte el lugar en un negocio próspero. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Mundo Panda -STR_PARK :Mundo Panda -STR_DTLS :Añade más atracciones y consigue más visitantes en este parque pandatemático. - - -STR_SCNR :Parque Tycoon -STR_PARK :Parque Tycoon -STR_DTLS : - -### - -STR_SCNR :Loma del cementerio -STR_PARK :Loma del cementerio -STR_DTLS :Esto es halloween, el Halloween UCES, ¡las calabazas gritan en la oscuridad de la noche! Este cementerio está en problemas y tu trabajo es salvarlo, ¡mientras dejas que los muertos descansen en paz! ¿Podrás mantener a los fantasmas en sus tumbas y escalofriar a tus clientes?{NEWLINE}Autor: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :El Faro de Alejandría -STR_PARK :El Faro de Alejandría -STR_DTLS :Alejandro construyó la ciudad; griegos, romanos y egipcios dejaron su huella. Pero el mayor honor fue una Maravilla del Mundo Antiguo - el Faro. ¡Visítalo y construye un parque!{NEWLINE}Autor: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Tal y como era en el día de su inauguración - 18 de mayo de 1905.{NEWLINE}Autor: Aetherwave - - -STR_SCNR :Monte Vesubio -STR_PARK :Monte Vesubio -STR_DTLS :Pompeya y Herculano fueron sepultadas por el Vesubio en el año 79 d.C. ¡Visita las excavaciones y construye un parque!{NEWLINE}Autor: Katatude - - -STR_SCNR :La caja de arena -STR_PARK :La caja de arena -STR_DTLS :Lo que todo el mundo quiere - ¡una caja de arena! Así que coge tu cubito y pala, ¡y a construir un parque!{NEWLINE}Autor: Katatude - - -STR_SCNR :Cataratas y Cañón del Niágara -STR_PARK :Cataratas del Niágara -STR_DTLS :La catarata Estadounidense, la catarata Velo de Novia y la catarata Canadiense en la frontera del Niágara, 1850.{NEWLINE}Autor: Katatude - - -STR_SCNR :Mineros de las Montañas Rocosas -STR_PARK :Mineros de las Montañas Rocosas -STR_DTLS :Un desprendimiento de rocas ha dañado tu ferrocarril. Tus trabajadores se han ido de exploración. ¿Hay oro en las montañas rusas?{NEWLINE}Autores: Squid, Buckone, Fossil - - -STR_SCNR :La Máquina del Tiempo -STR_PARK :La Máquina del Tiempo -STR_DTLS :La Máquina del Tiempo. Construida para ir - cuando quieras, donde quieras. La eternidad espera. Todo es relativo.{NEWLINE}Autor: Katatude - - -STR_SCNR :Torre de Babel -STR_PARK :Torre de Babel -STR_DTLS :¡Whoaa! ¡Mira dónde nos ha llevado la Máquina del Tiempo! ¿Dónde se ha ido todo el mundo?{NEWLINE}Autor: Fossil - - -STR_SCNR :Transformación -STR_PARK :Transformación -STR_DTLS :Te estábamos esperando…{NEWLINE}Autor: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :Los romanos están cansados de las aburridas luchas de gladiadores. Dales una emoción mejor, ¡convierte una ciudad romana en el mayor parque de atracciones de todos los tiempos!{NEWLINE}Autor: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Bajo el Árbol de Navidad -STR_PARK :País de las Maravillas Invernal -STR_DTLS :Mamá construyó esta escena bajo nuestro árbol. ¡Ahora quiere que construyamos un parque en ella! ¿Puedes ayudar?{NEWLINE}Autor: Katatude - - -STR_SCNR :Explosión en Rocagrande -STR_PARK :Explosión en Rocagrande -STR_DTLS :Tras una explosión en la Compañía Minera Rocagrande, los habitantes de Rocagrande tienen que construir un parque de atracciones para mantener vivo su pueblo.{NEWLINE}Autores: rbarclay & buckone - - -STR_SCNR :Campamento Ruiseñor -STR_PARK :Campamento Ruiseñor -STR_DTLS :¡Sólo 500$/semana para ir a este campamento de verano! Abre tu banco y después diviértete construyendo un parque. {NEWLINE}Autor: Katatude - - -STR_SCNR :Pueblo Choo-Choo -STR_PARK :Pueblo Choo-Choo -STR_DTLS :¡Mami! ¡Papi! !Quiero ir al pueblo Coo-Choo!{NEWLINE}Autor: Fossil - - -STR_SCNR :Archipiélago Dragon -STR_PARK :Archipiélago Dragon -STR_DTLS :¿Archipiélago Dragon? No estoy seguro de querer ir ahí…{NEWLINE}Autor: Fossil - - -STR_SCNR :Carnaval Infantil II -STR_PARK :Carnaval Infantil -STR_DTLS :¡Hey, chavales! ¡Vamos a divertirnos!{NEWLINE}Autores: Piehead & Fossil - - -STR_SCNR :Sand Dune -STR_PARK :Sand Dune -STR_DTLS :Como propietario de un pequeño parque, has comprado un gran terreno junto a la playa para ampliarlo y atraer a más visitantes a las hermosas dunas, pero cuidado: no puedes perturbar esas dunas ecológicamente frágiles.{NEWLINE}Autor: rbarclay diff --git a/data/language/fi-FI.txt b/data/language/fi-FI.txt index 1fdd738839..9314d9385c 100644 --- a/data/language/fi-FI.txt +++ b/data/language/fi-FI.txt @@ -3788,861 +3788,3 @@ STR_6706 :{WINDOW_COLOUR_2}Valittu kuvatiedosto: {BLACK}{STRING} STR_6707 :(ei mitään) STR_6708 :Tasoitusvoimakkuus STR_6709 :Anna tasoitusvoimakkuus väliltä {COMMA16}-{COMMA16} - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Metsämaan mekastus -STR_PARK :Metsämaan mekastus -STR_DTLS :Metsän syövereihin on raivattu laaja alue, johon voit rakentaa kukoistavan huvipuiston - - -STR_SCNR :Dynamiittidyynit -STR_PARK :Dynamiittidyynit -STR_DTLS :Aavikon keskelle on rakennettu puisto, jossa on vain yksi vuoristorata, mutta tilaa laajennukseen - - -STR_SCNR :Juurijärvi -STR_PARK :Juurijärvi -STR_DTLS :Tyhjästä aloittaen, rakenna teemapuisto suuren järven ympärille - - -STR_SCNR :Timanttimäki -STR_PARK :Timanttimäki -STR_DTLS :Timanttimäki on jo menestyksekäs teemapuisto, jossa on hyviä laitteita - kehitä puiston arvo kaksinkertaiseksi - - -STR_SCNR :Ikivihreä puutarha -STR_PARK :Ikivihreä puutarha -STR_DTLS :Muunna kaunis puutarha menestyväksi huvipuistoksi - - -STR_SCNR :Riemuranta -STR_PARK :Riemuranta -STR_DTLS :Kehitä Riemurannan pienestä huvipuistosta kukoistava teemapuisto - - -STR_SCNR :Kolmikkosaaret -STR_PARK :Kolmikkosaaret -STR_DTLS :Tämän upouuden huvipuiston pohjana toimii tämä saariryhmä - - -STR_SCNR :Ullan unelmapuisto -STR_PARK :Ullan unelmapuisto -STR_DTLS :Pieni huvipuisto, jossa on muutama laite ja tilaa laajentaa. Tehtävänäsi on tuplata puiston arvo. - - -STR_SCNR :Pikkupuisto -STR_PARK :Pikkupuisto -STR_DTLS :Pieni ja ahdas huvipuisto, joka on kattavan laajennuksen tarpeessa - - -STR_SCNR :Valkokosken puisto -STR_PARK :Valkokosken puisto -STR_DTLS :Puisto, jossa on pari mainiota vesilaitetta kaipaa laajennusta - - -STR_SCNR :Kimalluskaivokset -STR_PARK :Kimalluskaivokset -STR_DTLS :Muunna iso hylätty kaivos matkailukohteesta teemapuistoksi - - -STR_SCNR :Ratoja ja ratoja -STR_PARK :Ratoja ja ratoja -STR_DTLS :Metsään piilotettu suuri puisto, jossa on vain mikroautoratoja ja puisia vuoristoratoja - - -STR_SCNR :Mellun maailma -STR_PARK :Mellun maailma -STR_DTLS :Tässä huvipuistossa on muutama hyvin suunniteltu moderni laite, mutta myös paljon tilaa laajennukseen - - -STR_SCNR :Salakallio -STR_PARK :Salakallio -STR_DTLS :Rakenna upouusi huvipuisto Salakallion mäkiseen metsään - - -STR_SCNR :Ponnekkaat pyramidit -STR_PARK :Ponnekkaat pyramidit -STR_DTLS :Muunna egyptiläiset rauniot menestyväksi huvipuistoksi - - -STR_SCNR :Murumetsä -STR_PARK :Murumetsä -STR_DTLS :Suuri puisto, jossa on hyvin suunniteltuja mutta aika vanhoja laitteita. Korvaa vanhat laitteet tai rakenna uusia nostaaksesi puiston suosiota. - - -STR_SCNR :Eedenlaituri -STR_PARK :Eedenlaituri -STR_DTLS :Tee tästä pikkukylän laiturista menestyvä huvipuisto - - -STR_SCNR :Ukkosvuoret -STR_PARK :Ukkosvuoret -STR_DTLS :Kauniit Ukkosvuoret ovat vaeltajien ja turistien suosiossa. Käytä vapaana olevaa maata viehättääksesi enemmän jännitystä kaipaavia asiakkaita. - - -STR_SCNR :Norsunluutornit -STR_PARK :Norsunluutornit -STR_DTLS :Pitkälle kehitetty puisto, jossa on pari ongelmaa - - -STR_SCNR :Sateenkaarilaakso -STR_PARK :Sateenkaarilaakso -STR_DTLS :Sateenkaarilaakson paikallisviranomaiset eivät anna lupaa maansiirtoon tai isojen puiden kaatamiseen, mutta sinun tulee silti kehittää alueesta iso huvipuisto - - -STR_SCNR :Jyrykallio -STR_PARK :Jyrykallio -STR_DTLS :Jyrykallio seisoo keskellä aavikkoa ja vetää puoleensa paljon turisteja. Rakenna laitteita jotka vetäisivät entistä enemmän kävijöitä. - - -STR_SCNR :Megapuisto -STR_PARK :Megapuisto -STR_DTLS :Huvin vuoksi! - -## Added Attractions - -STR_SCNR :Kuikauskalliot -STR_PARK :Kuikauskalliot -STR_DTLS :Kehitä rannikkokallioista menestyvä huvipuisto - - -STR_SCNR :Kolmen apinan puisto -STR_PARK :Kolmen apinan puisto -STR_DTLS :Tämän laajan puisto keskellä on valtava kolmintaisteleva teräksinen vuoristorata - - -STR_SCNR :Kanariakaivokset -STR_PARK :Kanariakaivokset -STR_DTLS :Tämä hylätty kaivos on jo hyvää vauhtia muuttumassa matkailukohteeksi pienoisjunansa ja muutaman vuoristoradansa ansiosta - - -STR_SCNR :Simpukkasilta -STR_PARK :Simpukkasilta -STR_DTLS :Kehitä sinulle annetusta vanhasta hylätystä sillasta kukoistava huvipuisto - - -STR_SCNR :Hupitopia -STR_PARK :Hupitopia -STR_DTLS :Valtatien molemmille puolille sijoittuva puisto, jossa on jo muutama laite toiminnassa - - -STR_SCNR :Kummitussatama -STR_PARK :Kummitussatama -STR_DTLS :Paikallisviranomaiset ovat suostuneet myymään maata tämän pienen rantapuiston lähistöltä halvalla, kunhan vain tiettyjä laitteita ylläpidetään - - -STR_SCNR :Ilolinna -STR_PARK :Ilolinna -STR_DTLS :Tämä linna on annettu käsiisi teemapuiston kehitystä varten - - -STR_SCNR :Tulevaisuuden maa -STR_PARK :Tulevaisuuden maa -STR_DTLS :Tässä futuristisessa puistossa on runsaasti tilaa uusia laitteita varten - - -STR_SCNR :Lempeä laakso -STR_PARK :Lempeä laakso -STR_DTLS :Paikalliset pitävät lempeämmistä laitteista, joten laajenna puistoa heidän makunsa mukaan - - -STR_SCNR :Vinkeä viidakko -STR_PARK :Vinkeä viidakko -STR_DTLS :Viidakon syvyyksissä on laaja maa-alue, valmiina teemapuiston rakentamiseen - - -STR_SCNR :Kastekukkula -STR_PARK :Kastekukkula -STR_DTLS :Eritasoisten järvien sarja muodostaa perustan tälle uudelle huvipuistolle - - -STR_SCNR :Pirteä puisto -STR_PARK :Pirteä puisto -STR_DTLS :Tässä puistovanhuksessa on monta historiallista laitetta, mutta on pahasti velkakierteessä - - -STR_SCNR :Taikakortteli -STR_PARK :Taikakortteli -STR_DTLS :Laaja alue on raivattu ja puoliksi teemattu, valmiina teemapuiston kehitykseen - - -STR_SCNR :Hedelmätila -STR_PARK :Hedelmätila -STR_DTLS :Menestyksekäs hedelmätila on rakentanut rautatien tulojen kohentamiseksi - sinun tehtävänäsi on kehittää siitä täydellinen huvipuisto - - -STR_SCNR :Perhospato -STR_PARK :Perhospato -STR_DTLS :Tätä patoa ympäröivä alue on kuin luotu huvipuiston kehittämiseen - - -STR_SCNR :Kotkakanjoni -STR_PARK :Kotkakanjoni -STR_DTLS :Muunna tämä valtava kanjoni kukoistavaksi huvipuistoksi - - -STR_SCNR :Myrskypuisto -STR_PARK :Myrskypuisto -STR_DTLS :Ilmasto on täällä niin kostea että valtava pyramidi on rakennettu jotta jotkut laitteet voidaan rakentaa suojaan - - -STR_SCNR :Harmoniamäki -STR_PARK :Harmoniamäki -STR_DTLS :Paikallisviranomaiset eivät hyväksy puun latvoja korkeampia rakennusprojekteja - - -STR_SCNR :Roomalaiskylä -STR_PARK :Roomalaiskylä -STR_DTLS :Kehitä tätä roomalaisteemaista puistoa lisäämällä laitteita ja vuoristoratoja - - -STR_SCNR :Suolahti -STR_PARK :Suolahti -STR_DTLS :Osittain rakennettu saariryhmän päälle, tässä puistossa on jo kaksi isoa vuoristorataa keskipisteenä - - -STR_SCNR :Hurjavuori -STR_PARK :Hurjavuori -STR_DTLS :Rakenna puisto, joka tyydyttää paikallisia jännityksenjanoisia hurjapäitä - - -STR_SCNR :Utopiapuisto -STR_PARK :Utopia -STR_DTLS :Aavikon keskellä tämä keidas tarjoaa erikoisen tilaisuuden rakentaa huvipuisto - - -STR_SCNR :Laholahti -STR_PARK :Laholahti -STR_DTLS :Rikkaruohoinen ja ränsistynyt, pystytkö sinä elvyttämään tämän rappeutuneen puiston? - - -STR_SCNR :Katastrofikukkula -STR_PARK :Katastrofikukkula -STR_DTLS :Täynnä huonosti suunniteltuja ja vaarallisia laitteita, sinulla on vain vähän rahaa ja aikaa korjata ongelmat ja kääntää puiston suunta parempaan päin - - -STR_SCNR :Pikkelssipuisto -STR_PARK :Pikkelssipuisto -STR_DTLS :Paikallisviranomaiset eivät suostu minkäänlaiseen markkinointiin tai mainontaan, joten tämän puiston on menestyttävä pelkällä maineella - - -STR_SCNR :Riemuravit -STR_PARK :Riemuravit -STR_DTLS :Neliratainen hevosajelu on tämän laajentuvan puiston keskipiste - - -STR_SCNR :Mineraalipuisto -STR_PARK :Mineraalipuisto -STR_DTLS :Muunna tämä hylätty kivikaivos jännitystä kaipaavien turistien matkakohteeksi - - -STR_SCNR :Vuoristoradan räminät -STR_PARK :Vuoristoradan räminät -STR_DTLS :Sinulla on rajallisesti rahaa mutta rajattomasti aikaa muuntaa tämä vuoristomaisema laajaksi vuoristoratapuistoksi - - -STR_SCNR :Urbaanipuisto -STR_PARK :Urbaanipuisto -STR_DTLS :Pikkuruinen puisto on päässyt sopimukseen puiston laajennuksesta läpi lähikylän katujen - - -STR_SCNR :Paten puutarha -STR_PARK :Paten puutarha -STR_DTLS :Valtava puutarha pitäisi muuntaa kukoistavaksi huvipuistoksi - - -## Loopy Landscapes - -STR_SCNR :Jäävuorisaaret -STR_PARK :Jäävuorisaaret -STR_DTLS :Ryhmä jäävuoria on tämän kunnianhimoisen mutta kylmän huvipuiston pohjana - - -STR_SCNR :Tappuravuori -STR_PARK :Tappuravuori -STR_DTLS :Lepotilassa oleva tulivuori on tämän vuoristoratahaasteen keskipisteenä - - -STR_SCNR :Santarinne -STR_PARK :Santarinne -STR_DTLS :Maallisista rahoitushuolista vapaana, sinun tulee kehittää tästä aavikkopuistosta kävijöitä tyydyttävä huvipuisto - - -STR_SCNR :Terälohkare -STR_PARK :Terälohkare -STR_DTLS :Tehtävänäsi on rakentaa Terälohkareiden keskuuteen valtava puisto täynnä vuoristoratoja - - -STR_SCNR :Kraaterinjärvi -STR_PARK :Kraaterinjärvi -STR_DTLS :Muinaiseen kraateriin muodostunut suuri järvi on tämän puiston sijaintina - - -STR_SCNR :Huimahuippu -STR_PARK :Huimahuippu -STR_DTLS :Tässä puistossa on jo loistava hyper-vuoristorata, mutta sinun tulee kasvattaa puiston tuottoa - - -STR_SCNR :Eedenlaituri 2 -STR_PARK :Eedenlaituri 2 -STR_DTLS :Eedenlaituri on laajentanut kulkuväylien verkostoaan meren yllä, ja tehtävänäsi on laajentaa puistoa uuteen alaan - - -STR_SCNR :Lohikäärmelahti -STR_PARK :Lohikäärmelahti -STR_DTLS :Tämä merenrannan lahti on tämän vuoristoratahaasteen sijaintina - - -STR_SCNR :Hyvän ritarin puisto -STR_PARK :Hyvän ritarin puisto -STR_DTLS :Pari vuoristorataa sisältävä linna on vailla kehitystä isompaan puistoon - - -STR_SCNR :Temmellystunneli -STR_PARK :Temmellystunneli -STR_DTLS :Puisto, jossa suuri osa poluista ja vuoristoradoista on maan alla - - -STR_SCNR :Jäätikön jäynät -STR_PARK :Jäätikön jäynät -STR_DTLS :Jäätiköitä täynnä oleva laakso on sinun huvipuiston kehitystä varten - - -STR_SCNR :Kumma kraateri -STR_PARK :Kumma kraateri -STR_DTLS :Kaukaisessa maailmassa, jossa rahalle ei ole käyttöä, sinun tulee rakentaa huvipuisto, joka pitää kävijät tyytyväisenä - - -STR_SCNR :Aava autiomaa -STR_PARK :Aava autiomaa -STR_DTLS :Viisi vuoristorataa kaipaa viimeistelyä tässä aavikkopuistossa - - -STR_SCNR :Toukkapuisto -STR_PARK :Toukkapuisto -STR_DTLS :Tämä historiallinen puisto on saanut luvan ainoastaan vanhanaikaisten laitteiden rakennukseen - - -STR_SCNR :Ikaruspuisto -STR_PARK :Ikaruspuisto -STR_DTLS :Kehitä tätä avaruusoliopuistoa korottaaksesi sen tuottoa - - -STR_SCNR :Rämeen rällätys -STR_PARK :Rämeen rällätys -STR_DTLS :Tässä hienosti maisemoidussa huvipuistossa on jo monia laitteita, mutta myös tilaa laajennukseen - - -STR_SCNR :Painajaispuisto -STR_PARK :Painajaispuisto -STR_DTLS :Pelottava puisto, jossa on valtava vuoristorata keskipisteenä - - -STR_SCNR :Jylinäkalliot -STR_PARK :Jylinäkalliot -STR_DTLS :Kaksi suurta kivenlohkaretta törröttävät hiekasta, ja niiden päälle on tarkoitus rakentaa uusi huvipuisto - - -STR_SCNR :Kahdeksankulmion puisto -STR_PARK :Kahdeksankulmion puisto -STR_DTLS :Sinun tulee suunnitella ja rakentaa kymmenen vuoristorataa tähän suureen puistoon - - -STR_SCNR :Huvisaari -STR_PARK :Huvisaari -STR_DTLS :Saaren pitkä ja kapea muoto tekee vuoristoratojen rakennuksesta haastavaa - - -STR_SCNR :Pakkaspuisto -STR_PARK :Pakkaspuisto -STR_DTLS :Jäinen maisema on kukoistavan teemapuiston pohjana - - -STR_SCNR :Etelähietikko -STR_PARK :Etelähietikko -STR_DTLS :Aavikkopuisto, jossa muutama nerokas vuoristorata on kehitettävänäsi - - -STR_SCNR :Lilliputtitorni -STR_PARK :Lilliputtitorni -STR_DTLS :Sinun tulee viimeistellä tämän pikkuruisen puiston viisi vuoristorataa - - -STR_SCNR :Mikäpuisto -STR_PARK :Mikäpuisto -STR_DTLS :Valtava puisto jota reunoittaa uraauurtava kulkuväline - - -STR_SCNR :Tyynisaari -STR_PARK :Tyynisaari -STR_DTLS :Tämä suuri saari on valmiina huvipuiston kehitykseen - - -STR_SCNR :Betoniviidakko -STR_PARK :Betoniviidakko -STR_DTLS :Jättimäinen hylätty pilvenpiirtäjä on erikoinen tilaisuus huvipuiston rakentajalle - - -STR_SCNR :Kirkuva kylä -STR_PARK :Kirkuva kylä -STR_DTLS :Tämä urbaani alue on sinun huvipuiston kehitystä varten - - -STR_SCNR :Megamaailma -STR_PARK :Megamaailma -STR_DTLS :Tämä mittava puisto on pakattu täyteen laitteita, mutta parannuksen varaa löytyy - - -STR_SCNR :Venuslampi -STR_PARK :Venuslampi -STR_DTLS :Kaukaisella planeetalla tämä alue on huvipuiston rakennusta vailla - - -STR_SCNR :Mikropuisto -STR_PARK :Mikropuisto -STR_DTLS :Kokeile rakentaa maailman pienin tuottoisa huvipuisto - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Anakronismilinnake -STR_PARK :Anakronismilinnake -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official - -[TTPIRF05] -STR_NAME :Katto - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alppiseikkailu -STR_PARK :Alppiseikkailu -STR_DTLS :Muunna pieni vuoriston hiihtokeskus lumiteemaiseksi huvipuistoksi - - -STR_SCNR :Lennokas lentokenttä -STR_PARK :Lennokas lentokenttä -STR_DTLS :Rakenna lentoteemainen huvipuisto tämän hylätyn lentokentän kupeeseen - - -STR_SCNR :Sekasortosaari -STR_PARK :Sekasortosaari -STR_DTLS :Haasteenasi on rakentaa tuottoisa puisto tälle paratiisisaarelle - - -STR_SCNR :Rakenna oma Six Flags Belgiasi -STR_PARK :Six Flags Belgia -STR_DTLS :Rakenna oma versiosi tästä eurooppalaisesta Six Flags -puistosta - - -STR_SCNR :Rakenna oma Six Flags Great Adventuresi -STR_PARK :Six Flags Great Adventure -STR_DTLS :Käytä luovia kykyjäsi tämän Six Flags -puiston jäljennykseen - - -STR_SCNR :Rakenna oma Six Flags Hollantisi -STR_PARK :Six Flags Hollanti -STR_DTLS :Rakenna tämä eurooppalainen Six Flags -puisto kuten itse haluat - - -STR_SCNR :Rakenna oma Six Flags Magic Mountainisi -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Rakenna oma versiosi tästä valtavasta Six Flags -puistosta - - -STR_SCNR :Rakenna oma Six Flags yllä Teksasisi -STR_PARK :Six Flags yllä Teksasin -STR_DTLS :Aloittaen tyhjästä, rakenna kaikki tämän Six Flags -puiston laitteet - - -STR_SCNR :Rakenna oma Six Flags -puistosi -STR_PARK :Six Flags -STR_DTLS :Rakenna oma Six Flags -puistosi - rakenna joko muiden Six Flags -puistojen laitteet, tai luo ja rakenna omat laitteesi - - -STR_SCNR :Mukavat markkinat -STR_PARK :Mukavat markkinat -STR_DTLS :Aloittaen pienestä markkinapaikasta, haasteenasi on korottaa tuottoa pelkistä kojuista rakentamalla laitteita ja vuoristoratoja kävijöitä houkuttamaan - - -STR_SCNR :Hullulinna -STR_PARK :Hullulinna -STR_DTLS :Olet perinyt ison linnan. Toimenasi on muuntaa se pieneksi teemapuistoksi. - - -STR_SCNR :Tomuviheriö -STR_PARK :Tomuviheriö -STR_DTLS :Aavikon maantien risteyksen vieressä oleva Tomuviheriö on loistava tilaisuus muuntaa pieni golf-keskus kukoistavaksi huvipuistoksi - - -STR_SCNR :Peltopuisto -STR_PARK :Peltopuisto -STR_DTLS :Olet perinyt pienen maatilan, ja haasteenasi on rakentaa pieni huvipuisto peltojen ja maatilarakennusten oheen - - -STR_SCNR :Äärivuori -STR_PARK :Äärivuori -STR_DTLS :Rahahuolien kahleista vapautettuna, haasteenasi on laajentaa tätä aavikkopuistoa houkutellen kävijöitä jotka hakevat vain kaikista jännimpiä elämyksiä - - -STR_SCNR :Tehdastemput -STR_PARK :Tehdastemput -STR_DTLS :Hylätty tehdaskompleksi on hyvä tilaisuus rakentaa mekaanisen teemainen huvipuisto - - -STR_SCNR :Sienikorpi -STR_PARK :Sienikorpi -STR_DTLS :Haasteenasi on rakentaa kukoistava teemapuisto Sienikorpeen - mutta voit ainoastaan rakentaa vanhanaikaisia puulaitteita - - -STR_SCNR :Aavekaupunki -STR_PARK :Aavekaupunki -STR_DTLS :Suuren huvipuistoketjun palkkaamana sinun tehtävänäsi on rakentaa heille mittava vuoristoratapuisto hylätyn kaivoskylän ympärille - - -STR_SCNR :Mahtilehto -STR_PARK :Mahtilehto -STR_DTLS :Haasteenasi on rakentaa vuoristoratapuisto kauniiseen Mahtilehtoon. Ei muita laitteita, ainoastaan vuoristoratoja! - - -STR_SCNR :Hiisipuisto -STR_PARK :Hiisipuisto -STR_DTLS :Puisto, joka on arveluttavasti rakennettu laavakiven päälle magmavirtojen oheen - - -STR_SCNR :Onnenjärvi -STR_PARK :Onnenjärvi -STR_DTLS :Tätä rajattomilla rahoilla mutta vaikealla järvisijainnilla varustettua puistoa on haastaavaa laajentaa ja johtaa - - -STR_SCNR :Sateenkaarikukkula -STR_PARK :Sateenkaarikukkula -STR_DTLS :Tällä mäen reunaan rakennetulla puistolla ei ole lupaa rakentaa mitään korkeaa. Pystytkö sinä laajentamaan puistoa ja tehdä siitä menestyksen? - - -STR_SCNR :Six Flags Belgia -STR_PARK :Six Flags Belgia -STR_DTLS :Kokeile tämän Six Flags -puiston johtamista ja kehitystä - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Rakenna puuttuvat Six Flags -laitteet, tai tee omat luomuksesi puiston parantamiseksi! Mutta älä unohda tärkeintä tavoitettasi: houkuttele lisää kävijöitä puistoon! - - -STR_SCNR :Six Flags Hollanti -STR_PARK :Six Flags Hollanti -STR_DTLS :Kokeile tämän Six Flags -puiston johtamista ja kehitystä - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Rakenna puuttuvat Six Flags -laitteet, tai tee omat luomuksesi puiston parantamiseksi! Mutta älä unohda tärkeintä tavoitettasi: maksa velkasi pitäen puiston arvon korkealla! - - -STR_SCNR :Six Flags yllä Teksasin -STR_PARK :Six Flags yllä Teksasin -STR_DTLS :Rakenna puuttuvat Six Flags -laitteet, tai tee omat luomuksesi puiston parantamiseksi! Mutta älä unohda tärkeintä tavoitettasi: houkuttele lisää kävijöitä puistoon! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Afrikan kaivokset -STR_PARK :Afrikan kaivokset -STR_DTLS :Olet perinyt lakkautetun timanttikaivoksen, ja löydät arvokkaan timantin. Päätät sijoittaa myyntituotot maailmankuulun teemapuiston rakentamiseen. - - -STR_SCNR :Kangastuskivaa -STR_PARK :Kangastuskivaa -STR_DTLS :Aavikosta on löydetty keidas, joka olisi loistava paikka huvipuistolle. Kuljetus keitaalle on jo hoidettu. - - -STR_SCNR :Yli reunan -STR_PARK :Yli reunan -STR_DTLS :Juuri rakennettu pato tuottaa paljon halpaa vesivoimaa, jolla voi pyörittää huvipuistoa. Sinun täytyy nostaa puiston arvoa jotta voit maksaa takaisin padon rakennuslainan. - - -STR_SCNR :Jäinen seikkailu -STR_PARK :Jäinen seikkailu -STR_DTLS :Ympäristövirasto on kääntynyt puoleesi jotta vanhan öljynjalostamon rumilus voitaisiin muuttaa huippuluokan matkailukohteeksi. Maa on halpaa mutta lainakorot pilvissä. Voit myydä vanhat rakennukset. - - -STR_SCNR :Kiinan muuri -STR_PARK :Kiinan muuri -STR_DTLS :Paikalliset viranomaiset ovat päättäneet kehittää muurin alueen matkailua rakentamalla teemapuiston naapuritontille. Maksoi mitä maksoi! - - -STR_SCNR :Okinawan ranta -STR_PARK :Okinawan ranta -STR_DTLS :Rannikon puistolta on loppunut tila. Ainoa mahdollisuutesi on rakentaa mereen, joten olet ottanut lainaa. Korkeusrajoitukset ovat voimassa perustojen ja maanjäristyksien takia. - - -STR_SCNR :Maharadža-puisto -STR_PARK :Maharadža-puisto -STR_DTLS :Maharadža on käskenyt sinut tuomaan hupia ja viihdettä runsaslukuiselle paikallisväestölle. Rakenna puisto maharadžan palatsin innoittamana. - - -STR_SCNR :Uluru-seikkailu -STR_PARK :Uluru-seikkailu -STR_DTLS :Auta aboriginaaleja rakentamaan puisto osana heidän kulttuurinedistämisohjelmaa. Sinun täytyy houkutella suuri määrä kävijöitä opettaaksesi heille aboriginaalien kulttuuriperintöä. - - -STR_SCNR :Rantakivaa -STR_PARK :Rantakivaa -STR_DTLS :Paikallisen yrittäjän akvaario on mennyt konkurssiin. Sinulla on jo pieni huvipuisto vastarannalla, ja ostat konkurssipesän rakennusyhtiöltä. Kehitä yksi yhtenäinen puisto. - - -STR_SCNR :Euro-elämyksiä -STR_PARK :Euro-elämyksiä -STR_DTLS :Sinut on tuotu ottamaan haltuun yksi Euroopan kulttuurimatkakohteista, ja sinun tulee nostaa kävijämäärää jotta voit maksaa EU-tuen takaisin ennen Euroopan parlamentin vaalikauden loppua. - - -STR_SCNR :Tuhkista nousee -STR_PARK :Tuhkista nousee -STR_DTLS :Vanha puisto on päässyt ränsistymään. Saat Euroopan unionilta apurahaa tämän puutteellisen alueen kunnostamiseen! Sinun täytyy kunnostaa puisto ja maksaa apuraha takaisin. - - -STR_SCNR :Waikikileikki -STR_PARK :Waikikileikki -STR_DTLS :Havaijin ihmiset ovat tylsistyneitä surffaukseen, ja haluavat jotain jännittävämpää. Pidä tämä mielessä kun rakennat puistoa, joka ylläpitää alueen turistiluokitusta. - - -STR_SCNR :Kanjonikepposet -STR_PARK :Kanjonikepposet -STR_DTLS :Sinun tulee rakentaa puisto rajallisen kokoiselle alueelle tämän luonnon arteen molemmin puolin. Voit ostaa lisää tilaa naapurissa olevalta alkuperäiskansalta. Tavoitteen saavutus takaa paikalliskylän selviytymisen. - - -STR_SCNR :Vuoristoratojen mekka -STR_PARK :Vuoristoratojen mekka -STR_DTLS :Olet menestyksekäs liikemies sapattivapaalla, ja haluat käyttää tämän ajan kaupunginpuiston muuttamiseksi vuoristoratojen mekaksi. Raha ei ole este! - - -STR_SCNR :Kadonnut kaupunki -STR_PARK :Kadonnut kaupunki -STR_DTLS :Edistääksesi paikallista turismia, sinun tulee rakentaa puisto, joka on ympäristönsä kaltainen. - - -STR_SCNR :Sademetsän seikkailu -STR_PARK :Sademetsän seikkailu -STR_DTLS :Tila on niukassa tässä korvaamattomassa sademetsässä - sinun täytyy ahtaa mahdollisimman paljon jo raivattuun alueeseen, jotta paikalliselle puuteollisuudelle olisi kannattava vaihtoehto. - - -STR_SCNR :Sokerileipärannikko -STR_PARK :Sokerileipärannikko -STR_DTLS :Johdat pientä puisto Rion läheisyydessä, mutta pankki vaatii lainan takaisinmaksua. Sinun täytyy pikaisesti nostaa tuottotasoa jotta voit maksaa tämän ennakoimattoman menoerän. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Linnaranta -STR_PARK :Linnaranta -STR_DTLS :Paikallinen historian elävöitysryhmä ottaa harrastuksensa aika tosissaan. He ovat luottaneet tämän rannikkolinnan käsiisi, jotta voit rakentaa uuden keskiajan teemapuiston. - - -STR_SCNR :Sherwoodin metsä -STR_PARK :Sherwoodin metsä -STR_DTLS :Vapauttaaksesi rahat rikkailta ja jakaaksesi ne köyhille, sinä ja iloiset veikkosi olette päättäneet rakentaa huvipuiston Sherwoodin metsään. - - -STR_SCNR :Avaruusolentojen aukio -STR_PARK :Avaruusolentojen aukio -STR_DTLS :Kaukaisella planeetalla on sittenkin elämää! Rakenna avaruusolio-teemapuisto lyödäksesi rahoiksi tämän ennennäkemättömän kiinnostuksen ansiosta. - - -STR_SCNR :Kaksoskaupunki -STR_PARK :Kaksoskaupunki -STR_DTLS :Näytä kekseliäs utooppinen tulevaisuuden mielikuvasi - luo futuristinen puisto, jossa on kaikki huipputekniset laitteet. - - -STR_SCNR :Animatronian antia -STR_PARK :Animatronian antia -STR_DTLS :Sinulle on annettu tehtäväksi vanhan filmistudion paikalle rakennetun toimivan teemapuiston hoito ja laajennus. Rakenna kunnianosoitus niille stop motion -animaattoreille jotka toivat myyttiset hahmot ensi kertaa valkokankaalle. - - -STR_SCNR :Mytologian magiaa -STR_PARK :Mytologian magiaa -STR_DTLS :Omistat saaren jolla on jonkinlaista arkeologista arvoa. Olet päättänyt rahoittaa tämän kulttuuriperinnön suojelua rakentamalla alueen rikkaaseen mytologiaan perustuvan teemapuiston. - - -STR_SCNR :Kraaterikivaa -STR_PARK :Kraaterikivaa -STR_DTLS :Omistat pölyisen meteorikraaterin. Bisneselämän tosimiehenä olet päättänyt rakentaa asteroidin teemapuiston ja muuntaa näennäisesti arvottoman maatilkkusi mittavaksi omaisuudeksi. - - -STR_SCNR :Vuoristosaurus -STR_PARK :Vuoristosaurus -STR_DTLS :Tehtävänäsi on rakentaa jurassisen kauden teemapuisto. Jotta kävijät pääsevät helposti näkemään eksoottisia kasveja ja eläimiä, sinun tulee rakentaa laitteita joilla pääsee laakson yli ja alle. - - -STR_SCNR :Kivikepposet -STR_PARK :Kivikepposet -STR_DTLS :Estääksesi maantien rakennuksen ja mystisten kivirenkaiden tuhoamisen, sinun pitää rakentaa kivikauden teemapuisto ja tehdä voittoa. Kävijöiden houkutus saattaa tosin olla vaikeaa, koska maasto ei ole kovin vieraanvaraista. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :Surullisenkuuluisa Vankisaari - joka oli muinoin tupaten täynnä trokareita ja gangstereita - on nyt myynnissä. Olet päättänyt muodostaa siitä korkean luokan matkailukohteen, eikä rahalla ole niinkään väliä. - - -STR_SCNR :Schneiderrannat -STR_PARK :Schneiderrannat -STR_DTLS :Isoisäsi Schneider-nopeuskisan voitosta tulee kohta 75 vuotta täyteen. Kunnioita hänen saavutustaan rakentamalla teemapuisto tämän maineikkaan vesilentokonekilvan ympärille. - - -STR_SCNR :Metropoli -STR_PARK :Metropoli -STR_DTLS :Omistat tyhjän tontin pienasutusalueen vieressä. 20-luvun art deco -arkkitehtuurin innoittamana rakenna pilvenpiirtäjien teemapuisto puristaaksesi kaupunkitontistasi viimeisetkin tuoton pisarat. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Suuri vuosittainen musiikkifestivaali järjestetään maillasi. Rakenna tajuntaa laajentava huvipuisto vapaamielisen yleisön viihdyttämiseen. - - -STR_SCNR :Rock ’n’ rollin kukoistus -STR_PARK :Rock ’n’ rollin kukoistus -STR_DTLS :Tämä vanha huvipuisto on nähnyt parempia päiviä. Auta sen omistajaa antamalla sille retron rock ’n’ roll -muodonmuutoksen, joka tekee puistosta menestyksekkään viihdekeskuksen. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Pandamaailma -STR_PARK :Pandamaailma -STR_DTLS :Rakenna lisää laitteita ja houkuttele lisää kävijöitä tähän panda-teemaiseen puistoon - - -STR_SCNR :Pohattapuisto -STR_PARK :Pohattapuisto -STR_DTLS : - -### - -STR_SCNR :Kalmistokallio -STR_PARK :Kalmistokallio -STR_DTLS :Nyt on halloween, UCES halloween, kurpitsat kirkuvat öisin tääl’! Tämä hautausmaa on pulassa, ja vain sinä voit sen pelastaa - kunhan annat vainajien levätä rauhassa! Pystytkö pitämään kummitukset haudoissaan, ja kävijät värinöissään?{NEWLINE}Tekijä: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :Faroksen majakka -STR_PARK :Faroksen majakka -STR_DTLS :Aleksanteri rakensi kaupunkinsa; kreikkalaiset, roomalaiset, ja egyptiläiset jättivät jälkensä. Mutta kaupungin suurin kunnia on yksi vanhan maailman seitsemästä ihmeestä - Faroksen majakka. Vieraile ja rakenna puisto!{NEWLINE}Tekijä: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Aivan kuten se oli avajaispäivänään - 18. toukokuuta 1905.{NEWLINE}Tekijä: Aetherwave - - -STR_SCNR :Vesuvius -STR_PARK :Vesuvius -STR_DTLS :Pompejin ja Herculaneumin kaupungit hautautuivat Vesuviuksen purkauduttua vuonna 79. Vieraile kaivauspaikalla, ja rakenna puisto!{NEWLINE}Tekijä: Katatude - - -STR_SCNR :Hiekkalaatikko -STR_PARK :Hiekkalaatikko -STR_DTLS :Se, mitä kaikki aina haluavat - hiekkalaatikko! Tartu siis ämpäriin ja lapioon, ja rakenna puisto!{NEWLINE}Tekijä: Katatude - - -STR_SCNR :Niagaran putoukset -STR_PARK :Niagaran putoukset -STR_DTLS :American Falls, Bridal Falls ja kanadalainen Horseshoe Falls, Niagaran rajaseudulla vuonna 1850.{NEWLINE}Tekijä: Katatude - - -STR_SCNR :Kalliovuorten kaivos -STR_PARK :Kalliovuorten kaivos -STR_DTLS :Maavyöry tukki rautatien. Työntekijäsi lähtivät tutkimuksille. Onko vuoristoradoissa sittenkin kultaa?{NEWLINE}Tekijät: Squid, Buckone, Fossil - - -STR_SCNR :Aikakone -STR_PARK :Aikakone -STR_DTLS :Aikakone. Rakenna mennäksesi mihin vain, milloin vain. Ikuisuus odottaa. Kaikki on suhteellista.{NEWLINE}Tekijä: Katatude - - -STR_SCNR :Baabelin torni -STR_PARK :Baabelin torni -STR_DTLS :Oho! Mihinkäs aikakone nyt meidät toi? Mihin kaikki häipyivät?{NEWLINE}Tekijä: Fossil - - -STR_SCNR :Muutos -STR_PARK :Muutos -STR_DTLS :Olemme odottaneet teitä…{NEWLINE}Tekijä: Fossil - - -STR_SCNR :Urbis incognitus -STR_PARK :Urbis incognitus -STR_DTLS :Roomalaiset ovat kyllästyneitä tylsiin gladiaattoritaisteluihin. Näytä heille mitä todellinen huvitus on, muuttamalla roomalaiskaupunki kaikkien aikojen mahtavimmaksi huvipuistoksi!{NEWLINE}Tekijä: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Alla joulupuun -STR_PARK :Talven ihmemaa -STR_DTLS :Äiti rakensi tämän dioraaman joulukuusen alle. Nyt hän haluaa sinne huvipuiston! Pystytkö auttamaan?{NEWLINE}Tekijä: Katatude - - -STR_SCNR :Jättikiven jytky -STR_PARK :Jättikiven jytky -STR_DTLS :Jättikiven Kaivokset Oy:n räjähdysonnettomuuden jälkeen Jättikiven kylän asukkaat ovat rakentaneet huvipuiston kylänsä elinkeinoksi.{NEWLINE}Tekijät: rbarclay ja buckone - - -STR_SCNR :Matkijalinnun leiri -STR_PARK :Matkijalinnun leiri -STR_DTLS :Kesäleirille, vain 500€/viikko! Tili tyhjäksi, ja tule pitämään hauskaa puiston rakennuksen ohessa.{NEWLINE}Tekijä: Katatude - - -STR_SCNR :Tsuku-tsuku-kylä -STR_PARK :Tsuku-tsuku-kylä -STR_DTLS :Äiti! Isä! Tahdon mennä Tsuku-tsuku-kylään!{NEWLINE}Tekijä: Fossil - - -STR_SCNR :Lohikäärmesaaret -STR_PARK :Lohikäärmesaaret -STR_DTLS :Lohikäärmesaaret? En ole varma, haluanko mennä sinne…{NEWLINE}Tekijä: Fossil - - -STR_SCNR :Kakarakarnevaali II -STR_PARK :Kakarakarnevaali -STR_DTLS :Hei muksut! Pidetään hauskaa!{NEWLINE}Tekijät: Piehead ja Fossil - - -STR_SCNR :Hiekkadyyni -STR_PARK :Hiekkadyyni -STR_DTLS :Pienen puiston omistajana ostit valtavan rantatontin kävijöitä houkuttelevaa laajennusta varten. Mutta varo: et saa häiritä ekologisesti herkkiä hiekkadyynejä.{NEWLINE}Tekijä: rbarclay diff --git a/data/language/fr-FR.txt b/data/language/fr-FR.txt index 96aff33012..7890d42f35 100644 --- a/data/language/fr-FR.txt +++ b/data/language/fr-FR.txt @@ -3738,861 +3738,3 @@ STR_6657 :Terrain libre STR_6658 :Définir ce terrain comme n’appartenant pas au parc ni disponible à l’achat STR_6659 :Les visiteurs ignorent les prix STR_6660 :Les visiteurs ignoreront le prix des attractions et des boutiques - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Frontières Forestières -STR_PARK :Frontières Forestières -STR_DTLS :Au cœur de la forêt, construisez un parc à thème florissant dans une grande zone ouverte. - - -STR_SCNR :Dunes Dynamite -STR_PARK :Dunes Dynamite -STR_DTLS :Construit au milieu du desert, ce parc à thème n’a qu’une seule montagne russe mais a de la place pour s’agrandir. - - -STR_SCNR :Lac Luxuriant -STR_PARK :Lac Luxuriant -STR_DTLS :En partant de rien, construisez un parc à thème autour d’un grand lac. - - -STR_SCNR :Monts Diamant -STR_PARK :Monts Diamant -STR_DTLS :Monts Diamant est déjà un parc à thème très coté avec des attractions géniales — développez-le et doublez sa valeur. - - -STR_SCNR :Jardins Verdoyants -STR_PARK :Jardins Verdoyants -STR_DTLS :Transformez les magnifiques Jardins Verdoyants en un parc à thème florissant. - - -STR_SCNR :Plage Bourdonnante -STR_PARK :Plage Bourdonnante -STR_DTLS :Transformez le petit parc d’attractions de Plage Bourdonnante en un parc à thème florissant. - - -STR_SCNR :Îles Trinité -STR_PARK :Îles Trinité -STR_DTLS :Plusieurs îles constituent la base de ce nouveau parc. - - -STR_SCNR :Monde de Katie -STR_PARK :Monde de Katie -STR_DTLS :Un petit parc à thème avec peu d’attractions et peu de place pour s’agrandir. Votre mission est de doubler la valeur du parc. - - -STR_SCNR :Parc Minus -STR_PARK :Parc Minus -STR_DTLS :Un tout petit parc d’attractions à l’étroit qui a vraiment besoin de s’agrandir. - - -STR_SCNR :Parc Eau Pure -STR_PARK :Parc Eau Pure -STR_DTLS :Un parc avec quelques attractions aquatiques géniales qui a besoin de s’agrandir. - - -STR_SCNR :Mines Millennium -STR_PARK :Mines Millennium -STR_DTLS :Transformez une grande mine abandonnée qui fait la curiosité des touristes en un parc à thème. - - -STR_SCNR :Karts & Grands Huit -STR_PARK :Karts & Grands Huit -STR_DTLS :Un grand parc caché dans la forêt, avec uniquement des pistes de karting et des montagnes russes en bois. - - -STR_SCNR :Monde de Mel -STR_PARK :Monde de Mel -STR_DTLS :Ce parc à thème a quelques attractions modernes bien conçues, mais plein d’espace pour son expansion. - - -STR_SCNR :Montagnes Mystiques -STR_PARK :Montagnes Mystiques -STR_DTLS :Dans les forêts vallonnées des Montagnes Mystiques, construisez un parc à thème en partant de rien. - - -STR_SCNR :Pyramides Pacifiques -STR_PARK :Pyramides Pacifiques -STR_DTLS :Transformez les ruines égyptiennes prisées par les touristes en un parc à thème florissant. - - -STR_SCNR :Bois Craquants -STR_PARK :Bois Craquants -STR_DTLS :Un grand parc avec des attractions bien conçues mais plutôt anciennes. Remplacez les anciennes attractions ou ajoutez-en de nouvelles pour rendre le parc plus attractif. - - -STR_SCNR :Ponton Paradis -STR_PARK :Ponton Paradis -STR_DTLS :Transformez la jetée de cette ville endormie en un parc d’attractions florissant. - - -STR_SCNR :Pics Foudroyants -STR_PARK :Pics Foudroyants -STR_DTLS :Les magnifiques Pics Foudroyants sont très prisés par les randonneurs et les touristes. Utilisez le terrain disponible pour attirer une nouvelle clientèle avide de sensations fortes. - - -STR_SCNR :Tours d’Ivoire -STR_PARK :Tours d’Ivoire -STR_DTLS :Un parc bien établi, qui a quelques petits problèmes. - - -STR_SCNR :Vallée Arc-en-ciel -STR_PARK :Vallée Arc-en-ciel -STR_DTLS :Les autorités locales de la Vallée Arc-en-ciel ne permettront aucun changement dans l’aménagement du territoire ou l’abattage de gros arbres, mais vous devez transformer la zone en un grand parc à thème. - - -STR_SCNR :Roc Fracas -STR_PARK :Roc Fracas -STR_DTLS :Roc Fracas se trouve au milieu d’un désert et attire de nombreux touristes. Utilisez l’espace disponible pour construire des attractions qui attireront encore plus de personnes. - - -STR_SCNR :Mega Parc -STR_PARK :Mega Parc -STR_DTLS :Amusez-vous ! - -## Added Attractions - -STR_SCNR :Falaises Insidieuses -STR_PARK :Falaises Insidieuses -STR_DTLS :Transformer les falaises de bord de mer en parc d’attractions à succès. - - -STR_SCNR :Parc des Trois Singes -STR_PARK :Parc des Trois Singes -STR_DTLS :Au centre de ce grand parc en construction se trouvent des montagnes russes géantes en acier à triple voie. - - -STR_SCNR :Mine Canari -STR_PARK :Mine Canari -STR_DTLS :Cette mine désaffectée est un site idéal pour la construction d’un parc d’attractions, avec ses rails miniatures et ses deux montagnes russes à chute verticale. - - -STR_SCNR :Pont Baron -STR_PARK :Pont Baron -STR_DTLS :Vous pouvez transformer un vieux pont désaffecté en parc d’attractions. - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Entourant un grand axe routier, ce parc contient plusieurs attractions déjà en fonctionnement. - - -STR_SCNR :Baie des Chimères -STR_PARK :Baie des Chimères -STR_DTLS :Les autorités locales ont accepté de vendre à ce parc côtier des terrains proches à prix bas, à condition que certaines attractions soient préservées. - - -STR_SCNR :Forteresse Frivole -STR_PARK :Forteresse Frivole -STR_DTLS :À vous de transformer ce château en parc d’attractions. - - -STR_SCNR :Monde Futur -STR_PARK :Monde Futur -STR_DTLS :L’étrange paysage de ce parc futuriste offre suffisamment d’espace pour la construction de nouvelles attractions. - - -STR_SCNR :Ruisseau Reposant -STR_PARK :Ruisseau Reposant -STR_DTLS :La population locale préfère des attractions tranquilles et relaxantes ; c’est donc à vous d’adapter ce parc à ses goûts. - - -STR_SCNR :Jungle Joviale -STR_PARK :Jungle Joviale -STR_DTLS :Dans les profondeurs de la jungle se trouve une zone de terrain qui ferait un parc d’attractions parfait. - - -STR_SCNR :Monts Lacustres -STR_PARK :Monts Lacustres -STR_DTLS :Une série de lacs en dénivelé est à la base de ce nouveau parc. - - -STR_SCNR :Parc Pétillant -STR_PARK :Parc Pétillant -STR_DTLS :Ce parc assez ancien comporte de nombreuses attractions historiques mais est très endetté. - - -STR_SCNR :Quarts Magiques -STR_PARK :Quarts Magiques -STR_DTLS :Une grande zone a été dégagée et partiellement prête pour la construction d’un parc d’attractions. - - -STR_SCNR :Ferme Fruitière -STR_PARK :Ferme Fruitière -STR_DTLS :Une grosse exploitation fruitière a construit un chemin de fer miniature pour améliorer ses revenus ; à vous de le développer en parc d’attractions à succès. - - -STR_SCNR :Barrage Papillon -STR_PARK :Barrage Papillon -STR_DTLS :La zone entourant un barrage est disponible et peut être transformée en parc d’attractions. - - -STR_SCNR :Canyon Grondant -STR_PARK :Canyon Grondant -STR_DTLS :Transformez un grand canyon en parc d’attractions. - - -STR_SCNR :Parc Orageux -STR_PARK :Parc Orageux -STR_DTLS :Le temps est si humide qu’une pyramide gréante a été construite pour que certaines attractions restent à l’abri. - - -STR_SCNR :Collines Concorde -STR_PARK :Collines Concorde -STR_DTLS :Les autorités locales refuseront toute construction qui dépasse la hauteur des arbres dans ce parc. - - -STR_SCNR :Village Romain -STR_PARK :Village Romain -STR_DTLS :Développez ce parc à thème romain en en ajoutant des attractions et des montagnes russes. - - -STR_SCNR :Crique Cloaque -STR_PARK :Crique Cloaque -STR_DTLS :Construit partiellement sur de petites îles, ce parc contient déjà deux grosses montagnes russes en attractions principales. - - -STR_SCNR :Mont Adrénaline -STR_PARK :Mont Adrénaline -STR_DTLS :Construisez un parc qui plaira à la population locale en quête de sensations fortes. - - -STR_SCNR :Utopia -STR_PARK :Utopia -STR_DTLS :Une oasis en plein cœur d’un désert constitue une idée de parc originale. - - -STR_SCNR :Monts Putrides -STR_PARK :Monts Putrides -STR_DTLS :Pouvez-vous relancer ce parc envahi par la végétation et délabré qui connut jadis son heure de gloire ? - - -STR_SCNR :Forêt Faillite -STR_PARK :Forêt Faillite -STR_DTLS :Vous disposez d’un budget très limité et de peu de temps pour réparer et améliorer ce parc équipé d’attractions mal conçues et dangereuses. - - -STR_SCNR :Parc Pétrin -STR_PARK :Parc Pétrin -STR_DTLS :Les autorités locales interdisent tout type de publicité ou promotion, vous devez donc essayer de faire marcher ce parc par le bouche à oreille uniquement. - - -STR_SCNR :Pentes Glapissantes -STR_PARK :Pentes Glapissantes -STR_DTLS :L’attraction principale de ce parc en pleine expansion est un rodéo-montagnes. - - -STR_SCNR :Parc Minéral -STR_PARK :Parc Minéral -STR_DTLS :Transformez cette carrière de pierres désaffectée en un parc qui attirera les touristes en quête de sensations fortes. - - -STR_SCNR :Loopings en Folie -STR_PARK :Loopings en Folie -STR_DTLS :Vous disposez de peu de fonds mais d’un temps illimité pour transformer cette zone montagneuse en un parc de montagnes russes géant. - - -STR_SCNR :Parc Urbain -STR_PARK :Parc Urbain -STR_DTLS :Un parc minuscule a signé un accord avec la ville voisine pour autoriser son expansion dans la ville elle-même. - - -STR_SCNR :Jardins Geoffrey -STR_PARK :Jardins Geoffrey -STR_DTLS :Un grand parc de jardins doit être transformé en parc à thème prospère. - - -## Loopy Landscapes - -STR_SCNR :Îles Iceberg -STR_PARK :Îles Iceberg -STR_DTLS :Un ensemble d’icebergs constitue l’environnement glacial de cet ambitieux parc à thème. - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :Un volcan éteint est le site de ce défi à la construction de montagnes russes. - - -STR_SCNR :Hauteurs Arides -STR_PARK :Hauteurs Arides -STR_DTLS :Vous avez carte blanche pour développer ce parc désertique en assurant la joie de ses visiteurs. - - -STR_SCNR :Rocs Rasoirs -STR_PARK :Rocs Rasoirs -STR_DTLS :Vous devez construire un vaste parc rempli de montagnes russes près des Rocs Rasoirs. - - -STR_SCNR :Cratère Lacustre -STR_PARK :Cratère Lacustre -STR_DTLS :Ce parc a pour environnement un vaste lac dans un ancien cratère. - - -STR_SCNR :Vertigo -STR_PARK :Vertigo -STR_DTLS :Ce parc possède déjà un excellent tracé de super-montagnes russes, et vous devez en accroître massivement les profits. - - -STR_SCNR :Ponton Paradis 2 -STR_PARK :Ponton Paradis 2 -STR_DTLS :Ponton Paradis a étendu son réseau d’allées sur l’océan ; à vous d’exploiter cet espace en agrandissant le parc. - - -STR_SCNR :Crique du Dragon -STR_PARK :Crique du Dragon -STR_DTLS :Ce défi à la construction de montagnes russes a pour site une crique sur la côte. - - -STR_SCNR :Parc du Bon Chevalier -STR_PARK :Parc du Bon Chevalier -STR_DTLS :Vous devez développer ce château doté de deux montagnes russes en un vaste parc à thème. - - -STR_SCNR :Taupes Toquées -STR_PARK :Taupes Toquées -STR_DTLS :Un parc dont une bonne part des allées et des montagnes russes sont souterraines. - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :Il vous appartient de développer une vallée abritant un glacier en parc à thème. - - -STR_SCNR :Cratères Fumants -STR_PARK :Cratères Fumants -STR_DTLS :Vous devez construire, sur une planète éloignée où l’argent ne compte pas, un centre assurant le bonheur de la population. - - -STR_SCNR :Désert Sableux -STR_PARK :Désert Sableux -STR_DTLS :Cinq montagnes russes doivent être achevées dans ce parc désertique. - - -STR_SCNR :Parc Vermoulu -STR_PARK :Parc Vermoulu -STR_DTLS :Ce parc historique ne peut accueillir que des attractions de style ancien. - - -STR_SCNR :Parc Icarus -STR_PARK :Parc Icarus -STR_DTLS :Développez ce parc extraterrestre afin d’en maximiser les profits. - - -STR_SCNR :Marais Radieux -STR_PARK :Marais Radieux -STR_DTLS :Ce parc à thème bien choisi possède déjà quelques attractions, mais aussi une grande surface à exploiter. - - -STR_SCNR :Monts Epouvante -STR_PARK :Monts Epouvante -STR_DTLS :Un parc d’horreur dont le clou est un circuit de montagnes russes géant. - - -STR_SCNR :Rocs Fracas -STR_PARK :Rocs Fracas -STR_DTLS :Deux rochers émergeant du sable supportent les premiers éléments d’un parc à thème. - - -STR_SCNR :Parc Octogone -STR_PARK :Parc Octogone -STR_DTLS :Vous devez concevoir et construire dix montagnes russes dans ce vaste parc. - - -STR_SCNR :Îles Délices -STR_PARK :Îles Délices -STR_DTLS :Un vrai défi : implanter une sélection de montagnes russes sur une île longue et étroite. - - -STR_SCNR :Mondes Gelés -STR_PARK :Mondes Gelés -STR_DTLS :Vous devez transformer ce paysage glacé en parc à thème prospère. - - -STR_SCNR :Sable Austral -STR_PARK :Sable Austral -STR_DTLS :Vous devez étendre un parc désertique possédant déjà quelques montagnes russes intelligemment conçues. - - -STR_SCNR :Tours Ténues -STR_PARK :Tours Ténues -STR_DTLS :Vous devez achever la construction des cinq montagnes russes de ce tout petit parc. - - -STR_SCNR :Parc Nevermore -STR_PARK :Parc Nevermore -STR_DTLS :Un vaste parc entouré d’un nouveau mode de transport. - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Développez un parc d’amusement sur cette grande île. - - -STR_SCNR :Jungle Urbaine -STR_PARK :Jungle Urbaine -STR_DTLS :Un gratte-ciel géant à l’abandon : une occasion unique pour un concepteur de parc à thème. - - -STR_SCNR :Faubourg du Frisson -STR_PARK :Faubourg du Frisson -STR_DTLS :Développez un parc d’amusement dans cette zone urbaine. - - -STR_SCNR :Parc Mégagiga -STR_PARK :Parc Mégagiga -STR_DTLS :Un parc géant déjà rempli d’attractions exige des améliorations. - - -STR_SCNR :Mare Veneris -STR_PARK :Mare Veneris -STR_DTLS :Vous devez aménager en parc à thème ce terrain situé sur une planète lointaine. - - -STR_SCNR :Micro Parc -STR_PARK :Micro Parc -STR_DTLS :Essayez de créer le plus petit parc bénéficiaire du monde. - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronisme -STR_PARK :Fort Anachronisme -STR_DTLS : - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Le Grand blanc -STR_PARK :Le Grand blanc -STR_DTLS :Transformez une petite station de ski en parc d’attraction sur le thème de la neige. - - -STR_SCNR :La Piste de l’envol -STR_PARK :La Piste de l’envol -STR_DTLS :Construisez un parc d’attractions sur le thème de l’aéronautique dans cet aéroport abandonné. - - -STR_SCNR :Le Jardin d’Eden -STR_PARK :Le Jardin d’Eden -STR_DTLS :Construisez un parc très rentable sur cette île paradisiaque. - - -STR_SCNR :Construisez votre propre parc Six Flags en Belgique -STR_PARK :Six Flags Belgique -STR_DTLS :Construisez votre propre version de ce parc Six Flags européen. - - -STR_SCNR :Construisez votre propre Grande Aventure Six Flags -STR_PARK :Grande Aventure Six Flags -STR_DTLS :Utilisez vos dons de créateur pour rebâtir ce parc Six Flags. - - -STR_SCNR :Construisez votre propre parc Six Flags aux Pays-Bas -STR_PARK :Six Flags Pays-Bas -STR_DTLS :Construisez ce parc Six Flags européen comme bon vous semble. - - -STR_SCNR :Construisez votre propre Montagne Magique Six Flags -STR_PARK :Montagne Magique Six Flags -STR_DTLS :Créez votre propre version de ce gigantesque parc Six Flags. - - -STR_SCNR :Construisez votre propre parc Six Flags -STR_PARK :Six Flags -STR_DTLS :Construisez votre propre parc Six Flags : inspirez-vous des attractions des autres parcs Six Flags ou bien imaginez-les vous-même. - - -STR_SCNR :Construisez votre propre parc Six Flags au Texas -STR_PARK :Six Flags au Texas -STR_DTLS :Construisez toutes les attractions de ce parc Six Flags. - - -STR_SCNR :Le Grand bazar -STR_PARK :Le Grand bazar -STR_DTLS :Autour d’un petit marché, construisez des attractions et des montagnes russes qui permettront aux boutiques et aux magasins de s’enrichir. - - -STR_SCNR :Le Château des déments -STR_PARK :Le Château des déments -STR_DTLS :Transformez un grand château en petit parc à thème. - - -STR_SCNR :Les Sables émouvants -STR_PARK :Les Sables émouvants -STR_DTLS :Transformez ce parcours de golf, situé près d’une autoroute en plein milieu du désert, en un parc à thème enthousiasmant. - - -STR_SCNR :Les champs électriques -STR_PARK :Les Champs électriques -STR_DTLS :Vous avez hérité d’une petite ferme à partir de laquelle vous devez construire un petit parc à thème. - - -STR_SCNR :Vertigo -STR_PARK :Vertigo -STR_DTLS :Disposant de fonds illimités, vous devez développer ce parc situé dans le désert pour en faire un haut lieu de frissons. - - -STR_SCNR :L’Usine en folie -STR_PARK :L’Usine en folie -STR_DTLS :Construisez un parc d’attractions sur le thème de l’industrie dans cette usine désaffectée des plus appropriées. - - -STR_SCNR :Les Bois sauvages -STR_PARK :Les Bois sauvages -STR_DTLS :Construisez dans cette forêt un super parc à thème exclusivement réservé aux attractions en bois. - - -STR_SCNR :La Ville fantôme -STR_PARK :La Ville fantôme -STR_DTLS :En tant que nouvel employé d’une grande chaîne de parcs d’attraction, vous devez construire un parc de montagnes russes géantes autour d’une ville minière abandonnée. - - -STR_SCNR :Les Jardins de la gravité -STR_PARK :Les Jardins de la gravité -STR_DTLS :Construisez un parc constitué exclusivement de montagnes russes dans ces splendides Jardins de la gravité ! - - -STR_SCNR :Vue sur l’enfer -STR_PARK :Vue sur l’enfer -STR_DTLS :Parc niché en équilibre sur des roches de magma en fusion. - - -STR_SCNR :Lucky Lac -STR_PARK :Lucky Lac -STR_DTLS :Vous disposez de fonds illimités pour développer et gérer un parc sur ce lac en location. - - -STR_SCNR :L’Orée de l’arc-en-ciel -STR_PARK :L’Orée de l’arc-en-ciel -STR_DTLS :Ce parc a été construit sur le versant d’une colline, et ne peut donc comprendre aucune installation de grande taille. Saurez-vous malgré tout le développer et le rendre attractif ? - - -STR_SCNR :Six Flags Belgique -STR_PARK :Six Flags Belgique -STR_DTLS :Essayez de gérer et de développer ce parc Six Flags. - - -STR_SCNR :La Grande aventure Six Flags -STR_PARK :La Grande aventure Six Flags -STR_DTLS :Construisez les attractions Six Flags manquantes ou créez vos propres modèles afin d’améliorer votre parc ! Mais n’oubliez pas que votre but principal est d’attirer davantage de visiteurs dans votre parc ! - - -STR_SCNR :Six Flags Pays-Bas -STR_PARK :Six Flags Pays-Bas -STR_DTLS :Essayez de gérer et de développer ce parc Six Flags. - - -STR_SCNR :Montagne magique Six Flags -STR_PARK :Montagne magique Six Flags -STR_DTLS :Construisez les attractions Six Flags manquantes ou créez vos propres modèles afin d’améliorer votre parc ! Mais n’oubliez pas que votre but principal est de rembourser votre emprunt tout en augmentant la valeur de votre parc ! - - -STR_SCNR :Six Flags au Texas -STR_PARK :Six Flags au Texas -STR_DTLS :Construisez les attractions Six Flags manquantes ou créez vos propres modèles afin d’améliorer votre parc ! Mais n’oubliez pas que votre but principal est d’attirer davantage de visiteurs dans votre parc ! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines d’Afrique -STR_PARK :Mines d’Afrique -STR_DTLS :Vous héritez d’une mine de diamants désaffectée et découvrez un diamant de grande valeur. Vous décidez d’investir cet argent dans la construction d’un parc à thème de renommée mondiale. - - -STR_SCNR :Mirage fou -STR_PARK :Mirage fou -STR_DTLS :Une oasis offrant le cadre idéal pour un parc a été découverte dans le désert. Des moyens de transport ont été fournis. - - -STR_SCNR :Amortir la chute -STR_PARK :Amortir la chute -STR_DTLS :Un barrage offrant suffisamment de puissance hydroélectrique à faible coût pour la création d’un parc a été construit. Votre but est d’obtenir une haute rentabilité pour rembourser l’emprunt du barrage. - - -STR_SCNR :Aventures glacées -STR_PARK :Aventures glacées -STR_DTLS :L’agence pour l’environnement vous charge de transformer une vieille raffinerie de pétrole en attraction touristique de premier ordre. Le terrain n’est pas cher mais l’intérêt sur l’emprunt est élevé. Vous pouvez vendre les équipements. - - -STR_SCNR :Grande Muraille de Chine -STR_PARK :Grande Muraille de Chine -STR_DTLS :Les autorités ont décidé d’accroître le tourisme dans les environs de la Grande Muraille en construisant un parc à thème sur les terrains environnants. Aucune restriction financière. - - -STR_SCNR :Côte Okinawa -STR_PARK :Côte Okinawa -STR_DTLS :L’un de vos parcs au Japon ne peut plus s’étendre. Une seule possibilité : construire sur la mer. Vous contractez un emprunt et devez respecter des restrictions de hauteur en raison du risque de tremblement de terre. - - -STR_SCNR :Parc Maharajah -STR_PARK :Parc Maharajah -STR_DTLS :Le maharajah vous a chargé de divertir la nombreuse population locale. Construisez un parc inspiré du palais du maharajah. - - -STR_SCNR :L’aventure aborigène -STR_PARK :L’aventure aborigène -STR_DTLS :Vous aidez les Aborigènes à construire un parc s’inscrivant dans un programme de sensibilisation culturelle. Vous devez toucher un large public et l’intéresser au patrimoine authentique des Aborigènes. - - -STR_SCNR :Attractions sous les tropiques -STR_PARK :Attractions sous les tropiques -STR_DTLS :Le parc maritime d’un entrepreneur local fait faillite. Vous êtes à la tête d’un petit parc et devez trouver les fonds nécessaires au rachat de l’autre parc. Vous y parviendrez en visant la création d’un immense parc combiné. - - -STR_SCNR :L’extravagance européenne -STR_PARK :L’extravagance européenne -STR_DTLS :Vous avez été choisi pour reprendre un parc d’attractions culturel européen et devez augmenter sa fréquentation pour pouvoir rembourser les subventions européennes à la fin du mandat parlementaire européen. - - -STR_SCNR :La Renaissance -STR_PARK :La Renaissance -STR_DTLS :Un ancien parc est tombé en ruines. Vous recevez une subvention de l’Union Européenne pour rendre à cette zone défavorisée sa gloire passée. Vous devez rénover le parc et rembourser la subvention. - - -STR_SCNR :C’est parti Waikiki ! -STR_PARK :C’est parti Waikiki ! -STR_DTLS :Les habitants de Hawaii en ont assez de surfer et cherche des sensations plus fortes. Vous devez construire un parc qui les satisfera et qui garantira l’attrait touristique de la zone. - - -STR_SCNR :Pas de faille possible -STR_PARK :Pas de faille possible -STR_DTLS :Vous devez construire un parc à étendue limitée de chaque côté de ce cadeau de la nature. Vous pouvez acheter les terres avoisinantes aux Indiens locaux. Vous devez remplir cet objectif pour maintenir le nombre d’habitants dans la ville. - - -STR_SCNR :Le paradis des montagnes russes -STR_PARK :Le paradis des montagnes russes -STR_DTLS :Vous êtes un businessman accompli en période sabbatique de 4 ans, désirant construire un parc sans la moindre restriction financière. - - -STR_SCNR :Les aventuriers de la cité perdue -STR_PARK :Les aventuriers de la cité perdue -STR_DTLS :Pour dynamiser encore plus le tourisme local vous devez construire un parc en harmonie avec son environnement. - - -STR_SCNR :La forêt en folie -STR_PARK :La forêt en folie -STR_DTLS :L’espace est limité dans la précieuse forêt équatoriale : vous devez entasser les éléments autant que vous pouvez dans la clairière déjà existante, de manière à fournir une alternative à l’industrie sylvestre locale. - - -STR_SCNR :Au pied du pain de sucre -STR_PARK :Au pied du pain de sucre -STR_DTLS :Vous dirigez un petit parc près de Rio, mais la banque a demandé le remboursement de votre prêt. Vous devez rapidement augmenter votre rentabilité pour rembourser cette dette inattendue. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Château en bord de falaise -STR_PARK :Château en bord de falaise -STR_DTLS :Les sociétaires d’une association de reconstitution de combats médiévaux prennent leur activité très au sérieux. Ils vous ont chargé de construire un parc sur le thème du Moyen Âge sur les terres d’un château en bord de falaise. - - -STR_SCNR :Forêt de Sherwood -STR_PARK :Forêt de Sherwood -STR_DTLS :Pour voler l’argent des riches et le donner aux pauvres, vos joyeux compères et vous-même avez décidé de construire un parc dans la forêt de Sherwood. - - -STR_SCNR :Extravagance extraterrestre -STR_PARK :Extravagance extraterrestre -STR_DTLS :Une forme de vie a été découverte sur une autre planète. Construisez un parc sur le thème des extraterrestres pour engranger un maximum de profits. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Faites preuve de créativité et laissez parler vos talents de visionnaire en construisant un parc futuriste proposant des attractions du dernier cri. - - -STR_SCNR :Automates de l’Antiquité -STR_PARK :Automates de l’Antiquité -STR_DTLS :Vous êtes chargé(e) de rénover et d’exploiter un parc déjà existant, construit à partir d’un ancien décor de cinéma. Rendez hommage aux pionniers de l’animation d’automates qui ont donné vie à des créatures mythiques dans les salles obscures. - - -STR_SCNR :Folie mythologique -STR_PARK :Folie mythologique -STR_DTLS :Vous possédez une île contenant des trésors archéologiques. Vous avez décidé d’en financer la préservation en construisant un parc sur le thème des richesses mythologiques du site. - - -STR_SCNR :Cratère en folie -STR_PARK :Cratère en folie -STR_DTLS :Vous possédez un vieux cratère météoritique poussiéreux. Avec l’esprit d’entreprise qui vous caractérise, vous avez décidé de construire un parc sur le thème des astéroïdes et de rendre cet endroit rentable. - - -STR_SCNR :Le retour des dinosaures -STR_PARK :Le retour des dinosaures -STR_DTLS :Vous êtes chargé(e) de construire un parc sur le thème du jurassique. Pour optimiser l’accès des visiteurs aux plantes exotiques et aux exhibitions d’animaux, vous allez devoir construire des montagnes russes parcourant la vallée. - - -STR_SCNR :Promenade rocailleuse -STR_PARK :Promenade rocailleuse -STR_DTLS :Pour concurrencer les promoteurs d’autoroutes et préserver la beauté du site, vous devrez construire un parc sur le thème de l’âge de pierre et le rentabiliser. Attirer les visiteurs ne sera pas facile dans un contexte aussi inhospitalier. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :La fameuse prison, autrefois remplie de trafiquants et de racketteurs, est aujourd’hui à vendre. Vous avez décidé de la transformer en attraction touristique, sans restriction financière. - - -STR_SCNR :Course d’hydravions -STR_PARK :Course d’hydravions -STR_DTLS :Dans quelques années, ce sera le 75e anniversaire de la victoire de votre grand-père dans la Coupe Schneider. Vous allez lui rendre hommage en construisant un parc sur le thème de cette course légendaire d’hydravions. - - -STR_SCNR :Métropolis -STR_PARK :Métropolis -STR_DTLS :Vous possédez un terrain nu dans les faubourgs de la ville. Pour en tirer un maximum de revenus, construisez un parc sur le thème des gratte-ciel en vous inspirant de l’architecture art déco des années folles. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Un grand festival de musique se tient sur votre terrain chaque année. Construisez un parc sur le thème du mouvement hippie qui satisfera les amateurs du genre. - - -STR_SCNR :La renaissance du Rock & Roll -STR_PARK :La renaissance du Rock & Roll -STR_DTLS :Ce parc sur le thème du Rock & Roll a connu son heure de gloire. Aidez son propriétaire à le réaménager et à lui donner un second souffle. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Monde de Panda -STR_PARK :Monde de Panda -STR_DTLS :Ajoutez davantage d’attractions et attirez plus de visiteurs avec ce parc autour du thème du panda - - -STR_SCNR :Parc Tycoon -STR_PARK :Parc Tycoon -STR_DTLS : - -### - -STR_SCNR :Crête du cimetière -STR_PARK :Crête du cimetière -STR_DTLS :C’est Halloween, l’Halloween UCES, les citrouilles hurlent au milieu de la nuit ! Ce cimetière est en mauvaise posture et vous devez le sauver, tout en laissant les défunts reposer en paix ! Pouvez-vous garder les fantômes dans leurs tombes et faire frissonner vos clients ?{NEWLINE}Par : Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :Le Phare d’Alexandrie -STR_PARK :Le Phare d’Alexandrie -STR_DTLS :Alexandre a bâti la cité ; les Grecs, les Romains, les Égyptiens y ont laissé leur marque. Mais le plus grand accomplissement était une merveille de l’ancien monde — le Phare. Venez visiter et bâtir un parc !{NEWLINE}Par : Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Comme à son jour d’ouverture — 18 mai 1905.{NEWLINE}Par : Aetherwave - - -STR_SCNR :Le mont Vésuve -STR_PARK :Le mont Vésuve -STR_DTLS :Le mont Vésuve a enseveli Pompéi et Herculanum en 79 av. J.-C. Visitez le site de fouilles et construisez un parc !{NEWLINE}Par : Katatude - - -STR_SCNR :Le bac à sable -STR_PARK :Le bac à sable -STR_DTLS :Ce que tout le monde veut — un bac à sable ! Alors prenez votre pelle et votre râteau et contruisez un parc !{NEWLINE}Par : Katatude - - -STR_SCNR :Gorges et chutes du Niagara -STR_PARK :Chutes du Niagara -STR_DTLS :Les chutes américaines, les chutes du Voile de la Mariée et les chutes du Fer-à-Cheval sur la frontière du Niagara, 1850.{NEWLINE}Par : Katatude - - -STR_SCNR :Mineurs des montagnes Rocheuses -STR_PARK :Mineurs des montagnes Rocheuses -STR_DTLS :Un glissement de terrain a endommagé votre chemin de fer. Vos travailleurs sont partis prospecter. Y a-t-il de l’or dans les montagnes russes ?{NEWLINE}Par : Squid, Buckone, Fossil - - -STR_SCNR :La machine temporelle -STR_PARK :La machine temporelle -STR_DTLS :La machine temporelle. Construite pour partir — quand vous voulez, où vous voulez. L’éternité attend. Tout est relatif.{NEWLINE}Par : Katatude - - -STR_SCNR :La tour de Babel -STR_PARK :La tour de Babel -STR_DTLS :Ouaah ! Regardez où la machine temporelle nous a emmené ! Où est tout le monde ?{NEWLINE}Par : Fossil - - -STR_SCNR :Transformation -STR_PARK :Transformation -STR_DTLS :Nous vous attendions…{NEWLINE}Par : Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :Les Romains sont lassés des combats de gladiateurs ennuyants. Donnez-leur plus de frissons, faîtes d’une cité romaine le meilleur parc d’attractions de tous les temps !{NEWLINE}Par : Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Sous le sapin de Noël -STR_PARK :Pays de l’hiver -STR_DTLS :Maman a construit cette scène sous notre sapin. Maintenant elle veut qu’un parc y soit construit ! Pouvez-vous aider ?{NEWLINE}Par : Katatude - - -STR_SCNR :Explosion à Groscailloux -STR_PARK :Explosion à Groscailloux -STR_DTLS :Après une explosion à la Compagnie de Minage de Groscailloux, les habitants de Groscailloux doivent bâtir un parc d’attractions pour garder leur ville vivante.{NEWLINE}Par : rbarclay & buckone - - -STR_SCNR :Camp du geai moqueur -STR_PARK :Camp du geai moqueur -STR_DTLS :Seulement 500€ par semaine pour ce camp d’été ! Cassez votre tirelire et venez vous amuser et construire un parc.{NEWLINE}Par : Katatude - - -STR_SCNR :Tchoutchouville -STR_PARK :Tchoutchouville -STR_DTLS :Maman ! Papa ! Je veux aller à Tchoutchouville !{NEWLINE}Par : Fossil - - -STR_SCNR :Archipel du dragon -STR_PARK :Archipel du dragon -STR_DTLS :Archipel du dragon ? Je ne suis pas sûr de vouloir y aller…{NEWLINE}Par : Fossil - - -STR_SCNR :Carnaval des enfants II -STR_PARK :Carnaval des enfants -STR_DTLS :Eh les enfants ! Amusons-nous !{NEWLINE}Par : Piehead & Fossil - - -STR_SCNR :Dune ensablée -STR_PARK :Dune ensablée -STR_DTLS :En tant que propriétaire d’un petit parc, vous avez acheté un grand terrain le long de la plage pour vous étendre et attirer plus de visiteurs dans ces magnifiques dunes de sable, mais attention : vous ne pouvez pas perturber de fragile écosystème.{NEWLINE}Par : rbarclay - -########### -# Scenery # -########### - -## Start OpenRCT2 Official - -[TTPIRF05] -STR_NAME :Toit - -## End OpenRCT2 Official diff --git a/data/language/hu-HU.txt b/data/language/hu-HU.txt index 884d148c39..94f9869862 100644 --- a/data/language/hu-HU.txt +++ b/data/language/hu-HU.txt @@ -3778,850 +3778,3 @@ STR_6706 :{WINDOW_COLOUR_2}Jelenlegi képfájl: {BLACK}{STRING} STR_6707 :(nincs kiválasztva) STR_6708 :Simítási erősség STR_6709 :Add meg a simítási erősséget {COMMA16} és {COMMA16} között - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Elkerített Erdő -STR_PARK :Elkerített Erdő -STR_DTLS :Építs egy virágzó vidámparkot az erdő mélyén lévő nagy tisztáson - - -STR_SCNR :Dinamit Dűnék -STR_PARK :Dinamit Dűnék -STR_DTLS :Ez a sivatag közepén épült vidámpark csak egy hullámvasúttal rendelkezik, de van helye a terjeszkedésre - - -STR_SCNR :Leveles-tó -STR_PARK :Leveles-tó -STR_DTLS :A nulláról kezdve építs egy vidámparkot a nagy tó körül - - -STR_SCNR :Gyémánt-fennsík -STR_PARK :Gyémánt-fennsík -STR_DTLS :Gyémánt-fennsík már egy sikeres vidámpark, remek játékokkal - fejleszd, hogy megduplázd az értékét - - -STR_SCNR :Örökzöld Kert -STR_PARK :Örökzöld Kert -STR_DTLS :Alakítsd át a csodaszép Örökzöld Kertet egy virágzó vidámparkká - - -STR_SCNR :Suta Strand -STR_PARK :Suta Strand -STR_DTLS :Virágoztasd fel Suta Strand apró vidámparkját - - -STR_SCNR :Hármas-sziget -STR_PARK :Hármas-sziget -STR_DTLS :Egy frissen nyílt park, amelyet több sziget alkot - - -STR_SCNR :Katie Álomvilága -STR_PARK :Katie Álomvilága -STR_DTLS :Egy kis méretű vidámpark, pár játékkal és hellyel a terjeszkedéshez - A célod, hogy megduplázd a park értékét - - -STR_SCNR :Parányi Park -STR_PARK :Parányi Park -STR_DTLS :Egy kis méretű, zsúfolt vidámpark, amelynek jelentős terjeszkedésre van szüksége - - -STR_SCNR :Vadvízi Park -STR_PARK :Vadvízi Park -STR_DTLS :Ez a park néhány igazán kiváló vízi játékkal rendelkezik, de terjeszkedésre van szüksége - - -STR_SCNR :Ezeréves Bányák -STR_PARK :Ezeréves Bányák -STR_DTLS :Alakíts át egy nagy, elhagyatott bányát turistalátványosságból vidámparkká - - -STR_SCNR :Gokartok & Hullámvasutak -STR_PARK :Gokartok & Hullámvasutak -STR_DTLS :Egy nagy park, elrejtve az erdőben, amelyben csak gokart pályák és fa hullámvasutak vannak - - -STR_SCNR :Mel Világa -STR_PARK :Mel Világa -STR_DTLS :Ez a vidámpark már rendelkezik pár jól tervezett, modern játékkal, de bőven van helye terjeszkedésre - - -STR_SCNR :Misztikus-hegy -STR_PARK :Misztikus-hegy -STR_DTLS :A nulláról kezdve építs egy vidámparkot Misztikus-hegy dombos erdeiben - - -STR_SCNR :Pihenő Piramisok -STR_PARK :Pihenő Piramisok -STR_DTLS :Alakítsd át a turistalátványosságként szolgáló egyiptomi romokat egy virágzó vidámparkká - - -STR_SCNR :Recsegő Rengeteg -STR_PARK :Recsegő Rengeteg -STR_DTLS :Egy nagy park jól tervezett, de meglehetősen öreg játékokkal - Cseréld le az öreg játékokat, vagy építs újakat, hogy népszerűbb legyen a park - - -STR_SCNR :Paradicsom Móló -STR_PARK :Paradicsom Móló -STR_DTLS :Alakítsd át ennek az álmos kisvárosnak a mólóját virágzó attrakcióvá - - -STR_SCNR :Villámcsúcsok -STR_PARK :Villámcsúcsok -STR_DTLS :Villámcsúcsok gyönyörű hegyei népszerűek a természetjárók és a turisták körében - Használd ki a rendelkezésre álló területet, hogy új, izgalmakat kereső vendégkört vonzzon magához - - -STR_SCNR :Elefántcsont-tornyok -STR_PARK :Elefántcsont-tornyok -STR_DTLS :Egy jól működő park, amely néhány problémával küzd - - -STR_SCNR :Szivárványvölgy -STR_PARK :Szivárványvölgy -STR_DTLS :Szivárványvölgy helyi önkormányzata nem engedélyez semmilyen tájátalakítást vagy a nagy fák eltávolítását, de a területet egy hatalmas vidámparkká kell fejlesztened - - -STR_SCNR :Mennydörgő-szikla -STR_PARK :Mennydörgő-szikla -STR_DTLS :A Mennydörgő-szikla a sivatag közepén áll és igazi turistamágnes - Használd a rendelkezésre álló területet játékok építésére, hogy még több embert vonzon - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Csak a móka kedvéért! - -## Added Attractions - -STR_SCNR :Suttogó-sziklák -STR_PARK :Suttogó-sziklák -STR_DTLS :Fejleszd a tengerparti sziklákat virágzó vidámparkká - - -STR_SCNR :Három Majom Park -STR_PARK :Három Majom Park -STR_DTLS :A nagy, fejlődő park központi eleme egy óriási, hárompályás versenyző/párbajozó acél hullámvasút - - -STR_SCNR :Kanári Bányák -STR_PARK :Kanári Bányák -STR_DTLS :Ebben az elhagyatott bányában minden megvan ahhoz, hogy vonzó turisztikai látványosság legyen a kisvonatával és a függőleges esésű hullámvasútpárjával - - -STR_SCNR :Hűbéri Híd -STR_PARK :Hűbéri Híd -STR_DTLS :Egy öreg, feleslegessé vált híd, amelyet neked kell vidámparkká fejleszteni - - -STR_SCNR :Mókaland -STR_PARK :Mókaland -STR_DTLS :A parknak az autópálya mindkét oldalán van területe és már több játékot is üzemeltet - - -STR_SCNR :Kísértetjárta Kikötő -STR_PARK :Kísértetjárta Kikötő -STR_DTLS :A helyi önkormányzat beleegyezett, hogy a közeli földterületet olcsón eladja ennek a kis tengerparti parknak, azzal a feltétellel, hogy bizonyos játékai műemlékvédelem alá kerülnek - - -STR_SCNR :Vidám Vár -STR_PARK :Vidám Vár -STR_DTLS :Ez a vár csak arra vár, hogy vidámparkká alakítsd - - -STR_SCNR :Jövőbeli Világ -STR_PARK :Jövőbeli Világ -STR_DTLS :E futurisztikus park földönkívüli táján bőven van hely az új játékok számára - - -STR_SCNR :Szende-szurdok -STR_PARK :Szende-szurdok -STR_DTLS :A helyi lakosság az enyhe és nyugtató játékokat kedveli, úgyhogy a te feladatod a park ízlésüknek megfelelő bővítése - - -STR_SCNR :Derűs Dzsungel -STR_PARK :Derűs Dzsungel -STR_DTLS :Ez a dzsungel mélyén elterülő nagy földterület épp megfelelő egy vidámpark számára - - -STR_SCNR :Hidro-hegyek -STR_PARK :Hidro-hegyek -STR_DTLS :Egy lépcsőzetes tórendszer adja ennek az új parknak az alapját - - -STR_SCNR :Pezsgő Park -STR_PARK :Pezsgő Park -STR_DTLS :Ez az idős park számos történelmi játékkal rendelkezik, de súlyosan el van adósodva - - -STR_SCNR :Mágikus Negyedek -STR_PARK :Mágikus Negyedek -STR_DTLS :Egy nagy területet megtisztítottak és részben tematizáltak, így készen áll arra, hogy parkosított vidámparkká alakítsd - - -STR_SCNR :Gyümölcsfarm -STR_PARK :Gyümölcsfarm -STR_DTLS :Egy jól menő gyümölcsfarm vasutat épített a bevételeinek növelésére, a te feladatod, hogy teljes egészében vidámparkká fejleszd - - -STR_SCNR :Pillangó-gát -STR_PARK :Pillangó-gát -STR_DTLS :Egy gát körüli területen kell vidámparkot kialakítanod - - -STR_SCNR :Hullámvasút-kanyon -STR_PARK :Hullámvasút-kanyon -STR_DTLS :Alakíts ki egy vidámparkot a rendelkezésedre álló hatalmas kanyonban - - -STR_SCNR :Viharpark -STR_PARK :Viharpark -STR_DTLS :Annyira csapadékos ez a terület, hogy egy hatalmas piramis építésére volt szükség ahhoz, hogy néhány játék fedett helyre épülhessen - - -STR_SCNR :Harmonikus-hegyek -STR_PARK :Harmonikus-hegyek -STR_DTLS :A helyi önkormányzat nem engedélyezi számodra, hogy fák magassága felett építkezz ebben a parkban - - -STR_SCNR :Római Falu -STR_PARK :Római Falu -STR_DTLS :Fejleszd ezt a római témájú parkot játékok és hullámvasutak építésével - - -STR_SCNR :Mocsár-öböl -STR_PARK :Mocsár-öböl -STR_DTLS :A kis szigetcsoportra épült parkban már van egy nagy, központi elemként funkcionáló hullámvasútpár - - -STR_SCNR :Adrenalin-csúcsok -STR_PARK :Adrenalin-csúcsok -STR_DTLS :Építs egy parkot, amellyel bevonzhatod a helyi élmény- és izgalomkereső embereket - - -STR_SCNR :Utópia Park -STR_PARK :Utópia Park -STR_DTLS :A sivatag közepén elterülő oázis kivételes lehetőséget kínál vidámpark építésére - - -STR_SCNR :Rohadó Magaslatok -STR_PARK :Rohadó Magaslatok -STR_DTLS :Képes vagy feltámasztani ezt a valaha szebb napokat látott, ám mára gazzal benőtt és düledező vidámparkot? - - -STR_SCNR :Elbaltázott Erdő -STR_PARK :Elbaltázott Erdő -STR_DTLS :Meglehetősen korlátozottak az anyagi és időbeli lehetőségeid arra, hogy rendbe rakd ezt a rosszul tervezett és veszélyes játékokkal teli parkot - - -STR_SCNR :Pác Park -STR_PARK :Pác Park -STR_DTLS :A helyi önkormányzat nem engedélyez semmiféle reklámot vagy promóciót, úgyhogy a parknak kizárólag a jó hírnevére alapozva kell sikereket elérnie - - -STR_SCNR :Kacaj-dombság -STR_PARK :Kacaj-dombság -STR_DTLS :Egy négysávos akadályverseny-játék a központi eleme ennek a terjeszkedő parknak - - -STR_SCNR :Ásvány Park -STR_PARK :Ásvány Park -STR_DTLS :Változtasd ezt az elhagyatott kőbányát az izgalomkereső turisták számára vonzó hellyé - - -STR_SCNR :Hullámvasút-őrület -STR_PARK :Hullámvasút-őrület -STR_DTLS :Szűkösek a pénzügyi forrásaid, de végtelen sok időd van arra, hogy egy hatalmas vidámparkot alakíts ki ezen a hegyoldali területen - - -STR_SCNR :Városi Park -STR_PARK :Városi Park -STR_DTLS :Egy apró park egyezséget kötött a közeli várossal, amelynek értelmében magán a városon keresztül terjeszkedhet - - -STR_SCNR :Geoffrey Kert -STR_PARK :Geoffrey Kert -STR_DTLS :Egy nagy kertnek arra van szüksége, hogy sikeres vidámpark legyen belőle - - -## Loopy Landscapes - -STR_SCNR :Jéghegy-szigetek -STR_PARK :Jéghegy-szigetek -STR_DTLS :Egy csoportnyi jéghegy hideg helyszínt biztosít ennek az ambiciózus vidámparknak - - -STR_SCNR :Vulkánia -STR_PARK :Vulkánia -STR_DTLS :Egy szunnyadó vulkán adja ennek a hullámvasút-építő kihívásnak a helyszínét - - -STR_SCNR :Száraz Magaslatok -STR_PARK :Száraz Magaslatok -STR_DTLS :Az a kihívásod, hogy gondoskodj a park fejlesztéséről, miközben biztosítod a vendégek jókedvét, pénzügyi korlátok nélkül - - -STR_SCNR :Penge Sziklák -STR_PARK :Penge Sziklák -STR_DTLS :Az a feladatod, hogy egy masszív, hullámvasutakkal teli parkot alakíts ki a Penge Sziklák között - - -STR_SCNR :Kráter-tó -STR_PARK :Kráter-tó -STR_DTLS :Egy ősi kráterben elterülő hatalmas tó a park a helyszíne - - -STR_SCNR :Szédítő Kilátások -STR_PARK :Szédítő Kilátások -STR_DTLS :Ebben a nagy parkban már van egy kiváló hiperhullámvasút, de sokkal nyereségesebbé kell tenned - - -STR_SCNR :Paradicsom Móló 2 -STR_PARK :Paradicsom Móló 2 -STR_DTLS :Paradicsom Móló kiterjesztette a tenger feletti sétány-hálózatát és a feladatod az, hogy a park bővítésével biztosítsd az extra hely kihasználtságát - - -STR_SCNR :Sárkány-öböl -STR_PARK :Sárkány-öböl -STR_DTLS :Ez a tengerparti öböl a helyszíne ennek a hullámvasút-építő kihívásnak - - -STR_SCNR :Jó Lovag Park -STR_PARK :Jó Lovag Park -STR_DTLS :Egy kastély két hullámvasúttal, amit egy nagyobb vidámparkká kell fejlesztened - - -STR_SCNR :Nyüzsgő Nyúlkert -STR_PARK :Nyüzsgő Nyúlkert -STR_DTLS :Egy park, ahol az utak és hullámvasutak nagy része föld alatt van - - -STR_SCNR :Nagy Gleccser -STR_PARK :Nagy Gleccser -STR_DTLS :Fejleszd vidámparkká ezt a gleccserekkel teli völgyet - - -STR_SCNR :Őrült Kráterek -STR_PARK :Őrült Kráterek -STR_DTLS :Egy messzi világban, ahol nincs szükség pénzre, szórakoztató központot kell építened, hogy biztosítsd az emberek boldogságát - - -STR_SCNR :Sivár Sivatag -STR_PARK :Sivár Sivatag -STR_DTLS :Öt hullámvasutat kell befejezni ebben a sivatagi parkban - - -STR_SCNR :Fakukac Park -STR_PARK :Fakukac Park -STR_DTLS :Ez a történelmi park csak régi stílusú játékokat építhet - - -STR_SCNR :Ikarusz Park -STR_PARK :Ikarusz Park -STR_DTLS :Fejleszd ezt a földönkívüli parkot, hogy maximalizáld a nyereségét - - -STR_SCNR :Napos Mocsarak -STR_PARK :Napos Mocsarak -STR_DTLS :Ennek a jól tematizált vidámparknak már számos játéka van, de bőven van helye a terjeszkedésre - - -STR_SCNR :Rémálom Dombok -STR_PARK :Rémálom Dombok -STR_DTLS :Egy rémisztő vidámpark, a közepén egy hatalmas hullámvasúttal - - -STR_SCNR :Mennydörgő-sziklák -STR_PARK :Mennydörgő-sziklák -STR_DTLS :Két nagy szikladarab emelkedik ki a homokból, amelyekre egy vidámpark alapjai épülnek - - -STR_SCNR :Oktogon Park -STR_PARK :Oktogon Park -STR_DTLS :Tíz hullámvasutat kell tervezned és építened ebben a nagy parkban - - -STR_SCNR :Élménysziget -STR_PARK :Élménysziget -STR_DTLS :A hosszú, keskeny sziget kihívásokkal teli helyszín a megadott hullámvasutak építésére - - -STR_SCNR :Jégcsap Világok -STR_PARK :Jégcsap Világok -STR_DTLS :Alakítsd át a jeges tájat virágzó vidámparkká - - -STR_SCNR :Déli Homok -STR_PARK :Déli Homok -STR_DTLS :Egy sivatagi park néhány ügyesen megtervezett hullámvasúttal arra vár, hogy kibővítsd - - -STR_SCNR :Törpe Tornyok -STR_PARK :Törpe Tornyok -STR_DTLS :Öt meglévő hullámvasutat kell befejezned ebben a kis parkban - - -STR_SCNR :Sohamár Park -STR_PARK :Sohamár Park -STR_DTLS :Egy nagy park, újszerű közlekedési rendszerrel a szélén - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Ez a nagy sziget csak a tiéd, hogy vidámparkká fejleszd - - -STR_SCNR :Városi Dzsungel -STR_PARK :Városi Dzsungel -STR_DTLS :Ez a hatalmas elhagyatott felhőkarcoló egyedi lehetőség egy vidámpark-fejlesztő számára - - -STR_SCNR :Terrorváros -STR_PARK :Terrorváros -STR_DTLS :Ez a városi terület csak a tiéd, hogy vidámparkká fejleszd - - -STR_SCNR :Megavilág Park -STR_PARK :Megavilág Park -STR_DTLS :Egy óriási park, amely már így is tele van játékokkal, fejlesztésre szorul - - -STR_SCNR :Vénusz Tavak -STR_PARK :Vénusz Tavak -STR_DTLS :Alakítsd át egy messzi bolygó földterületét vidámparkká - - -STR_SCNR :Mikro Park -STR_PARK :Mikro Park -STR_DTLS :Próbáld meg létrehozni a világ legkisebb nyereséges parkját - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide Park -STR_PARK :Heide Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Anakronizmus-erőd -STR_PARK :Anakronizmus-erőd -STR_DTLS : - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpesi Kalandok -STR_PARK :Alpesi Kalandok -STR_DTLS :Alakíts át egy kis hegyi síközpontot havas témájú vidámparkká - - -STR_SCNR :Barátság Repülőtér -STR_PARK :Barátság Repülőtér -STR_DTLS :Építs egy repülés témájú vidámparkot ezen az elhagyatott repülőtéren - - -STR_SCNR :Botanikus Hullámok -STR_PARK :Botanikus Hullámok -STR_DTLS :A kihívásod az, hogy építs egy igazán nyereséges parkot ezen a paradicsomi szigeten - - -STR_SCNR :Építsd meg a saját Six Flags Belgiumodat -STR_PARK :Six Flags Belgium -STR_DTLS :Építsd meg a saját változatodat ebből európai Six Flags parkból - - -STR_SCNR :Építsd meg a saját Six Flags Great Adventure-ödet -STR_PARK :Six Flags Great Adventure -STR_DTLS :Használd a tervezői képességeidet, hogy újraalkosd ezt a Six Flags parkot - - -STR_SCNR :Építsd meg a saját Six Flags Hollandodat -STR_PARK :Six Flags Holland -STR_DTLS :Építsd meg ezt az európai Six Flags parkot úgy, ahogyan szeretnéd - - -STR_SCNR :Építsd meg a saján Six Flags Magic Mountain-edet -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Készítsd el a saját verziódat ebből a hatalmas Six Flags parkból - - -STR_SCNR :Építsd meg a saját Six Flags over Texasodat -STR_PARK :Six Flags over Texas -STR_DTLS :A semmiből kiindulva építsd meg ebben a Six Flags parkban a játékokat - - -STR_SCNR :Építsd meg a saját Six Flags parkodat -STR_PARK :Six Flags -STR_DTLS :Építs saját tervezésű Six Flags parkot - vagy más Six Flags parkokból építs játékokat, vagy tervezz és építs saját játékokat - - -STR_SCNR :Bumfordi Bazár -STR_PARK :Bumfordi Bazár -STR_DTLS :Egy kis piaci bazárral kezdve, a kihívásod a boltok és bódék nyereségének növelése azzal, hogy több vendéget vonzol be játékok és hullámvasutak építésével - - -STR_SCNR :Őrült Kastély -STR_PARK :Őrült Kastély -STR_DTLS :Örököltél egy nagy kastélyt. Az a feladatod, hogy átalakítsd egy kis vidámparkká. - - -STR_SCNR :Poros Golfpálya -STR_PARK :Poros Golfpálya -STR_DTLS :A sivatagban, egy autópálya-csomópont közelében található Poros Golfpálya lehetőséget kínál egy kis golfüdülő virágzó vidámparkká fejlesztésére - - -STR_SCNR :Elektromos Mezők -STR_PARK :Elektromos Mezők -STR_DTLS :Örököltél egy kis farmot, és a kihívásod egy kis vidámpark építése a mezők és a farmépületek között - - -STR_SCNR :Extrém Magaslatok -STR_PARK :Extrém Magaslatok -STR_DTLS :Pénzügyi korlátoktól mentesen, a kihívásod ennek a sivatagi parknak a bővítése úgy, hogy magához vonzza a maximális izgalmakat kereső embereket - - -STR_SCNR :Gyári Móka -STR_PARK :Gyári Móka -STR_DTLS :Az elhagyatott gyárkomplexum lehetőség egy mechanikus témájú vidámpark építésére - - -STR_SCNR :Gombaerdő -STR_PARK :Gombaerdő -STR_DTLS :Kizárólag régebbi stílusú, fából készült hullámvasutakra korlátozva, a kihívásod egy virágzó vidámpark építése Gombaerdőben - - -STR_SCNR :Szellemváros -STR_PARK :Szellemváros -STR_DTLS :Egy nagy vidámparklánc felbérelt, hogy építs nekik óriási hullámvasútparkot egy elhagyatott bányászváros köré - - -STR_SCNR :Gravitációs Kert -STR_PARK :Gravitációs Kert -STR_DTLS :A kihívásod az, hogy építs egy hullámvasútparkot a gyönyörű Gravitációs Kertben. Semmi más játékot, csak hullámvasutakat! - - -STR_SCNR :Pokoli Kilátások -STR_PARK :Pokoli Kilátások -STR_DTLS :A park bizonytalanul fészkel a magmafolyamokkal övezett lávasziklákon - - -STR_SCNR :Szerencsés-tó -STR_PARK :Szerencsés-tó -STR_DTLS :Korlátlan pénzzel, de egy kihívást jelentő tavi helyszínen, ezt a parkot igazi próbatétel lesz bővíteni és igazgatni - - -STR_SCNR :Szivárvány Csúcs -STR_PARK :Szivárvány Csúcs -STR_DTLS :A domboldalon épült parkban tilos bármi magasat építeni. Sikerül bővítened a parkot és sikeressé tenni? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Próbáld ki magad ennek a Six Flags parknak az üzemeltetésében és fejlesztésében - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Építsd meg a hiányzó Six Flags játékokat, vagy készíts saját terveket a park fejlesztésére! De ne feledkezz meg a végső célodról: több vendéget vonzani a parkba! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Próbáld ki magad ennek a Six Flags parknak az üzemeltetésében és fejlesztésében - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Építsd meg a hiányzó Six Flags játékokat, vagy készíts saját terveket a park fejlesztésére! De ne feledkezz meg a végső célodról: több vendéget vonzani a parkba! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Építsd meg a hiányzó Six Flags játékokat, vagy készíts saját terveket a park fejlesztésére! De ne feledkezz meg a végső célodról: több vendéget vonzani a parkba! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Afrikai Bányák -STR_PARK :Afrikai Bányák -STR_DTLS :Egy elhagyatott gyémántbányát örököltél, és találtál egy értékes gyémántot. Úgy döntesz, hogy ezt a pénzt egy világhírű vidámpark építésébe fekteted. - - -STR_SCNR :Délibábos Őrület -STR_PARK :Délibábos Őrület -STR_DTLS :Felfedeztek egy sivatagi oázist, amely gyönyörű helyszínt biztosítana egy parknak. Az oázisba való eljutás biztosított. - - -STR_SCNR :A Szakadék Szélén -STR_PARK :A Szakadék Szélén -STR_DTLS :Egy gát épült, amely bőséges és olcsó vízenergiát kínál a park működtetéséhez. Magas parkértéket kell elérned, hogy segítsen visszafizetni a gátra felvett kölcsönt. - - -STR_SCNR :Jeges Kalandok -STR_PARK :Jeges Kalandok -STR_DTLS :A környezetvédelmi ügynökség rád bízta, hogy egy ökológiára káros régi olajfinomítót alakíts át első osztályú turisztikai látványossággá. A föld olcsó, de a hitelkamatok magasak. Az öreg épületeket értékesítheted újrahasznosítási célokra. - - -STR_SCNR :Kínai Nagy Fal -STR_PARK :Kínai Nagy Fal -STR_DTLS :A hatóságok úgy döntöttek, hogy a Nagy Fal körüli turizmus élénkítésére egy vidámparkot építenek a szomszédos területen. A pénz nem számít! - - -STR_SCNR :Okinawa Partjai -STR_PARK :Okinawa Partjai -STR_DTLS :Egy már meglévő park kifogyott a területből. Az egyetlen lehetőséged a tenger felé történő bővítés, ehhez pedig kölcsönt kell felvenned. Az épületekre vonatkozó magassági korlátozások a talapzatok és az esetleges földrengési kockázatok miatt vannak érvényben. - - -STR_SCNR :Maharadzsa Park -STR_PARK :Maharadzsa Park -STR_DTLS :A maharadzsa megbízott, hogy szórakoztasd a nagyszámú helyi lakosságot. Építs egy parkot, amelyet a maharadzsa palotája ihletett. - - -STR_SCNR :Ayers Kaland -STR_PARK :Ayers Kaland -STR_DTLS :Segítesz az aborigineknek egy parkot építeni egy kulturális tudatossági program részeként. Rengeteg vendéget kell szerezned, hogy megismertesd velük az aborigin nép egyedülálló örökségét. - - -STR_SCNR :Tengerparti Grillparti -STR_PARK :Tengerparti Grillparti -STR_DTLS :Egy helyi vállalkozó tengeri élményparkja tönkrement. Már üzemeltetsz egy kis parkot, és megveszed a másik parkot az építővállalattól. Alakíts ki egy nagy, összekapcsolt parkot. - - -STR_SCNR :Európai Extravagancia -STR_PARK :Európai Extravagancia -STR_DTLS :Felkértek, hogy vegyél át egy európai kulturális látványosságot, és növelned kell a vendégszámot, hogy a jelenlegi európai parlamenti ciklus végéig visszafizethesd az EU-támogatást. - - -STR_SCNR :Hamvakból -STR_PARK :Hamvakból -STR_DTLS :Egy régi park leromlott állapotba került. Elnyersz egy európai uniós támogatást, hogy ez a lepusztult terület újra régi fényében tündökölhessen! Fel kell újítanod a parkot, és vissza kell fizetned a támogatást. - - -STR_SCNR :Veszett Waikiki -STR_PARK :Veszett Waikiki -STR_DTLS :Hawaii lakói már unják a szörfözést, és valami intenzívebbet keresnek. Erre tekintettel kell parkot építened, hogy a terület turisztikai vonzereje magasan maradjon. - - -STR_SCNR :Kanyon Kalamajkák -STR_PARK :Kanyon Kalamajkák -STR_DTLS :Egy parkot kell építened a természeti kincs mindkét oldalán, de korlátozott a rendelkezésre álló terület - lehetőséged van a szomszédos területek megvásárlására az őslakos amerikai indiánoktól. El kell érned a célt, hogy fenntartsd a helyi város lakosságát. - - -STR_SCNR :Hullámvasút Paradicsom -STR_PARK :Hullámvasút Paradicsom -STR_DTLS :Egy sikeres iparmágnás vagy, aki hosszú szabadságon van, és ezt az időt arra szeretné felhasználni, hogy a városi parkot hullámvasút paradicsommá alakítsa át. A pénz nem számít! - - -STR_SCNR :Elveszett Város Alapító -STR_PARK :Elveszett Város Alapító -STR_DTLS :A helyi turizmus további fellendítése érdekében egy olyan parkot kell létrehoznod, amely harmonizál a környezetével. - - -STR_SCNR :Esőerdei Kaland -STR_PARK :Esőerdei Kaland -STR_DTLS :A tér korlátozott az értékes esőerdőben - mindent be kell zsúfolnod a meglévő tisztásra, hogy életképes alternatívát nyújthass a helyi faiparnak. - - -STR_SCNR :Cukorsüveg-part -STR_PARK :Cukorsüveg-part -STR_DTLS :Egy kis parkot üzemeltetsz Rio mellett, de a bank felmondta a hiteledet. Gyorsan növelned kell a jövedelemtermelő képességedet, hogy vissza tudd fizetni ezt a váratlan adósságot. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Sziklaoldali Vár -STR_PARK :Sziklaoldali Vár -STR_DTLS :A hagyományörző egyesület helyi tagjai komolyan veszik az emlékcsatákat. Rád bízták a feladatot, hogy építs egy sötét középkor témájú parkot a Sziklaoldali Vár területén. - - -STR_SCNR :Sherwoodi Erdő -STR_PARK :Sherwoodi Erdő -STR_DTLS :Hogy a gazdagoktól elvegyétek a vagyonukat és szétosszátok az elesettek között, te és a Vidám Fiúk úgy döntöttetek, hogy vidámparkot építetek Sherwood erdejében. - - -STR_SCNR :Földönkívüli Felhajtás -STR_PARK :Földönkívüli Felhajtás -STR_DTLS :Életet fedeztek egy távoli bolygón. Építs egy űrlény témájú parkot, hogy megtollasodhass a példátlan érdeklődésnek köszönhetően. - - -STR_SCNR :Gemini Város -STR_PARK :Gemini Város -STR_DTLS :Mutass egy újszerű, utópisztikus jövőképet - találj ki egy futurisztikus parktervet, amely magában foglalja a legmodernebb látványosságokat. - - -STR_SCNR :Animatronikus Mókák -STR_PARK :Animatronikus Mókák -STR_DTLS :Egy már létező vidámpark vezetését és fejlesztését kaptad feladatul, amely egy régi film díszleteire épült. Építs egy emlékművet az úttörő stop-motion animátoroknak, akik először keltettek életre mitikus lényeket a mozivásznon. - - -STR_SCNR :Mitológiai Őrület -STR_PARK :Mitológiai Őrület -STR_DTLS :Egy különleges régészeti értékkel bíró sziget tulajdonosa vagy. Úgy döntöttél, hogy finanszírozod a megőrzését egy vidámpark létrehozásával, amely az terület gazdag mitológiai örökségére épül. - - -STR_SCNR :Kráter Káosz -STR_PARK :Kráter Káosz -STR_DTLS :Egy poros, régi meteoritkráter tulajdonosa vagy. Az igazi vállalkozói szellem jegyében úgy döntöttél, hogy egy aszteroida témájú parkot építesz, és a látszólag értéktelen területedet egy nagyobb vagyonná alakítod. - - -STR_SCNR :Vasútszaurusz -STR_PARK :Vasútszaurusz -STR_DTLS :Azt a feladatot kaptad, hogy építs egy jura kori vidámparkot. Ahhoz, hogy a látogatók optimálisan közelíthessék meg az egzotikus növény- és állatkiállításokat, a völgy fölé és a völgybe vezető hullámvasutakat kell építened. - - -STR_SCNR :Sziklás Túrák -STR_PARK :Sziklás Túrák -STR_DTLS :Hogy megakadályozd az autópálya-építőket és megőrizd a titokzatos ősi kőköröket, egy kőkorszaki vidámparkot kell építened, és nyereséget termelned. A látogatók vonzása azonban kihívást jelenthet, mivel a terep kissé barátságtalan. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :A hírhedt börtönsziget - amelynek lakossága egykor szeszcsempészektől és zsarolóktól duzzadt - most eladó. Úgy döntöttél, hogy turisztikai látványossággá alakítod át, és a pénz nem számít. - - -STR_SCNR :Schneider-part -STR_PARK :Schneider-part -STR_DTLS :Néhány év múlva lesz nagyapád Schneider-kupa győzelmének 75. évfordulója. Azzal tisztelegsz a teljesítménye előtt, hogy egy vidámparkot építesz a híres vízi repülős versenyről mintázva. - - -STR_SCNR :Metropolisz -STR_PARK :Metropolisz -STR_DTLS :Egy üres telek tulajdonosa vagy a város alacsonyabb részéhez közel. Hogy a legtöbbet hozd ki városi ingatlanodból, építs egy felhőkarcoló témájú parkot, amelyet a húszas évek szárnyaló art deco építészete ihletett. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Évente megrendezésre kerül egy nagyszabású zenei fesztivál a területeden. Építs egy menő vidámparkot, hogy szórakoztasd a szabad szellemű közönséget. - - -STR_SCNR :Rock ‘n’ Roll Újjáéledés -STR_PARK :Rock ‘n’ Roll Újjáéledés -STR_DTLS :Ez az idős park egykor jobb napokat látott. Segíts a tulajdonosnak a retró rock 'n' roll stílusú átalakításban, hogy a hely sikeres szórakozóhellyé váljon. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Panda Világ -STR_PARK :Panda Világ -STR_DTLS :Szerezz be további játékokat, hogy több ember látogasson el ebbe a panda-témájú parkba - - -STR_SCNR :Tycoon Park -STR_PARK :Tycoon Park -STR_DTLS : - -### - -STR_SCNR :Temető-gerinc -STR_PARK :Temető-gerinc -STR_DTLS :Itt van halloween, UCES halloween, tök lámpás ami gyertyát rejt! Mentsd meg a bajba jutott temetőt, ügyelve a halottak békéjére! Képes vagy a szellemeket sírjukban tartani és frászt hozni a vendégeidre?{NEWLINE}Szerző: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :Alexandriai világítótorony -STR_PARK :Alexandriai világítótorony -STR_DTLS :Sándor építette a várost; a görögök, rómaiak, egyiptomiak rányomták bélyegüket. De a legnagyobb megtiszteltetés az ókori világ egy csodája - a világítótorony. Látogass el és hozz létre egy parkot!{NEWLINE}Szerző: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Amilyen a megnyitó napján volt - 1905. május 18-án.{NEWLINE}Szerző: Aetherwave - - -STR_SCNR :Vezúv -STR_PARK :Vezúv -STR_DTLS :Pompejit és Herculaneumot a Vezúv temette maga alá Kr.u. 79-ben. Látogass el az ásatásokra és építs egy parkot!{NEWLINE}Szerző: Katatude - - -STR_SCNR :A Homokozó -STR_PARK :A Homokozó -STR_DTLS :Amit mindenki akar - egy homokozó! Szóval ragadjátok meg a kis vödrötöket és lapátotokat és építsetek egy parkot!{NEWLINE}Szerző: Katatude - - -STR_SCNR :Niagara-vízesés és szurdok -STR_PARK :Niagara-vízesés -STR_DTLS :Amerikai-zuhatag, Menyasszonyi fátyol-zuhatag és a kanadai Patkó-zuhatag a Niagara határon, 1850.{NEWLINE}Szerző: Katatude - - -STR_SCNR :Sziklás-hegyi bányászok -STR_PARK :Sziklás-hegyi bányászok -STR_DTLS :Egy sziklaomlás megrongálta a vasutadat. A munkásaid elmentek kutatni. Van arany a hullámvasutakban?{NEWLINE}Szerzők: Squid, Buckone, Fossil - - -STR_SCNR :Az Időgép -STR_PARK :Az Időgép -STR_DTLS :Az időgép. Építsd meg, hogy mehess - amikor akarsz, ahová akarsz. Az örökkévalóság vár. Minden relatív.{NEWLINE}Szerző: Katatude - - -STR_SCNR :Bábel tornya -STR_PARK :Bábel tornya -STR_DTLS :Hűű! Nézd csak, hova vitt minket az időgép! Hová tűnt mindenki?{NEWLINE}Szerző: Fossil - - -STR_SCNR :Transzformáció -STR_PARK :Transzformáció -STR_DTLS :Vártunk téged…{NEWLINE}Szerző: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :A rómaiak belefáradtak az unalmas gladiátorharcokba. Adj nekik valami izgalmasabbat, változtass egy római várost minden idők legnagyobb vidámparkjává!{NEWLINE}Szerző: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :A karácsonyfa alatt -STR_PARK :Téli Csodaország -STR_DTLS :Anyu építette ezt a jelenetet a fánk alá. Most azt akarja, hogy parkot csináljunk bele! Tudsz segíteni?{NEWLINE}Szerző: Katatude - - -STR_SCNR :Robbanás Bigrockban -STR_PARK :Robbanás Bigrockban -STR_DTLS :Miután robbanás történt a Bigrock Bányászati Vállalatnál, Bigrock lakosainak egy vidámparkot kell építeniük, hogy életben tartsák városukat.{NEWLINE}Szerzők: rbarclay & buckone - - -STR_SCNR :Feketerigó Tábor -STR_PARK :Feketerigó Tábor -STR_DTLS :Csak $500/hét ez a nyári tábor! Törd fel a malacperselyed, aztán szórakozz és építs egy parkot.{NEWLINE}Szerző: Katatude - - -STR_SCNR :Sihuhu Város -STR_PARK :Sihuhu Város -STR_DTLS :Anyu! Apu! Sihuhu városba akarok menni!{NEWLINE}Szerző: Fossil - - -STR_SCNR :Sárkány-szigetek -STR_PARK :Sárkány-szigetek -STR_DTLS :Sárkány-szigetek? Nem biztos, hogy oda akarok menni…{NEWLINE}Szerző: Fossil - - -STR_SCNR :Kölyökkarnevál II -STR_PARK :Kölyökkarnevál -STR_DTLS :Hé, gyerekek! Érezzük jól magunkat!{NEWLINE}Szerzők: Piehead & Fossil - - -STR_SCNR :Homokdűne -STR_PARK :Homokdűne -STR_DTLS :Egy kis park tulajdonosaként vásároltál egy nagy darab földet a tengerparton, hogy bővíts és még több vendéget vonzz a gyönyörű homokdűnékhez, de vigyázz: nem bolygathatod az ökológiailag érzékeny homokdűnéket.{NEWLINE}Szerző: rbarclay diff --git a/data/language/it-IT.txt b/data/language/it-IT.txt index 410ae6a0be..eb8810cfee 100644 --- a/data/language/it-IT.txt +++ b/data/language/it-IT.txt @@ -3748,858 +3748,3 @@ STR_6669 :Mostra i trucchi sul personale STR_6670 :Comportamento visitatori STR_6671 :Mostra i “veri” nomi del personale STR_6672 :Alterna tra i nomi “veri” del personale e i loro numeri - - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Costruisci un fiorente parco a tema in una zona disboscata all’interno della foresta - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Costruito in mezzo al deserto, questo parco a tema contiene un solo percorso di Montagne Russe ma ha grandi spazi per lo sviluppo - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Partendo da zero, costruisci un grande parco a tema attorno a un grande lago - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights è già un parco a tema di successo con grandi percorsi: sviluppalo e raddoppiane il valore. - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Trasforma i bellissimi Evergreen Gardens in un fiorente parco a tema - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Sviluppa il piccolo parco di divertimento di Bumbly Beach e trasformalo in un fiorente parco a tema - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :La base per questo nuovo parco è formata da diverse isole - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :Un piccolo parco a tema con pochi percorsi e grande spazio per lo sviluppo. Il tuo compito è di raddoppiarne il valore - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :Un parco di divertimento molto ristretto che necessita di grande sviluppo - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :Un parco con alcuni ottimi percorsi ad acqua che richiede ulteriore espansione - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Trasforma l’attrazione turistica della miniera abbandonata in un parco a tema - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :Un grande parco nascosto nella foresta; dispone solo di percorsi per go-kart e per Montagne Russe in legno - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :Questo parco a tema presenta alcuni percorsi moderni e ben progettati, ma ha anche molto spazio per ulteriori sviluppi - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :Costruisci da zero un parco a tema nelle foreste collinose della Mystic Mountain - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Trasforma l’attrazione turistica delle rovine egizie in un fiorente parco a tema - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :Un grande parco con percorsi ben congegnati ma vecchi. Sostituisci i vecchi percorsi o creane dei nuovi per renderlo più popolare - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Trasforma questo tranquillo molo in una fiorente attrazione - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :Le splendide montagne di Lightning Peaks sono popolari tra turisti ed escursionisti; sfrutta il terreno disponibile per attirare una clientela desiderosa di sensazioni più forti - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :Un parco conosciuto, ma con qualche problema - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Le autorità di Rainbow Valley non permettono modifiche al panorama o estesi disboscamenti; cerca comunque di sviluppare l’area e creare un parco a tema più grande - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :L’altopiano di Thunder Rock si trova in mezzo al deserto e attira molti turisti; sfrutta lo spazio disponibile per costruire percorsi che attirino altra gente - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Divertimento puro! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Sviluppa le cascate in un fiorente parco a tema - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Al centro di questo grande parco in sviluppo c’è un gigantesco ottovolante in acciaio a tre percorsi gareggianti - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Questa miniera abbandonata ha già la stoffa di un’attrazione turistica con la sua ferrovia in miniatura e un paio di ottovolanti a caduta verticale - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :Un vecchio ponte superfluo è pronto per essere trasformato in un parco a tema - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Un parco ai bordi di un’autostrada, con alcune attrazioni già operative - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :L’autorità locale ha accettato di svendere i terreni confinanti a questo piccolo parco sul mare, a condizione che alcune attrazioni vengano mantenute - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Un castello pronto per diventare un parco a tema - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Questo parco futuristico dal tema alieno ha molto spazio per nuove attrazioni - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :La popolazione locale preferisce attrazioni tranquille e rilassanti, il tuo compito è di espandere il parco per soddisfarla - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Nel profondo della giungla si trova una larga zona di terreno pronta per essere trasformata in un parco a tema - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :Una serie di laghi a cascata sono la base per questo nuovo parco - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Questo vecchio parco ha molte attrazioni storiche ma è in crisi finanziaria - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Una larga area di terreno è stata appiattita e parzialmente tematizzata per essere trasformata in un parco a tema paesaggistico - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :Una fiorente fattoria ha costruito una ferrovia per aumentare il suo reddito, il tuo compito è quello di svilupparla in vero parco a tema - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Quest’area intorno a una diga è pronta per diventare un parco a tema - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :Un vasto canyon è tuo per trasformarlo in un parco a tema - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :Il clima qui è così umido che è stata costruita una piramide gigante per permettere la costruzione sotterranea di alcune attrazioni - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :L’autorità locale non permette di costruire sopra la linea di altezza degli alberi in questo parco - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Sviluppa questo parco a tema romano aggiungendo attrazioni e ottovolanti - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Costruito parzialmente su una serie di piccole isole, questo parco ha già un paio di ottovolanti come principale attrattiva - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Costruisci un parco per attirare gli amanti del brivido della zona - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :Un’oasi nel mezzo del deserto offre un’opportunità unica per costruire un parco a tema - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Coperto di vegetazione e fatiscente, puoi resuscitare questo grande parco di divertimenti? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Pieno di corse mal progettate e pericolose, hai un budget e tempo molto limitato per risolvere i problemi e trasformare il parco - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :L’autorità locale non permetterà alcun tipo di pubblicità o promozione, quindi questo parco deve avere successo solo per la reputazione - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :Una passeggiata a quattro corsie è il fulcro di questo parco in espansione - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Trasforma questa cava di pietra abbandonata in un luogo per attrarre turisti in cerca di emozioni - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Hai fondi limitati ma un tempo illimitato per trasformare questa zona di montagna in un vasto parco di montagne russe - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :Un piccolo parco ha fatto un accordo con la vicina città per consentire l’espansione attraverso la città stessa - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :Un grande parco giardino ha bisogno di trasformarsi in un fiorente parco a tema - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :Questo ambizioso parco a tema è costituito da iceberg che creano un ambiente di tipo artico - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :Questa sfida di costruzione di montagne russe è ambientata presso un vulcano addormentato - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Senza limiti finanziari, la tua sfida consiste nello sviluppare questo parco deserto, mantenendo felici i tuoi visitatori - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Il tuo compito è costruire un gigantesco parco pieno di attrazioni presso Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :Questo parco è ambientato in un grande lago all’interno di un antico cratere - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Questo grande parco ha già un’iper-coaster eccellente, ma il tuo compito è quello di aumentare il suo profitto - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier ha ampliato la sua rete di passaggi lungo il mare e il tuo compito è quello di ampliare il parco per utilizzare lo spazio in più - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :Questa baia sul mare rappresenta la cornice di questa sfida per la costruzione di montagne - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Un castello con un paio di montagne russe deve diventare un parco tematico più grande - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :Un parco che ha molti dei suoi sentieri e montagne russe sotterranee - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :Una valle piena di ghiacciai è tua per svilupparci un parco a tema - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :In un mondo lontano dove non è necessario il denaro, è necessario costruire un centro di intrattenimento per rendere felici le persone - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Cinque montagne russe richiedono di essere completate in questo parco desertico - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :In questo parco storico è consentito solo costruire percorsi vecchio stile - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Sviluppa questo parco alieno per massimizzare il suo profitto - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :Questo parco divertimenti a tema ha già diversi percorsi, ma ha molto spazio per l’espansione - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :Un parco spaventoso con una montagna russa gigante centrale - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Due grandi pezzi di roccia sbucano dalla sabbia, che saranno le base di un parco a tema - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :In questo grande parco è necessario progettare e costruire dieci montagne russe - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :Una lunga isola sottile è una base impegnativa per la costruzione di una selezione di montagne russe - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Un paesaggio ghiacciato ha bisogno di trasformarsi in un fiorente parco a tema - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :Un parco nel deserto con alcuni ottimi ottovolanti necessita di espansione - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :In questo parco occorre completare la costruzione di cinque ottovolanti già esistenti - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :Un grande parco con un nuovo sistema di trasporto lungo i suoi confini - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Questa larga isola è pronta per essere sviluppata in un parco a tema - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :Un gigantesco grattacielo abbandonato è un’occasione unica per un creatore di aree tematiche - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Questa zona urbana è pronta per diventare un parco di divertimenti - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :Un parco gigante già pieno di percorsi deve migliorare - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :Su un pianeta lontano questo pezzo di terra ha bisogno di trasformarsi in un parco a tema - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Prova a creare un piccolo parco facendo dei soldi - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Tetto -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - - - -STR_SCNR :Avventure alpine -STR_PARK :Avventure alpine -STR_DTLS :Converti un piccolo rifugio d’alta quota in un parco dei divertimenti a tema nevoso - - -STR_SCNR :Campo d’aviazione dell’amicizia -STR_PARK :Campo d’aviazione dell’amicizia -STR_DTLS :Costruisci un parco avente come tema il volo in questo aeroporto abbandonato - - -STR_SCNR :Distruttori botanici -STR_PARK :Distruttori botanici -STR_DTLS :La sfida è quella di costruire un parco ad alto profitto su questa isola paradisiaca - - -STR_SCNR :Costruisci il tuo Six Flags Belgio -STR_PARK :Six Flags Belgio -STR_DTLS :Costruisci la tua versione personale di questo parco europeo Six Flags - - -STR_SCNR :Costruisci la tua Grande avventura Six Flags -STR_PARK :Grande avventura Six Flags -STR_DTLS :Usa la tua abilità nel progettare per ricreare questo parco Six Flags - - -STR_SCNR :Costruisci il tuo Six Flags Olanda -STR_PARK :Six Flags Olanda -STR_DTLS :Costruisci questo parco europeo Six Flags come piace a te - - -STR_SCNR :Costruisci la tua Montagna magica Six Flags -STR_PARK :Montagna magica Six Flags -STR_DTLS :Crea la tua versione personale di questo immenso parco Six Flags - - -STR_SCNR :Costruisci il tuo parco Six Flags -STR_PARK :Six Flags -STR_DTLS :Costruisci il tuo progetto di parco Six Flags: costruisci le attrazioni degli altri parchi Six Flags oppure progettale da solo - - -STR_SCNR :Costruisci il tuo Six Flags sul Texas -STR_PARK :Six Flags sul Texas -STR_DTLS :Cominciando da zero, costruisci tutte le attrazioni di questo parco Six Flags - - -STR_SCNR :Bazar nei guai -STR_PARK :Bazar nei guai -STR_DTLS :A partire da un bazar in un piccolo mercato, devi far aumentare i profitti dei negozi e dei chioschi costruendo attrazioni e ottovolanti per attirare più clienti - - -STR_SCNR :Castello pazzo -STR_PARK :Castello pazzo -STR_DTLS :Hai ereditato un grande castello: il tuo compito è convertirlo in un piccolo parco tematico. - - -STR_SCNR :Green polverosi -STR_PARK :Green polverosi -STR_DTLS :Situato vicino a un’uscita autostradale nel deserto, Green polverosi è un’ottima opportunità per trasformare un piccolo club di golf in un eccitante parco a tema - - -STR_SCNR :Campi elettrici -STR_PARK :Campi elettrici -STR_DTLS :Hai ereditato una piccola fattoria. La sfida è costruire un piccolo parco a tema tra i campi e gli edifici della fattoria - - -STR_SCNR :Altezze estreme -STR_PARK :Altezze estreme -STR_DTLS :Libero da restrizioni economiche, la sfida sta nell’espandere questo parco deserto per attrarre le persone che vogliono sperimentare la massima ebbrezza - - -STR_SCNR :Stramberie industriali -STR_PARK :Stramberie industriali -STR_DTLS :Un complesso industriale abbandonato è un’opportunità ideale per costruire un parco dei divertimenti con a tema la meccanica - - -STR_SCNR :Boschi fungosi -STR_PARK :Boschi fungosi -STR_DTLS :La sfida sta nel costruire un entusiasmante parco a tema nei Boschi fungosi utilizzando solo attrazioni di legno d’altri tempi - - -STR_SCNR :Città fantasma -STR_PARK :Città fantasma -STR_DTLS :Sei stato assunto da una grande catena di parchi di divertimento per costruire un parco con ottovolanti giganti intorno a una città abbandonata vicino a una miniera - - -STR_SCNR :Giardini gravitazionali -STR_PARK :Giardini gravitazionali -STR_DTLS :La sfida è costruire un parco con ottovolanti in questi bellissimi giardini gravitazionali. Non altre attrazioni, solo ottovolanti!! - - -STR_SCNR :Viste infernali -STR_PARK :Viste infernali -STR_DTLS :Un parco arroccato pericolosamente su roccia vulcanica e tra fiumi di lava - - -STR_SCNR :Lago fortunato -STR_PARK :Lago fortunato -STR_DTLS :Nonostante i fondi illimitati, la posizione di questo parco ti darà del filo da torcere se vorrai espanderlo e gestirlo - - -STR_SCNR :Vertice dell’arcobaleno -STR_PARK :Vertice dell’arcobaleno -STR_DTLS :Questo parco, costruito sul lato di una collina, non può avere attrazioni molto alte. Riuscirai a espandere il parco e a renderlo un enorme successo? - - -STR_SCNR :Six Flags Belgio -STR_PARK :Six Flags Belgio -STR_DTLS :Mettiti alla prova gestendo e migliorando questo parco Six Flags - - -STR_SCNR :Grande avventura Six Flags -STR_PARK :Grande avventura Six Flags -STR_DTLS :Costruisci le attrazioni Six Flags mancanti o crea dei progetti tutti tuoi per migliorare il parco!! Ma non dimenticare il tuo vero scopo: attirare più visitatori al parco!! - - -STR_SCNR :Six Flags Olanda -STR_PARK :Six Flags Olanda -STR_DTLS :Mettiti alla prova gestendo e migliorando questo parco Six Flags - - -STR_SCNR :Montagna magica Six Flags -STR_PARK :Montagna magica Six Flags -STR_DTLS :Costruisci le attrazioni Six Flags mancanti o crea dei progetti tutti tuoi per migliorare il parco!! Ma non dimenticare il tuo vero scopo: restituire il prestito mantenendo al tempo stesso alto il valore del parco!! - - -STR_SCNR :Six Flags sul Texas -STR_PARK :Six Flags sul Texas -STR_DTLS :Costruisci le attrazioni Six Flags mancanti o crea dei progetti tutti tuoi per migliorare il parco!! Ma non dimenticare il tuo vero scopo: attirare più visitatori al parco!! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Miniere africane -STR_PARK :Miniere africane -STR_DTLS :Hai ereditato una miniera di diamanti abbandonata, da cui è stato estratto l’ultimo prezioso diamante. Decidi di investire il ricavato per creare un parco che diventi famoso in tutto il mondo. - - -STR_SCNR :Il miraggio -STR_PARK :Il miraggio -STR_DTLS :Nel deserto è stata scoperta un’oasi che costituirebbe una splendida ambientazione per un parco. I mezzi di trasporto per raggiungerla esistono già. - - -STR_SCNR :Tuffo nel vuoto -STR_PARK :Tuffo nel vuoto -STR_DTLS :È stata costruita una diga che eroga energia idroelettrica a basso prezzo e in quantità, con la quale è possibile alimentare un parco. Per rimborsare il prestito della diga, dovrai creare un parco di grande valore. - - -STR_SCNR :Avventure fra i ghiacci -STR_PARK :Avventure fra i ghiacci -STR_DTLS :L’agenzia dei servizi ambientali si è rivolta a te per trasformare una vecchia raffineria, vero pugno nell’occhio, in rinomata attrazione turistica. La terra costa poco ma l’interesse sui prestiti è alto. Puoi vendere i vecchi edifici. - - -STR_SCNR :La Grande Muraglia Cinese -STR_PARK :La Grande Muraglia Cinese -STR_DTLS :Le autorità hanno deciso di promuovere il turismo presso la Grande Muraglia costruendo un parco a tema nei paraggi. I soldi non sono un problema - - -STR_SCNR :Costa di Okinawa -STR_PARK :Costa di Okinawa -STR_DTLS :Un parco esistente ha esaurito lo spazio a sua disposizione. L’unica possibilità è costruire in mare aperto e per riuscirci hai chiesto un prestito. Le limitazioni di altezza sono piuttosto restrittive, a causa del terreno cedevole. - - -STR_SCNR :Il parco del Maragià -STR_PARK :Il parco del Maragià -STR_DTLS :Il Maragià ti ha incaricato di creare qualcosa che intrattenga la vasta popolazione locale. Costruisci un parco ispirato al palazzo del Maragià. - - -STR_SCNR :Avventura all’Ayers -STR_PARK :Avventura all’Ayers -STR_DTLS :Nell’ambito di un programma di rivalutazione culturale, stai aiutando gli aborigeni a creare un parco. Devi attrarre un numero elevato di visitatori per trasmettergli l’eredità culturale degli aborigeni. - - -STR_SCNR :Barbecue balneare -STR_PARK :Barbecue balneare -STR_DTLS :Il parco marino di un imprenditore locale è fallito. Tu possiedi già un piccolo parco e per comprare l’altro devi trovare dei soldi, sviluppando poi entrambi in una grossa struttura combinata. - - -STR_SCNR :Festival europeo -STR_PARK :Festival europeo -STR_DTLS :Ti è stato chiesto di gestire una grande attrazione culturale europea. Devi incrementare il numero di visite per ripagare i sussidi UE prima che scada il termine stabilito dal Parlamento Europeo. - - -STR_SCNR :Rinascita dalle ceneri -STR_PARK :Rinascita dalle ceneri -STR_DTLS :Un vecchio parco è in sfacelo. Ti viene concesso un prestito dall’Unione Europea per riportare questa zona desolata alla sua bellezza originaria. Dovrai rinnovare il parco e ripagare il prestito. - - -STR_SCNR :Brivido a Waikiki -STR_PARK :Brivido a Waikiki -STR_DTLS :Gli abitanti delle Hawaii sono stufi del surf e cercano qualcosa di più eccitante. Devi costruire un parco che soddisfi le loro aspettative, mantenendo alto il livello di attrazione turistica locale. - - -STR_SCNR :Calamità nel canyon -STR_PARK :Calamità nel canyon -STR_DTLS :Devi costruire un parco ai due lati di questa meraviglia naturale. Hai dei limiti di spazio da rispettare, ma potrai acquistare terreno dagli indiani locali. Dovrai raggiungere l’obiettivo per sostenere la popolazione locale. - - -STR_SCNR :Paradiso dell’ottovolante -STR_PARK :Paradiso dell’ottovolante -STR_DTLS :Sei un magnate della finanza di grande successo, che si è preso 4 anni di vacanza dagli affari e desidera costruire un parco senza badare a spese. - - -STR_SCNR :Il fondatore della città perduta -STR_PARK :Il fondatore della città perduta -STR_DTLS :Per potenziare il turismo, devi creare un parco intonato all’ambiente. - - -STR_SCNR :Scorribanda nella foresta -STR_PARK :Scorribanda nella foresta -STR_DTLS :Nella preziosa foresta pluviale, lo spazio è limitato. Devi sfruttare al meglio la radura già esistente per creare una valida alternativa all’industria locale del legno. - - -STR_SCNR :Pan di zucchero -STR_PARK :Pan di zucchero -STR_DTLS :Gestisci un piccolo parco presso Rio e la banca ti ha chiesto di rimborsare un debito. Devi aumentare rapidamente le tue entrate per fronteggiare questa situazione imprevista. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Castello di Cliffside -STR_PARK :Castello di Cliffside -STR_DTLS :I membri locali della società per il ripristino delle leggi sulle battaglie prendono seriamente il loro hobby. Ti hanno affidato l’incarico di costruire un parco a tema sull’Età Oscura, da erigere sulle fondamenta del Castello di Cliffside. - - -STR_SCNR :Foresta di Sherwood -STR_PARK :Foresta di Sherwood -STR_DTLS :Per sottrarre i beni ai ricchi e donarli ai poveri, tu e i tuoi uomini avete deciso di costruire un parco a tema nella Foresta di Sherwood. - - -STR_SCNR :Stravaganza extraterrestre -STR_PARK :Stravaganza extraterrestre -STR_DTLS :Su un lontano pianeta è stata scoperta la vita Costruisci un parco a tema sugli alieni e goditi un successo di visitatori senza precedenti. - - -STR_SCNR :Città di Gemini -STR_PARK :Città di Gemini -STR_DTLS :Metti in gioco la tua fantastica e utopistica visione del futuro e costruisci un parco futuristico composto dalle attrazioni più all’avanguardia. - - -STR_SCNR :Animatronica antichità -STR_PARK :Animatronica antichità -STR_DTLS :Hai ricevuto l’incarico di gestire un parco a tema esistente, costruito sul set di un vecchio film. Rendi omaggio ai pionieri dell’animazione cinematografica che per primi hanno portato sul grande schermo e creature mitologiche. - - -STR_SCNR :Follia mitologica -STR_PARK :Follia mitologica -STR_DTLS :Possiedi un’isola di eccezionale valore archeologico. Hai deciso di preservarne le origini costruendo un parco a tema basato sull’eredità mitologica della zona. - - -STR_SCNR :Il massacro del cratere -STR_PARK :Il massacro del cratere -STR_DTLS :Possiedi un vecchio cratere meteoritico. Con lo spirito che ti contraddistingue, hai deciso di costruire un parco sugli asteroidi, tramutando così la tua terra in una fonte di ingente guadagno. - - -STR_SCNR :Ottovolantosauro -STR_PARK :Ottovolantosauro -STR_DTLS :Hai ricevuto l’incarico di costruire un parco preistorico ispirato al Giurassico. Per ottimizzare l’accesso dei visitatori, dovrai costruire tragitti che sovrastano la valle e vi si inoltrano. - - -STR_SCNR :Passeggiata tra le rocce -STR_PARK :Passeggiata tra le rocce -STR_DTLS :Per scoraggiare i costruttori di autostrade e conservare i misteriosi e antichi cerchi di pietra, dovrai costruire un parco a tema sull’Età della Pietra e farlo fruttare. L’impresa è una vera e propria sfida, dato il territorio inospitale. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :L’infame isola carceraria, la cui popolazione un tempo si dedicava al contrabbando e alle attività illecite, è in vendita. Hai deciso di trasformarla in un’importante attrazione turistica e il denaro non è un problema. - - -STR_SCNR :Costa di Schneider -STR_PARK :Costa di Schneider -STR_DTLS :Manca poco aI 75° anniversario della conquista della Coppa Schneider da parte di tuo nonno. Hai deciso di onorare la sua impresa costruendo un parco a tema basato sulla famosa corsa di idrovolanti. - - -STR_SCNR :Metropoli -STR_PARK :Metropoli -STR_DTLS :Possiedi un lotto di terra vuoto vicino alla parte meno sviluppata della città. Per sfruttare al meglio la tua proprietà, costruisci un parco caratterizzato da grattacieli ispirandoti all’architettura art decò degli anni Venti. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Un importante festival musicale si tiene ogni anno sulla tua proprietà. Costruisci un parco a tema di ispirazione hippy per attrarre gli spiriti liberi. - - -STR_SCNR :La rinascita del Rock & Roll -STR_PARK :La rinascita del Rock & Roll -STR_DTLS :Questo vecchio parco a tema ha vissuto tempi migliori. Aiuta il proprietario a ristrutturarlo in stile Rock & Roll e trasformalo in un luogo di successo. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Il Mondo dei Panda -STR_PARK :Il Mondo dei Panda -STR_DTLS :Aggiungi più attrazioni per attirare più visitatori in questo parco a tema sui panda. - -### - -STR_SCNR :Cemetery Ridge -STR_PARK :Cemetery Ridge -STR_DTLS :Questo è Halloween, l’Halloween di UCES, le zucche urlano nel bel mezzo della notte! Questo cimitero è in grossi guai e tocca a te salvarlo, lasciando però i morti riposare in pace! Sarai in grado di tenere i fantasmi all’interno delle loro tombe e far rabbrividire i tuoi visitatori?{NEWLINE}Autore: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :The Lighthouse of Alexandria -STR_PARK :The Lighthouse of Alexandria -STR_DTLS :Alessandro costruì la città; i greci, i romani e gli egiziani lasciarono le loro tracce. Ma il più grande regalo è una delle Meraviglie del Mondo Antico, il Faro. Visitalo e creaci un parco!{NEWLINE}Autore: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Proprio com’era il giorno della sua apertura, il 18 maggio 1905.{NEWLINE}Autore: Aetherwave - - -STR_SCNR :Mount Vesuvius -STR_PARK :Mount Vesuvius -STR_DTLS :Pompei ed Ercolano furono ricoperte dal Vesuvio nel 79 a.C. Visita gli scavi e costruiscici un parco!{NEWLINE}Autore: Katatude - - -STR_SCNR :The Sandbox -STR_PARK :The Sandbox -STR_DTLS :Quello che tutti desiderano - una sandbox! Quindi prendi secchio e pala e costruisci un parco!{NEWLINE}Autore: Katatude - - -STR_SCNR :Niagara Falls & Gorge -STR_PARK :Niagara Falls -STR_DTLS :Le American Falls, le Bridal Falls e le Canadian Horseshoe Falls sul confine del Niagara, 1850.{NEWLINE}Autore: Katatude - - -STR_SCNR :Rocky Mountain Miners -STR_PARK :Rocky Mountain Miners -STR_DTLS :Una frana ha danneggiato la tua ferrovia. I tuoi lavoratori sono andati a scavare, ci sarà dell’oro nelle montagne russe?{NEWLINE}Autori: Squid, Buckone, Fossil - - -STR_SCNR :The Time Machine -STR_PARK :The Time Machine -STR_DTLS :La macchina del tempo. Costruisci e viaggia, dove vuoi, quando vuoi. L’eternità ti aspetta. È tutto relativo.{NEWLINE}Autore: Katatude - - -STR_SCNR :Tower of Babel -STR_PARK :Tower of Babel -STR_DTLS :Ehii! Guarda dove ci ha portato adesso la macchina del tempo! Dove sono finiti tutti?{NEWLINE}Autore: Fossil - - -STR_SCNR :Transformation -STR_PARK :Transformation -STR_DTLS :Ti stavamo aspettando…{NEWLINE}Autore: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :I romani sono stanchi delle lotte noiose tra gladiatori. Dagli qualcosa di più eccitante, trasforma la città romana nel più grande parco divertimenti della storia!{NEWLINE}Autore: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Beneath the Christmas Tree -STR_PARK :Winter Wonderland -STR_DTLS :La mamma ha costruito questa scena sotto al nostro albero. Ora vuole che ci costruiamo un parco! Puoi aiutarci?{NEWLINE}Autore: Katatude - - -STR_SCNR :Bigrock Blast -STR_PARK :Bigrock Blast -STR_DTLS :Dopo un’esplosione alle Miniere Pietragrossa S.p.A., agli abitanti di Pietragrossa tocca costruire un parco divertimenti per mantenere la loro città viva.{NEWLINE}Autori: rbarclay & buckone - - -STR_SCNR :Camp Mockingbird -STR_PARK :Camp Mockingbird -STR_DTLS :Solo 500 dollari a settimana per questo campo estivo! Spacca il salvadanaio e divertiti a costruire un parco.{NEWLINE}Autore: Katatude - - -STR_SCNR :Choo-Choo Town -STR_PARK :Choo-Choo Town -STR_DTLS :Mamma! Papà! Voglio andare a Choo-Choo Town!{NEWLINE}Autore: Fossil - - -STR_SCNR :Dragon Islands -STR_PARK :Dragon Islands -STR_DTLS :L’isola dei dragoni? Non sono sicuro di volerci andare…{NEWLINE}Autore: Fossil - - -STR_SCNR :Kiddie Karnival II -STR_PARK :Kiddie Karnival -STR_DTLS :Ehi bambini! Divertiamoci!{NEWLINE}Autori: Piehead & Fossil - - -STR_SCNR :Sand Dune -STR_PARK :Sand Dune -STR_DTLS :In veste di proprietario di un piccolo parco, hai acquistato un ampio terreno lungo la costa per espanderti e portare più visitatori tra le dune di sabbia, ma stai attento: non puoi disturbare queste dune così ecologicamente fragili!{NEWLINE}Autore: rbarclay - diff --git a/data/language/ja-JP.txt b/data/language/ja-JP.txt index 4caa76ef28..3b3ca8f451 100644 --- a/data/language/ja-JP.txt +++ b/data/language/ja-JP.txt @@ -3779,749 +3779,3 @@ STR_6706 :{WINDOW_COLOUR_2}現在の画像ファイル:{BLACK}{STRING} STR_6707 :(選択されていません) STR_6708 :スムース強度 STR_6709 :{COMMA16}と{COMMA16}の間でスムース強度を入力してください - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :フォレスト・フロンティア -STR_PARK :Forest Frontiers -STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area - - -STR_SCNR :ダイナマイト・デューンス -STR_PARK :Dynamite Dunes -STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion - - -STR_SCNR :リーフィー・レーク -STR_PARK :Leafy Lake -STR_DTLS :Starting from scratch, build a theme park around a large lake - - -STR_SCNR :ダイヤモンド・ハイツ -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value - - -STR_SCNR :エバーグリーン・ガーデンズ -STR_PARK :Evergreen Gardens -STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park - - -STR_SCNR :バンブリー・ビーチ -STR_PARK :Bumbly Beach -STR_DTLS :Develop Bumbly Beach’s small amusement park into a thriving theme park - - -STR_SCNR :トリニティ島 -STR_PARK :トリニティ島 -STR_DTLS :Several islands form the basis for this new park - - -STR_SCNR :ケイティーズ・ドリームランド -STR_PARK :Katie’s Dreamland -STR_DTLS :A small theme park with a few rides and room for expansion - Your aim is to double the park value - - -STR_SCNR :ポキー・パーク -STR_PARK :Pokey Park -STR_DTLS :A small, cramped amusement park which requires major expansion - - -STR_SCNR :ホワイト・ウォーター・パーク -STR_PARK :White Water Park -STR_DTLS :A park with some excellent water-based rides requires expansion - - -STR_SCNR :ミレニアム鉱山 -STR_PARK :ミレニアム鉱山 -STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park - - -STR_SCNR :カートとコースター -STR_PARK :カートとコースター -STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters - - -STR_SCNR :メルの世界 -STR_PARK :メルの世界 -STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion - - -STR_SCNR :ミスティック・マウンテン -STR_PARK :Mystic Mountain -STR_DTLS :In the hilly forests of Mystic Mountain, build a theme park from scratch - - -STR_SCNR :パシフィック・ピラミッド -STR_PARK :Pacific Pyramids -STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park - - -STR_SCNR :クランブリ・ウッズ -STR_PARK :Crumbly Woods -STR_DTLS :A large park with well-designed but rather old rides - Replace the old rides or add new rides to make the park more popular - - -STR_SCNR :パラダイス・ピア -STR_PARK :Paradise Pier -STR_DTLS :Convert this sleepy town’s pier into a thriving attraction - - -STR_SCNR :ライトニング・ピーク -STR_PARK :Lightning Peaks -STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers - Use the available land to attract a new thrill-seeking clientele - - -STR_SCNR :アイボリー・タワーズ -STR_PARK :Ivory Towers -STR_DTLS :A well-established park, which has a few problems - - -STR_SCNR :レインボー・バレー -STR_PARK :Rainbow Valley -STR_DTLS :Rainbow Valley’s local authority won’t allow any landscape changes or large tree removal, but you must develop the area into a large theme park - - -STR_SCNR :サンダー・ロック -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists - Use the available space to build rides to attract more people - - -STR_SCNR :メガ・パーク -STR_PARK :Mega Park -STR_DTLS :楽しみだけ! - - -## Added Attractions - -STR_SCNR :ウィスペリング・クリフス -STR_PARK :Whispering Cliffs -STR_DTLS :Develop the seaside cliffs into a thriving amusement park - - -STR_SCNR :スリー・モンキー・パーク -STR_PARK :Three Monkeys Park -STR_DTLS :Central to this large developing park is a giant triple-track racing/duelling steel coaster - - -STR_SCNR :カナリー鉱山 -STR_PARK :カナリー鉱山 -STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its miniature railway and a pair of vertical drop roller coasters - - -STR_SCNR :バリー・ブリッジ -STR_PARK :Barony Bridge -STR_DTLS :An old redundant bridge is yours to develop into an amusement park - - -STR_SCNR :ファントピア -STR_PARK :ファントピア -STR_DTLS :Covering land both sides of a highway, this park has several rides already operating - - -STR_SCNR :ホーンテッド・ハーバー -STR_PARK :Haunted Harbour -STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved - - -STR_SCNR :ファン・フォートレス -STR_PARK :Fun Fortress -STR_DTLS :This castle is all yours to turn into a theme park - - -STR_SCNR :未来世界 -STR_PARK :未来世界 -STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape - - -STR_SCNR :ジェントル・グレン -STR_PARK :Gentle Glen -STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes - - -STR_SCNR :ジョリー・ジャングル -STR_PARK :Jolly Jungle -STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park - - -STR_SCNR :ハイドロ・ヒルズ -STR_PARK :Hydro Hills -STR_DTLS :A series of stepped lakes form the basis for this new park - - -STR_SCNR :スポライトリー・パーク -STR_PARK :Sprightly Park -STR_DTLS :This elderly park has many historical rides but is badly in debt - - -STR_SCNR :マジック・クォーターズ -STR_PARK :Magic Quarters -STR_DTLS :A large area of land has been cleared and partially themed ready for you to develop into a landscaped theme park - - -STR_SCNR :フルーツ・ファーム -STR_PARK :Fruit Farm -STR_DTLS :A thriving fruit farm has built a railroad to boost its income, your job is to develop it into a full-blown amusement park - - -STR_SCNR :バタフライダム -STR_PARK :Butterfly Dam -STR_DTLS :The area around a dam is available for you to develop into an amusement park - - -STR_SCNR :コースター・キャニオン -STR_PARK :Coaster Canyon -STR_DTLS :A vast canyon is yours to turn into a theme park - - -STR_SCNR :サンダーストーム・パーク -STR_PARK :Thunderstorm Park -STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover - - -STR_SCNR :ハーモニック・ヒルズ -STR_PARK :Harmonic Hills -STR_DTLS :The local authority won’t allow you to build above tree height in this park - - -STR_SCNR :ローマン・ビレッジ -STR_PARK :Roman Village -STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters - - -STR_SCNR :スワンプ・コーブ -STR_PARK :Swamp Cove -STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centrepiece - - -STR_SCNR :アドレナリン・ハイツ -STR_PARK :Adrenaline Heights -STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people - - -STR_SCNR :ユートピア・パーク -STR_PARK :Utopia -STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park - - -STR_SCNR :ロッティングハイツ -STR_PARK :Rotting Heights -STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? - - -STR_SCNR :フィアスコ・フォレスト -STR_PARK :Fiasco Forest -STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around - - -STR_SCNR :ピクル・パーク -STR_PARK :Pickle Park -STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only - - -STR_SCNR :ギゴル・ダウンズ -STR_PARK :Giggle Downs -STR_DTLS :A four lane steeplechase ride is the centrepiece of this expanding park - - -STR_SCNR :ミネラル・パーク -STR_PARK :Mineral Park -STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists - - -STR_SCNR :コースター・クレイジー -STR_PARK :Coaster Crazy -STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park - - -STR_SCNR :アーバン・パーク -STR_PARK :Urban Park -STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself - - -STR_SCNR :ジェフリー・ガーデンズ -STR_PARK :Geoffrey Gardens -STR_DTLS :A large garden park needs turning into a thriving theme park - - -## Loopy Landscapes - -STR_SCNR :アイスベルグ・アイランド -STR_PARK :Iceberg Islands -STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park - - -STR_SCNR :ボルカニア -STR_PARK :Volcania -STR_DTLS :A dormant volcano is the setting of this coaster-building challenge - - -STR_SCNR :アリド・ハイツ -STR_PARK :Arid Heights -STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy - - -STR_SCNR :レーザー・ロック -STR_PARK :Razor Rocks -STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks - - -STR_SCNR :クレーター・レーク -STR_PARK :Crater Lake -STR_DTLS :A large lake in an ancient crater is the setting for this park - - -STR_SCNR :バーチゴ・ビューズ -STR_PARK :Vertigo Views -STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit - - -STR_SCNR :パラダイス・ピアー・2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space - - -STR_SCNR :ドラゴンス・コーブ -STR_PARK :Dragon’s Cove -STR_DTLS :This sea-side cove is the setting for this coaster-building challenge - - -STR_SCNR :グッド・ナイト・パーク -STR_PARK :Good Knight Park -STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park - - -STR_SCNR :ウェッキー・ウォレン -STR_PARK :Wacky Warren -STR_DTLS :A park which has much of its footpaths and coasters underground - - -STR_SCNR :グランド・グレーシアー -STR_PARK :Grand Glacier -STR_DTLS :A glacier-filled valley is yours to develop into a theme park - - -STR_SCNR :クレージ・クレーター -STR_PARK :Crazy Craters -STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy - - -STR_SCNR :ダスティー・デザルト -STR_PARK :Dusty Desert -STR_DTLS :Five coasters require completion in this desert park - - -STR_SCNR :ウードウォーム・パーク -STR_PARK :Woodworm Park -STR_DTLS :This historical park is only allowed to build older-styled rides - - -STR_SCNR :イカラス・パーク -STR_PARK :Icarus Park -STR_DTLS :Develop this alien park to maximise its profit - - -STR_SCNR :サニー・スワンプ -STR_PARK :Sunny Swamps -STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion - - -STR_SCNR :フライトメア・ヒルズ -STR_PARK :Frightmare Hills -STR_DTLS :A scary park with a giant centrepiece coaster - - -STR_SCNR :サンダー・ロック -STR_PARK :Thunder Rocks -STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed - - -STR_SCNR :オクタゴン・パーク -STR_PARK :Octagon Park -STR_DTLS :In this large park you must design and build ten large coasters - - -STR_SCNR :プレジャー・アイランド -STR_PARK :Pleasure Island -STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters - - -STR_SCNR :アイシクル・ワールド -STR_PARK :Icicle Worlds -STR_DTLS :An icy landscape needs turning into a thriving theme park - - -STR_SCNR :サザーン・サンド -STR_PARK :Southern Sands -STR_DTLS :A desert park with some cleverly designed coasters is yours to expand - - -STR_SCNR :タイニー・タワーズ -STR_PARK :Tiny Towers -STR_DTLS :In this tiny park you must finish building the five existing coasters - - -STR_SCNR :ネヴァーモア・パーク -STR_PARK :Nevermore Park -STR_DTLS :A large park with a novel transportation system around its edge - - -STR_SCNR :パシフィカ -STR_PARK :Pacifica -STR_DTLS :This large island is all yours to develop as an amusement park - - -STR_SCNR :アーバン・ジャングル -STR_PARK :Urban Jungle -STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer - - -STR_SCNR :タッラー・タウン -STR_PARK :Terror Town -STR_DTLS :This urban area is all yours to develop into an amusement park - - -STR_SCNR :メガワールド・パーク -STR_PARK :Megaworld Park -STR_DTLS :A giant park already packed full of rides needs improving - - -STR_SCNR :ビーナス・ポンド -STR_PARK :Venus Ponds -STR_DTLS :On a far-away planet this area of land needs turning into a theme park - - -STR_SCNR :マイクロ・パーク -STR_PARK :Micro Park -STR_DTLS :Try to create the world’s smallest profitable park - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :アルトン・タワーズ -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :ハイデ・パーク -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :ブラックプール・プレジャー・ビーチ -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :フォート・アナクロニズム -STR_PARK :Fort Anachronism -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :屋根 -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :高山アドベンチャー -STR_PARK :Alpine Adventures -STR_DTLS :山あいの小さなスキーリゾート地を、雪をテーマにした遊園地に造り替えてください - - -STR_SCNR :アミティ・エアフィールド -STR_PARK :Amity Airfield -STR_DTLS :この放置された空港を、飛行をテーマにした遊園地に造り替えてください - - -STR_SCNR :ボタニー・ブレイカーズ -STR_PARK :Botany Breakers -STR_DTLS :この楽園のような島に、高い収益を生み出す遊園地を建設するのがあなたに与えられた課題です - - -STR_SCNR :自身のシックス・フラッグス・ベルギー -STR_PARK :Six Flags Belgium -STR_DTLS :このヨーロパであるテーマパークに自身のシックス・フラッグス・パークを作って下さい。 - - -STR_SCNR :自身のシックス・フラッグス・グレート・アドベンチャー -STR_PARK :Six Flags Great Adventure -STR_DTLS :このテーマパークに自身のシックス・フラッグス・パークを作って下さい。 - - -STR_SCNR :自身のシックス・フラッグス・オランダ -STR_PARK :Six Flags Holland -STR_DTLS :このヨーロパであるテーマパークに自身のシックス・フラッグス・パークを作って下さい。 - - -STR_SCNR :自身のシックス・フラッグス・マジック・マウンテン -STR_PARK :Six Flags Magic Mountain -STR_DTLS :この大きなパークで自身のシックス・フラッグス・パークを作って下さい。 - - -STR_SCNR :自身のシックス・フラッグス・オバー・テキサス -STR_PARK :Six Flags over Texas -STR_DTLS :このテーマパークに自身のシックス・フラッグス・パークを作って下さい。 - - -STR_SCNR :自身のシックス・フラッグス・パーク -STR_PARK :Six Flags -STR_DTLS :このテーマパークに自身シックス・フラッグス・パークを作って下さい。 - - -STR_SCNR :バンブリー商店街 -STR_PARK :Bumbly Bazaar -STR_DTLS : 小さな商店街からスタートし、乗物やローラーコースターで来園客を呼び寄せ、店や売店の利益を増やしてください - - -STR_SCNR :クレイジーキャッスル -STR_PARK :Crazy Castle -STR_DTLS :あなたは、大きな城を相続しました - ここを、小さなテーマパークに造り替えてください. - - -STR_SCNR :ダスティ・グリーン -STR_PARK :Dusty Greens -STR_DTLS :砂漠の中の、高速道路のジャンクションに近いダスティ・グリーンゴルフ場。ここを、人気遊園地にすることができますか - - -STR_SCNR :エレクトリック・フィールド -STR_PARK :Electric Fields -STR_DTLS :小さな農場を相続したあなたに与えられた課題は、畑や農場の建物の間に、小さなテーマパークを造ることです - - -STR_SCNR :超高層 -STR_PARK :Extreme Heights -STR_DTLS :財政上の制限なしで、この砂漠の遊園地を拡張し、究極のスリルを求める人々を呼び寄せてください - - -STR_SCNR :ファクトリー・ケイパーズ -STR_PARK :Factory Capers -STR_DTLS :放置された工業コンビナートは、機械風のテーマの遊園地を造るのにうってつけです - - -STR_SCNR :キノコの森 -STR_PARK :Fungus Woods -STR_DTLS :この「キノコの森」では、乗物は昔風の木造のものしか造れません。果たして、あなたはここを人気遊園地にできるでしょうか - - -STR_SCNR :ゴーストタウン -STR_PARK :Ghost Town -STR_DTLS :大遊園地チェーンに雇われたあなたは、この古ぼけた鉱山の町の周りに巨大ローラーコースター遊園地を造らなければなりません - - -STR_SCNR :グラビティー・ガーデン -STR_PARK :Gravity Gardens -STR_DTLS :あなたに与えられた課題は、この美しいグラビティー・ガーデンにローラーコースター遊園地を造ることです - ローラーコースターだけですよ、他の乗物はなしです! - - -STR_SCNR :地獄絵図 -STR_PARK :Infernal Views -STR_DTLS :すぐ近くを溶岩とマグマが流れる、危険な遊園地です - - -STR_SCNR :ラッキー・レイク -STR_PARK :Lucky Lake -STR_DTLS :この遊園地では資金は使い放題ですが、湖畔に位置しているので、拡張と経営はきっと困難なものとなるでしょう - - -STR_SCNR :レインボーサミット -STR_PARK :Rainbow Summit -STR_DTLS :丘の中腹にあるこの遊園地では、いかなる高層建築物も禁止されています。遊園地を拡張し、成功に導くことができるでしょうか - - -STR_SCNR :シックスフラッグス・ベルギー -STR_PARK :Six Flags Belgium -STR_DTLS :このシックスフラッグス遊園地で、あなたの経営と改良の手腕を見せてください - - -STR_SCNR :シックスフラッグス・グレートアドベンチャー -STR_PARK :Six Flags Great Adventure -STR_DTLS :不足しているシックスフラッグスの乗物を設置するか、またはご自分でオリジナルデザインの乗物を作成して遊園地を改良してください!しかし、本来の最終目標である、遊園地 - - -STR_SCNR :シックスフラッグス・オランダ -STR_PARK :Six Flags Holland -STR_DTLS :このシックスフラッグス遊園地で、あなたの経営と改良の手腕を見せてください - - -STR_SCNR :シックスフラッグス・マジックマウンテン -STR_PARK :Six Flags Magic Mountain -STR_DTLS :不足しているシックスフラッグスの乗物を設置するか、またはご自分でオリジナルデザインの乗物を作成して遊園地を改良してください!しかし、本来の最終目標である、遊園地 - - -STR_SCNR :シックスフラッグス・オーバーテキサス -STR_PARK :Six Flags over Texas -STR_DTLS : 不足しているシックスフラッグスの乗物を設置するか、またはご自分でオリジナルデザインの乗物を作成して遊園地を改良してください!しかし、本来の最終目標である、遊園地 - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :アフリカの鉱山 -STR_PARK :アフリカの鉱山 -STR_DTLS :You inherited a disused diamond mine, and find a valuable diamond. You decide to invest that money to build a world-famous theme park. - - -STR_SCNR :ミラージュ・マッドネス -STR_PARK :ミラージュ・マッドネス -STR_DTLS :A desert Oasis has been discovered and would provide a beautiful location for a park. Transport to the oasis has been provided. - - -STR_SCNR :オーバー・ザ・エッジ -STR_PARK :オーバー・ザ・エッジ -STR_DTLS :A dam has been built offering abundant, cheap hydroelectric power with which to run a park. You need to reach a high park value to help repay the loan for the dam. - - -STR_SCNR :氷の冒険 -STR_PARK :氷の冒険 -STR_DTLS :The environment agency has turned to you to transform an old oil refinery ecological eyesore into a top tourist attraction. Land is cheap but loan interest is high. You can sell the old buildings for salvage. - - -STR_SCNR :万里の長城 -STR_PARK :万里の長城 -STR_DTLS :The authorities have decided to enhance tourism around the Great Wall by building a theme park on the adjacent land. Money is no object! - - -STR_SCNR :沖縄海岸 -STR_PARK :沖縄海岸 -STR_DTLS :An existing park has run out of space. Your only option is to build out into the sea, and so you have taken out a loan. Height restrictions on your building are enforced due to foundations and earthquake risk. - - -STR_SCNR :パーク・マハラジャ -STR_PARK :パーク・マハラジャ -STR_DTLS :You have been commissioned by the Maharaja to bring entertainment to the large local population. Build a park inspired by the Maharaja’s palace. - - -STR_SCNR :エアーズ・アドベンチャー -STR_PARK :エアーズ・アドベンチャー -STR_DTLS :You are helping Aboriginal people to build a park as part of a cultural awareness program. You need to get a large number of guests to educate them in the unique heritage of the Aboriginal people. - - -STR_SCNR :ビーチ・バーベキュー -STR_PARK :ビーチ・バーベキュー -STR_DTLS :A local entrepreneur’s sealife park has gone bust. You already operate a small park and buy the other park from the construction company. Develop a big combined park. - - -STR_SCNR :ヨーロッパ文化祭 -STR_PARK :ヨーロッパ文化祭 -STR_DTLS :You have been brought in to take over a European Cultural Visitor Attraction and must increase the number of guests in order to pay back the EU subsidy by the end of the current European parliament term. - - -STR_SCNR :灰の中から -STR_PARK :灰の中から -STR_DTLS :An old park has fallen into disrepair. You gain a European Union grant to return this deprived area to its former glory! You need to renovate the park and repay the grant. - - -STR_SCNR :ワッキー・ワイキキ -STR_PARK :ワッキー・ワイキキ -STR_DTLS :The people of Hawaii are bored of surfing and are looking for something more intense. You need to build a park with this in mind to keep the area’s tourist attraction rating high. - - -STR_SCNR :キャニオン・カラミティー -STR_PARK :キャニオン・カラミティー -STR_DTLS :You have to build a park on limited land either side of this natural treasure - you do have the opportunity to buy neighbouring land from the Native American Indians. You need to complete the objective to sustain the local town’s population. - - -STR_SCNR :ジェットコースター天国 -STR_PARK :ジェットコースター天国 -STR_DTLS :You are a successful business tycoon on long sabbatical who desires to use this time transforming the city park into Rollercoaster Heaven. Money is no object! - - -STR_SCNR :ロスト・シティ -STR_PARK :ロスト・シティ -STR_DTLS :To further boost local tourism you must construct a park that is in tune with its surroundings, and has height restrictions. - - -STR_SCNR :熱帯雨林高原 -STR_PARK :熱帯雨林高原 -STR_DTLS :Space is limited in the precious rainforest - you must cram as much as possible into the existing clearing, in order to provide a viable alternative to the local timber industry. - - -STR_SCNR :シュガーローフ・ショアーズ -STR_PARK :シュガーローフ・ショアーズ -STR_DTLS :You run a small park near Rio but the bank has called in your loan. You need to quickly increase your earning capacity to repay this unexpected debt. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :崖側の城 -STR_PARK :崖側の城 -STR_DTLS :Local members of the battle re-enactment society are rather serious about their hobby. They’ve entrusted you with the job of constructing a Dark Age theme park on the grounds of Cliffside Castle. - - -STR_SCNR :シャーウッドの森 -STR_PARK :シャーウッドの森 -STR_DTLS :To liberate wealth from the rich and distribute it to the needy, you and your Merry Men have decided to build a theme park in Sherwood Forest. - - -STR_SCNR :地球外な壮観 -STR_PARK :地球外な壮観 -STR_DTLS :Life has been discovered on a distant planet Build an alien theme park to cash in on the unprecedented wave of interest. - - -STR_SCNR :ジェミニ・シティ -STR_PARK :ジェミニ・シティ -STR_DTLS :Show off your inventive, utopian vision of the future - come up with a futuristic park design that incorporates state-of-the-art attractions. - - -STR_SCNR :アニマトロ・アンティクス -STR_PARK :アニマトロ・アンティクス -STR_DTLS :You have been given the task of running and improving an existing theme park, which has been built on an old film set. Build a tribute to the pioneering stop-motion animators who first brought mythical creatures to life on the silver screen. - - -STR_SCNR :神話の狂気 -STR_PARK :神話の狂気 -STR_DTLS :You own an island of particular archaeological value. You’ve decided to fund its preservation by constructing a theme park based on the area’s rich Mythological heritage. - - -STR_SCNR :クレーターの大虐殺 -STR_PARK :クレーターの大虐殺 -STR_DTLS :You own a dusty old meteor crater. In the true entrepreneurial spirit, you’ve decided to construct an asteroid theme park and convert your seemingly worthless land into a sizeable fortune. - - -STR_SCNR :コースターサウルス -STR_PARK :コースターサウルス -STR_DTLS :You’ve been given the task of constructing a Jurassic era theme park. To optimize your visitors’ access to the exotic plant and animal exhibits, you will need to build rides going over and into the valley. - - -STR_SCNR :ロッキー・ランブル -STR_PARK :ロッキー・ランブル -STR_DTLS :To thwart the highway developers and preserve the mysterious ancient stone circles, you will need to construct a Stone Age theme park and turn a profit. However, attracting visitors may pose a challenge, as the terrain is a tad inhospitable. - - -STR_SCNR :アルカトラズ -STR_PARK :アルカトラズ -STR_DTLS :The infamous Prison Island - whose population once swelled with bootleggers and racketeers - is now up for sale. You’ve decided to convert it into a top tourist attraction, and money is no object - - -STR_SCNR :シュナイダー・ショーズ -STR_PARK :シュナイダー・ショーズ -STR_DTLS :The 75th anniversary of your grandfather’s Schneider Cup victory is coming up in a few years. You’re going to honour his achievement by building a theme park based on the famous seaplane race. - - -STR_SCNR :メトロポリス -STR_PARK :メトロポリス -STR_DTLS :You own an empty lot near the low-rise part of town. To squeeze the most out of your urban property, build a skyscraper theme park inspired by the soaring art deco architecture of the twenties. - - -STR_SCNR :ウッドストック -STR_PARK :ウッドストック -STR_DTLS :A large annual music festival takes place on your land. Build a hip theme park to keep the free-spirited audience entertained. - - -STR_SCNR :ロックンロール・リバイバル -STR_PARK :ロックンロール・リバイバル -STR_DTLS :This aging theme park has seen better days. Help the owner give it a retro rock ’n’ roll makeover and turn the place into a successful venue. diff --git a/data/language/ko-KR.txt b/data/language/ko-KR.txt index 9316dc27bb..4d2497d80b 100644 --- a/data/language/ko-KR.txt +++ b/data/language/ko-KR.txt @@ -3781,858 +3781,3 @@ STR_6706 :{WINDOW_COLOUR_2}현재 이미지 파일: {BLACK}{STRING} STR_6707 :(선택 안 함) STR_6708 :부드러움 강도 STR_6709 :부드러움 강도를 {COMMA16}∼{COMMA16} 사이의 값으로 입력하세요 - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :미개척된 숲 -STR_DTLS :깊은 숲 속 넓은 공터에 번창한 놀이공원을 건설하세요. - - -STR_SCNR :Dynamite Dunes -STR_PARK :다이너마이트 모래언덕 -STR_DTLS :사막 한가운데 건설된 이 놀이공원에는 롤러코스터 한 대만이 있지만 확장할 수 있는 곳이 많습니다. - - -STR_SCNR :Leafy Lake -STR_PARK :나뭇잎 호수 -STR_DTLS :처음부터 시작하여 큰 호수 주변에 놀이공원을 건설하세요. - - -STR_SCNR :Diamond Heights -STR_PARK :다이아몬드 언덕 -STR_DTLS :다이아몬드 언덕은 멋진 놀이기구를 통해 이미 성공한 놀이공원입니다. 공원의 가치를 두 배로 늘려 보세요. - - -STR_SCNR :Evergreen Gardens -STR_PARK :상록수 정원 -STR_DTLS :아름다운 상록수 정원을 번창한 놀이공원으로 바꿔보세요. - - -STR_SCNR :Bumbly Beach -STR_PARK :범블리 해변 -STR_DTLS :범블리 해변의 작은 놀이공원을 번창한 놀이공원으로 발전시키세요. - - -STR_SCNR :Trinity Islands -STR_PARK :삼위일체 섬 -STR_DTLS :몇 개의 섬이 이 새로운 공원의 기반입니다. - - -STR_SCNR :Katie’s Dreamland -STR_PARK :케이티의 드림랜드 -STR_DTLS :몇 개의 놀이기구와 확장할 공간이 있는 작은 놀이공원으로, 여러분의 목표는 공원 가치를 두 배로 늘리는 것입니다. - - -STR_SCNR :Pokey Park -STR_PARK :비좁은 공원 -STR_DTLS :대대적인 확장을 해야 하는 비좁은 놀이공원입니다. - - -STR_SCNR :White Water Park -STR_PARK :맑은 물 공원 -STR_DTLS :훌륭한 물 놀이기구를 몇 개 갖고 있지만 확장이 필요한 공원입니다. - - -STR_SCNR :Millennium Mines -STR_PARK :밀레니엄 광산 -STR_DTLS :버려져있는 커다란 탄광을 관광시설에서 놀이공원으로 바꿔보세요. - - -STR_SCNR :Karts & Coasters -STR_PARK :카트 & 코스터 -STR_DTLS :몇 개의 고 카트 트랙과 우든 롤러코스터가 숲속에 숨겨진 대형 놀이공원입니다. - - -STR_SCNR :Mel’s World -STR_PARK :멜의 세계 -STR_DTLS :이 놀이공원에는 잘 디자인된 현대식 놀이기구가 있지만, 아직도 확장해야 할 곳이 많습니다. - - -STR_SCNR :Mystic Mountain -STR_PARK :신비한 산 -STR_DTLS :비밀스런 숲 속 언덕에 처음부터 놀이공원을 건설하세요. - - -STR_SCNR :Pacific Pyramids -STR_PARK :평화로운 피라미드 -STR_DTLS :이집트 유적 관광지를 번창한 놀이공원으로 바꿔보세요. - - -STR_SCNR :Crumbly Woods -STR_PARK :부서지기 쉬운 숲 -STR_DTLS :잘 디자인되었지만 다소 낡은 놀이기구를 가진 대형 공원입니다. 오래된 놀이기구를 교체하거나 새로운 놀이기구를 추가하여 보다 인기있는 공원을 만들어보세요. - - -STR_SCNR :Paradise Pier -STR_PARK :파라다이스 부두 -STR_DTLS :이 조용한 마을의 부두를 번창한 놀이공원으로 바꿔보세요. - - -STR_SCNR :Lightning Peaks -STR_PARK :번개치는 산꼭대기 -STR_DTLS :번개치는 산꼭대기의 아름다운 산은 경치를 즐기며 산책을 즐기는 사람들에게 인기가 높습니다. 사용 가능한 땅을 이용해서 스릴을 찾는 새로운 고객을 유혹해보세요. - - -STR_SCNR :Ivory Towers -STR_PARK :상아 탑 -STR_DTLS :문제가 몇 가지 있지만 잘 구성된 공원입니다. - - -STR_SCNR :Rainbow Valley -STR_PARK :무지개 계곡 -STR_DTLS :무지개 계곡의 지역 당국이 풍경을 바꾸거나 큰 나무를 제거할 수 없게 금지했지만, 이 지역을 개발하여 대형 놀이공원으로 바꿔야만 합니다. - - -STR_SCNR :Thunder Rock -STR_PARK :천둥 바위 -STR_DTLS :천둥 바위는 사막 한가운데에서 많은 관광객을 끌어모으고 있습니다. 사용 가능한 공간을 이용해 놀이기구를 건설해서 더 많은 사람을 끌어 보세요. - - -STR_SCNR :Mega Park -STR_PARK :대공원 -STR_DTLS :그냥 즐기세요! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :속삭이는 절벽 -STR_DTLS :해변의 절벽을 인기 있는 놀이공원으로 발전시키세요. - - -STR_SCNR :Three Monkeys Park -STR_PARK :세 원숭이 공원 -STR_DTLS :개발 중인 이 거대한 공원의 한 가운데에는 동시에 경주하는 거대한 세쌍둥이 철제 롤러코스터가 있습니다. - - -STR_SCNR :Canary Mines -STR_PARK :카나리아 광산 -STR_DTLS :이 버려진 탄광은 모형 기차와 수직 낙하 롤러코스터로 이미 관광객의 인기를 끌고 있습니다. - - -STR_SCNR :Barony Bridge -STR_PARK :남작의 다리 -STR_DTLS :필요없는 오래된 다리를 놀이공원으로 개발할 수 있습니다. - - -STR_SCNR :Funtopia -STR_PARK :펀토피아 -STR_DTLS :고속도로 양쪽을 잘 활용한 이 공원은 이미 몇 가지 놀이기구를 운영하고 있습니다. - - -STR_SCNR :Haunted Harbour -STR_PARK :유령 항구 -STR_DTLS :지역 당국은 특정 놀이기구는 파괴할 수 없다는 조건을 걸고 이 작은 해변 공원 근처의 땅을 저렴하게 팔기로 합의했습니다. - - -STR_SCNR :Fun Fortress -STR_PARK :즐거운 요새 -STR_DTLS :이 성은 이제 당신의 소유입니다. 이 성을 놀이공원으로 바꾸어보세요. - - -STR_SCNR :Future World -STR_PARK :미래 세계 -STR_DTLS :이 미래지향적인 공원에는 외계 지형 위에 새로운 놀이기구를 지을 넓은 공간이 있습니다. - - -STR_SCNR :Gentle Glen -STR_PARK :얌전한 골짜기 -STR_DTLS :이 지역의 주민들은 격렬하지 않고 얌전한 놀이기구를 선호합니다. 이 공원을 그들의 취향에 맞게 확장해보세요. - - -STR_SCNR :Jolly Jungle -STR_PARK :즐거운 정글 -STR_DTLS :정글 속 깊은 곳에 놀이공원으로 탈바꿈할 수 있는 넓은 대지가 있습니다. - - -STR_SCNR :Hydro Hills -STR_PARK :하이드로 언덕 -STR_DTLS :몇 개의 호수를 기반으로 새로운 공원을 건설할 수 있습니다. - - -STR_SCNR :Sprightly Park -STR_PARK :활기 넘치는 공원 -STR_DTLS :이 오래된 공원에는 아주 역사적인 놀이기구가 많이 있지만 심각한 적자에 시달리고 있습니다. - - -STR_SCNR :Magic Quarters -STR_PARK :매직 쿼터 -STR_DTLS :비어있는 넓은 지역의 일부분을 아름다운 풍경의 테마파크로 개발할 준비가 되었습니다. - - -STR_SCNR :Fruit Farm -STR_PARK :과일 농장 -STR_DTLS :무성한 과일 농장에 모형 기차를 건설해서 수익을 극대화하고 있습니다. 여러분의 임무는 이 농장을 최고의 놀이공원으로 만드는 것입니다. - - -STR_SCNR :Butterfly Dam -STR_PARK :나비 댐 -STR_DTLS :댐 주변 지역을 놀이공원으로 개발할 수 있습니다. - - -STR_SCNR :Coaster Canyon -STR_PARK :코스터 협곡 -STR_DTLS :광대한 협곡을 테마파크로 개발할 수 있습니다. - - -STR_SCNR :Thunderstorm Park -STR_PARK :폭풍우 공원 -STR_DTLS :날씨가 너무 습해서 거대한 피라미드를 짓고 일부 놀이기구를 그 속에 두기로 했습니다. - - -STR_SCNR :Harmonic Hills -STR_PARK :조화로운 언덕 -STR_DTLS :이 공원의 지역 당국은 나무 높이 이상의 건설을 허용하지 않습니다. - - -STR_SCNR :Roman Village -STR_PARK :로마의 마을 -STR_DTLS :이 로마 스타일의 테마파크에 놀이기구와 롤러코스터를 추가해서 더욱 발전시켜보세요. - - -STR_SCNR :Swamp Cove -STR_PARK :습지 골짜기 -STR_DTLS :몇 개의 작은 섬에 부분 부분 건설된 이 공원에는 이미 중앙에 한 쌍의 거대한 롤러코스터가 있습니다. - - -STR_SCNR :Adrenaline Heights -STR_PARK :아드레날린 언덕 -STR_DTLS :격렬한 스릴을 즐기는 사람들을 위한 공원을 건설하세요. - - -STR_SCNR :Utopia Park -STR_PARK :유토피아 공원 -STR_DTLS :사막 한가운데의 오아시스에 놀이공원을 건설해보세요. - - -STR_SCNR :Rotting Heights -STR_PARK :썩어버린 언덕 -STR_DTLS :지나치게 성장해서 황폐화되어버린 이곳을 다시 멋진 공원으로 바꿀 수 있습니까? - - -STR_SCNR :Fiasco Forest -STR_PARK :실패한 숲 -STR_DTLS :위험하고 잘못 설계된 놀이기구가 많이 있습니다. 공원을 둘러보고 문제를 수정할 시간과 예산이 매우 부족합니다. - - -STR_SCNR :Pickle Park -STR_PARK :피클 공원 -STR_DTLS :지역 당국이 광고나 홍보를 불허했기 때문에 이 공원은 사람들의 입을 통해서만 알릴 수 있습니다. - - -STR_SCNR :Giggle Downs -STR_PARK :웃기는 구릉 지대 -STR_DTLS :이 넓은 공원의 중앙에는 네 쌍둥이 스티플체이스 놀이기구가 있습니다. - - -STR_SCNR :Mineral Park -STR_PARK :광물 공원 -STR_DTLS :이 버려진 채석장을 스릴을 찾는 사람들을 유혹할만한 장소로 바꿔보세요. - - -STR_SCNR :Coaster Crazy -STR_PARK :미친 코스터 -STR_DTLS :이 산악 지대에 다양한 롤러코스터를 건설해보세요. 예산은 한정되어 있지만 시간은 제한이 없습니다. - - -STR_SCNR :Urban Park -STR_PARK :도시 공원 -STR_DTLS :이 작은 공원은 이 도시뿐만 아니라 근교 도시의 주민들에게까지 인기를 모으고 있습니다. - - -STR_SCNR :Geoffrey Gardens -STR_PARK :제프리의 정원 -STR_DTLS :대규모의 정원 공원을 북적이는 놀이공원으로 바꿔야 합니다. - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :빙산 섬 -STR_DTLS :빙산이 이 야심찬 놀이공원에 차가운 이미지를 더하고 있습니다. - - -STR_SCNR :Volcania -STR_PARK :볼케이니아 -STR_DTLS :이번 롤러코스터 건설 도전에서는 휴화산이 무대가 됩니다. - - -STR_SCNR :Arid Heights -STR_PARK :건조한 언덕 -STR_DTLS :아무런 재정적 제한 없는 상황에서, 손님들을 언제나 행복하게 만들 수 있는 공원을 사막에 건설해보세요. - - -STR_SCNR :Razor Rocks -STR_PARK :날카로운 바위 -STR_DTLS :여러분의 임무는 날카로운 바위 사이에 롤러코스터로 가득한 거대한 공원을 만드는 것입니다. - - -STR_SCNR :Crater Lake -STR_PARK :분화구 호수 -STR_DTLS :이 공원의 부지는 고대 분화구에 만들어진 커다란 호수입니다. - - -STR_SCNR :Vertigo Views -STR_PARK :어지러운 풍경 -STR_DTLS :이 거대한 공원에는 이미 훌륭한 하이퍼코스터가 있습니다. 여러분의 임무는 그 매출을 아주 극대화하는 것입니다. - - -STR_SCNR :Paradise Pier 2 -STR_PARK :파라다이스 부두 2 -STR_DTLS :파라다이스 부두는 바다 위의 산책로를 확장했습니다. 여러분의 임무는 이 새로운 공간을 이용하여 공원을 확장하는 것입니다. - - -STR_SCNR :Dragon’s Cove -STR_PARK :용의 만 -STR_DTLS :이번 롤러코스터 건설 도전에서는 바닷가 근처의 만이 무대가 됩니다. - - -STR_SCNR :Good Knight Park -STR_PARK :훌륭한 기사 공원 -STR_DTLS :한 쌍의 롤러코스터가 있는 성을 더 큰 놀이공원으로 발전시켜야 합니다. - - -STR_SCNR :Wacky Warren -STR_PARK :괴짜 미로 -STR_DTLS :대부분의 보도와 롤러코스터가 지하에 있는 공원입니다. - - -STR_SCNR :Grand Glacier -STR_PARK :웅장한 빙하 -STR_DTLS :놀이공원으로 만들기 위해 당신에게 빙하가 가득한 계곡이 주어졌습니다. - - -STR_SCNR :Crazy Craters -STR_PARK :미친 분화구 -STR_DTLS :돈이 필요없는 머나먼 세상에서, 여러분은 사람들을 행복하게 해줄 놀이공원을 건설해야 합니다. - - -STR_SCNR :Dusty Desert -STR_PARK :먼지투성이 사막 -STR_DTLS :이 사막 공원에 있는 다섯 대의 롤러코스터를 완성하십시오. - - -STR_SCNR :Woodworm Park -STR_PARK :나무좀벌레 공원 -STR_DTLS :이 역사적인 공원에는 오직 오래된 스타일의 놀이기구만을 건설할 수 있습니다. - - -STR_SCNR :Icarus Park -STR_PARK :이카루스 공원 -STR_DTLS :이 외계 공원을 개발하여 최대한의 매출을 올리세요. - - -STR_SCNR :Sunny Swamps -STR_PARK :맑은 늪지 -STR_DTLS :이 잘 구성된 놀이공원에는 이미 몇 개의 놀이기구가 존재하지만, 아직은 확장할 수 있는 공간이 충분합니다. - - -STR_SCNR :Frightmare Hills -STR_PARK :무시무시한 언덕 -STR_DTLS :거대한 롤러코스터가 공원 가운데에 있는 무시무시한 공원 - - -STR_SCNR :Thunder Rocks -STR_PARK :천둥 바위들 -STR_DTLS :놀이공원의 기초가 될 두 개의 커다란 바위가 사막의 모래 위에 솟아 있습니다. - - -STR_SCNR :Octagon Park -STR_PARK :팔각형 공원 -STR_DTLS :이 거대한 공원에 여러분은 10개의 거대한 롤러코스터를 디자인하고 만들어야 합니다. - - -STR_SCNR :Pleasure Island -STR_PARK :즐거운 섬 -STR_DTLS :길고 가느다란 섬에서 롤러코스터 건설에 도전해보세요. - - -STR_SCNR :Icicle Worlds -STR_PARK :고드름 세상 -STR_DTLS :얼음으로 덮인 땅을 번창하는 놀이공원으로 바꿔보세요. - - -STR_SCNR :Southern Sands -STR_PARK :남부 사막 -STR_DTLS :잘 디자인된 롤러코스터가 있는 사막 공원을 확장해보세요. - - -STR_SCNR :Tiny Towers -STR_PARK :조그마한 탑 -STR_DTLS :이 조그마한 공원에 있는 다섯 개의 미완성된 롤러코스터를 모두 완성해야 합니다. - - -STR_SCNR :Nevermore Park -STR_PARK :네버모어 공원 -STR_DTLS :공원 주변에 참신한 운송수단이 설치된 거대한 공원입니다. - - -STR_SCNR :Pacifica -STR_PARK :패시피카 -STR_DTLS :놀이공원으로 개발하기 위해 이 거대한 섬이 여러분에게 주어졌습니다. - - -STR_SCNR :Urban Jungle -STR_PARK :도시의 정글 -STR_DTLS :버려진 거대한 마천루 빌딩은 놀이공원 개발자에게는 독특한 기회일 것입니다. - - -STR_SCNR :Terror Town -STR_PARK :공포스러운 마을 -STR_DTLS :놀이공원으로 개발하기 위해 이 도시 지역이 여러분에게 주어졌습니다. - - -STR_SCNR :Megaworld Park -STR_PARK :대세상 공원 -STR_DTLS :이미 놀이기구로 가득한 거대한 공원을 확장해야 합니다. - - -STR_SCNR :Venus Ponds -STR_PARK :비너스의 연못 -STR_DTLS :멀리 떨어진 행성에 있는 이 지역을 놀이공원으로 바꿔야 합니다. - - -STR_SCNR :Micro Park -STR_PARK :마이크로 공원 -STR_DTLS :세상에서 가장 작지만 수익이 좋은 공원을 만들어보세요. - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :알턴 타워스 -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :하이데 파르크 -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :블랙풀 플레저 비치 -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :역사적인 성채 -STR_DTLS : - -########### -# Scenery # -########### -[TTPIRF05] -STR_NAME :지붕 - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :알프스의 모험 -STR_PARK :알프스의 모험 -STR_DTLS :작은 산악 스키 리조트를 눈 테마 놀이공원으로 바꿔보세요. - - -STR_SCNR :우호 비행장 -STR_PARK :우호 비행장 -STR_DTLS :이 버려진 비행장에 날아다니는 것을 주제로 한 놀이공원을 만들어보세요. - - -STR_SCNR :보타니의 하얀 파도 -STR_PARK :보타니의 하얀 파도 -STR_DTLS :당신의 목표는 이 파라다이스 섬에 고수익 공원을 만드는 것입니다. - - -STR_SCNR :식스 플래그 벨기에 건설 -STR_PARK :식스 플래그 벨기에 -STR_DTLS :이 유럽의 식스 플래그 공원을 당신만의 스타일으로 만들어 보세요. - - -STR_SCNR :식스 플래그 그레이트 어드벤처 건설 -STR_PARK :그레이트 어드벤처 -STR_DTLS :이 식스 플래그 공원을 당신의 디자인 기술로 재탄생시키십시오. - - -STR_SCNR :식스 플래그 네덜란드 건설 -STR_PARK :식스 플래그 네덜란드 -STR_DTLS :이 유럽의 식스 플래그 공원을 당신이 원하는 대로 만들어 보세요. - - -STR_SCNR :식스 플래그 매직 마운틴 건설 -STR_PARK :매직 마운틴 -STR_DTLS :이 대형 식스 플래그 공원을 당신만의 스타일로 만들어 보세요. - - -STR_SCNR :식스 플래그 오버 텍사스 건설 -STR_PARK :오버 텍사스 -STR_DTLS :이 식스 플래그 공원에 처음부터 놀이기구를 건설하여 시작해보세요. - - -STR_SCNR :당신만의 식스 플래그 공원 건설 -STR_PARK :식스 플래그 -STR_DTLS :당신만의 디자인대로 식스 플래그 공원을 만드세요. 다른 식스 플래그 공원의 놀이기구를 짓거나 자신만의 놀이기구를 만들어보세요. - - -STR_SCNR :북적이는 시장 -STR_PARK :북적이는 시장 -STR_DTLS :이 작은 시장에 고객들을 유치하기 위해 놀이기구와 롤러코스터를 지어 상점과 가게의 수익을 늘리는 것이 목표입니다. - - -STR_SCNR :이상한 성 -STR_PARK :이상한 성 -STR_DTLS :당신은 큰 성을 물려받았습니다. 이제 이 성을 작은 놀이공원으로 바꾸는 것이 당신이 해야 할 일입니다. - - -STR_SCNR :먼지투성이 그린 -STR_PARK :먼지투성이 그린 -STR_DTLS :사막의 고속도로 교차로 근처에 있는 먼지투성이 그린을 작은 골프 리조트에서 번화한 놀이공원으로 개발할 기회가 생겼습니다. - - -STR_SCNR :일렉트릭 농장 -STR_PARK :일렉트릭 농장 -STR_DTLS :당신은 작은 농장을 물려받았습니다. 각 지역과 농장의 건물 사이에 작은 놀이공원을 건설하는 것이 당신의 목표입니다. - - -STR_SCNR :극한의 높이 -STR_PARK :극한의 높이 -STR_DTLS :재정적 제한이 없는 이 사막 공원을 사람들이 극한의 스릴을 찾는 곳으로 확장하는 것이 당신의 목표입니다. - - -STR_SCNR :공장 놀이터 -STR_PARK :공장 놀이터 -STR_DTLS :버려진 공장 지대에 기계를 주제로 한 놀이공원을 만들어보세요. - - -STR_SCNR :버섯 숲 -STR_PARK :버섯 숲 -STR_DTLS :당신의 목표는 오직 오래된 나무 놀이기구만을 사용해서 버섯 숲에 번화한 놀이공원을 만드는 것입니다. - - -STR_SCNR :유령 도시 -STR_PARK :유령 도시 -STR_DTLS :대형 놀이공원 회사에 고용된 당신의 임무는 버려진 광산촌 주위에 대형 롤러코스터 공원을 건설하는 것입니다. - - -STR_SCNR :그래비티 정원 -STR_PARK :그래비티 정원 -STR_DTLS :당신의 목표는 아름다운 그래비티 정원에 롤러코스터 공원을 만드는 것입니다. 다른 놀이기구는 안 됩니다. 롤러코스터만 만드세요! - - -STR_SCNR :지옥 풍경 -STR_PARK :지옥 풍경 -STR_DTLS :마그마 강이 흐르는 용암으로 위태롭게 둘러싸인 공원입니다. - - -STR_SCNR :행운의 호수 -STR_PARK :행운의 호수 -STR_DTLS :자본에는 제한이 없지만 호수가 있는 곳이기 때문에 이 공원을 확장하고 관리하는 건 많이 힘들 것입니다. - - -STR_SCNR :무지개 정상 -STR_PARK :무지개 정상 -STR_DTLS :이 공원은 산허리에 만들어야 하고, 높은 건물은 지을 수 없습니다. 공원을 확장하여 성공할 자신이 있습니까? - - -STR_SCNR :식스 플래그 벨기에 -STR_PARK :식스 플래그 벨기에 -STR_DTLS :직접 팔을 걷어붙이고 이 식스 플래그 공원을 개선해보세요. - - -STR_SCNR :식스 플래그 그레이트 어드벤처 -STR_PARK :그레이트 어드벤처 -STR_DTLS :식스 플래그의 빠진 놀이기구를 건설해보거나, 공원을 개선하기 위해 자신만의 놀이기구를 건설해보세요! 하지만 공원에 더 많은 손님을 모아야 한다는 궁극적인 목표를 잊어서는 안됩니다! - - -STR_SCNR :식스 플래그 네덜란드 -STR_PARK :식스 플래그 네덜란드 -STR_DTLS :직접 팔을 걷어붙이고 이 식스 플래그 공원을 개선해보세요. - - -STR_SCNR :식스 플래그 매직 마운틴 -STR_PARK :매직 마운틴 -STR_DTLS :식스 플래그의 빠진 놀이기구를 건설해보거나, 공원을 개선하기 위해 자신만의 놀이기구를 건설해보세요! 하지만 대출을 갚고 공원 가치를 높여야 한다는 궁극적인 목표를 잊으면 안됩니다! - - -STR_SCNR :식스 플래그 오버 텍사스 -STR_PARK :오버 텍사스 -STR_DTLS :식스 플래그의 빠진 놀이기구를 건설해보거나, 공원을 개선하기 위해 자신만의 놀이기구를 건설해보세요! 하지만 공원에 더 많은 손님을 모아야 한다는 궁극적인 목표를 잊어서는 안됩니다! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :아프리카의 광산 -STR_PARK :아프리카의 광산 -STR_DTLS :다이아몬드 폐광을 물려받은 당신은 값비싼 다이아몬드를 발견했고 그 판매 수익으로 세계 일류의 테마파크를 짓기로 결심했습니다. - - -STR_SCNR :신기루의 광기 -STR_PARK :신기루의 광기 -STR_DTLS :사막에서 놀이공원을 짓기에 아주 적당한 오아시스를 발견했습니다. 오아시스로 가는 교통편은 이미 존재합니다. - - -STR_SCNR :폭포 너머 -STR_PARK :폭포 너머 -STR_DTLS :공원을 운영하기 충분하고 값싼 전기를 생산하는 수력 발전 댐이 지어졌습니다. 댐을 건설하느라 진 빚을 갚기 위해 높은 가치의 놀이공원을 지어야 합니다. - - -STR_SCNR :얼음에 뒤덮인 모험 -STR_PARK :얼음에 뒤덮인 모험 -STR_DTLS :환경부에서 눈꼴사납고 낡은 정유 시설을 최고의 관광 명소로 만들어달라고 합니다. 땅값은 싸지만 대출 이자는 높습니다. 오래된 건물은 고철로 팔아 버릴 수 있습니다. - - -STR_SCNR :만리장성 -STR_PARK :만리장성 -STR_DTLS :관광 당국이 만리장성 주변의 땅에 놀이공원을 지어서 관광객 수를 늘리기로 결정했습니다. 돈이 문제가 아니군요! - - -STR_SCNR :오키나와 해변 -STR_PARK :오키나와 해변 -STR_DTLS :기존 공원은 이미 공간이 모자랍니다. 대출을 받아서 바다로 확장해나갈 수밖에 없습니다. 지진 우려와 약한 기반을 이유로 건설 높이가 제한됩니다. - - -STR_SCNR :마하라자 공원 -STR_PARK :마하라자 공원 -STR_DTLS :인도의 왕에게서 국민들에게 즐길 거리를 만들어달라는 임무를 받았습니다. 마하라자 궁전을 연상시키는 공원을 만들어보세요. - - -STR_SCNR :에어즈 어드벤처 -STR_PARK :에어즈 어드벤처 -STR_DTLS :문화 인식 프로그램의 일환으로, 오스트레일리아 원주민들을 도와서 공원을 개발하려 합니다. 원주민들의 독특한 문화유산을 알리기 위해 많은 관광객을 모아야 합니다. - - -STR_SCNR :해변의 바베큐 파티 -STR_PARK :해변의 바베큐 파티 -STR_DTLS :근처 지역 사업가의 해안 공원이 파산해버렸습니다. 이미 작은 공원을 운영하는 당신은 건설사로부터 그 공원을 구입하였습니다. 두 공원을 합쳐 크게 사업을 확장해보세요. - - -STR_SCNR :유럽의 축제 -STR_PARK :유럽의 축제 -STR_DTLS :유럽 문화 축제의 경영권을 확보한 당신은 이제 유럽 연합의 보조금을 갚기 위해 현재의 유럽 의회 임기가 끝날 때까지 손님을 늘려야합니다. - - -STR_SCNR :잿더미를 딛고 -STR_PARK :잿더미를 딛고 -STR_DTLS :방치된 낡은 공원이 있습니다. 이 공원이 과거에 누렸던 영광을 재현하기 위해 유럽 연합의 허가를 받았습니다! 허가를 받은 만큼 공원을 혁신해서 보답하세요. - - -STR_SCNR :왁자지껄 와이키키 -STR_PARK :왁자지껄 와이키키 -STR_DTLS :하와이 주민들이 이제 파도타기가 지겨워져서 좀 더 자극적인 뭔가를 원하고 있습니다. 주민들도 만족시키면서 이 지역의 관광객들이 찾아오고 싶어 하는 공원을 만드세요. - - -STR_SCNR :불행의 계곡 -STR_PARK :불행의 계곡 -STR_DTLS :이 아름답지만 제한적인 공간에 공원을 만들어야 합니다. 미국 원주민에게서 반대편 땅을 살 수 있습니다. 줄어들고 있는 마을 인구를 유지하기 위해서라도 목표를 달성해야 합니다. - - -STR_SCNR :롤러코스터 천국 -STR_PARK :롤러코스터 천국 -STR_DTLS :당신은 긴 휴식기를 가지는 동안 이 도시 공원을 롤러코스터 천국으로 바꾸고자 하는 성공한 사업 거물입니다. 돈은 문제가 되지 않는군요! - - -STR_SCNR :잊혀진 도시의 발견자 -STR_PARK :잊혀진 도시의 발견자 -STR_DTLS :이 지역의 관광산업을 보다 활기차게 만들기 위해서는 주변 환경과 잘 어울리는 공원을 지어야 합니다. - - -STR_SCNR :열대우림 고원 -STR_PARK :열대우림 고원 -STR_DTLS :소중한 열대우림 속의 제한된 공간만을 받았습니다. 이곳의 벌목 산업을 대신할 수 있는 방법을 제공하기 위해 기존의 빈 공간을 최대한 많이 활용해야 합니다. - - -STR_SCNR :슈거로프 해안 -STR_PARK :슈거로프 해안 -STR_DTLS :리오 근처의 작은 공원을 운영하고 있는데 은행이 대출금을 조기 회수하려 합니다. 때 이른 빚 독촉을 갚기 위해서 빨리 돈을 벌어야 합니다. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :클리프사이드 성 -STR_PARK :클리프사이드 성 -STR_DTLS :이 지역의 전투 재현 단체는 자신들의 취미를 진지하게 생각하고 있습니다. 그들은 당신에게 클리프사이드 성 부지에 암흑시대 테마파크를 건설해달라고 요청해왔습니다. - - -STR_SCNR :셔우드 숲 -STR_PARK :셔우드 숲 -STR_DTLS :부자들의 재산을 빼앗아 필요한 사람들에게 나누어주기 위해서 당신과 수하들은 셔우드 숲에 놀이공원을 만들기로 결정했습니다. - - -STR_SCNR :외계인의 축제 -STR_PARK :외계인의 축제 -STR_DTLS :먼 행성에서 생명체가 발견되었습니다. 외계인을 주제로 한 놀이공원을 만들어서 전에 없던 관심을 받아 돈을 벌어보세요. - - -STR_SCNR :제미니 시티 -STR_PARK :제미니 시티 -STR_DTLS :당신의 미래에 대한 독창적이고 이상적인 시각을 보여줄 때입니다. 첨단의 매력이 느껴지는 미래의 공원 디자인을 제안해봅시다. - - -STR_SCNR :애니매트로닉 앤틱스 -STR_PARK :애니매트로닉 앤틱스 -STR_DTLS :이번 임무는 옛 영화 세트장에 설립된 기존 테마파크를 운영하고 발전시키는 것입니다. 흑백 스크린에 신화 속 인물을 옮겨놓은 스톱 모션 애니메이션의 선구자들에게 이 공원을 헌정합시다. - - -STR_SCNR :신화의 광기 -STR_PARK :신화의 광기 -STR_DTLS :특별한 고고학적 가치를 가진 섬을 소유하게 되었습니다. 이 지역의 풍부한 신화적 유산을 기반으로 한 테마파크를 건설해서 유산 보존 기금을 마련하기로 결정했습니다. - - -STR_SCNR :크레이터 대학살 -STR_PARK :크레이터 대학살 -STR_DTLS :당신은 오래된 운석공을 소유하고 있습니다. 기업가 정신을 발휘한 당신은 운석 테마 파크를 건설해서 쓸모없어 보이는 이 땅을 엄청난 행운의 땅으로 바꾸기로 결심했습니다. - - -STR_SCNR :코스터사우르스 -STR_PARK :코스터사우르스 -STR_DTLS :당신은 쥐라기 시대 놀이공원을 건설하는 임무를 받았습니다. 색다른 식물과 동물 전시장에 관객이 쉽게 접근할 수 있도록 하려면, 계곡을 가로지르는 놀이기구를 만들어야 할 것입니다. - - -STR_SCNR :돌무더기 산책 -STR_PARK :돌무더기 산책 -STR_DTLS :고속도로 개발자들을 막고 고대 열석을 보호하기 위해, 석기 시대 테마파크를 건설하여 수익을 내야 합니다. 하지만 사람이 살기 조금 힘든 곳인 만큼 손님을 모으기가 어려울 것입니다. - - -STR_SCNR :앨커트래즈 -STR_PARK :앨커트래즈 -STR_DTLS :주류 밀매자와 폭력범으로 득실대던 악명 높은 감옥 섬이 경매에 부쳐졌습니다. 이곳을 최고의 관광지로 바꾸기로 한 당신에게 돈은 신경 쓸 필요가 없네요. - - -STR_SCNR :슈나이더 해안 -STR_PARK :슈나이더 해안 -STR_DTLS :할아버지의 슈나이더 컵 우승 75주년이 얼마 남지 않았습니다. 당신은 할아버지의 업적을 기리기 위해 유명한 수상비행기 경주를 딴 놀이공원을 짓기로 했습니다. - - -STR_SCNR :메트로폴리스 -STR_PARK :메트로폴리스 -STR_DTLS :당신은 도시 저층부 근처의 빈 공간을 갖게 되었습니다. 최대한 이익을 많이 얻기 위해, 20년대에 유행했던 아르데코식 건축물을 본딴 마천루 테마파크를 지어보세요. - - -STR_SCNR :우드스톡 -STR_PARK :우드스톡 -STR_DTLS :매년 열리는 대형 음악 축제가 당신의 땅에서 열립니다. 최신 유행하는 놀이공원을 지어, 자유로운 영혼을 가진 관객들이 즐거워할 수 있게 만드세요. - - -STR_SCNR :로큰롤 부흥 -STR_PARK :로큰롤 부흥 -STR_DTLS :이 오래된 놀이공원은 더 나은 미래를 기대하고 있습니다. 소유자를 도와 이 공원을 복고풍의 로큰롤 공원으로 바꾸어 성공적인 장소로 변모시켜보세요. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :판다 월드 -STR_PARK :판다 월드 -STR_DTLS :이 판다 테마의 공원에 놀이기구를 더 지어서 손님들을 더 끌어모으세요. - - -STR_SCNR :Tycoon Park -STR_PARK :타이쿤 공원 -STR_DTLS : - -### - -STR_SCNR :Cemetery Ridge -STR_PARK :묘지 언덕 -STR_DTLS :핼러원, UCES의 핼러윈, 호박이 비명을 지르는 죽음의 밤! 죽은 자들을 편히 쉬게 하는 동시에 어려운 처지에 놓여있는 이 묘지를 구하는 것은 당신의 몫입니다! 유령을 무덤에 가둬놓고 손님들에게 오들오들함을 선사할 수 있나요?{NEWLINE}제작자: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :The Lighthouse of Alexandria -STR_PARK :알렉산드리아의 등대 -STR_DTLS :알렉산더 대왕은 도시를 건설했습니다. 그리스인, 로마인, 이집트인들이 흔적을 남겼죠. 하지만 가장 큰 영예는 고대의 불가사의인 등대였습니다. 이 곳을 공원으로 만들어보세요!{NEWLINE}제작자: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :루나 파크 -STR_DTLS :공원 개장일이었떤 1905년 5월 18일처럼.{NEWLINE}제작자: Aetherwave - - -STR_SCNR :Mount Vesuvius -STR_PARK :베수비오 산 -STR_DTLS :폼페이와 헤르쿨라네움은 서기 79년에 베수비오 화산 폭발로 묻혀버렸습니다. 이 발굴지를 공원으로 만들어보세요!{NEWLINE}제작자: Katatude - - -STR_SCNR :The Sandbox -STR_PARK :모래 상자 -STR_DTLS :모두가 원하는 모래 상자! 이제 양동이와 삽을 들고 원하는 공원을 만드세요!{NEWLINE}제작자: Katatude - - -STR_SCNR :Niagara Falls & Gorge -STR_PARK :나이아가라 폭포 -STR_DTLS :1850년 나이아가라 폭포의 아메리카 폭포, 브라이들 폭포, 캐나다 폭포{NEWLINE}제작자: Katatude - - -STR_SCNR :Rocky Mountain Miners -STR_PARK :록키 산맥 광부 -STR_DTLS :산사태로 철도가 손상되었습니다. 직원들이 탐사에 나섰습니다. 롤러코스터에 금이 있을까요?{NEWLINE}제작자: Squid, Buckone, Fossil - - -STR_SCNR :The Time Machine -STR_PARK :타임 머신 -STR_DTLS :원하는 때, 원하는 곳으로 갈 수 있도록 타임 머신을 만드세요. 영원이 당신을 기다립니다. 모든 것은 상대적이니 말이죠.{NEWLINE}제작자: Katatude - - -STR_SCNR :Tower of Babel -STR_PARK :바벨 탑 -STR_DTLS :우와, 타임머신이 우릴 어디로 대려왔는지 보세요! 근데 다들 어디갔죠?{NEWLINE}제작자: Fossil - - -STR_SCNR :Transformation -STR_PARK :트랜스포메이션 -STR_DTLS :널 기다리고 있었어…{NEWLINE}제작자: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :알 수 없는 도시 -STR_DTLS :로마인들은 글래디에이터의 전투가 이제 질렸다고 합니다. 그들에게 더 많은 스릴을 선사해서 이 로마 도시를 전 시대를 통틀어 가장 거대한 놀이 공원으로 바꿔보세요!{NEWLINE}제작자: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Beneath the Christmas Tree -STR_PARK :겨울 원더 랜드 -STR_DTLS :엄마가 우리 나무 아래를 이렇게 만들었어요. 이제 공원을 만들고 싶으시대요. 도와주실 수 있나요?{NEWLINE}제작자: Katatude - - -STR_SCNR :Bigrock Blast -STR_PARK :빅록 폭발 -STR_DTLS :빅록 채광 주식회사에서 폭발 사건이 일어난 이후, 빅록의 사람들은 마을을 유지하기 위해 놀이공원을 지어야만 한다고 합니다.{NEWLINE}제작자: rbarclay & buckone - - -STR_SCNR :Camp Mockingbird -STR_PARK :앵무새 캠프 -STR_DTLS :이번 여름 캠프가 일주일에 단돈 $500! 은행 금고를 열고 공원을 만들면서 놀아보세요.{NEWLINE}제작자: Katatude - - -STR_SCNR :Choo-Choo Town -STR_PARK :칙칙폭폭 마을 -STR_DTLS :엄마! 아빠! 나 칙칙폭폭 마을에 가고 싶어요!{NEWLINE}제작자: Fossil - - -STR_SCNR :Dragon Islands -STR_PARK :용의 섬 -STR_DTLS :용의 섬이라고? 거기 가고 싶은지 확신이 안 서는 걸…{NEWLINE}제작자: Fossil - - -STR_SCNR :Kiddie Karnival II -STR_PARK :어린이 카니발 -STR_DTLS :어린이 여러분! 같이 신나게 놀아봐요!{NEWLINE}제작자: Piehead & Fossil - - -STR_SCNR :Sand Dune -STR_PARK :모래 언덕 -STR_DTLS :이 작은 공원의 소유자로써, 아름다운 모래 언덕을 방문하여 더 많은 목표를 유치하고 확장하기 위해 해변을 따라 큰 땅을 샀지만 조심하세요! 생태학적으로 소중한 이 모래 언덕을 건드릴 수는 없습니다.{NEWLINE}제작자: rbarclay diff --git a/data/language/nb-NO.txt b/data/language/nb-NO.txt index ed7e68ef68..4351df4a82 100644 --- a/data/language/nb-NO.txt +++ b/data/language/nb-NO.txt @@ -3690,850 +3690,3 @@ STR_6619 :Objekt-type kan ikke bli begrenset! STR_6620 :Kunne ikke finne objekt! STR_6621 :Begrens STR_6622 :Begrens objekt til Scenario-redigerer og Sandkassemodus. - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Bygg en blomstrende fornøyelsespark i en stor lysning dypt inni skogen - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Denne ørken-fornøyelsesparken har kun én berg-og-dal-bane, men stort rom for utvidelse - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Fra bunnen av, bygg en fornøyelsespark rundt en stor innsjø - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights er allerede en vellykket fornøyelsespark med flotte attraksjoner – Målet ditt er å doble parkens verdi - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Konverter den praktfulle parken Evergreen Gardens til en blomstrende fornøyelsespark - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Utvid den lille fornøyelsesparken i Bumbly Beach til å bli en storslått versjon av seg selv - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :En liten øysamling er grunnlaget for denne nye parken - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :En liten fornøyelsespark med noen få attraksjoner og rom for utvidelse – Målet ditt er å doble parkens verdi - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :En liten og trang fornøyelsespark som trenger massiv utvidelse - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :En park med forteffelige vannbaserte attraksjoner trenger utvidelse - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Konverter en forlatt gruve fra en turistattraksjon til en fornøyelsespark - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :En stor bortgjemt park i skogen, med kun go karts og tre-berg-og-dal-baner - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :Denne fornøyelsesparken har allerede et par veldesignede moderne attraksjoner, men stort rom for utvidelse - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :Bygg en fornøyelsespark fra bunnen av i Mystic Mountains skogkledde åser - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Konverter disse egyptiske ruinene til en blomstrende fornøyelsespark - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :En stor park med gode, men aldrende attraksjoner – Erstatt de gamle attraksjonene eller bygg nye for å gjøre parken mer populær - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Gjør om denne døsige byens brygge til en tiltrekkende attraksjon - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :Lightning Peaks sine praktfulle fjell er allerede populære hos turgåere og turister – Bruk det tilgjengelige arealet til å tiltrekke et nytt spenningssøkende klientell - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :En veletablert park med noen problemer - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :De lokale myndighetene i Rainbow Valley tillater hverken endringer i landskapet eller felling av trær, men du må utvikle området til å bli en stor fornøyelsespark - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock er ørkenens midtpunkt og en stor turistattraksjon – Bruk det tilgjengelige området til å bygge attraksjoner for å tiltrekke flere folk - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Bare for gøy! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Videreutvikle sjøklippene til å bli en flott fornøyelsespark - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :En gigangisk duellerende stål-berg-og-dal-bane er sentral i denne store parken - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Denne forlatte gruven er et godt utgangspunkt for en god turistattraksjon, allerede med en miniatyrtogbane og et par vertikalt-fall berg-og-dal-baner - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :Du får utvikle en gammel ubrukt bro til en fornøyelsespark - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Denne parken som dekker begge sider av en motorvei har allerede flere aktive attraksjoner - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :De lokale myndighetene har gått med på å selge land billig, gitt at enkelte attraksjoner bevares - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Du får gjøre dette slottet om til en fornøyelsespark - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Denne framtidsparken med sitt utenomjordiske landskap har stor plass for nye attraksjoner - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :Det er din jobb å utvide denne parken med rolige attraksjoner, etter preferansene til regionens innbyggere - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Dypt i jungelen er det et passende område for en fornøyelsespark - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :En rekke paternostersjøer danner grunnlaget for denne nye parken - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Denne eldre parken har har flere historiske attraksjoner, men er i dyp gjeld - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Et stort landområde har blitt klargjort og delvis dekorert, klar for at du skal utvikle det til en fornøyelsespark - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :En blomstrende fruktgård har bygget en togbane for ekstra inntekt - Din jobb er å utvikle den til en fullverdig fornøyelsespark - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Området rundt en demning er tilgjengelig for fornøyelsesparken din - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :Du får bygge ut en enorm kløft til en fornøyelsespark - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :En gigantisk pyramide har blitt satt opp for at du skal kunne bygge attraksjoner skjermet fra det våte klimaet - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :De lokale myndighetene tillater ikke at du bygger høyere enn trærne i denne parken - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Videreutvikle denne romerparken ved å bygge spennende attraksjoner - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Denne parken bygd delvis på en liten øyrekke har allerede et par store berg-og-dal-baner - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Bygg en park som appellerer til de høye intensitetskravene til den lokale befolkningen - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :En oase midt i ørkenen byr på en uvanlig mulighet for en fornøyelsespark - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Kan du gjenopplive den fordums storheten til denne falleferdige og gjengrodde fornøyelsesparken? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Du har begrenset tid og budsjett til å fikse problemene til denne parken full av dårlig designet og farlige attraksjoner - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :De lokale myndighetene tillater ikke reklame så denne parken må overleve på ryktet alene - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :Midtpunktet i denne voksende parken er et firefelts hinderløp - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Gjør dette forlatte steinbruddet til et sted som trekker spenningssøkende turister - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Du har begrensede midler, men ubegrenset tid, til å gjøre denne fjellsiden til en enorm berg-og-dal-bane-park - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :En liten park har laget en avtale med nærmeste by som tillater bygging inne i byen - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :En stor hagepark trenger å gjøres om til en blomstrende fornøyelsespark - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :En samling isfjell danner en kald setting for denne ambisiøse fornøyelsesparken - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :Omgivelsene for denne berg-og-dal-bane-utfordringen er en sovende vulkan - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Utfordringen din er å bygge en ørkenpark med høye krav, fri for økonomiske begrensinger - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Din oppgave er å bygge en massiv park fylt med berg-og-dal-baner midt i Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :En stor innsjø i et eldgammelt krater er settingen for denne parken - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Denne store parken har allerede en utmerket hyper-berg-og-dal-bane, din oppgave er å gjøre massiv profitt - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier har utvidet sitt netverk av gangbroer over sjøen, som du skal bruke for å utvide parken - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :Bygg derg-og-dal-baner i denne bukta - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Et slott med et par berg-og-dal-baner trenger din hjelp for å utvide til en stor fornøyelsespark - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :En park hvor de fleste gangstier og berg-og-dal-baner er under bakken - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :Bygg en fornøyelsespark i denne isbre-dalen - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :Bygg et underholdningssenter for å holde folk glade i en fjern verden hvor penger ikke finnes - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Ferdigstill fem berg-og-dal-baner i denne ørkenparken - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :I denne historiske parken får du kun bygge attraksjoner i eldre stil - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Utvikle denne utenomjordiske parken for å maksimere inntektene - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :Denne veldekorerte fornøyelsesparken har allerede flere attraksjoner, men stor plass for utvidelse - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :En skumel park med en gigantisk berg-og-dal-bane som midtpunkt - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :To store steinformasjoner stikker ut av sanden, hvor starten på en fornøyelsespark er bygget - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :I denne store parken må du designe og bygge ti store berg-og-dal-baner - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :En lang tynn øy blir utfordrende omgivelser for å bygge et utvalg berg-og-dal-baner - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Dette islandskapet trenger å bli gjort om til en blomstrende fornøyelsespark - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :Du får utvide en ørkenpark med et par smarte berg-og-dal-baner - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :I denne lille parken må du fullføre de fem eksisterende berg-og-dal-banene - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :En stor park med et nyskapende transportsystem rundt periferien - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Du har en stor øy helt for deg selv til å utvikle en fornøyelsespark - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :En gigantisk forlatt skyskraper er en unik mulighet for en fornøyelsesparkentrepenør - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Du får utvikle en fornøyelsespark i dette urbane området - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :En gigantisk park allerede stappfull av attraksjoner trenger forbedring - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :På en planet langt, langt borte må du gjøre om et landområde til en fornøyelsespark - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Prøv å lage verdens minste lønnsomme park - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Konverter en liten alpinbakke til en fornøyelsespark med snø-tema - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Bygg en fornøyelsespark på denne forlatte flyplassen med fly-tema - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Din utfordring er å bygge en lukrativ park i dette øyparadiset - - -STR_SCNR :Bygg din egen Six Flags Belgia -STR_PARK :Six Flags Belgia -STR_DTLS :Bygg din egen versjon av denne Europeiske Six Flags parken - - -STR_SCNR :Bygg din egen Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Bruk dine designferdigheter for å gjenskape denne Six Flags parken - - -STR_SCNR :Bygg din egen Six Flags Nederland -STR_PARK :Six Flags Nederland -STR_DTLS :Bygg denne Europeiske Six Flags parken slik du vil - - -STR_SCNR :Bygg din egen Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Skap din egen versjon av denne massive Six Flags parken - - -STR_SCNR :Bygg din egen Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Bygg attraksjonene i denne Six Flags parken fra bunnen opp - - -STR_SCNR :Bygg din egen Six Flags Park -STR_PARK :Six Flags -STR_DTLS :Bygg din en egendefinerte Six Flags park - Enten bygg attraksjoner fra andre Six Flags parker eller design dine egne attraksjoner - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Du starter med en liten basar og din utfordring blir å øke profitten fra butikker og boder ved å bygge attraksjoner og berg-og-dal-baner for å tiltrekke flere kunder - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :Du har arvet et stort slott. Din jobb er å konvertere den til en liten fornøyelsespark. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Plassert nær et motorveikryss i ørkenen, er Dusty Greens en mulighet til å utvikle en liten golfbane til en blomstrende fornøyelsespark - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :Du har arvet en liten gård, og din utfordring er å bygge en liten fornøyelsespark mellom åkrene og låvene - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Fritatt fra økonomiske begrensninger, er din utfordring å utvide denne ørkenparken for å tiltrekke folk som søker den ultimate spenningen - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Et forlatt fabrikkområde er en mulighet til å bygge en fornøyelsespark med mekanisk tema - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Begrenset til å kun bygge gammeldagse tre-attraksjoner, er din utfordring å bygge en blomstrende fornøyelsespark i Fungus Woods - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Ansatt av en stor fornøyelsespark-kjede, er din oppgave å bygge en enorm berg-og-dal-banepark for dem rundt en forlatt gruvelandsby - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Din utfordring er å bygge en berg-og-dal-banepark i den vakre Gravity Gardens. Ingen andre attraksjoner, kun berg-og-dal-baner! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :En park plassert i utrygge omgivelser på lavastein med elver av magma - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :Med uendelig finansiering, men med et utfordrende område rundt en innsjø, vil denne parken bli utfordrende å utvide og drive - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Bygget på en fjellside, har denne parken fått forbud fra å bygge høye attraksjoner. Klarer du å utvide parken og gjøre den til en suksess? - - -STR_SCNR :Six Flags Belgia -STR_PARK :Six Flags Belgia -STR_DTLS :Gjør et forsøk på å drifte og forbedre denne Six Flags parken - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Bygg de savnede Six Flags attraksjonene, eller skap dine egne designer for å forbedre parken! Men ikke glem ditt overordnede mål: å tiltrekke fler gjester til parken! - - -STR_SCNR :Six Flags Nederland -STR_PARK :Six Flags Nederland -STR_DTLS :Gjør et forsøk på å drifte og forbedre denne Six Flags parken - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Bygg de savnede Six Flags attraksjonene, eller skap dine egne designer for å forbedre parken! Men ikke glem ditt overordnede mål: å betale ned ditt lån mens du vedlikeholder parkverdien! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Bygg de savnede Six Flags attraksjonene, eller skap dine egne designer for å forbedre parken! Men ikke glem ditt overordnede mål: å tiltrekke fler gjester til parken! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :Du arvet en forlatt diamantgruve, og finner en verdifull diamant. Du bestemmer deg for å investere pengene i å bygge en verdensberømt fornøyelsespark. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :En ørkenoase har blitt oppdaget og vil være et vakkert sted for å bygge en park. Transport til oasen har blitt sørget for. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :En demning har blitt bygd, som tilbyr store mengder billig strøm som kan drive en park. Du trenger å nå en høy parkverdi for å hjelpe deg betale ned lånet for demningen. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :Miljøbyrået har kontaktet deg for å få transformert et gammelt, stygt oljeraffineri til en populær turistattraksjon. Land er billig men lånerentene er høye. Du kan selge de gamle bygningene for å hjelpe med betalingen. - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :Myndighetene har bestemt seg for å øke turismen rundt Den Kinesiske Mur ved å bygge en fornøyelsespark ved siden av. Penger er ikke noe problem! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :En eksisterende park har gått tom for plass. Din eneste mulighet er å bygge ut i sjøen, og så har du tatt ut et lån. Høyderestriksjoner på bygningene blir vernet om pga. fundamenter og jordskjelvsfare. - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :Du har fått i oppdrag av Maharajaen å bringe underholdning til den store lokale befolkningen. Bygg en park inspirert av Maharajaen's palass. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :Du hjelper Aboriginske folk å bygge en park som del av et kulturelt kunnskapsprogram. Du trenger en stor mengde gjester for å utdanne de om den unike arven til Aboriginerne. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :En lokal entreprenør's marinepark har gått konkurs. Du driver allerede en liten park og kjøper den andre parken fra konstruksjonsfirmaet. Utvikle en stor, kombinert park. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :Du har blitt brakt inn for å overta en European Cultural Visitor Attraction og må øke antall gjester slik at du kan betale tilbake pengestøtten til EU ved slutten av det nåværende Europeiske stortingets termin. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :En gammel park har forfalt. Du mottar et stipend fra den Europeiske Union for å returne dette forfalne området tilbake til sin tidligere prakt! Du må renovere parken og betale tilbake stipendet. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :Folket på Hawaii er lei av surfing og ser etter noe mer intenst. Du trenger å bygge en park med tanke på dette for å holde tiltrekningen av turister til området på et høyt nivå. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :Du må bygge en park på et begrenset område på hver side av denne naturlige skjønnheten - du har muligheten til å kjøpe land fra de innfødte Amerikanske Indianerne. Du trenger å fullføre oppdraget for å opprettholde den lokale landsbyens befolkning. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :Du er en suksessfull forretningsmagnat på en lang ferie som ønsker å bruke denne tiden til å transformere byparken til Rollercoaster Heaven. Penger er ikke noe problem! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :For å videre øke turisme må du konstruere en park som tar hensyn til sine omgivelser. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Plass er begrenset i den faretruede regnskogen - du må klemme så mye som mulig inn i den eksisterende klaringen, for å bringe et lønnsomt alternativ til den lokale tømmerindustrien. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :Du driver en liten park nær Rio, men banken krever du skal betale ned lånet ditt. Du trenger å raskt øke din inntekt for å betale denne overraskende gjelden. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Lokale medlemmer av krigs-gjenskapelsesforeningen are svært seriøse med sin hobby. De har betrodd deg med jobben av å lage en middelaldersk fornøyelsespark på marken til Cliffside Castle. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :Å ta fra de rike og gi til de fattige, du og dine Glade Menn har bestemt dere for å bygge en fornøyelsespark i Sherwood Forest. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Liv har blitt funnet på en fjern planet. Bygg en utenomjordisk fornøyelsespark for å utnytte den enestående bølgen av interesse. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Vis fram din oppfinnsomme, utopiske visjon av fremtiden - skap en futuristisk parkdesign som inneholder toppmoderne attraksjoner. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :Du har blitt gitt oppgaven av å drive og forbedre en eksisterende fornøyelsespark, som har blitt bygd på et gammelt filmstudio. Bygg en hyllest til pionerene av stop-motion animatører som først brakte mytiske skapninger til liv på filmlerretet. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :Du eier en øy av spesiell arkeologisk verdi. Du har bestemt deg for å finansiere dens bevaring ved å bygge en fornøyelsespark basert på områdets rike mytologiske arv. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :Du eier et støvete gammelt metorittkrater. I sann gründer-ånd, har du bestemt deg for å bygge en fornøyelsespark med asteroide-tema og konvertere din tilsynelatende verdiløse tomt til en stor formue. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :Du har blitt gitt oppgaven av å bygge en fornøyelsepark med Juratids-tema. For å optimalisere besøkendes adgang til eksotiske plante- og dyre-utstillinger, trenger du å bygge attraksjoner som går over og ned i dalen. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :For å stanse byggingen av motorveier og å bevare de mystiske eldgamle steinsirklene, må du bygge en fornøyelsespark med steinalder-tema og skape en profitt. Derimot, å tiltrekke gjester vil være utfordrende pga. det grove terrenget. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :Den berømte fengselsøya - som en gang huset smuglere og andre kriminelle - er nå til salgs. Du har bestemt deg for å konvertere den til en populær turist-attraksjon, og penger er ikke noe problem - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :75års dagen til din bestefars Schneider Cup seiere kommer om et par år. Du har tenkt til å hedre hans prestasjon ved å bygge en fornøyelsespark basert på det berømte sjøfly-løpet. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :Du eier en øde tomt nær utkanten av byen. For å skvise mest mulig ut av din urbane eiendom, bygg en fornøyelsespark med skyskraper-tema inspirert av art deco arkitekturen til tjuetallet. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :En stor, årlig musikkfestival finner sted på din tomt. Bygg en hipp fornøyelsespark for å holde det frisinnede publikummet underholdt. - - -STR_SCNR :Rock ‘n’ Roll Revival -STR_PARK :Rock ‘n’ Roll Revival -STR_DTLS :Denne aldrende fornøyelsesparken har sett bedre dager. Hjelp eieren å gi den en retro rock ‘n’ roll makeover og forvandle stedet til en suksessfull møteplass. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Panda World -STR_PARK :Panda World -STR_DTLS :Bygg flere attraksjoner og få inn flere gjester til denne panda-inspirerte parken - - -STR_SCNR :Tycoon Park -STR_PARK :Tycoon Park -STR_DTLS : - -### - -STR_SCNR :Cemetery Ridge -STR_PARK :Cemetery Ridge -STR_DTLS :Dette er Halloween, UCES Halloween, gresskar skriker i nattens mørke! Denne kirkegården har trøbbel og det er opp til deg å redde den, mens du lar de døde hvile i fred! Kan du holde spøkelsene i deres graver og bringe frysninger til dine kunder?{NEWLINE}Forfatter: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :The Lighthouse of Alexandria -STR_PARK :The Lighthouse of Alexandria -STR_DTLS :Alexander bygde byen; Grekerne, Romerne, Egypterne satte sine spor. Men den største æren var ett Under fra den Antikke Verden - Fyrtårnet. Besøk og lag en park!{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Som den var på sin åpningsdag - 18 Mai 1905.{NEWLINE}Forfatter: Aetherwave - - -STR_SCNR :Mount Vesuvius -STR_PARK :Mount Vesuvius -STR_DTLS :Pompeii og Herculaneum ble begravd av Mt. Vesuvius i 79 A.D. Besøk utgravingene og bygg en park!{NEWLINE}Forfatter: Katatude - - -STR_SCNR :The Sandbox -STR_PARK :The Sandbox -STR_DTLS :Det alle vil ha - en sandboks! Så hent ditt lille spann og spade og bygg en park!{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Niagara Falls & Gorge -STR_PARK :Niagara Falls -STR_DTLS :American Falls, Bridal Falls & Canadian Horseshoe Falls på Niagara Frontier, 1850.{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Rocky Mountain Miners -STR_PARK :Rocky Mountain Miners -STR_DTLS :Et steinras skadde din jernbane. Arbeiderne dine har dratt for å grave. Er det gull i berg-og-dal-baner?{NEWLINE}Forfattere: Squid, Buckone, Fossil - - -STR_SCNR :The Time Machine -STR_PARK :The Time Machine -STR_DTLS :Tidsmaskinen. Bygg for å dra - når du vil, hvor du vil. Evigheten venter. Alt er relativt.{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Tower of Babel -STR_PARK :Tower of Babel -STR_DTLS :Jøss! Se hvor tidsmaskinen førte oss nå! Hvor ble alle av?{NEWLINE}Forfatter: Fossil - - -STR_SCNR :Transformation -STR_PARK :Transformation -STR_DTLS :Vi har ventet på deg…{NEWLINE}Forfatter: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :Romerne er lei av kjedelige gladiatorkamper. Gi dem en bedre spenning, gjør en Romersk by til den beste fornøyelsesparken gjennom tidene!{NEWLINE}Forfatter: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Beneath the Christmas Tree -STR_PARK :Winter Wonderland -STR_DTLS :Mamma bygde denne scenen under vårt tre. Nå vil hun ha en park bygget i det! Kan du hjelpe?{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Bigrock Blast -STR_PARK :Bigrock Blast -STR_DTLS :Etter en eksplosjon på Bigrock Mining Co., må Bigrock's innbyggere bygge en fornøyelsespark for å holde deres landsby i live.{NEWLINE}Forfatter: rbarclay & buckone - - -STR_SCNR :Camp Mockingbird -STR_PARK :Camp Mockingbird -STR_DTLS :Kun $500/uke til denne sommerleiren! Gjør et innbrudd i din bank og ha det gøy med å bygge en park.{NEWLINE}Forfatter: Katatude - - -STR_SCNR :Choo-Choo Town -STR_PARK :Choo-Choo Town -STR_DTLS :Mamma! Pappa! Jeg vil dra til Choo-Choo By!{NEWLINE}Forfatter: Fossil - - -STR_SCNR :Dragon Islands -STR_PARK :Dragon Islands -STR_DTLS :Drageøyene? Jeg er ikke sikker på om jeg vil dra dit…{NEWLINE}Forfatter: Fossil - - -STR_SCNR :Kiddie Karnival II -STR_PARK :Kiddie Karnival -STR_DTLS :Hei unger! La oss ha det gøy!{NEWLINE}Forfattere: Piehead & Fossil - - -STR_SCNR :Sand Dune -STR_PARK :Sand Dune -STR_DTLS :Som eieren av en liten park, kjøpte du et stort stykke land langs stranda for å utvide og tiltrekke flere gjester til å besøke de vakre sanddynene, men være på vakt: du kan ikke forstyrre de økologisk skjøre sanddynene.{NEWLINE}Forfatter: rbarclay diff --git a/data/language/nl-NL.txt b/data/language/nl-NL.txt index d20a774264..e2b379166c 100644 --- a/data/language/nl-NL.txt +++ b/data/language/nl-NL.txt @@ -3777,925 +3777,3 @@ STR_6706 :{WINDOW_COLOUR_2}Geselecteerd bestand: {BLACK}{STRING} STR_6707 :(n.v.t.) STR_6708 :Afrondsterkte STR_6709 :Voer een afrondsterkte in tussen {COMMA16} en {COMMA16} - -############# -# Scenarios # -############# - -## RCT1 Original - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Bouw een bloeiend pretpark diep in het bos, op een grote open plek. - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Dit park, gebouwd in de woestijn, beschikt over slechts één achtbaan maar heeft ruimte voor uitbreiding. - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Bouw vanaf het begin een pretpark rond een groot meer. - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights is al een succesvol pretpark met fantastische attracties. Verbeter het om de waarde ervan te verdubbelen. - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Verander de schitterende Evergreen Gardens in een bloeiend pretpark. - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Verander het kleine amusementspark van Bumbly Beach in een succesvol pretpark. - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Verscheidene eilanden vormen de basis voor dit nieuwe park. - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :Een klein pretpark met een paar attracties en ruimte voor uitbreiding. Jouw doel is om de parkwaarde te verdubbelen. - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :Een klein, krap pretpark dat grote uitbreiding vereist. - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :Een park met enkele uitstekende waterattracties vereist uitbreiding. - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Verander een grote verlaten mijn (een toeristische attractie) in een pretpark. - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :Een groot park, verscholen in het bos, met alleen kartbanen en houten achtbanen. - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :Dit pretpark heeft goed ontworpen, moderne attracties, maar heeft ook veel ruimte voor uitbreiding. - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :Bouw vanaf het begin een pretpark in de heuvelachtige bossen van Mystic Mountain. - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Verander de Egyptische ruïnes (een toeristische attractie) in een bloeiend pretpark. - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :Een groot park met goed ontwerpen maar nogal oude attracties. Vervang de oude attracties of voeg nieuwe toe om het park populairder te maken. - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Verander de pier van dit slaperige stadje in een bloeiende attractie. - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :De mooie bergen van Lightning Peaks zijn populair bij wandelaars en toeristen. Gebruik de beschikbare grond om nieuwe sensatiezoekende klanten aan te trekken. - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :Een gevestigd park met een aantal problemen. - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Van de gemeenteraad van Rainbow Valley mag het landschap niet gewijzigd worden en er mogen er geen grote bomen worden gekapt. Desondanks moet je het gebied ontwikkelen tot een groot pretpark. - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock staat midden in een woestijn en trekt veel toeristen aan. Gebruik de beschikbare ruimte om attracties te bouwen en meer mensen aan te trekken. - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Gewoon voor de lol! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Ontwikkel het rotsgebied bij de kust tot een bloeiend pretpark. - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Het middelpunt van dit grote park in ontwikkeling is een enorme duellerende stalen achtbaan met drie sporen. - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Deze verlaten mijn heeft reeds kenmerken van een toeristische attractie: een miniatuurspoorweg en een paar verticale achtbanen. - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :Je hebt de beschikking over een oude, niet meer gebruikte brug. Verander deze in een pretpark. - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Dit park beslaat land aan beide zijden van een snelweg en beschikt reeds over enkele functionerende attracties. - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :De gemeente is bereid het omliggende land voor een gunstige prijs te verkopen aan dit kleine kustpark, op voorwaarde dat bepaalde attracties behouden blijven. - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Je mag dit kasteel naar eigen inzicht veranderen in een pretpark. - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Dit futuristische park met buitenaards landschap heeft genoeg ruimte beschikbaar voor nieuwe attracties. - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :De lokale bevolking heeft een voorkeur voor rustige en ontspannende attracties, dus is het je taak om dit park uit te breiden naar hun smaak. - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Dit grote stuk land, diep in het oerwoud, ligt klaar om te worden veranderd in een attractiepark. - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :Een aantal meren op verschillende hoogtes vormt de basis voor dit nieuwe park. - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Dit oude park heeft veel historische attracties maar ook grote schulden. - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Een groot stuk land is al voor je ontruimd en gedeeltelijk gethematiseerd, zodat je het kunt ontwikkelen tot een themapark. - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :Een bloeiende fruitplantage heeft een spoorweg gebouwd om haar inkomen te vergroten. Jouw taak is om de plantage uit te breiden tot een bloeiend pretpark. - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Je mag het gebied rondom een dam ontwikkelen tot een attractiepark. - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :Je mag een enorme kloof ontwikkelen tot een attractiepark. - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :In dit park regent het zo vaak dat er een enorme piramide is gebouwd om overdekte attracties te kunnen bouwen. - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :De gemeenteraad staat bouwen boven boomniveau niet toe in dit park. - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Ontwikkel dit Romeinse themapark door achtbanen en andere attracties toe te voegen. - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Dit park is gedeeltelijk gebouwd op een serie kleine eilanden en heeft al een paar grote achtbanen als trekpleister. - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Bouw een park dat de lokale bevolking, die op zoek is naar snelheid en spanning, aanspreekt. - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :Een oase midden in de woestijn vormt een ongebruikelijke gelegenheid tot het bouwen van een pretpark. - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Dit park is overwoekerd en vervallen. Kun je het weer in ere herstellen? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Dit park staat vol met slecht ontworpen en gevaarlijke attracties. Je hebt een zeer beperkt budget en weinig tijd om het park weer op de rails te krijgen. - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :De gemeenteraad staat geen enkele vorm van adverteren toe, dus dit park kan enkel slagen op basis van zijn reputatie. - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :De trekpleister van dit park is een duellerende Steeplechase met vier sporen naast elkaar. - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Verander deze verlaten steengroeve in een park dat sensatiezoekende toeristen aanspreekt. - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Je hebt een beperkt budget om dit berggebied in een groot park vol achtbanen te veranderen, maar tijd speelt geen rol. - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :Een piepklein park heeft een overeenkomst afgesloten met de gemeente om uit te breiden door de stad zelf. - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :Een groot tuinpark moet worden veranderd in een bloeiend themapark. - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :Een hele verzameling ijsbergen vormt de ijzige achtergrond van dit ambitieuze themapark. - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :De achtergrond van deze vlammende achtbaanuitdaging is een slapende vulkaan. - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Het is je taak dit woestijnpark te ontwikkelen terwijl je de gasten tevreden houdt. Geld speelt geen rol! - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Het is je taak een park vol met achtbanen te bouwen tussen de Razor Rocks. - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :De achtergrond van dit park wordt gevormd door een groot meer in oude krater. - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Dit park heeft al een uitstekende hypercoaster, maar je taak is om de winst flink te verhogen. - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier heeft extra pieren bijgebouwd, en het is je taak om het park erlangs uit te breiden. - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :Deze baai vormt de achtergrond van deze achtbaanuitdaging. - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Een kasteel met twee achtbanen moet worden ontwikkeld tot een groot themapark. - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :Een park waarin de meeste voetpaden en achtbanen onder de grond liggen. - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :Je mag een vallei met een gletsjer ontwikkelen tot een themapark. - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :In een verre wereld waar geld geen rol speelt moet je een park bouwen om de mensen te vermaken. - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :In dit woestijnpark staan vijf achtbanen die moeten worden afgemaakt. - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :Dit historische park mag alleen oudere soorten attracties bouwen. - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Ontwikkel dit buitenaardse park om de winst zo groot mogelijk te maken. - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :Dit goed gethematiseerde pretpark heeft al diverse attracties, maar nog voldoende ruimte voor uitbreiding. - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :Een eng park met een grote achtbaan als trekpleister. - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Het fundament van dit themapark wordt gevormd door twee enorme rotsen die in het zand staan. - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :In dit grote park moet je tien grote achtbanen ontwerpen en bouwen. - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :Dit lange, smalle eiland is een uitdagende locatie om een aantal achtbanen te bouwen. - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Een ijzig landschap moet worden veranderd in een bloeiend themapark. - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :Je mag een woestijnpark met enkele slim ontwerpen achtbanen verder ontwikkelen. - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :In dit kleine park moet je de vijf bestaande achtbanen afmaken. - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :Een groot park dat omringd wordt door een bijzonder transportsysteem. - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Je mag dit grote eiland ontwikkelen tot een pretpark. - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :Deze enorme verlaten wolkenkrabber is een unieke kans voor een pretparkontwikkelaar. - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Je mag deze stedelijke omgeving ontwikkelen tot een pretpark. - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :Een enorm park dat al tjokvol attracties staat moet worden verbeterd. - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :Dit stuk land op een verre planet moet worden veranderd in een themapark. - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Je moet proberen het kleinste winstgevende pretpark ter wereld te bouwen. - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -## RCT2 Original - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Maak van een klein skistation in de bergen een amusementspark met een sneeuwthema. - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Bouw een amusementspark met een luchtvaartthema op dit verlaten vliegveld. - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Het is je uitdaging om een zeer winstgevend park te bouwen op dit paradijselijke eiland. - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Je begint met een kleine markt. Je opdracht is om de winst van je winkels en kraampjes te vergroten door attracties en achtbanen te bouwen en zo meer klanten te trekken. - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :Je hebt een groot kasteel geërfd. Het is je opdracht er een klein themapark van te maken. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Dusty Greens ligt aan een snelwegknooppunt in de woestijn. Het is een gelegenheid om van een kleine golfbaan een succesvol themapark te maken. - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :Je hebt een kleine boerderij geërfd, en het is je uitdaging een klein themapark tussen de velden en de boerderijen te bouwen. - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Het is de uitdaging om dit woestijnpark uit te breiden om mensen te trekken die op zoek zijn naar extreme sensatie. Geld speelt geen rol. - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Een verlaten fabriekscomplex is een gelegenheid om een amusementspark met een fabrieksthema te bouwen. - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Het is je uitdaging om een succesvol themapark in Fungus Woods te bouwen, maar je bent beperkt tot ouderwetse houten attracties. - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Je bent aangenomen door een grote keten van amusementsparken. Het is je taak een gigantisch park met achtbanen te bouwen rond een verlaten mijnstadje. - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Het is je uitdaging een park met achtbanen in de prachtige Gravity Gardens te bouwen… geen andere attracties, alleen maar achtbanen! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :Een park dat op een hachelijke plaats is gevestigd: op een vulkaan, naast stromende lava. - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :Met een onbeperkt budget, maar gesitueerd op een veeleisende locatie is het een uitdaging dit park uit te breiden en te beheren. - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :In dit park, gelegen op een heuvel, zijn hoge bouwwerken verboden. Kun je het park uitbreiden en het succesvol maken? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Probeer dit Six Flags-park op je eigen manier te beheren en te verbeteren. - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: meer bezoekers naar het park halen! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Probeer dit Six Flags-park op je eigen manier te beheren en te verbeteren. - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: je lening terugbetalen terwijl je de waarde van je park laat stijgen! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: meer bezoekers naar het park halen! - - -STR_SCNR :Bouw je eigen Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Bouw je eigen versie van dit Europese Six Flags-park. - - -STR_SCNR :Bouw je eigen Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Gebruik je ontwerpvaardigheden om dit Six Flags-park opnieuw te maken. - - -STR_SCNR :Bouw je eigen Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Bouw je eigen versie van dit Europese Six Flags-park. - - -STR_SCNR :Bouw je eigen Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Maak je eigen versie van dit enorme Six Flags-park. - - -STR_SCNR :Bouw je eigen Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Maak je eigen versie van dit Six Flags-park. - - -STR_SCNR :Bouw je eigen Six Flags-park -STR_PARK :Six Flags -STR_DTLS :Maak je eigen Six Flags-park, door gebruik te maken van attracties uit andere Six Flags-parken of door zelf nieuwe attracties te ontwerpen. - -## Wacky Worlds Scenarios - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :Je hebt een verlaten diamantmijn geërfd en een waardevolle diamant gevonden. Je besluit dit geld te investeren om een wereldberoemd themapark te bouwen. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :Er is een oase in de woestijn gevonden die een prachtige locatie van een park zou vormen. Voor transport van en naar de oase is gezorgd. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :Er is een stuwdam gebouwd die goedkope energie in overvloed levert voor je park. Je moet een hoge parkwaarde bereiken om de lening voor de dam terug te betalen. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :De milieuorganisatie heeft je gevraagd om een lelijke oude olieraffinaderij om te vormen tot een toeristische trekpleister. Land is goedkoop maar de rente op leningen is hoog. Je kunt de oude gebouwen verkopen als schroot. - - -STR_SCNR :De Chinese Muur -STR_PARK :De Chinese Muur -STR_DTLS :De regering heeft besloten om meer toeristen naar de Chinese Muur door er een themapark naast te bouwen. Geld speelt geen rol! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :Een bestaand pretpark heeft geen ruimte meer. Je enige optie is om naar de zee uit te breiden, waarvoor je geld hebt geleend. Vanwege het aardbevingsgevaar zijn er hoogtebeperkingen van kracht. - - -STR_SCNR :Park Maharadja -STR_PARK :Park Maharadja -STR_DTLS :De Maharadja heeft jou aangewezen om de lokale bevolking te vermaken. Bouw een park dat is geïnspireerd door het paleis van de Maharadja. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :Je helpt de Aboriginals om een park te bouwen om het bewustzijn voor hun cultuur te vergroten. Je moet een groot aantal bezoekers aantrekken om hen de unieke geschiedenis van de Aboriginals bij te brengen. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :Het themapark van een lokale ondernemer is over de kop gegaan. Je bezit zelf al een klein park en hebt het andere park overgenomen. Combineer beide parken tot één groot park. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :Je bent aangesteld om het beheer over een attractiepark over de Europese cultuur over te nemen. Je moet het aantal bezoekers verhogen om de EU-subsidie terug te betalen voor het einde van de huidige termijn van het Europees Parlement. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :Een oud park is vervallen. Je hebt een lening van de Europese Unie gekregen om het troosteloze terrein weer in oude luister te herstellen! Je moet het park renoveren en de lening terugbetalen. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :De bevolking van Hawaii wil wel eens iets spannenders dan surfen. Houd dit in het achterhoofd bij het bouwen van een park om zoveel mogelijk mogelijk toeristen aan te trekken. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :Je moet een park bouwen op de beperkte ruimte aan weerszijden van dit natuurschoon. Hierbij heb je de mogelijkheid om land te kopen van de indianen. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :Je bent een succesvol zakenman op een lange sabbatical. Die wil je gebruiken om het stadspark om te toveren in een achtbanenparadijs. Geld speelt geen rol! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :Om nog meer toeristen te trekken moet je een park bouwen dat past bij de omgeving. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :In het regenwoud is er niet veel plek. Je moet zo veel mogelijk in de open plek zien te persen om een goed alternatief voor de lokale houtindustrie te vormen. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :Je hebt een klein park in de buurt van Rio, maar de bank wil haar lening terug. Je moet je winst zien te verhogen om je schuld terug te betalen. - -## Time Twister - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :De leden van de lokale vereniging die oude veldslagen naspeelt nemen hun hobby serieus. Ze hebben jou de klus toevertrouwd om van Cliffside Castle een middeleeuws themapark te maken. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :Om geld van de rijken naar de armen te brengen hebben jij en je Merry Men besloten een themapark te bouwen in Sherwood Forest. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Er is leven ontdekt op een verre planeet! Bouw een buitenaards themapark om munt te slaan uit de onverwachte golf van interesse. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Laat je inventieve, utopische visie van de toekomst zien! Bedenk een furistisch ontwerp met state-of-the-art attracties. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :Je moet een bestaand pretpark, gebouwd op een oude filmset, beheren en verbeteren. Bouw een eerbetoon aan de pioniers van de stop-motionanimatie, die de wezens uit de mythologie tot leven brachten op het witte doek. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :Je bezit een eiland van grote archeologische waarde, dat je voor het nageslacht wilt beschermen. Dit wil je bekostigen door een park te bouwen met de mythologische geschiedenis van je eiland als thema. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :Je bezit een stoffige oude meteorietkrater. Als echte ondernemer heb je besloten om er een themapark van te maken en zo munt te slaan uit je (op het eerste gezicht) waardeloze land. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :Je moet een themapark bouwen in Jurastijl. Om de bezoekers zo dicht mogelijk bij de exotische planten en dieren te laten komen, moeten je attracties over en door de vallei gaan lopen. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :Om te voorkomen dat er een snelweg wordt aangelegd en zo de mysterieuze prehistorische steencirkels te beschermen, moet je een winstgevend themapark bouwen. Het kan echter lastig worden om bezoekers aan te trekken, aangezien het terrein vrij ruw is. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :Het beruchte gevangeniseiland, dat ooit volzat met illegale drankstokers en gangsters, is nu te koop. Je hebt besloten het te veranderen in een toeristentrekpleister. Geld speelt geen rol! - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :Het is al bijna 75 jaar geleden dat je grootvader de Schneider Cup won. Je hebt besloten zijn prestatie te eren met een themapark dat is geïnspireerd door de beroemde watervliegtuigenrace. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :Je bezit een lege kavel in de stad, tussen de laagbouw. Bouw een themapark van wolkenkrabbers, geïnspireerd door de artdecostijl van de jaren twintig. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Een groot jaarlijks muziekfestival vindt plaats op jouw terrein. Bouw een hip themapark om het publiek van vrije geesten te vermaken. - - -STR_SCNR :Rock ’n’ Roll Revival -STR_PARK :Rock ’n’ Roll Revival -STR_DTLS :Dit verouderde themapark heeft betere tijden gekend. Geef het park een rock-’n-roll-makeover en verander het in een succesvolle onderneming. - -#OCC - -STR_SCNR :Panda World -STR_PARK :Panda World -STR_DTLS :Voeg meer attracties toe aan dit park met pandathema, en trek meer bezoekers aan. - - -STR_SCNR :Tycoon Park -STR_PARK :Tycoon Park -STR_DTLS : - -### - -STR_SCNR :Cemetery Ridge -STR_PARK :Cemetery Ridge -STR_DTLS :Het is Allerheiligenavond bij UCES en de pompoenen komen tot leven! Deze begraafplaats is in de problemen gekomen en het is jouw taak om deze op te lossen, zonder de doden te storen! Gaat het je lukken om de geesten in de graven te houden en je bezoekers koude rillingen te bezorgen?{NEWLINE}Gemaakt door: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :De vuurtoren van Alexandrië -STR_PARK :De vuurtoren van Alexandrië -STR_DTLS :Alexander bouwde deze stad. De Grieken, Romeinen en Egyptenaren drukten er hun stempel op. Maar het pronkstuk was dit wereldwonder: de vuurtoren. Kom langs en bouw een park!{NEWLINE}Gemaakt door: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Zoals het eruitzag op de openingsdag, 18 mei 1905.{NEWLINE}Gemaakt door: Aetherwave - - -STR_SCNR :Vesuvius -STR_PARK :Vesuvius -STR_DTLS :Pompeii en Herculaneum werden in 79 n.Chr. door de Vesuvius bedolven onder de as. Bezoek de opgravingen en bouw een park!{NEWLINE}Gemaakt door: Katatude - - -STR_SCNR :De zandbak -STR_PARK :De zandbak -STR_DTLS :Iedereen wil toch wel eens in de zandbak spelen? Pak je emmertje en je schepje en bouw een park!{NEWLINE}Gemaakt door: Katatude - - -STR_SCNR :Niagara Falls -STR_PARK :Niagara Falls -STR_DTLS :American Falls, Bridal Falls en Canadian Horseshoe Falls op de grens bij de Niagara, 1850.{NEWLINE}Gemaakt door: Katatude - - -STR_SCNR :Rocky Mountain Miners -STR_PARK :Rocky Mountain Miners -STR_DTLS :Door een aardverschuiving is je spoorweg bedolven onder het puin. Je werknemers zijn het gebied gaan verkennen. Zijn achtbanen misschien de gouden bergen waar je naar op zoek was?{NEWLINE}Gemaakt door: Squid, Buckone, Fossil - - -STR_SCNR :De tijdmachine -STR_PARK :The Time Machine -STR_DTLS :De tijdmachine, die je overal heen brengt waar en wanneer je maar wilt. De eeuwigheid wacht op je. Maar alles is relatief.{NEWLINE}Gemaakt door: Katatude - - -STR_SCNR :De toren van Babel -STR_PARK :Babel -STR_DTLS :Waar zijn we nu weer beland? Waar is iedereen?{NEWLINE}Gemaakt door: Fossil - - -STR_SCNR :Transformation -STR_PARK :Transformation -STR_DTLS :We hadden je al verwacht…{NEWLINE}Gemaakt door: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :De Romeinen hebben zo onderhand wel genoeg van al die gladiatorengevechten. Zorg voor nieuwe vormen van vermaak door een Romeins stadje om te toveren in het beste attractiepark aller tijden!{NEWLINE}Gemaakt door: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Beneath the Christmas Tree -STR_PARK :Winter Wonderland -STR_DTLS :Je moeder heeft dit tafereel onder de kerstboom gebouwd. Nu is het jouw beurt om er een park van te maken!{NEWLINE}Gemaakt door: Katatude - - -STR_SCNR :Bigrock Blast -STR_PARK :Bigrock Blast -STR_DTLS :Na een explosie bij de Bigrock Mining Co. moeten de inwoners van Bigrock hun stad in leven zien te houden. Ze hebben jou ingehuurd om deze klus te klaren.{NEWLINE}Gemaakt door: rbarclay & buckone - - -STR_SCNR :Camp Mockingbird -STR_PARK :Camp Mockingbird -STR_DTLS :Dit zomerkamp kost maar 500 euro per week! Plunder je spaarrekening en kom bouwen!{NEWLINE}Gemaakt door: Katatude - - -STR_SCNR :Choo-Choo Town -STR_PARK :Choo-Choo Town -STR_DTLS :Mam! Pap! Ik wil naarChoo-Choo Town!{NEWLINE}Gemaakt door: Fossil - - -STR_SCNR :Dragon Islands -STR_PARK :Dragon Islands -STR_DTLS :Dragon Islands? Dat klinkt niet erg veilig…{NEWLINE}Gemaakt door: Fossil - - -STR_SCNR :Kiddie Karnival II -STR_PARK :Kiddie Karnival -STR_DTLS :Tijd om de kleintjes te vermaken!{NEWLINE}Gemaakt door: Piehead & Fossil - - -STR_SCNR :Sand Dune -STR_PARK :Sand Dune -STR_DTLS :Je bezit al een klein park en hebt besloten om een groot stuk land bij het strand erbij te kopen, om meer bezoekers naar deze prachtige duinen te trekken. Maar let op: de duinen zijn een gevoelig ecosysteem dat je niet mag verstoren.{NEWLINE}Gemaakt door: rbarclay - -################################## -# Rides/attractions / Attracties # -################################## - -# Boat Ride / Bootverhuur -#CC -[AE-SWIM] -STR_NAME :Zwembad -STR_DESC :Een steiger waarvan bezoekers het water in kunnen om een stukje te zwemmen. Door ‘The Amazing Earl’. -STR_CPTY :1 bezoeker per ‘boot’ -# End of Boat Ride / Bootverhuur - -# Space rings / Ruimteringen -#CC -[RIDE7MKY] -STR_NAME :Springkussens -STR_DESC :Bezoekers springen op en neer op met lucht gevulde kussens. -STR_CPTY :1 bezoeker per kussen -# End of Space rings / Ruimteringen - -# Looping RC / Stalen achtbaan -#CC -[AE-MTRHN] -STR_NAME :Matterhorntrein -STR_DESC :Achtbaantrein in de stijl van de beroemde Matterhorn voor de 50e verjaardag van Disneyland. Door ‘The Amazing Earl’. -STR_CPTY :4 passagiers per karretje -# End of Looping RC / Stalen achtbaan - -# Steeplechase (Single Rail RC) -#CC -[AE-REIND] -STR_NAME :Runaway Reindeer -STR_DESC :Passagiers zitten in paren op rendiervormige karretjes - compleet met knipperende rode neuzen. Door ‘The Amazing Earl’. -STR_CPTY :2 passagiers per rendier -# End of Steeplechase (Single Rail RC) - -# Twist -#CC -[RIDE4MKY] -STR_NAME :Zweefmolen -STR_DESC :Passagiers zitten in stoeltjes die onder een molen hangen en naar buiten vliegen als deze gaat draaien. -STR_CPTY :18 passagiers - -#CC -[AE-SWING] -STR_NAME :Zweefmolen -STR_DESC :Passagiers zitten in stoeltjes die onder een molen hangen en naar buiten vliegen als deze gaat draaien. Door ‘The Amazing Earl’. -STR_CPTY :18 passagiers -# End of Twist - -#################################### -# Shops/stalls / Winkels/kraampjes # -#################################### - -# Information Kiosks -#CC -[INFO1MKY] -STR_NAME :Informatiekiosk -STR_DESC :Een kiosk waar bezoekers kaarten van het park en paraplu’s kunnen kopen. - -# End of Information Kiosks - -################# -# Small objects # -################# - -## Start CC -## TT Pirate roofs and eaves -[TTPIRF05] -STR_NAME :Dak - -[TTPRF09] -STR_NAME :Dak - -[TTPRF10] -STR_NAME :Dak - -[TTPRF11] -STR_NAME :Dak -## End CC - - diff --git a/data/language/pl-PL.txt b/data/language/pl-PL.txt index 9e356720a5..0c6df46c26 100644 --- a/data/language/pl-PL.txt +++ b/data/language/pl-PL.txt @@ -3578,758 +3578,3 @@ STR_6502 :Wprowadź wartość pomiędzy {COMMA16} a {COMMA16} STR_6503 :Musi być wybrany przynajmniej jeden obiekt stacji STR_6504 :Należy wybrać co najmniej jeden element powierzchni terenu STR_6505 :Należy wybrać co najmniej jeden element krawędzi terenu - - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :W środku lasu zbuduj tętniący życiem park rozrywki korzystając z pustego kawałka terenu - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Zbudowany na środku pustyni tylko z jednym roller coasterem, ma solidne podstawy do dalszej rozbudowy - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Zaczynając od podstaw, wybuduj park rozrywki wokół sporego jeziora - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights to odnoszący sukcesy park ze świetnymi atrakcjami - podwój jego wartość - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Przemień piękne Evergreen Gardens w kwitnący park tematyczny - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Rozwiń małe Bumbly Beach w tętniący życiem park rozrywki - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Kilka wysp stanowi podstawę dla nowego parku - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :Mały park z kilkoma atrakcjami oraz przestrzenią do rozwoju - podwój jego wartość - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :Mały, zwarty park rozrywki wymaga znacznej rozbudowy - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :Park ze świetnymi przejażdżkami wodnymi wymaga dalszej rozbudowy - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Przemień tą wielką porzuconą kopalnię z zwykłej atrakcji turystycznej w park tematyczny - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :Wielki park w środku lasu, jedynie z gokartami i drewnianymi kolejkami - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :Park posiada już kilka ciekawych nowoczesnych kolejek, ale nadal pozostało trochę przestrzeni do rozbudowy - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :W pagórkowatych lasach Mystic Mountain, zbuduj nowy park od podstaw - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Zamień egipskie ruiny ze nudnej atrakcji turystycznej w tętniący życiem park rozrywki - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :Wielki, dobrze zaprojektowany park, jednak ze starymi atrakcjami. Wymień stare atrakcje i zbuduj nowe, aby zwiększyć popularność parku. - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Przekształć te senne miasteczko w tętniący życiem park rozrywki - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :Piękne góry w Lightning Peaks są bardzo popularne wśród spacerowiczów oraz turystów. Wykorzystaj dostępny teren, aby przyciągnąć ludzi szukających wrażeń - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :Park z ugruntowaną pozycją, jednak z kilkoma problemami - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Lokalne władze nie pozwolą na żadne zmiany krajobrazu ani na wycinkę dużej liczby drzew, lecz mimo to musisz zbudować tutaj wielki park rozrywki - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Park Thunder Rock stoi pośrodku pustyni dlatego przyciąga wielu turystów, wykorzystaj dostępny teren i zbuduj więcej atrakcji, aby przyciągnąć więcej ludzi - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Po prostu zabawa! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Rozwiń nadmorskie klify w kwitnący park rozrywki - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :W centrum tego dużego parku jest wielki potrójny tor do wyścigów kolejek na stalowych torach - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Ta opuszczona kopalnia już jest atrakcją ze swoją miniaturową kolejką i parą kolejek górskich pionowego spadku - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :Stary nieużywany most zostaje przekazany w Twoją dyspozycję w celu przemienienia go w park rozrywki - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Rozbuduj się po obu stronach autostrady, ten park ma już kilka atrakcji - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :Lokalne władze zgodziły się na sprzedaż pobliskiego terenu za niską kwotę pod warunkiem zachowania kilku z funkcjonujących atrakcji - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Zamień ten zamek w wymarzony park rozrywki - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Ten futurystyczny park posiada pełno miejsca na nowe atrakcje w jego obcym krajobranie - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :Lokalna ludność preferuje łagodne i relaksujące atrakcje, także Twoim zadaniem jest rozbudowa parku wedle ich upodobań - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Głęboko w dżungli znajduje się wielki teren gotowy na przekształcenie w park rozrywki - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :Seria stopniowanych jezior tworzy podstawę tego nowego parku - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Ten wiekowy park posiada wiele historycznych atrakcji, jednak jest bardzo zadłużony - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Duża powierzchnia gruntu została wyczyszczona i jest już częściowo przygotowana na rozwój wielkiego parku krajobrazowego - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :Dobrze prosperujące gospodarstwo uprawiające owoce zbudowało kolej, aby zwiększyć swoje dochody. Musisz to wykorzystać i zbudować park pełny rozrywki - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Obszar wokół zapory jest dostępy dla Ciebie, zbuduj tutaj park rozrywki - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :Ogromny kanion jest do Twojej dyspozycji, byś mógł zbudować tutaj park rozrywki - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :Pogoda tutaj jest bardzo deszczowa, dlatego zbudowano wielką piramidę, aby schować pod nią kilka atrakcji - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :Lokalne władze nie pozwolą Ci budować powyżej wysokości drzew - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Rozwiń ten park w stylu rzymskim budując atrakcje i kolejki górskie - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Zabuduj kilka małych wysepek, ten park ma już pare dużych koleje górskich w centralnej części - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Zbuduj park aby zadowolić ludzi szukających mocno intensywnych atrakcji - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :Oaza w środku pustyni zapewnia niezwykłą okazję do zbudowania wesołego miasteczka - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Zarośnięty i zrujnowany, czy jesteś w stanie przywrócić świetność temu wesołemu miasteczku? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Pełen źle zaprojektowanych i niebezpiecznych kolejek, masz ograniczony budżet i mało czasu, aby działać i ulepszyć park - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :Lokalne władze nie zgodzą się na żadne promocje lub reklamy, dlatego sukces musi być oparty tylko na reputacji - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :Czterotorowy bieg z przeszkodami jako centralna atrakcja tego rozwijającego się parku - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Przekształć opuszczony kamieniołom w miejsce przyciągające ludzi szukających dreszczyku emocji - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Masz ograniczony budżet ale nie ogranicza Cię czas, aby zmienić to zbocze góry w ogromny park rozrywki - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :Mały park doszedł do porozumienia z pobliskim miastem i ma zgodę na rozbudowę przez miasto - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :Wielki ogród wymaga przemiany w tętniący życiem park rozrywki - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :Góry lodowe w parku sprawiają chłodne wrażenie w tym parku rozrywki - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :Uśpiony wulkan w tym zadaniu jest wyzwaniem utrudniającym budowę parku - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Bez limitów finansowych, Twoim zadaniem jest zamiana tej pustyni w park gdzie goście są szczęśliwi - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Twoje zadanie polega na budowie wielkich kolejek w parku znajdującym się wśród gór Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :W tej misji znajduje się wielkie jezioro w starożytnym kraterze - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Park ten posiada już kilka ścietnych kolejek, jednak twoim zadaniem jest maksymalizacji zysków z nich - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier rozwinął skrzydła budując molo nad morzem, Twoim zadaniem jest zabudowa dodatkowego miejsca - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :W scenariuszu znajduje się nadmorska zatoka - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Zamek z paroma kolejkami górskimi wymaga przemiany w duży park rozrywki - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :Park ze sporą ilością podziemnych ścieżek i atrakcji - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :Dolina wypełniona lodowcem czeka na przemianę w park rozrywki - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :W przyszłości, w świecie gdzie nie potrzebne są pieniądze, Twoim zadanie jest zbudowanie centrum rozrywki zapewniające radość ludziom - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Pięć kolejek wymaga dokończenia w tym pustynnym parku - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :W tym starodawnym parku dozwolona jest tylko budowa kolejek starego typu - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Rozwiń ten kosmiczny park w celu maksymalizacji zysków - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :Ten dobrze ustrojony park ma już kilka atrakcji, ale posiada także masę miejsca na rozbudowę - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :Przerażający park rozrywki z wielką kolejką pośrodku. - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Dwa wielkie głazy wystające z piasku stanowią zalążek wystroju tego parku - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :W tym ogromnym parku musisz zaprojektować i zbudować wielkie kolejki - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :Długie i cienkie wyspy są wyzwaniem przy budowie kolejek - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Lodowy wystruj potrzebuje transformacji w kwitnący park rozrywki - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :Pustynny park z paroma pomysłowymi kolejkami czeka na Twoją pomoc w rozbudowie - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :W tym małym parku musisz dokończyć budowę pięciu kolejek - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :Ogromny park z oryginalnym systemem transportu gości wokół granic parku - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Ta wielka wyspa jest do Twojej dyspozycji i czeka na budowę wielkiego parku rozrywki - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :Wielki opuszczony drapacz chmur jest świetną okazją do wykorzystania w wystroju parku - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Ten miejski teren jest do Twojej dyspozycji, przekształć go w park rozrywki - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :Gigantyczny park zawalony kolejkami potrzebuje udoskonalenia - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :Na odległej planecie mamy kawałek terenu, który trzeba zagospodarować na park rozrywki - - -STR_SCNR :Micro Park -STR_PARK :Micro Parkwiecie -STR_DTLS :Spróbuj stworzyć najmniejszy dochodowy park rozrywki na świecie - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Roof - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Przekształć niewielki ośrodek narciarski w lunapark z wystrojem zimowym. - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Wybuduj na tym opuszczonym lotnisku park rozrywki z lotniczym wystrojem. - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Twoim zadaniem jest wybudować na tej rajskiej wyspie lunapark przynoszący duże zyski. - - -STR_SCNR :Wybuduj własny park “Six Flags Belgium” -STR_PARK :Six Flags Belgium -STR_DTLS :Wybuduj własną wersję tego europejskiego parku “Six Flags” - - -STR_SCNR :Wybuduj własny park “Six Flags Great Adventure” -STR_PARK :Six Flags Great Adventure -STR_DTLS :Skorzystaj ze swoich umiejętności projektowania, aby odtworzyć ten park “Six Flags” - - -STR_SCNR :Wybuduj własny park “Six Flags Holland” -STR_PARK :Six Flags Holland -STR_DTLS :Wybuduj ten europejski park “Six Flags” wedle własnego uznania - - -STR_SCNR :Wybuduj własny park “Six Flags Magic Mountain” -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Stwórz własną wersję tego wielkiego parku “Six Flags” - - -STR_SCNR :Wybuduj własny park “Six Flags over Texas” -STR_PARK :Six Flags over Texas -STR_DTLS :Wybuduj obiekty w tym parku “Six Flags”, zaczynając od samego początku - - -STR_SCNR :Wybuduj własny park “Six Flags” -STR_PARK :Six Flags -STR_DTLS :Wybuduj własny park “Six Flags” - wykorzystaj obiekty z innych parków tej sieci lub projektuj i buduj własne atrakcje. - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Zaczynasz od małego targowiska, a twoim zadaniem jest zwiększenie zysku przynoszonego przez sklepy i stragany. Buduj karuzele i kolejki, aby przyciągnąć klientów. - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :Otrzymujesz w spadku wielki zamek - twoim zadaniem jest przekształcić go w mały park tematyczny. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Masz sposobność przekształcić Dusty Greens - niewielki klub golfowy znajdujący się przy skrzyżowaniu autostrad - w kwitnący lunapark. - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :Otrzymujesz w spadku małą farmę, a twoim zadaniem jest wybudowanie małego parku tematycznego na polach, wśród budynków gospodarczych. - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Nie musisz kłopotać się finansami - twoim zadaniem jest rozbudowa tego pustynnego lunaparku w celu przyciągnięcia amatorów ekstremalnych wrażeń. - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Opuszczony kompleks fabryczny to świetne miejsce pod budowę parku rozrywki z wystrojem mechanicznym. - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Twoim zadaniem jest stworzenie kwitnącego lunaparku w Grzybowych Lasach, przy czym musisz ograniczyć się do staroświeckich drewnianych obiektów. - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Otrzymujesz zlecenie od sieci lunaparków na wybudowanie wielkiego parku kolejek górskich wokół opuszczonego miasteczka górniczego. - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Twoim zadaniem jest wybudowanie lunaparku z kolejkami górskimi w pięknych ogrodach Grawitacji - żadnych karuzel, same kolejki! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :Lunapark umieszczony na polu lawy, poprzecinanym strumieniami rozpalonej magmy. - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :Z uwagi na trudne położenie nad jeziorem rozbudowa i zarządzanie tym lunaparkiem będzie dużym wyzwaniem pomimo nieograniczonych funduszy. - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Ten park, ulokowany na zboczu wzgórza, nie może zawierać żadnych wysokich obiektów. Czy uda ci się go rozbudować i zapewnić mu powodzenie? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Spróbuj poprowadzić i rozbudować ten park “Six Flags” - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Wybuduj brakujące obiekty “Six Flags” lub upiększ lunapark własnymi projektami! Tylko nie zapomnij o ostatecznym celu - musisz przyciągnąć do parku więcej gości! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Spróbuj poprowadzić i rozbudować ten park “Six Flags” - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Wybuduj brakujące obiekty “Six Flags” lub upiększ lunapark własnymi projektami! Tylko nie zapomnij o ostatecznym celu - musisz spłacić kredyt, równocześnie zwiększając wartość parku! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Wybuduj brakujące obiekty “Six Flags” lub upiększ lunapark własnymi projektami! Tylko nie zapomnij o ostatecznym celu - musisz przyciągnąć do parku więcej gości! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :Otrzymujesz w spadku nieużywaną kopalnię diamentów i znajdujesz w niej cenny kamień szlachetny. Postanawiasz zainwestować zdobytą fortunę w budowę parku tematycznego, który zasłynie na całym świecie. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :Odkryto pustynną oazę, która może stać się dobrym miejscem pod budowę lunaparku. Transport został zapewniony. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :Wybudowano tamę umożliwiającą produkcję taniej energii w hydroelektrowni, która będzie zasilać park. Musisz sprawić, aby osiągnął on dużą wartość, dzięki czemu spłacisz kredyt zaciągnięty na budowę. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :Agencja ochrony środowiska skierowała cię do przekształcenia starej rafinerii, będącej solą w oku ekologów, w czołową atrakcję turystyczną. Ziemia jest tania, lecz odsetki od kredytów wysokie. Możesz sprzedać stare budynki, aby powiększyć swoje fundusze. - - -STR_SCNR :Wielki Mur Chiński -STR_PARK :Wielki Mur Chiński -STR_DTLS :Władze postanowiły przyciągnąć więcej turystów w okolice Wielkiego Muru, budując w pobliżu park tematyczny. Pieniądze nie grają roli! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :W pewnym parku zabrakło miejsca. Twoją jedyną szansą jest wyjście w morze i w tym celu zaciągasz kredyt. Twoje budowle muszą mieć ograniczoną wysokość z uwagi na obciążenie fundamentów i zagrożenie trzęsieniem ziemi. - - -STR_SCNR :Park Maharadży -STR_PARK :Park Maharadży -STR_DTLS :Maharadża zlecił ci zapewnienie rozrywki swoim licznym poddanym. Wybuduj lunapark, wzorując się na pałacu maharadży. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :Pomagasz Aborygenom w budowie lunaparku w ramach programu świadomości kulturalnej. Musisz przyciągnąć wielu gości i zapoznać ich z unikalnym dziedzictwem ludu Aborygenów. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :Miejscowe oceanarium zbankrutowało. Masz już niewielki własny lunapark i kupujesz drugi park od firmy budowlanej. Przekształć je w duży połączony lunapark. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :Zlecono ci objęcie kierownictwa działu Turystycznych Atrakcji Kulturalnych. Musisz zwiększyć liczbę gości, aby spłacić unijne dofinansowanie przed zakończeniem bieżącej kadencji parlamentu europejskiego. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :Pewien stary lunapark popadł w ruinę. Otrzymujesz fundusze z Unii Europejskiej, aby przywrócić temu żałosnemu miejscu jego dawną chwałę! Musisz odnowić park i zwrócić otrzymany kredyt. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :Mieszkańcy Hawajów znudzili się surfowaniem i szukają bardziej intensywnych przeżyć. Budując swój lunapark, musisz o tym pamiętać, aby utrzymać wysoką ocenę dla turystów. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :Twoim celem jest wybudowanie lunaparku na ograniczonym terenie znajdującym się na jednym z brzegów tego przyrodniczego cudu. Będziesz mógł kupować ziemię od Indian. Musisz osiągnąć swój cel, aby zapewnić utrzymanie mieszkańcom pobliskiego miasteczka. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :Jesteś znanym biznesmenem na urlopie i pragniesz wykorzystać wolny czas na przekształcenie miejskiego lunaparku w raj dla miłośników kolejek górskich. Pieniądze nie grają roli! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :W celu lepszego wypromowania miejscowej turystyki musisz wybudować lunapark pasujący do swego otoczenia. Obowiązuje ograniczenie wysokości budynków. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :W lesie deszczowym miejsce jest bardzo cenne - musisz upchnąć jak najwięcej obiektów na dostępnym wykarczowanym obszarze, aby lunapark stał się dobrą alternatywą dla miejscowego przemysłu drzewnego. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :Prowadzisz mały lunapark pod Rio, a bank wezwał cię do spłacenia kredytu. Musisz szybko zwiększyć swoje przychody, aby zwrócić dług. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Miejscowi miłośnicy odtwarzania rycerskich turniejów podchodzą do swego hobby raczej poważnie. Powierzyli ci zadanie budowy lunaparku stylizowanego na średniowiecze, który ma powstać na ziemiach Zamku na urwisku. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :Aby uwolnić bogatych od bogactwa i rozdać go biednym, wraz ze swą bandą wesołych ludzi z lasu planujesz wybudować park tematyczny w lesie Sherwood. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Odkryto życie na odległej planecie! Wybuduj park tematyczny, którego motywem przewodnim będą kosmici, a zgarniesz kasę dzięki bezprecedensowej fali zainteresowania tym zagadnieniem. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Pokaż ludziom swoją twórczą, utopijną wizję przyszłości - wybuduj futurystyczny lunapark, oferujący atrakcje najwyższej jakości. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :Otrzymujesz zadanie prowadzenia i rozbudowy istniejącego lunaparku, wybudowanego na dawnym planie filmowym. Stwórz hołd dla pionierów animacji poklatkowej, którzy przywoływali do życia mitologiczne potwory na srebrnym ekranie. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :Jesteś właścicielem pewnej wyspy o dużej wartości archeologicznej. Postanawiasz sfinansować konserwację tych zabytków, budując lunapark w stylu inspirowanym mitologicznym dziedzictwem regionu. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :Otrzymujesz na własność zakurzony krater po meteorycie. Jako przedsiębiorca z krwi i kości, postanawiasz zbudować park tematyczny związany z tym obiektem i przekształcić w ten sposób swój bezwartościowy teren w źródło przyzwoitych dochodów. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :Otrzymujesz zadanie wybudowania lunaparku w stylu jurajskim. Aby goście mogli wygodnie podziwiać egzotyczne rośliny i okazy zwierząt, musisz skonstruować kolejki przejeżdżające nad doliną i prowadzące do niej. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :Aby powstrzymać budowniczych autostrady i zachować dla potomności tajemnicze kamienne kręgi, musisz wybudować lunapark w stylu epoki kamiennej i osiągnąć zyski. Jednak przyciągnięcie gości może okazać się trudne, bo okolica jest wybitnie niegościnna. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :Niesławna wyspa więzienna, której ludność składała się niegdyś z przemytników i bandytów, jest na sprzedaż. Postanawiasz przekształcić ją w niesamowitą atrakcję turystyczną - pieniądze nie grają roli. - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :Za kilka lat będzie mieć miejsce 75. rocznica zdobycia przez twego dziadka Pucharu Schneidera. Postanawiasz uczcić ten wielki sukces, budując lunapark stylizowany na ów sławny wyścig hydroplanów. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :Jesteś właścicielem pustej parceli w pobliżu dzielnicy o niskiej zabudowie. Aby wycisnąć jak największy zysk ze swej nieruchomości, wybuduj lunapark, którego motywem wiodącym będą drapacze chmur w stylu art deco, charakterystycznym dla lat dwudziestych. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Na twoim terenie odbywa się wielki doroczny festiwal muzyczny. Wybuduj lunapark w stylu hipisowskim, by wolnomyślicielska publiczność mogła się w nim zabawić. - - -STR_SCNR :Rock ’n’ Roll Revival -STR_PARK :Rock ’n’ Roll Revival -STR_DTLS :Ten starzejący się lunapark ma najlepsze dni za sobą. Pomóż właścicielom nadać mu stylowy, rockandrollowy wygląd i przekształć to miejsce w dochodowe przedsięwzięcie. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Świat Pand -STR_PARK :Świat Pand -STR_DTLS :Dodaj nowe atrakcje i sprowadź więcej osób do tego parku o tematyce zbudowanej wokół pand. diff --git a/data/language/pt-BR.txt b/data/language/pt-BR.txt index 5ee5797373..7d8bfd2a87 100644 --- a/data/language/pt-BR.txt +++ b/data/language/pt-BR.txt @@ -3778,859 +3778,3 @@ STR_6706 :{WINDOW_COLOUR_2}Arquivo de imagem atual: {BLACK}{STRING} STR_6707 :(nenhum selecionado) STR_6708 :Intensidade da Suavização STR_6709 :Digite a intensidade da suavização entre {COMMA16} e {COMMA16} - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Fronteiras Florestais -STR_PARK :Fronteiras Florestais -STR_DTLS :No meio da floresta, construa um próspero parque temático numa grande área aberta. - - -STR_SCNR :Dunas Dinamite -STR_PARK :Dunas Dinamite -STR_DTLS :Construído no meio do deserto, este parque temático contém apenas uma montanha-russa, mas tem espaço para expansão. - - -STR_SCNR :Lago Frondoso -STR_PARK :Lago Frondoso -STR_DTLS :Partindo do zero, construa um parque temático em torno de um grande lago. - - -STR_SCNR :Picos Diamantinos -STR_PARK :Picos Diamantinos -STR_DTLS :Picos Diamantinos já é um parque temático de sucesso com excelentes brinquedos. Desenvolva-o para dobrar seu valor. - - -STR_SCNR :Jardins Perenes -STR_PARK :Jardins Perenes -STR_DTLS :Converta os belos Jardins Perenes em um próspero parque temático. - - -STR_SCNR :Praia Bamba -STR_PARK :Praia Bamba -STR_DTLS :Desenvolva o pequeno parque de diversões da Praia Bamba, transformando-o num próspero parque temático. - - -STR_SCNR :Ilhas da Trindade -STR_PARK :Ilhas da Trindade -STR_DTLS :Algumas ilhas formam a base para este novo parque. - - -STR_SCNR :Mundo de Katie -STR_PARK :Mundo de Katie -STR_DTLS :Um pequeno parque temático com alguns brinquedos e espaço para expansão - Seu objetivo é dobrar o valor do parque. - - -STR_SCNR :Parque Pequeno -STR_PARK :Parque Pequeno -STR_DTLS :Um pequeno e limitado parque de diversões que requer mais expansão. - - -STR_SCNR :Parque Aquático -STR_PARK :Parque Aquático -STR_DTLS :Um parque com algumas atrações aquáticas ótimas que requer expansão. - - -STR_SCNR :Minas do Milênio -STR_PARK :Minas do Milênio -STR_DTLS :Converta uma grande mina abandonada de ponto turístico em um parque temático. - - -STR_SCNR :Karts e Montanhas-Russas -STR_PARK :Karts e Montanhas-Russas -STR_DTLS :Um grande parque escondido na floresta, somente com pistas de karts e montanhas-russas de madeira. - - -STR_SCNR :Mundo de Mel -STR_PARK :Mundo de Mel -STR_DTLS :Este parque temático tem algumas atrações modernas bem projetadas e muito espaço para expansão. - - -STR_SCNR :Montanha Mística -STR_PARK :Montanha Mística -STR_DTLS :Nas florestas da Montanha Mística, construa um parque temático do zero. - - -STR_SCNR :Pirâmides Pacíficas -STR_PARK :Pirâmides Pacíficas -STR_DTLS :Converta a atração turística Ruínas Egípcias em um próspero parque temático - - -STR_SCNR :Madeiras Velhas -STR_PARK :Madeiras Velhas -STR_DTLS :Um grande parque com atrações bem projetadas, porém muito velhas - Substitua as atrações velhas ou adicione novas para tornar o parque mais popular. - - -STR_SCNR :Cais do Paraíso -STR_PARK :Cais do Paraíso -STR_DTLS :Converta o cais desta cidade sonolenta em uma atração próspera. - - -STR_SCNR :Picos do Relâmpago -STR_PARK :Picos do Relâmpago -STR_DTLS :As belas montanhas de Picos do Relâmpago são populares com andarilhos e turistas - Use a área disponível para atrair uma nova clientela em busca de emoção. - - -STR_SCNR :Torres de Marfim -STR_PARK :Torres de Marfim -STR_DTLS :Um parque bem estabelecido, que possui alguns problemas. - - -STR_SCNR :Vale do Arco-íris -STR_PARK :Vale do Arco-íris -STR_DTLS :A autoridade local do Vale do Arco-íris não permite mudanças no terreno ou remover as árvores, mas você deve desenvolver a área em um grande parque temático. - - -STR_SCNR :A Rocha do Trovão -STR_PARK :A Rocha do Trovão -STR_DTLS :A Rocha do Trovão fica no meio de um deserto e atrai muitos turistas - Use o espaço disponível para construir atrações e atrair mais pessoas. - - -STR_SCNR :Mega Parque -STR_PARK :Mega Parque -STR_DTLS :Apenas por diversão! - -## Added Attractions - -STR_SCNR :Penhascos Sussurrantes -STR_PARK :Penhascos Sussurrantes -STR_DTLS :Transforme os penhascos à beira-mar em um parque de diversões próspero. - - -STR_SCNR :Parque dos Três Macacos -STR_PARK :Parque dos Três Macacos -STR_DTLS :No centro deste grande parque em crescimento está a grande montanha-russa de aço de corrida tripla. - - -STR_SCNR :Minas Canárias -STR_PARK :Minas Canárias -STR_DTLS :Esta mina abandonada já tem os ingredientes de uma atração turística com sua ferrovia em miniatura e um par de montanhas-russas de queda vertical. - - -STR_SCNR :Ponte Baronato -STR_PARK :Ponte Baronato -STR_DTLS :Uma velha ponte redundante é sua para transformar em um parque de diversões. - - -STR_SCNR :Divertopia -STR_PARK :Divertopia -STR_DTLS :Cobrindo terra em ambos os lados de uma estrada, este parque já tem vários brinquedos em operação. - - -STR_SCNR :Porto Assombrado -STR_PARK :Porto Assombrado -STR_DTLS :A autoridade local concordou em vender barato o terreno para este pequeno parque litorâneo, com a condição de que certos brinquedos são preservados. - - -STR_SCNR :Fortaleza Divertida -STR_PARK :Fortaleza Divertida -STR_DTLS :Este castelo é todo seu para transformar em um parque temático. - - -STR_SCNR :Mundo Futurista -STR_PARK :Mundo Futurista -STR_DTLS :Este parque futurista tem muito espaço para novas atrações em sua paisagem alienígena. - - -STR_SCNR :Vale Gentil -STR_PARK :Vale Gentil -STR_DTLS :A população local prefere atrações calmas e relaxantes, então é seu trabalho expandir este parque para suprir o gosto dela. - - -STR_SCNR :Selva da Alegria -STR_PARK :Selva da Alegria -STR_DTLS :Selva adentro jaz uma grande área pronta para ser transformada em um parque temático. - - -STR_SCNR :Colinas Hídricas -STR_PARK :Colinas Hídricas -STR_DTLS :Uma série de lagos íngremes formam a base para este novo parque. - - -STR_SCNR :Parque Animado -STR_PARK :Parque Animado -STR_DTLS :Este parque ancião tem muitas atrações históricas, mas está muito endividado. - - -STR_SCNR :Áreas Mágicas -STR_PARK :Áreas Mágicas -STR_DTLS :Uma grande área foi limpa e parcialmente tematizada pronta para você desenvolver um parque temático. - - -STR_SCNR :Fazenda de Frutas -STR_PARK :Fazenda de Frutas -STR_DTLS :Uma próspera fazenda de frutas construiu uma ferrovia para acelerar sua receita, seu trabalho é transformá-la em um parque de diversões desenvolvido. - - -STR_SCNR :Barragem da Borboleta -STR_PARK :Barragem da Borboleta -STR_DTLS :A área envolta de uma barragem está disponível para você desenvolver um parque de diversões. - - -STR_SCNR :Atração no Desfiladeiro -STR_PARK :Atração no Desfiladeiro -STR_DTLS :Um vasto desfiladeiro é todo seu para transformar em um parque temático. - - -STR_SCNR :Parque Trovoada -STR_PARK :Parque Trovoada -STR_DTLS :O clima é tão molhado aqui que uma pirâmide gigantesca foi construída para permitir que alguns brinquedos fossem construídos cobertos. - - -STR_SCNR :Colinas Harmônicas -STR_PARK :Colinas Harmônicas -STR_DTLS :A autoridade local não te permite construir acima da altura das árvores neste parque. - - -STR_SCNR :Vila Romana -STR_PARK :Vila Romana -STR_DTLS :Desenvolva um parque com tema romano adicionando brinquedos e montanhas-russas. - - -STR_SCNR :Angra do Pântano -STR_PARK :Angra do Pântano -STR_DTLS :Construído parcialmente em uma série de pequenas ilhas, este parque já tem um par de grandes montanhas-russas como sua peça central. - - -STR_SCNR :Picos da Adrenalina -STR_PARK :Picos da Adrenalina -STR_DTLS :Construa um parque para apelar às pessoas locais buscadoras de emoção de alta intensidade. - - -STR_SCNR :Parque Utopia -STR_PARK :Utopia -STR_DTLS :Um oásis no meio de um deserto fornece uma oportunidade incomum de construir um parque de diversões. - - -STR_SCNR :Picos Apodrecidos -STR_PARK :Picos Apodrecidos -STR_DTLS :Repleto de vegetação e delapidado, você consegue fazer este parque de diversões que já foi grande ressurgir? - - -STR_SCNR :Floresta Fiasco -STR_PARK :Floresta Fiasco -STR_DTLS :Cheio de brinquedos perigosos e mal projetados, você tem um orçamento muito limitado, tempo para consertar os problemas e transformar este parque. - - -STR_SCNR :Parque dos Picles -STR_PARK :Parque dos Picles -STR_DTLS :A autoridade local não permite qualquer tipo de campanha publicitária ou promoções, então este parque deve ser um sucesso só pela reputação. - - -STR_SCNR :Colinas do Riso -STR_PARK :Colinas do Riso -STR_DTLS :Uma corrida de obstáculos quádrupla é a peça central deste parque em expansão. - - -STR_SCNR :Parque Mineral -STR_PARK :Parque Mineral -STR_DTLS :Transforme esta pedreira abandonada em um lugar para atrair turistas caçadores de emoções. - - -STR_SCNR :Encostas Loucas -STR_PARK :Encostas Loucas -STR_DTLS :Você tem fundos limitados, mas tempo ilimitado para transformar esta área montanhosa em um vasto parque de montanha-russa. - - -STR_SCNR :Parque Urbano -STR_PARK :Parque Urbano -STR_DTLS :Um parque minúsculo fez um acordo com a cidade vizinha para permitir a expansão através da própria cidade. - - -STR_SCNR :Jardins Geoffrey -STR_PARK :Jardins Geoffrey -STR_DTLS :Um grande parque de jardim precisa ser transformado em um próspero parque temático. - - -## Loopy Landscapes - -STR_SCNR :Ilhas Iceberg -STR_PARK :Ilhas Iceberg -STR_DTLS :Uma coleção de icebergs faz um ambiente frio para este ambicioso parque temático. - - -STR_SCNR :Vulcânia -STR_PARK :Vulcânia -STR_DTLS :Um vulcão dormente é o ambiente para este desafio de construção de montanha-russa. - - -STR_SCNR :Picos Áridos -STR_PARK :Picos Áridos -STR_DTLS :Livre de qualquer limite financeiro, seu desafio é desenvolver este parque desértico enquanto mantém os visitantes felizes. - - -STR_SCNR :Pedras de Navalha -STR_PARK :Pedras de Navalha -STR_DTLS :Sua tarefa é construir um parque repleto de montanhas-russas no meio das Pedras de Navalha. - - -STR_SCNR :Lago da Cratera -STR_PARK :Lago da Cratera -STR_DTLS :Um grande lago numa cratera anciã é o ambiente para este parque. - - -STR_SCNR :Visões de Vertigem -STR_PARK :Visões de Vertigem -STR_DTLS :Este grande parque já tem uma excelente hipermontanha-russa, mas sua tarefa é aumentar massivamente seu lucro. - - -STR_SCNR :Cais do Paraíso 2 -STR_PARK :Cais do Paraíso 2 -STR_DTLS :O Cais do Paraíso expandiu sua rede de passarelas sobre o mar, e sua tarefa é expandir o parque para usar o espaço extra. - - -STR_SCNR :Enseada do Dragão -STR_PARK :Enseada do Dragão -STR_DTLS :Esta enseada à beira-mar é o ambiente para este desafio de construção de montanha-russa. - - -STR_SCNR :Parque do Bom Cavaleiro -STR_PARK :Parque do Bom Cavaleiro -STR_DTLS :Um castelo com um par de montanhas-russas precisa ser desenvolvido em um parque temático maior. - - -STR_SCNR :Tocas Malucas -STR_PARK :Tocas Malucas -STR_DTLS :Um parque que tem boa parte de seus caminhos e montanhas-russas subterrâneos. - - -STR_SCNR :Grande Geleira -STR_PARK :Grande Geleira -STR_DTLS :Um vale cheio de geleira é seu para desenvolver um parque temático. - - -STR_SCNR :Crateras Loucas -STR_PARK :Crateras Loucas -STR_DTLS :Em um mundo muito distante onde dinheiro não é necessário, você deve construir um centro de entretenimento para manter as pessoas felizes. - - -STR_SCNR :Deserto Empoeirado -STR_PARK :Deserto Empoeirado -STR_DTLS :Cinco montanhas-russas requerem ser terminadas neste parque desértico. - - -STR_SCNR :Parque da Minhoca da Madeira -STR_PARK :Parque da Minhoca da Madeira -STR_DTLS :Neste parque histórico só é permitido construir atrações no estilo antigo. - - -STR_SCNR :Parque de Ícaro -STR_PARK :Parque de Ícaro -STR_DTLS :Desenvolva este parque alienígena para maximizar seu lucro. - - -STR_SCNR :Pântanos Ensolarados -STR_PARK :Pântanos Ensolarados -STR_DTLS :Este parque de diversões bem tematizado já tem vários brinquedos e muito espaço para expansão. - - -STR_SCNR :Colinas do Medo -STR_PARK :Colinas do Medo -STR_DTLS :Um parque assustador com uma montanha-russa gigantesca como peça central. - - -STR_SCNR :Rochas do Trovão -STR_PARK :Rochas do Trovão -STR_DTLS :Dois grandes pedaços de pedra saem da areia, sobre os quais o início de um parque temático é construído. - - -STR_SCNR :Parque Octogonal -STR_PARK :Parque Octogonal -STR_DTLS :Neste grande parque você deve projetar e construir dez grandes montanhas-russas. - - -STR_SCNR :Ilha do Prazer -STR_PARK :Ilha do Prazer -STR_DTLS :Uma longa ilha fina fornece um cenário desafiador para construir uma seleção de montanhas-russas. - - -STR_SCNR :Mundo das Estalactites e Estalagmites -STR_PARK :Mundo das Estalactites e Estalagmites -STR_DTLS :Uma paisagem congelante precisa ser transformada em um parque temático próspero. - - -STR_SCNR :Areias do Sul -STR_PARK :Areias do Sul -STR_DTLS :Um parque desértico com algumas montanhas-russas projetadas com inteligência é seu para expandir. - - -STR_SCNR :Pequenas Torres -STR_PARK :Pequenas Torres -STR_DTLS :Neste parque minúsculo você deve terminar de construir cinco montanhas-russas existentes. - - -STR_SCNR :Parque do Nunca -STR_PARK :Parque do Nunca -STR_DTLS :Um grande parque com um novo sistema de transporte envolta de sua borda. - - -STR_SCNR :Ilha Pacífica -STR_PARK :Ilha Pacífica -STR_DTLS :Esta grande ilha é toda sua para desenvolver um parque de diversões. - - -STR_SCNR :Selva Urbana -STR_PARK :Selva Urbana -STR_DTLS :Um gigante arranha-céu abandonado é a oportunidade única para um desenvolvedor de parque temático. - - -STR_SCNR :Cidade do Terror -STR_PARK :Cidade do Terror -STR_DTLS :Esta área urbana é toda sua para desenvolver um parque de diversões. - - -STR_SCNR :Parque Megalândia -STR_PARK :Parque Megalândia -STR_DTLS :Um grande parque empacotado com muitos brinquedos precisa de melhoras. - - -STR_SCNR :Lagoas de Vênus -STR_PARK :Lagoas de Vênus -STR_DTLS :Em um planeta distante, esta área precisa ser transformada em um parque temático. - - -STR_SCNR :Microparque -STR_PARK :Microparque -STR_DTLS :Tente criar o menor parque mais lucrativo do mundo. - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Parque Heide -STR_PARK :Parque Heide -STR_DTLS : - - -STR_SCNR :Praia do Prazer em Blackpool -STR_PARK :Praia do Prazer em Blackpool -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Castelo Anacronismo -STR_PARK :Castelo Anacronismo -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Telhado -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Aventuras Alpinas -STR_PARK :Aventuras Alpinas -STR_DTLS :Converta um pequeno resort de ski de montanha em um parque de diversões com tema de neve - - -STR_SCNR :Aeroporto da Amizade -STR_PARK :Aeroporto da Amizade -STR_DTLS :Construa um parque de diversões com tema voador nesse aeroporto abandonado - - -STR_SCNR :Invasores Botânicos -STR_PARK :Invasores Botânicos -STR_DTLS :Seu desafio é construir um parque altamente lucrativo nessa ilha paradisíaca - - -STR_SCNR :Construa seu próprio Six Flags Bélgica -STR_PARK :Six Flags Bélgica -STR_DTLS :Construa sua própria versão deste parque Six Flags europeu - - -STR_SCNR :Construa sua própria Grande Aventura Six Flags -STR_PARK :Grande Aventura Six Flags -STR_DTLS :Use suas habilidades de design para recriar este parque Six Flags - - -STR_SCNR :Construa seu próprio Six Flags Holanda -STR_PARK :Six Flags Holanda -STR_DTLS :Construa esse parque Six Flags europeu do jeito que você quiser - - -STR_SCNR :Construa sua própria Montanha Mágica Six Flags -STR_PARK :Montanha Mágica Six Flags -STR_DTLS :Crie sua própria versão desse grande parque Six Flags - - -STR_SCNR :Construa seu próprio Six Flags no Texas -STR_PARK :Six Flags no Texas -STR_DTLS :Começando do zero, construa os brinquedos nesse parque Six Flags - - -STR_SCNR :Construa seu próprio Parque Six Flags -STR_PARK :Six Flags -STR_DTLS :Construa seu próprio design do parque Six Flags - Ou construa atrações de outros parques Six Flags ou projete e construa suas próprias atrações - - -STR_SCNR :Bazar Bamba -STR_PARK :Bazar Bamba -STR_DTLS :Começando com um pequeno mercado de bazar, seu desafio é aumentar o lucro das lojas e barracas construindo brinquedos e montanhas-russas para atrair mais visitantes - - -STR_SCNR :Castelo Maluco -STR_PARK :Castelo Maluco -STR_DTLS :Você herdou um grande castelo - Seu trabalho é convertê-lo em um pequeno parque temático - - -STR_SCNR :Gramados Solitários -STR_PARK :Gramados Solitários -STR_DTLS :Situado perto de uma junção de rodovias no deserto, Gramados Solitários é uma oportunidade para desenvolver um pequeno resort de golfe em um próspero parque temático - - -STR_SCNR :Campos Elétricos -STR_PARK :Campos Elétricos -STR_DTLS :Você herdou uma pequena fazenda, e seu desafio é construir um pequeno parque temático entre os campos e prédios da fazenda - - -STR_SCNR :Alturas Radicais -STR_PARK :Alturas Radicais -STR_DTLS :Livre de restrições financeiras, seu desafio é expandir este parque deserto para atrair pessoas que procuram fortes emoções - - -STR_SCNR :Loucuras na Fábrica -STR_PARK :Loucuras na Fábrica -STR_DTLS :Um complexo de fábricas abandonado é uma oportunidade para construir um parque de diversões com tema mecânico - - -STR_SCNR :Bosque dos Cogumelos -STR_PARK :Bosque dos Cogumelos -STR_DTLS :Restrito a apenas brinquedos de madeira de estilo antigo, seu desafio é construir um próspero parque temático no Bosque dos Cogumelos - - -STR_SCNR :Cidade Fantasma -STR_PARK :Cidade Fantasma -STR_DTLS :Contratado por uma grande cadeia de parques de diversões, sua tarefa é construir para eles um grande parque de montanha-russa em volta de uma cidade mineira abandonada - - -STR_SCNR :Jardins de Gravidade -STR_PARK :Jardins de Gravidade -STR_DTLS :Seu desafio é construir um parque de montanha russa no belo Jardins de Gravidade - Nenhum outro brinquedo, apenas montanhas-russas! - - -STR_SCNR :Visões Infernais -STR_PARK :Visões Infernais -STR_DTLS :Um parque precariamente aninhado em pedras de lava com vapores de magma - - -STR_SCNR :Lago da Sorte -STR_PARK :Lago da Sorte -STR_DTLS :Com fundos ilimitados, mas com uma localização desafiadora no lago, este parque será um desafio para expandir e gerenciar - - -STR_SCNR :Cúpula do Arco-Íris -STR_PARK :Cúpula do Arco-Íris -STR_DTLS :Construído numa encosta, este parque é proibido de construir qualquer coisa alta. Você consegue expandir o parque e torná-lo bem-sucedido? - - -STR_SCNR :Six Flags Bélgica -STR_PARK :Six Flags Bélgica -STR_DTLS :Tente gerir e melhorar este parque Six Flags - - -STR_SCNR :Grande Aventura Six Flags -STR_PARK :Grande Aventura Six Flags -STR_DTLS :Construa os brinquedos Six Flags que faltam, ou crie seus próprios projetos para melhorar o parque! Mas não esqueça seu objetivo principal - Atrair mais visitantes para o parque! - - -STR_SCNR :Six Flags Holanda -STR_PARK :Six Flags Holanda -STR_DTLS :Tente gerir e melhorar este parque Six Flags - - -STR_SCNR :Montanha Mágica Six Flags -STR_PARK :Montanha Mágica Six Flags -STR_DTLS :Construa os brinquedos Six Flags que faltam, ou crie seus próprios projetos para melhorar o parque! Mas não esqueça seu objetivo principal - Pagar seu empréstimo enquanto mantém o valor do parque alto! - - -STR_SCNR :Six Flags no Texas -STR_PARK :Six Flags no Texas -STR_DTLS :Construa os brinquedos Six Flags que faltam, ou crie seus próprios projetos para melhorar o parque! Mas não esqueça seu objetivo principal - Atrair mais visitantes para o parque! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Minas da África -STR_PARK :Minas da África -STR_DTLS :Você herdou uma mina de diamante fora de uso, e encontra um diamante valioso. Você decide investir este dinheiro para construir um parque temático famoso mundialmente. - - -STR_SCNR :Loucuras da Miragem -STR_PARK :Loucuras da Miragem -STR_DTLS :Um Oásis deserto foi encontrado e proporcionaria uma bela localização para um parque. Transporte para o oasis foi fornecido. - - -STR_SCNR :No limite -STR_PARK :No limite -STR_DTLS :Uma barreira foi construída oferecendo energia hidroelétrica barata e abundante com a qual funcionará um parque. Você precisa atingir um alto valor de parque para ajudar a reembolsar o empréstimo para a barreira. - - -STR_SCNR :Aventuras Geladas -STR_PARK :Aventuras Geladas -STR_DTLS :Ajude a agência de ambiente a transformar uma grande e velha refinaria ecológica de petróleo em atração turística de alto nível. Terrenos baratos, mas juros do empréstimo não. Pode-se vender os prédios velhos para melhorar a situação. - - -STR_SCNR :Grande Muralha da China -STR_PARK :Grande Muralha da China -STR_DTLS :As autoridades decidiram melhorar o turismo em volta da Grande Muralha construindo um parque no terreno ao lado. Dinheiro não é o problema! - - -STR_SCNR :Costa de Okinawa -STR_PARK :Costa de Okinawa -STR_DTLS :Um parque já existente ficou sem espaço. Sua única opção é construir em cima do mar, e também você pegou um empréstimo. Restrições de altura nas suas construções são obrigatórias por causa das fundações e riscos de terremotos. - - -STR_SCNR :Parque do Marajá -STR_PARK :Parque do Marajá -STR_DTLS :Você foi contratado pelo Marajá para trazer entretenimento para a grande população local. Construa um parque inspirado no palácio Mahajara. - - -STR_SCNR :Aventura Uluru -STR_PARK :Aventura Uluru -STR_DTLS :Você está ajudando os aborígenes a construir um parque como parte do programa de conscientização cultural. Você precisa conseguir um grande número de visitantes para educá-los no patrimônio único dos aborígenes. - - -STR_SCNR :Explosão de Churrasco na Praia -STR_PARK :Explosão de Churrasco na Praia -STR_DTLS :Um empreendimento local de parque de vida marinha foi derrubado. Você já opera um pequeno parque e compra o outro parque da companhia de construção. Desenvolva um grande parque combinado. - - -STR_SCNR :Extravagância Europeia -STR_PARK :Extravagância Europeia -STR_DTLS :Você foi trazido para controlar uma Atração Cultural Europeia do Visitante e deve aumentar o número de visitantes a fim de reembolsar o subsídio da União Europeia no fim do mandato atual do Parlamento Europeu. - - -STR_SCNR :Das Cinzas -STR_PARK :Das Cinzas -STR_DTLS :Um velho parque caiu em ruínas. Você ganha uma concessão da União Europeia para retornar essa área privada à sua antiga glória! Você precisa renovar o parque e reembolsar a concessão. - - -STR_SCNR :Waikiki Maluca -STR_PARK :Waikiki Maluca -STR_DTLS :As pessoas do Havaí estão entediadas de surfar e estão procurando por algo mais intenso. Você precisa construir um parque com isto em mente para manter a atração turística da área com classificação alta. - - -STR_SCNR :Calamidades do Canyon -STR_PARK :Calamidades do Canyon -STR_DTLS :Você tem que construir um parque num terreno limitado nos dois lados desse tesouro natural - tenha a oportunidade de comprar terrenos vizinhos dos Índios Nativos Americanos. Você precisa completar o objetivo para suprir a população da cidade local. - - -STR_SCNR :Paraíso da Montanha-Russa -STR_PARK :Paraíso da Montanha-Russa -STR_DTLS :Você é um bem-sucedido magnata dos negócios em longas férias que deseja usar esse tempo transformando o parque da cidade em um Céu de Montanha-Russa. Dinheiro não é o problema! - - -STR_SCNR :Fundadação da Cidade Perdida -STR_PARK :Fundadação da Cidade Perdida -STR_DTLS :Para dar um impulso adicional ao turismo local você deve construir um parque que está em sintonia com seus arredores. - - -STR_SCNR :Diversão na Floresta -STR_PARK :Diversão na Floresta -STR_DTLS :Espaço é limitado nessa preciosa floresta tropical - você deve amontoar o máximo possível na clareira existente, a fim de prover uma alternativa viável para a indústria madeireira local. - - -STR_SCNR :Praia do Pão de Açúcar -STR_PARK :Praia do Pão de Açúcar -STR_DTLS :Você gere um pequeno parque perto do Rio, mas o banco convocou o seu empréstimo. Você precisa aumentar rapidamente a sua capacidade de ganhos para reembolsar este débito inesperado. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Castelo Cliffside -STR_PARK :Castelo Cliffside -STR_DTLS :Membros locais da sociedade de reconstituição da batalha são bastante sérios acerca de seus hobbies. Eles lhe confiaram o trabalho de construir um parque temático da Idade das Trevas nos terrenos do Castelo Cliffside. - - -STR_SCNR :Floresta de Sherwood -STR_PARK :Floresta de Sherwood -STR_DTLS :Para liberar a riqueza dos ricos e distribuir para os necessitados, você e seus seguidores decidiram construir um parque temático na Floresta de Sherwood. - - -STR_SCNR :Extravagância Extraterrestre -STR_PARK :Extravagância Extraterrestre -STR_DTLS :Vida foi descoberta em um planeta distante. Construa um parque temático alienígena para ganhar dinheiro com a onda de juros sem precedentes. - - -STR_SCNR :Cidade Gemini -STR_PARK :Cidade Gemini -STR_DTLS :Mostre sua inventiva, utópica visão do futuro - mostre um projeto futurista de parque que incorpore atrações de ponta. - - -STR_SCNR :Travessuras Animatrônicas -STR_PARK :Travessuras Animatrônicas -STR_DTLS :Você foi designado para gerir e melhorar um parque temático existente, que foi construído num velho set de filme. Faça um tributo aos animadores pioneiros de stop-motion, os primeiros a trazer criaturas míticas à vida na tela prateada. - - -STR_SCNR :Loucura Mitológica -STR_PARK :Loucura Mitológica -STR_DTLS :Você é dono de uma ilha de valor arqueológico particular. Você decidiu financiar sua preservação construindo um parque temático baseado no rico patrimônio Mitológico da área. - - -STR_SCNR :Diversão na Cratera -STR_PARK :Diversão na Cratera -STR_DTLS :Você é dono de uma velha cratera de meteoro empoeirada. No verdadeiro espírito empreendedor, você decidiu construir um parque temático de asteroide e converta seu terreno aparentemente sem valor em uma grande fortuna. - - -STR_SCNR :Parquessauro -STR_PARK :Parquessauro -STR_DTLS :Você recebeu a tarefa de construir um parque temático da Era Jurássica. Para otimizar o acesso de seus visitantes para a exibição de plantas e animais exóticos, você precisará construir brinquedos envolta e dentro do vale. - - -STR_SCNR :Passeio Rochoso -STR_PARK :Passeio Rochoso -STR_DTLS :Frustre os construtores da rodovia e preserve os misteriosos círculos de pedra antigos ao construir um parque temático da Idade da Pedra e lucrar. No entanto, atrair visitantes pode ser desafiador, já que o terreno é um pouco inóspito. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :A infame Ilha da Prisão - cuja população uma vez inchou com contrabandistas e estragos - agora está à venda. Você decidiu convertê-la em uma atração turística de alto nível, e dinheiro não é o problema. - - -STR_SCNR :Praia Schneider -STR_PARK :Praia Schneider -STR_DTLS :O 75º aniversário da vitória do seu avô na Copa Schneider está chegando em alguns anos. Você vai honrar a conquista dele construindo um parque temático baseado na famosa corrida de hidroavião. - - -STR_SCNR :Metrópole -STR_PARK :Metrópole -STR_DTLS :Você é dono de um lote vazio perto da parte baixa da cidade. Para espremer o máximo de sua propriedade urbana, construa um parque temático arranha-céu inspirado pela arquitetura Art Déco crescente dos anos vinte. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Um grande festival anual de música acontece em seu terreno. Construa um parque temático moderno para manter a audiência de espírito livre entretida. - - -STR_SCNR :Renascimento do Rock ’n’ Roll -STR_PARK :Renascimento do Rock ’n’ Roll -STR_DTLS :Este parque temático envelhecido já viu dias melhores. Ajude o dono dar uma aparência rock ’n’ roll retrô e transforme o lugar em um local bem-sucedido. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Mundo Panda -STR_PARK :Mundo Panda -STR_DTLS :Adicione mais atrações e atraia mais pessoas a esse parque com temática panda - - -STR_SCNR :Parque Tycoon -STR_PARK :Parque Tycoon -STR_DTLS : - -### - -STR_SCNR :Cemetery Ridge -STR_PARK :Cemetery Ridge -STR_DTLS :É Halloween, Halloween do UCES, abóboras gritam na calada da noite! Esse cemitério está em apuros e cabe a você salvá-lo enquanto deixa os mortos descansarem em paz! Você consegue manter os fantasmas em seus túmulos e dar calafrios aos seus clientes?{NEWLINE}Autor: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :O Farol de Alexandria -STR_PARK :O Farol de Alexandria -STR_DTLS :Alexandre construiu a cidade; Gregos, romanos, egípcios deixaram suas marcas. Mas a maior honra foi um monumento do mundo antigo - o farol. Visite e faça um parque!{NEWLINE}Autor: Katatude - - -STR_SCNR :Luna Park, Cleveland -STR_PARK :Luna Park -STR_DTLS :Como estava no seu dia de inauguração - 18 de maio de 1905.{NEWLINE}Autor: Aetherwave - - -STR_SCNR :Monte Vesúvio -STR_PARK :Monte Vesúvio -STR_DTLS :Pompeia e Herculano foram soterradas pelo Monte Vesúvio em 79 d.C. Visite as escavações e construa um parque!{NEWLINE}Autor: Katatude - - -STR_SCNR :A Caixa de Areia -STR_PARK :A Caixa de Areia -STR_DTLS :O que todos querem: uma caixa de areia! Então pegue seu baldinho e sua pá e construa um parque!{NEWLINE}Autor: Katatude - - -STR_SCNR :Cataratas e Desfiladeiro do Niágara -STR_PARK :Cataratas do Niágara -STR_DTLS :Cataratas Americanas, Cataratas “Véu da Noiva” & Cataratas “Ferradura” na fronteira Niágara, 1850.{NEWLINE}Autor: Katatude - - -STR_SCNR :Mineradores da Montanha Rochosa -STR_PARK :Mineradores da Montanha Rochosa -STR_DTLS :Um deslizamento de pedras danificou sua linha de trem. Seus trabalhadores saíram para explorar. Há ouro em montanhas-russas?{NEWLINE}Autores: Squid, Buckone, Fossil - - -STR_SCNR :A Máquina do Tempo -STR_PARK :A Máquina do Tempo -STR_DTLS :A Máquina do Tempo. Construa para ir: quando quiser, aonde quiser. A eternidade espera. É tudo relativo.{NEWLINE}Autor: Katatude - - -STR_SCNR :Torre de Babel -STR_PARK :Torre de Babel -STR_DTLS :Eita! Olha aonde a máquina do tempo nos trouxe agora! Aonde foram todos?{NEWLINE}Autor: Fossil - - -STR_SCNR :Transformação -STR_PARK :Transformação -STR_DTLS :Estávamos te esperando…{NEWLINE}Autor: Fossil - - -STR_SCNR :Urbis Incognitus -STR_PARK :Urbis Incognitus -STR_DTLS :Os romanos estão cansados de lutas entediantes de gladiadores. Dê a eles algo mais emocionante, transforme uma cidade romana no maior parque de diversões de todos os tempos!{NEWLINE}Autor: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Debaixo da Árvore de Natal -STR_PARK :Inverno das Maravilhas -STR_DTLS :Mamãe construiu esse cenário debaixo de nossa árvore. Agora ela quer um parque feito nele! Você pode ajudar?{NEWLINE}Autor: Katatude - - -STR_SCNR :Explosão de Pedragrande -STR_PARK :Explosão de Pedragrande -STR_DTLS :Após uma explosão na Companhia de Mineração de Pedragrande, as pessoa de Pedragrande tem de construir um parque de diversões para manter sua cidade viva.{NEWLINE}Autores: rbarclay & buckone - - -STR_SCNR :Acampamento Sabiá -STR_PARK :Acampamento Sabiá -STR_DTLS :Apenas R$500/semana para esse acampamento de verão! Abra sua carteira e se divirta construindo um parque.{NEWLINE}Autor: Katatude - - -STR_SCNR :Cidade do Piuí -STR_PARK :Cidade do Piuí -STR_DTLS :Mamãe! Papai! Quero ir pra Cidade do Piuí!{NEWLINE}Autor: Fossil - - -STR_SCNR :Ilhas do Dragão -STR_PARK :Ilhas do Dragão -STR_DTLS :Ilhas do Dragão? Não tenho certeza se quero ir lá…{NEWLINE}Autor: Fossil - - -STR_SCNR :Kiddie Karnival II -STR_PARK :Kiddie Karnival -STR_DTLS :Ei crianças! Vamos nos divertir!{NEWLINE}Autores: Piehead & Fossil - - -STR_SCNR :Duna de Areia -STR_PARK :Duna de Areia -STR_DTLS :Como o dono de um pequeno parque, você comprou um grande terreno ao longo da praia para expandir e atrair mais visitantes para visitar as lindas dunas de areia, mas cuidado: você não pode perturbar essas dunas de areia frágeis ecologicamente.{NEWLINE}Autor: rbarclay diff --git a/data/language/ru-RU.txt b/data/language/ru-RU.txt index f6deee16b8..47345cde78 100644 --- a/data/language/ru-RU.txt +++ b/data/language/ru-RU.txt @@ -2667,303 +2667,3 @@ STR_6164 :{WHITE}❌ # This language is unmaintained. All untranslated strings have been removed. # If you intend to become the maintainer, please copy the missing strings from en-GB.txt and translate them. - -######### -# Parks # -######### - -## Original -## RCT2 Original - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Превратите горнолыжный курорт в тематический парк развлечений. - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Постройте парк на территории заброшенного аэродрома. - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Вы должны построить прибыльный парк на этом райском острове. - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Вы должны добиться увеличения прибыли небольшого базара за счет строительства аттракционов и привлечения покупателей. - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :Вы унаследовали большой замок. Превратите его в уютный тематический парк. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Вам предлагается превратить небольшое поле для гольфа Дасти Гринз в тематический парк развлечений. - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :Вы унаследовали небольшую ферму и теперь должны построить тематический парк среди полей и лесов. - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Финансовых ограничений нет. Вы должны расширить пустынный парк и привлечь туристов. - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Заброшенный промышленный комплекс - отличное место для строительство парка развлечений. - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Задача - построить парк развлеченийв Грибном Лесу, используя только деревянные аттракционы. - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Ваша задача - построить гигантский парк американских горок вокруг заброшенного шахтерского городка. - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Ваша задача - построить парк аттракционов в прекрасных Висячих Садах. Стройте только американские горки! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :Парк, расположенный на скале из застывшей лавы. - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :Этот парк станет настоящим испытанием для самого опытного менеджера. - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :В этом парке нельзя строить ничего высокого. Попробуйте сделать этот парк успешным. - -## Real parks - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Попробуйте свои силы на этом парке Six Flags. - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Постройте недостающие аттракционы, или создайте парк по собственному плану! Но не забудьте - вы должны привлечь как можно больше гостей! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Попробуйте свои силы на этом парке Six Flags. - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Постройте недостающие аттракционы, или создайте собственный парк! Но не забудьте - вы должны выплатить кредит! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Постройте недостающие аттракционы, или создайте парк по собственному плану! Но не забудьте - вы должны привлечь как можно больше гостей! - -## Build your own - -STR_SCNR :Постройте свой парк Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Постройте свою версию европейского парка Six Flags. - - -STR_SCNR :Постройте свой парк Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Восстановите этот парк Six Flags. - - -STR_SCNR :Постройте свой парк Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Постройте этот европейский парк Six Flags. - - -STR_SCNR :Постройте свой парк Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Постройте собственную версию парка Six Flags. - - -STR_SCNR :Постройте свой парк Six Flags over Texas. -STR_PARK :Six Flags over Texas -STR_DTLS :Постройте аттракционы в этом парке Six Flags. - - -STR_SCNR :Постройте Парк Six Flags -STR_PARK :Six Flags -STR_DTLS :Постройте собственный парк Six Flags. Вы можете строить собственные аттракционы. - - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Шахты Африки -STR_PARK :Шахты Африки -STR_DTLS :Вы унаследовали алмазную шахту и нашли дорогой алмаз. Затем вы решили инвестировать деньги в тематический парк. - - -STR_SCNR :Мираж -STR_PARK :Мираж -STR_DTLS :Был открыт пустынный оазис, который может стать прекрасным местом для парка. Транспорт в оазис уже обеспечен. - - -STR_SCNR :Водопад -STR_PARK :Водопад -STR_DTLS :Была построена плотина, котор. дала дешёвую электроэнергию. Вам надо увеличить доходы парка, чтобы помочь выплатить заем за плотину. - - -STR_SCNR :Ледовый Мир -STR_PARK :Ледовый Мир -STR_DTLS :Агентство по охране природы обратилось к вам, чтобы попросить помощи в строительстве парка развлечений. Земля недорога, но процент по кредитам высок. Можете продавать старые постройки. - - -STR_SCNR :Великая стена -STR_PARK :Великая стена -STR_DTLS :Власти решили развивать туризм вокруг ВКС, построив тематический парк. Деньги - не проблема! - - -STR_SCNR :Окинава -STR_PARK :Окинава -STR_DTLS :Парку не хватает земли. Единственный шанс - строить в море, и вы берете заем. Высоту сооружений ограничивает фундамент и риск землетрясений. - - -STR_SCNR :Парк Магарадж -STR_PARK :Парк Магарадж -STR_DTLS :Вас выбрали развлекать людей вокруг Магараджи. Постройте парк в духе дворца Магараджей. - - -STR_SCNR :Приключение Айа -STR_PARK :Приключение Айа -STR_DTLS :Вы помогаете аборигенам построить парк, как часть культурной программы. Вам нужно привлечь большое число гостей и передать им уникальное наследие местной культуры. - - -STR_SCNR :Барбекю на Берегу -STR_PARK :Барбекю на Берегу -STR_DTLS :Местный морской парк потерпел банкротство. У вас уже есть небольшой парк и вы можете купить еще один у строительной компании. Создайте один общий парк. - - -STR_SCNR :Европейский Фестиваль -STR_PARK :Европейский Фестиваль -STR_DTLS :Вам передали в управление Европейский Культурный Центр. Вы должны увеличить число гостей и вернуть субсидию Евросоюза до начала парламентских выборов. - - -STR_SCNR :Возрождение -STR_PARK :Возрождение -STR_DTLS :Старый парк пришел в запустение. Вы получили грант Евросоюза и должны вернуть эту землю к былой славе! Необходимо обновить парк и выплатить грант. - - -STR_SCNR :Ваки Ваикики -STR_PARK :Ваки Ваикики -STR_DTLS :Населению Гаваев надоело заниматься сёрфингом и они желают что-нибудь более экстремальное. Вам надо построить парк, чтобы жители островов снова почувствовали вкус жизни! - - -STR_SCNR :Гранд Каньон -STR_PARK :Гранд Каньон -STR_DTLS :Вы должны построить парк на небольшом участке земли - у вас есть возможность покупать близлежащие территории у местных индейцев. Необходимо поддерживать население местного городка. - - -STR_SCNR :Горки в Небесах -STR_PARK :Горки в Небесах -STR_DTLS :Вы - успешный предприниматель и желаете сделать из городского парка Горки на Небесах. Деньги для вас - не проблема! - - -STR_SCNR :Город Инков -STR_PARK :Город Инков -STR_DTLS :Чтобы развивать местный туризм, вы должны создать парк в духе местных достопримечательностей. - - -STR_SCNR :Тропический Лес -STR_PARK :Тропический Лес -STR_DTLS :Место ограничено ценнейшими тропическими лесами - вы должны строить на существующей территории, чтобы не дать вырубать леса. - - -STR_SCNR :Сахарный Берег -STR_PARK :Сахарный Берег -STR_DTLS :У вас небольшой парк близ Рио, но банк требует вернуть кредит. Вам срочно нужно увеличить прибыли, чтобы вернуть долг. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Замок на Скале -STR_PARK :Замок на Скале -STR_DTLS :Члены местного исторического клуба серьезно увлечены своим хобби. Они уговаривают вас построить Парк развлечений на средневековую тематику на территории Старинного Замка. - - -STR_SCNR :Шервудский Лес -STR_PARK :Шервудский Лес -STR_DTLS :Чтобы отобрать деньги у богатых и отдать их беднякам, вы и ваши друзья-разбойники решили построить парк развлечений в Шервудском Лесу. - - -STR_SCNR :Фантастическая Феерия -STR_PARK :Фантастическая Феерия -STR_DTLS :На отдаленной планете была открыта жизнь. Постройте инопланетный тематический парк, чтобы заработать на сенсации. - - -STR_SCNR :Геминеи -STR_PARK :Геминеи -STR_DTLS :Покажите свое видение будущего - постройте тематический парк футуристической направленности с потрясающими аттракционами. - - -STR_SCNR :Студия Абсурда -STR_PARK :Студия Абсурда -STR_DTLS :Вам поставили задачу улучшить существующий тематический парк, построенный на месте старой киностудии. Сделайте акцент на мифических существах, которых оживили пионеры анимации. - - -STR_SCNR :Мифическое Безумство -STR_PARK :Мифическое Безумство -STR_DTLS :Вы владеете островом, имеющим особое археологическое значение. И решили построить парк развлечений, основанный на богатом мифологическом наследии острова. - - -STR_SCNR :Кратер -STR_PARK :Кратер -STR_DTLS :Вы владеете старым метеоритным кратером. И решаете превратить дешевую бесполезную землю в процветающее предприятие, построив тематический парк. - - -STR_SCNR :Брегозавр -STR_PARK :Брегозавр -STR_DTLS :Вам поставили задачу построить парк развлечений Юрского Периода. Для оптимизации доступа посетителей к экзотическим растениям и животным вам придется соорудить аттракционы, катающие людей по территории. - - -STR_SCNR :Деревня -STR_PARK :Деревня -STR_DTLS :Чтобы помешать дорожным строителям и сохранить таинственные каменные круги, вам придётся построить тематический парк каменного века и получить с него прибыль. Однако, местность вам досталась не особо гостеприимная. - - -STR_SCNR :Алкатрас -STR_PARK :Алкатрас -STR_DTLS :Безымянный тюремный остров, чье население раньше составляли контрабандисты и рэкетиры, сейчас выставлен на продажу. Вы решили превратить его в туристическую достопримечательность. - - -STR_SCNR :Кубок Шнайдера -STR_PARK :Кубок Шнайдера -STR_DTLS :Через несколько лет наступает 75я годовщина завоевания вашим дедушкой Кубка Шнайдера. Вы собираетесь отметить его достижение, построив тематический парк, посвящённый гонкам на гидросамолетах. - - -STR_SCNR :Метрополис -STR_PARK :Метрополис -STR_DTLS :Вы владеете пустырём в одном из районов города. Чтобы выжать из своей земли максимум, постройте парк развлечений в виде небоскрёба в духе двадцатых годов. - - -STR_SCNR :Цветник -STR_PARK :Цветник -STR_DTLS :На вашей земле проводится ежегодный музыкальный фестиваль. Постройте людям парк развлечений в духе музыки и свободы. - - -STR_SCNR :Рок-н-Ролл Жив -STR_PARK :Рок-н-Ролл Жив -STR_DTLS :Этот чудесный парк видел и лучшие дни. Помогите его владельцу улучшить дела и превратить парк в процветающее предприятие. diff --git a/data/language/sv-SE.txt b/data/language/sv-SE.txt index 5d8e79d5b0..cae9f1ba39 100644 --- a/data/language/sv-SE.txt +++ b/data/language/sv-SE.txt @@ -3730,761 +3730,3 @@ STR_6652 :Felmeddelande STR_6653 :Alla källor visas STR_6654 :Visar {POP16}{UINT16} källor STR_6655 :Endast ‘{POP16}{STRINGID}’ - -############# -# Scenarion # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Djupt inne i skogen ska du bygga en utgrenande nöjespark i en stor öppen glänta - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Bygg i den varma ökenhettan, detta nöjesfält har bara en berg- och dalbana men har plats för utveckling - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Börja från grunden med att bygga ett nöjesfält runt en stor sjö - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights är redan en framgångsrik nöjespark – utveckla den för att dubbla värdet - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Gör om den vackra trädgården till en spännande nöjespark - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Utveckla Bumbly Beachs lilla nöjespark nära stranden till en spännande turistattraktion - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Flera små öar som är till för att bygga en megapark - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :Ett litet nöjesfält som behöver fräschas upp och utökas – Ditt mål är att dubbla parkvärdet - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :En liten, trång nöjespark som behöver en stor uppfräschning och utvidgning - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :En park med fantastiska vattenattraktioner som behöver utökas - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Bygg om en stor övergiven gruva till ett stort nöjesfält - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :En stor park gömd i skogen, med endast gokarter och träberg- och dalbanor - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :Detta nöjesfält har några moderna karuseller, men med massor av plats för utökning - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :Bygg ett nöjesfält från grunden i den bergiga skogen Mystic Mountain - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Förvandla de egyptiska ruinerna till en spännande nöjespark - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :En stor park med väldesignade, men åldrande attraktioner – Byt ut de gamla eller skaffa nya för att göra parken mer populär - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Förvandla denna trötta pir till en livlig attraktion - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :De vackra bergen vid Lightning Peaks är populära bland fotgängare och äventyrare – Använd marken för att attrahera nya spänningssökande besökare - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :En välgrundad park som har några problem - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Rainbow Valleys lokala myndighet tillåter inga landändringar eller stora trädfällningar, men du måste göra en stor park av marken ändå - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock ligger i mitten av öknen och attraherar många turister – Använd den tillgängliga marken för att locka fler turister - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :För skojs skull! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Utveckla havskustens klippor till en spännande nöjespark - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :I centrum av denna stora, växande park finns ett trespårig racingberg- och dalbana i stål - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Denna övergivna gruva har redan några få turistattraktioner som en miniatyrtågbana och ett par berg- och dalbanor - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :En gammal övergiven bro som du får förvandla till ett nöjesfält - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Utsträckande mark på båda sidor av en motorväg, denna park har ett flertal åkturer igång - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :Den lokala myndigheten har givit tillåtelse att sälja land i närheten billigt till denna lilla sjösatta park, på villkoret att vissa åkturer är bevarade - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Detta slott är ditt att förvandla till ett nöjesfält - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Denna futuristiska park har massor med plats för nya åkturer i dess rymdlandskap - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :Den lokala befolkningen föredrar lugna attraktioner, det är ditt jobb att bygga ut denna park med deras behov i åtanke - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Djupt in i djungeln ligger en öppen mark och väntar på att bli förvandlad till ett nöjesfält - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :En serie av sjöar och berg formar grunden till detta nöjesfält - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Denna åldrande park har mycket historia, men är också djupt skuldsatt - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Ett stort landområde har blivit rensat och delvis tematiserat, redo att utvecklas till en anlagd temapark - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :En populär fruktfarm har byggt en järnväg för att öka sin inkomst, ditt jobb är att förvandla det till en spektakulär nöjespark - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Området runt dammen är ditt för att skapa ett nöjesfält - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :En stor ravin som är din för att byggas till ett nöjesfält - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :Vädret är så vått att den stora pyramiden byggdes för att skydda attraktioner från regnet - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :Den lokala myndigheten tillåter dig inte att bygga högre än trädtopparna i denna park - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Utveckla denna romerska park genom att utöka den - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Denna park byggd på små öar har redan några berg- och dalbanor - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Bygg en park för den intensitets- och spänningssökande lokala befolkningen - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :En oas i mitten av öknen skapar en ovanlig chans till att bygga en nöjespark - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Igenvuxet och förfallet, kan du återuppliva detta övergivna nöjesfält? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Parken är full av dåliga och farliga berg- och dalbanor, och du har en väldigt tajt budget att fixa problemen och vända den tillbaka till det positiva - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :De lokala myndigheterna tillåter ingen reklam eller marknadsföring, så denna park måste klara sig på sitt rykte - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :En hästbana för hinderlöpning är i centrum för denna växande park - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Förvandla detta övergivna stenbrott till en plats som lockar spänningssökande turister - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Du har begränsade resurser men oändligt med tid att förvandla denna klippsida till en stor park med många berg- och dalbanor - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :En liten park som har gjort en uppgörelse med staden som tillåter byggnationer genom staden - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :En stor trädgård måste förvandlas till ett spännande nöjesfält - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :En samling av isberg i detta kalla klimat ska förvandlas till ett nöjesfält - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :En utdöd vulkan är grunden till denna utmanande park som ska fyllas med berg- och dalbanor - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Din utmaning är att, fri från finansiella gränser, utöka denna ökenpark medan du håller besökarna glada - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Ditt mål är att bygga en stor berg- och dalbanepark mellan sylvassa stenar - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :En stor sjö i en uråldrig krater är grunden för parken - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Denna stora park har redan en imponerande berg- och dalbana, ditt mål är att öka vinsten - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier har utökat sitt nätverk med bryggor över havet, ditt mål är att utöka parken för att nyttja den tillgängliga ytan - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :Denna havsvik är grunden för denna berg- och dalbaneutmaning - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Ett slott med ett par karuseller ska utvecklas till en större nöjespark - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :En park som har sina gångar och karuseller under jorden - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :En glaciärdal är din för att skapa ett nöjesfält - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :I en värld långt bort där pengar inte är nödvändigt, ska du bygga ett nöjesfält för att göra befolkningen glada - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Fem berg- och dalbanor måste slutföras i detta ökenområde - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :I denna historiska park är det endast tillåtet att bygga äldre, historiska attraktioner - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Utveckla denna utomjordiska park för att maximera deras vinst - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :Denna temapark har redan ett antal åkturer med gott om utrymme för utökning - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :En läskig park centrerad runt en stor berg- och dalbana - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Två stora stenar sticker upp från sanden, vilket är början till konstruktionen av en nöjespark - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :I denna stora park måste du designa och bygga tio berg- och dalbanor - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :En lång smal ö gör det utmanande att bygga berg- och dalbanor med endast ett fåtal att välja mellan - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Ett isigt landskap måste byggas om till en glödande nöjespark - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :En ökenpark med några läckra attraktioner är din att bygga på - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :I denna lilla park måste du slutföra de fem ofärdiga berg- och dalbanorna - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :En stor park med ett ovanligt transportsystem runt kanterna - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Denna stora ö är din att bygga ett nöjesfält på - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :En gigantisk övergiven skyskrapa är en unik chans till att bygga en park - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Detta stadsområde är ditt för att göras till en nöjespark - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :En gigantisk park fylld av attraktioner behöver upprustas - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :På en planet långt bort behöver denna mark förvandlas till en nöjespark - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Försök att skapa världens minsta vinstgivande park - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Tak - -## End OpenRCT2 Official - - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpinäventyr -STR_PARK :Alpinäventyr -STR_DTLS :Förvandla en liten bergsskidort till en nöjespark med vintertema - - -STR_SCNR :Vänskapsflygfält -STR_PARK :Vänskapsflygfält -STR_DTLS :Bygg en nöjespark med flygtema på den här övergivna flygplatsen - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Din utmaning är att bygga en högvinstspark på den här paradisön - - -STR_SCNR :Bygg ditt eget Six Flags Belgien -STR_PARK :Six Flags Belgien -STR_DTLS :Bygg din egen version av det här europeiska Six Flags-nöjesfältet - - -STR_SCNR :Bygg ditt eget Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Använd din designförmåga för att återskapa den här Six Flags-parken - - -STR_SCNR :Bygg ditt eget Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Bygg det här europeiska Six Flags-nöjesfältet på ditt eget sätt - - -STR_SCNR :Bygg ditt eget Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Skapa din egen version av det här omfattande Six Flags-nöjesfältet - - -STR_SCNR :Bygg din egen Six Flags-Park -STR_PARK :Six Flags -STR_DTLS :Designa din egen Six Flags-park – Bygg antingen attraktioner från andra Six Flags-parker eller designa och bygg dina egna attraktioner - - -STR_SCNR :Bygg ditt eget Six Flags över Texas -STR_PARK :Six Flags över Texas -STR_DTLS :Börja från början, bygg attraktionerna på det här Six Flags-nöjesfältet - - -STR_SCNR :Bumbly basar -STR_PARK :Bumbly basar -STR_DTLS :Du börjar med en liten marknad, och din utmaning är att öka vinsten från affärer och stånd genom att bygga attraktioner och berg- och dalbanor för att locka fler kunder - - -STR_SCNR :Roliga slottet -STR_PARK :Roliga slottet -STR_DTLS :Du har ärvt ett stort slott – Ditt jobb är att förvandla det till en liten temapark. - - -STR_SCNR :Dammiga greener -STR_PARK :Dammiga greener -STR_DTLS :Beläget nära motorvägspåfarten i öknen, är Dusty Greens en möjlighet att utveckla en liten golfort till en blomstrande temapark - - -STR_SCNR :Elektriska fält -STR_PARK :Elektriska fält -STR_DTLS :Du har ärvt en liten gård och din utmaning är att bygga en liten temapark bland fälten och gårdsbyggnaderna - - -STR_SCNR :Extrema höjder -STR_PARK :Extrema höjder -STR_DTLS :Din utmaning är att, utan ekonomiska begränsningar, utvidga den här ökenparken för att locka personer som söker den ultimata spänningen - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Ett övergivet fabrikskomplex är en möjlighet för att bygga en nöjespark med mekaniskt tema - - -STR_SCNR :Fungus skogar -STR_PARK :Fungus skogar -STR_DTLS :Begränsad till bara äldre sorters träattraktioner är det din utmaning att bygga en framgångsrik temapark i Fungus’ skogar - - -STR_SCNR :Spökstad -STR_PARK :Spökstad -STR_DTLS :Som anställd av en stor nöjesparkskedja, är det din uppgift att bygga en jätteberg- och dalbana runt en övergiven gruvstad - - -STR_SCNR :Gravitationsträdgårdarna -STR_PARK :Gravitationsträdgårdarna -STR_DTLS :Din utmaning är att bygga en berg- och dalbanepark i Gravitationsträdgårdarna – Inga andra attraktioner, bara berg- och dalbanor! - - -STR_SCNR :Infernaliska utsikter -STR_PARK :Infernaliska utsikter -STR_DTLS :En park som ligger osäkert på lavasten med strömmar av magma - - -STR_SCNR :Tursjön -STR_PARK :Tursjön -STR_DTLS :Med obegränsat kapital men en utmanande sjöplats kommer det här nöjesfältet att bli en utmaning att expandera och driva - - -STR_SCNR :Rainbow Summit -STR_PARK :Regnbågstopp -STR_DTLS :Parken är belägen på en sluttning, och förbjuden att bygga något högt. Kan du utvidga parken och göra den framgångsrik? - - -STR_SCNR :Six Flags Belgien -STR_PARK :Six Flags Belgien -STR_DTLS :Utmana dig själv genom att leda och förbättra den här Six Flags-parken - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Bygg de Six Flags-attraktionerna som saknas eller skapa dina egna för att förbättra parken! Men glöm inte bort ditt syfte – Att locka fler besökare till parken - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Utmana dig själv genom att leda och förbättra den här Six Flags-parken - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Bygg de Six Flags-attraktionerna som saknas eller skapa dina egna för att förbättra parken! Men glöm inte bort ditt syfte – Att betala tillbaka dina lån medan du håller parkens värde uppe! - - -STR_SCNR :Six Flags över Texas -STR_PARK :Six Flags över Texas -STR_DTLS :Bygg de Six Flags-attraktionerna som saknas eller skapa dina egna för att förbättra parken! Men glöm inte bort ditt syfte – Att locka fler besökare till parken - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Afrikas gruvor -STR_PARK :Afrikas gruvor -STR_DTLS :Du har hittat en diamant efter att ha ärvt en övergiven diamantgruva. Du beslutar dig för att satsa pengarna på ett storslaget nöjesfält. - - -STR_SCNR :Hägring och fägring -STR_PARK :Hägring och fägring -STR_DTLS :Man har upptäckt en ökenoas som skulle passa utmärkt till ett nöjesfält. Transportmöjligheter till oasen har ordnats redan. - - -STR_SCNR :Över kanten -STR_PARK :Över kanten -STR_DTLS :En nybyggd damm ger tillräckligt med billig vattenkraft för att kunna driva ett nöjesfält. Du måste dock uppnå ett högt parkvärde för att kunna betala tillbaka lånet för dammen. - - -STR_SCNR :Iskallt äventyr -STR_PARK :Iskallt äventyr -STR_DTLS :En miljöorganisation har bett dig att bygga om ett gammalt, miljöfarligt oljeraffinaderi till en toppmodern turistattraktion. Marken är billig, men låneräntan är hög. Du kan dock sälja de gamla byggnaderna. - - -STR_SCNR :Kinesiska muren -STR_PARK :Kinesiska muren -STR_DTLS :Myndigheterna har beslutat att stödja turismen kring Kinesiska muren genom att bygga ett nöjesfält i dess närhet. Pengar är inget hinder! - - -STR_SCNR :Okinawa-kusten -STR_PARK :Okinawa-kusten -STR_DTLS :Ett nöjesfält behöver mer plats. Din enda möjlighet är att ta ett lån och bygga ut mot havet. Höjdrestriktioner råder på grund av jordbävningsfaran. - - -STR_SCNR :Maharadjaparken -STR_PARK :Maharadjaparken -STR_DTLS :Du har fått i uppdrag av maharadjan att underhålla lokalbefolkningen. Inhämta inspiration från maharadjans palats när du bygger nöjesfältet. - - -STR_SCNR :Ayers äventyr -STR_PARK :Ayers äventyr -STR_DTLS :Du hjälper urbefolkningen att bygga ett nöjesfält som en del av ett kulturprogram. Du måste locka tillräckligt med besökare för att kunna sprida urbefolkningens kultur. - - -STR_SCNR :Strandhugg -STR_PARK :Strandhugg -STR_DTLS :En lokal affärsmans vattenpark har gått i konkurs. Du driver redan en liten välfungerande park, och har köpt upp konkursboet. Utveckla det hela till en stor gemensam park. - - -STR_SCNR :Europeisk festival -STR_PARK :Europeisk festival -STR_DTLS :Du har blivit erbjuden att ta över en europeisk turistattraktion, men måste öka besöksfrekvensen för att kunna betala tillbaka ett EU-lån innan det europeiska parlamentet tar sommarlov. - - -STR_SCNR :Ur askan -STR_PARK :Ur askan -STR_DTLS :Ett gammalt nöjesfält har förfallit. Du har beviljats ett EU-lån för att kunna återställa det nedgångna området till sin forna prakt. Du måste renovera nöjesfältet och betala tillbaka lånet. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :Folket på Hawaii har tröttnat på att surfa och vill göra något mer spännande. Du måste bygga ett nöjesfält för att hålla dem på gott humör och bibehålla områdets attraktionskraft. - - -STR_SCNR :Trubbel i Canyon -STR_PARK :Trubbel i Canyon -STR_DTLS :Du måste bygga ett nöjesfält på ett begränsat område på båda sidor om detta naturfenomen. Du har möjlighet att köpa upp angränsande land från urbefolkningen. Målet med bygget är att bibehålla den lokala befolkningssiffran. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :Du är en framgångsrik affärsman som under ett sabbatsår beslutar dig för att förvandla en stadspark till ett ”Rollercoaster Heaven”, oavsett kostnad! - - -STR_SCNR :Grundare av Förlorade Staden -STR_PARK :Grundare av Förlorade Staden -STR_DTLS :Du måste öka de lokala turistintäkterna genom att bygga ett nöjesfält som passar omgivningen och håller sig inom höjdrestriktionerna. - - -STR_SCNR :Kul i regnskog -STR_PARK :Kul i regnskog -STR_DTLS :Utrymmet är begränsat i den utrotningshotade regnskogen. Du måste få plats med så mycket som möjligt i gläntan för att kunna erbjuda ett alternativ till den lokala timmerindustrin. - - -STR_SCNR :Sockersöta stränder -STR_PARK :Sockersöta stränder -STR_DTLS :Du driver ett litet nöjesfält nära Rio, men banken kräver plötsligt betalning av ditt lån. Du måste öka dina intäkter snabbt för att kunna klara den uppkomna krisen. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Slott på klipporna -STR_PARK :Slott på klipporna -STR_DTLS :Medlemmarna i den lokala medeltidsföreningen tar sin hobby på allvar. De har bett dig konstruera en nöjespark med medeltidstema på det gamla slottets ägor. - - -STR_SCNR :Sherwoodskogen -STR_PARK :Sherwoodskogen -STR_DTLS :För att kunna stjäla mer från de rika och ge till de fattiga har du och dina män bestämt er för att bygga ett nöjesfält i Sherwoodskogen. - - -STR_SCNR :Utomjordisk extravagans -STR_PARK :Utomjordisk extravagans -STR_DTLS :Liv har påträffats på en främmande planet. Bygg en park med utomjordiskt tema för att tjäna pengar på folks nyväckta intresse. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Realisera din innovativa och utopiska vision av framtiden. Bygg en futuristisk park med de allra senaste attraktionerna. - - -STR_SCNR :Animatroniska äventyr -STR_PARK :Animatroniska äventyr -STR_DTLS :Du har fått i uppgift att driva och förbättra en existerande park som ligger på en gammal filminspelningsplats. Bygg en hyllning till filmhistoriens animationspionjärer som först gav liv åt förhistoriska vidunder på vita duken. - - -STR_SCNR :Mytologiskt arv -STR_PARK :Mytologiskt arv -STR_DTLS :Du äger en ö av högt arkeologiskt värde. Du har bestämt dig för att finansiera dess bevarande genom att konstruera ett nöjesfält med ett tema baserat på områdets rika mytologiska arv. - - -STR_SCNR :Kraterkatastrof -STR_PARK :Kraterkatastrof -STR_DTLS :Du äger en dammig gammal meteorkrater. Som den entreprenör du är bestämmer du dig för att bygga ett nöjesfält med asteroidtema och omvandla den till synes värdelösa marken till en förmögenhet. - - -STR_SCNR :Bergosaurier -STR_PARK :Bergosaurier -STR_DTLS :Du har fått i uppgift att bygga en park med Juratema. För att besökarna ska kunna uppleva den exotiska floran och faunan ordentligt krävs det att du bygger attraktioner som går ovanför och ned i dalen. - - -STR_SCNR :Stenigt värre -STR_PARK :Stenigt värre -STR_DTLS :Stoppa motorvägsbygget och bevara de urtida stencirklarna genom att bygga ett nöjesfält med stenålderstema som går med vinst. Det kan dock bli en smula problematiskt att locka besökare eftersom terrängen är aningen oländig. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :Den ökända fängelseön, vars befolkning en gång i tiden utgjordes av smugglare och gangsters, är till salu. Du har bestämt dig för att förvandla den till en förstklassig turistattraktion. Pengar är inget hinder. - - -STR_SCNR :Schneiders strand -STR_PARK :Schneiders strand -STR_DTLS :75-årsjubiléet av din faders vinst av Schneidertrofén inträffar om några år. Du vill hedra hans prestation genom att bygga en park baserad på den berömda sjöflygplanstävlingen. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :Du äger en tom tomt i närheten av stadens lågt byggda kvarter. För att få ut så mycket vinst som möjligt av marken bygger du ett nöjesfält i form av en skyskrapa inspirerad av tjugotalets art déco-arkitektur. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :En stor årlig rockfestival äger rum på din mark. Bygg en hipp nöjespark i den fritänkande publikens smak. - - -STR_SCNR :Rock’n’roll-revival -STR_PARK :Rock’n’roll-revival -STR_DTLS :Denna åldrande park har sett bättre dagar. Hjälp ägaren med att ge den ett retro-rock’n’roll-tema för att förvandla den till en framgångsrik park. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Panda World -STR_PARK :Panda World -STR_DTLS :Bygg flera attraktioner för att locka folk till denna panda-inspirerade park - -#Everyone is allowed to edit this document diff --git a/data/language/tr-TR.txt b/data/language/tr-TR.txt index 0f808b65de..130adc7edc 100644 --- a/data/language/tr-TR.txt +++ b/data/language/tr-TR.txt @@ -3358,748 +3358,3 @@ STR_6524 :Seçili varlık paketinin önceliğini yükselt. STR_6525 :Etkinleştirilmiş varlık paketleri ile beraber oyundaki tüm varlıkları yeniden yükleyin. STR_6526 :(ana grafikler, müzik ve ses efektleri) STR_6527 :Yarışmalar - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Ormanın içinde boş bir alanda güzel bir Lunapark inşa ediniz - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Çölün orta yerine bir Lunapark oluşturunuz. Bu parkta sadece bir hız treni bulunmakta fakat arazi genişletmek için imkanlar var - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Bu muhteşem doğanın içinde bir park oluşturunuz - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights şimdiden çok başarılı ve yüksek değeri olan bir park - parkın değerini iki misline katınız - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Evergreen Gardens isimli bu alanı güzel bir Lunaparka dönüştürünüz - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Bumbly Beach’in küçük lunaparkını güzel bir lunaparka dönüştürünüz - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Üç çeşitli adanın üstünde lunapark oluşturunuz - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :Küçük fakat büyütme imkanları sunan bir lunapark - Hedefiniz parkın değerini iki misline katmak - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :Çok küçük olan bu lunaparkı büyütünüz ve başarıya imza atınız - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :Sulu lunaparkın büyümeye ihtiyacı var - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Bu terk edilmiş maden ocağı uzun süre turistlik bir alandı fakat şimdi sizin genişletebileceğiniz küçük bir lunapark kuruldu - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :Ormanın içinde gizlenmiş ve sadece Kart Yarışı ve Ahşap Hız Trenleri bulunduran bir lunapark - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :Bu lunaparkta modern tasarımlı hız trenleri bulunmakta - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :Bir dağın eteğine lunapark inşa ediniz - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Bu tarihi yeri bir lunaparka dönüştürünüz - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :Bu lunapark güzel alet tasarımları bulunduruyor. Fakat aletler çok eski. Ya aletleri yenileyiniz ya da yeni aletler inşa ediniz - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Bu küçük şehrin kullanılmayan iskelesini lunaparka dönüştürünüz - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :Doğası güzel olan bu dağın tepesine lunapark inşa ediniz - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :Küçük araziye fakat büyük sorunlara sahip bir lunapark - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Yerel makamlardan arazi değişiklikleri yasaklanmış bir alanda lunapark oluşturunuz - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :‘Thunder Rock’ ile adlandırılan bu tepe turistlerin çok ziyaret ettiği bir yer - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :İyi eğlenceler! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Bir uçurumun kenarına lunapark inşa ediniz - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Yarışan hız trenleri bulunduran bir lunapark - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :Terk edilmiş maden ocağının üstüne inşa edilmiş küçük bir lunapark - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :Eski bir yedek köprünün etrafına lunapark inşa ediniz - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Bir karayolunun sağına ve soluna kurulmuş bir lunapark - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :Küçük bir plajın yanında bulunan küçük bir lunapark. Yerel makamlar araziyi genişletmeye izin veriyor - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :Eski bir kalenin alanına lunapark kurunuz - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :Bu uzaylı ve Mars temalı park müşterileri diğer bir gezegene götürüyor - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :Etrafı su ile sarılı bir adanın üstünde lunapark - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Cengelin ortasına bir lunapark oluşturunuz - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :Lunaparkın arazisi dört büyük gölden oluşmakta - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :Tarihi aletlete sahip olan bu lunapark aşırı derecede borçlanmış - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :Dört yanı çeşitli iklime sahip olan bir alanda lunapark inşa ediniz - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :Meyve çiftliği bulunan bu arazide lunapark oluşturunuz - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :Barajın etrafındaki boş alana lunapark inşa ediniz - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :Bu kanyonda güzel bir lunapark oluşturunuz - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :İklimin çok yağmurlu olmasından dolayı aletleri yağmurdan korumak için piramit inşa edilmiş - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :Yerel makamlar tarafından ağaçlardan daha yüksek alet inşası yasaklanmıştır - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Roma temalı dekorasyonlar içeren bir lunapark - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Küçük adalar bulunduran bu araziye lunapark inşa ediniz - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Yerel halk için heyecan dolu bir lunapark inşa ediniz - - -STR_SCNR :Utopia Park -STR_PARK :Utopia Park -STR_DTLS :Bir çölün ortasında bulunan vahanın etrafına bir lunapark inşa ediniz - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Terk edilmiş bu lunaparkı geride kalmış parlak haline getiriniz - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Çok kötü tasarlanmış alet bulunduran ve bütçesi sınırlı olan bu lunaparkın sorunlarını ortadan kaldırınız - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :Yerel makamlar tarafından pazarlama kampanyaları yasaklanmış. Parkın şöhreti ile müşteri sayısını yükseltmeye çalışınız - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :Çocuklara özel inşa edilmiş bir lunapark - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Terk edilmiş taş ocağını güzel bir lunaparka çeviriniz - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :Bu dağlık bölgeyi geniş bir lunaparka dönüştürmek için sınırsız süreniz fakat sınırlı sermayeniz var - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :Şehir içi bulunan bu mikro parkta satılı arazi kısıtlı - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :Lunaparka dönüştürülmeyi bekleyen bir bahçe - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :Buz dağlarının üstüne lunapark inşa ediniz - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :Uyuyan yanardağın içine lunapark inşa ediniz - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Bir çölün ortasını sınırsız bütçe ile lunapark inşa ediniz - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :‘Razor Rocks’ adlı bu alana bir lunapark kurunuz - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :Sönmüş yanardağın içinde zamanla göl oluşan bu alanda lunapark kurunuz - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :Bu lunaparkta henüz kârlı bir hız treni bulunmakta. Sizin hedefiniz o hız treninin kârını sekize katlamaktır - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Bu küçük şehrin önceden kullanılmayan iskelesini fakat şimdi lunapark bulunduran bu yeri geliştiriniz - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :Bu dağlık alan alet inşasını zorlaştırıyor - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :Bir adanın üstünde bulunan eski kaleyi lunaparka dönüştürünüz - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :Yolları genelde yerin altında bulunan bir lunapark - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :Buzul ile kaplı olan bu vadide lunapark oluşturunuz - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :Paranın gereksiz olduğu uzak bir diyarda lunapark inşa ediniz - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Çölün ortasında beş kısmen inşa edilmiş hız treni bulunduran bir lunapark - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :Bu tarihi lunaparkta sadece eski tarz aletlerin inşasına izin veriliyor - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Kârını zirveye çıkarmanız gerektiren bir uzaylı lunaparkı - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :Bu güzel dekorasyonlu lunapark bir kaç alet bulunduruyor - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :Büyük bir hız treni bulunduran korkunç lunapark - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :İki büyük kayalık üstünde lunapark kurunuz. Bu iki kayalık hız treni ile birbirine bağlı - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :Bu büyük alanda on çeşitli hız treni inşa etmelisiniz - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :Uzun ince bir adanın üstüne lunapark inşa ediniz - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :Buzlu bir alana lunapark inşa ediniz - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :Çölde bulunan bu lunaparkı geliştiriniz - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :Bu mikro lunaparkta beş kısmen inşa edilmiş hız trenlerini tamamlayınız - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :Büyük bir alanda gölün etrafında bir lunapark. Müşteri taşıma sistemi hız treni ile gerçekleşiyor - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :Bu tropikal adanın üstünde lunapark inşa ediniz - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :Bu terk edilmiş gökdelenin üstüne ve etrafına lunapark kurunuz - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :Bu terk edilmiş şehri lunaparka dönüştürünüz - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :Çok büyük ölçüde alet bulunduran bir lunapark - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :Dünyadan uzaklarda bir gezegenin üstünde lunapark inşa ediniz - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Mikro bir alanda park değerinin yüksek olmasını sağlamaya çalışınız - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS :Gerçekte İngiltere’de bulunan bir lunapark - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS :Gerçekte Almanya’da bulunan bir lunapark - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS :Gerçekte İngiltere’de bulunan bir lunapark - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Çatı -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Küçük bir kayak merkezini başarılı bir lunaparka dönüştürünüz - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Bu terk edilmiş havalimanına lunapark inşa ediniz - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Bu tropikal adanın üzerinde başarılı lunapark inşa ediniz - - -STR_SCNR :Build your own Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Kendi Six Flags Belgium parkınızı inşa ediniz - - -STR_SCNR :Build your own Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Kendi Six Flags Great Adventure parkınız inşa ediniz - - -STR_SCNR :Build your own Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Kendi Six Flags Holland parkınız inşa ediniz - - -STR_SCNR :Build your own Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Kendi Six Flags Magic Mountain parkınızı inşa ediniz - - -STR_SCNR :Build your own Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Kendi Six Flags over Texas parkınızı inşa ediniz - - -STR_SCNR :Build your own Six Flags Park -STR_PARK :Six Flags -STR_DTLS :Kendi Six Flags parkınızı inşa ediniz - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Küçük bir pazar yeri ile başlayan bu yeri başarılı bir lunaparka çeviriniz - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :Büyük bir kaleyi lunaparka çeviriniz - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Bir karayolunun yakınındaki bu golf tesisini lunaparka dönüştürünüz - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :Satın aldığınız küçük bir çiftliği lunaparka dönüştürünüz - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Çok sayıda kumul bulunduran bu alanda parasız lunapark inşa ediniz - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Terk edilmiş bir sanayi bölgesine lunapark inşa ediniz - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Sadece eski tarz aletler inşasına izin verilen bir lunapark - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Bir büyük lunapark zinciri tarafından bu terk edilmiş maden kasabasına lunapark inşa etmeniz istendi - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Bu lunaparkta sadece hız treni inşa etmenize izin veriliyor - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :Kenarlarında magma akan bu alanda lunapark kurunuz - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :Paranız sınırsız fakat gölün içindeki kayalıklar alet inşasını zorlaştırıyor - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Bir dağın eteğine lunapark kurunuz. Fakat yüksek aletlerin inşasına izin verilmiyor - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Gerçekte Belçika’da bulunan bir lunapark - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Gerçekte ABD’nin New Jersey eyaletinde bulunan bir lunapark - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Gerçekte Hollanda’da bulunan bir lunapark - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Gerçekte ABD’nin Kaliforniya eyaletinde bulunan bir lunapark - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Gerçekte ABD’nin Texas eyaletinde bulunan bir lunapark - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :Kullanılmayan bir elmas madeni satın aldınız. Bu madende değerli bir elmas buldunuz ve onun satışı ile popüler bir lunapark inşa etmeye karar verdiniz - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :Afrika’da bir vaha buldunuz ve bu vahanın etrafına güzel bir lunapark inşa etmeye karar verdiniz - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :Ucuza ve bol miktarda park için cereyan üretmek amacıyla bir baraj inşa ettirdiniz. Baraj için çektiğiniz krediyi geri ödediniz bile. Şimdi park değerini yükseltmeye çalışınız - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :Çevre koruma makamı size eski petrol rafinerisini görüntü kirliliği olduğundan dolayı yıkıp yerine güzel bir lunapark inşa etmenizi istedi. Arazi satın alma ucuz fakat kredi faizi çok yüksek - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :Yetkililer, bitişik arazide bir lunapark inşa ederek Çin Seddi çevresindeki turizmi geliştirmeye karar verdiler. Paranız sınırsız - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :Burada kurulu olan lunaparkın yeri bitmek üzere. Bundan dolayı suyun üstüne inşa etmeniz gerekli. Bu yüzden kredi çekmeniz gereklidir. Deprem riskinden dolayı yüksek inşa yasağı koyulmuştur - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :Maharaja ailesi sizden yerel halkın eğlenmesi için Maharaja Sarayının etrafına lunapark inşa etmenizi diledi - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :Aborjin halkının kültürünü anma programı için bir lunapark kurmanız rica edildi. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :Yerel bir girişimcinin deniz yaşamı parkı kapandı. Siz henüz küçük bir lunaparka sahipsiniz ve kapalı olan diğer parkında satın aldınız. Bu parkları birleştiriniz - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :Avrupa kültürel festivalinin yöneticisi olarak seçildiniz. Sizden festivale daha fazla müşteri getirmeniz bekleniyor - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :Eski bir lunapark harabeye dönüştü. Avrupa Birliği size bu parkı eski ihtişamına getirmek dileği ile verdi. Parkı yenilemeniz ve krediyi geri ödemeniz gerekiyor. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :Hawaii’de yaşayan insanlar bütün gün sörf yapmaktan sıkılmış ve daha heyecanlı bir şey yapmak istiyorlar. Sizden turistlerin ziyaret edeceği ve yerel halkı memnun edecek bir park inşa etmeniz bekleniyor - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :Bu doğal hazinenin her iki tarafında sınırlı bir alanda bir park inşa etmelisiniz. - Yerli Kızılderililerden toprak satın alma imkânınız var. Yerel kasabanın nüfusunu sürdürmek için hedefi tamamlamanız gerekiyor. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :Çok başarılı bir iş adamısınız ve uzun bir müddet tatile çıktınız. Bu tatilde şehrin göbeğinde bulunan boş araziye başarılı bir lunapark inşa etmeye karar verdiniz. Paranız sınırsız - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :Yerel turizmi güçlendirmek için çevresiyle uyumlu bir park kurmanız gereklidir. Fakat inşa için yükseklik sınırı koyulmuştur - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Bu yağmur ormanında boş alan kısıtlı - yerel kereste endüstrisine bir alternatif sunmak için bu kısıtlı alanda lunapark inşa ediniz - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :Rio yakınlarında küçük bir park işletiyorsun fakat banka kredinizi aradı. Bu beklenmedik borcu geri ödemek için kârınızı hızla artırmanız gerekiyor. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Savaşın yeniden canlandırılması toplumunun yerel üyeleri, hobileri hakkında oldukça ciddi. Cliffside Kalesi’nin arazisinde bir Karanlık Çağ temalı park inşa etmenizi dilediler - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :Zenginlerden para kırpıp ve muhtaçlara dağıtmak için, siz ve ‘Mutlu Adamlarınız’ Sherwood Ormanı’nda bir lunapark kurmaya karar verdiniz - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Uzak bir gezegende hayat keşfedildi. Bu gezegende bir uzaylı lunaparkı inşa ediniz - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Geleceğin yaratıcı, ütopik vizyonunu sergileyin - son teknoloji konumlarını içeren fütüristik bir park tasarımı ile parkınızı oluşturunuz - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :Eski bir film setinde kurulmuş olan mevcut bir lunaparkını işletme ve geliştirme görevi size verilmiştir - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :Arkeolojik eserler bulunduran bir adaya sahipsiniz. Bu eserlerin korunmasını sağlamak için lunapark kurmaya karar verdiniz - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :Eski bir meteor kraterine sahipsiniz. Gerçek girişimci ruhu içinde, bir asteroid lunaparkı kurmaya ve görünüşte değersiz arazinizi büyük bir servete dönüştürmeye karar verdiniz - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :Jura devri tarzı lunapark inşa etme görevini üstlendiniz. Müşterilerin egzotik bitki ve hayvan sergilerine erişimini optimize etmek için, vadiye giden ve gelen aletler inşa etmeniz gerekecektir - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :Karayolu kurulmasını engellemek için bu araziyi satın aldınız ve Taş Devri temalı bir lunapark inşa etmeye karar verdiniz - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :ABD’nin meşhur hapishanesini satın aldınız ve burayı güzel bir lunaparka çevirmeye karar verdiniz. Paranız sınırsızdır - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :Dedeniz 75 yıl önce Schneider Kupasını kazanmış ve onun zaferini anmak için buraya bir lunapark inşa etmeye karar verdiniz - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :Şehrin içinde boş bir araziye sahipsiniz ve bu boş araziye şehir ve yirmili yıllar temalı bir lunapark inşa etmeye karar verdiniz - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :Büyük bir müzik festivalinin yanına bir lunapark inşa ediniz ki festival ziyaretçileri daha çok eğlensin - - -STR_SCNR :Rock ’n’ Roll Revival -STR_PARK :Rock ’n’ Roll Revival -STR_DTLS :Bu lunapark zamanında çok başarılıymış. Fakat şimdi git gide bu parkın başarısı ve parlaklığı geriliyor. Park sahibi sizden parkı geri canlandırmanızı ve eski parlaklığına getirmenizi diliyor diff --git a/data/language/uk-UA.txt b/data/language/uk-UA.txt index 09b4364da3..f312567fa7 100644 --- a/data/language/uk-UA.txt +++ b/data/language/uk-UA.txt @@ -3730,836 +3730,3 @@ STR_6626 :Анімація йде задом наперед STR_6642 :{STRING} ({COMMA32} / {COMMA32}) STR_6643 :{STRING} ({COMMA32} / {COMMA32} Кб) - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Лісові кордони -STR_PARK :Лісові кордони -STR_DTLS :Глибоко в лісі побудуйте успішний тематичний парк на великій розчищеній території - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Starting from scratch, build a theme park around a large lake - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Develop Bumbly Beach’s small amusement park into a thriving theme park - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Several islands form the basis for this new park - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :A small theme park with a few rides and room for expansion. Your aim is to double the park value. - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :A small, cramped amusement park which requires major expansion - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :A park with some excellent water-based rides requires expansion - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :In the hilly forests of Mystic Mountain, build a theme park from scratch - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :A large park with well-designed but rather old rides. Replace the old rides or add new rides to make the park more popular. - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Convert this sleepy town’s pier into a thriving attraction - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers. Use the available land to attract a new thrill-seeking clientele. - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :A well-established park, which has a few problems - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Rainbow Valley’s local authority won’t allow any landscape changes or large tree removal, but you must develop the area into a large theme park - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists. Use the available space to build rides to attract more people. - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Just for fun! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Develop the seaside cliffs into a thriving amusement park - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Central to this large developing park is a giant triple-track racing/duelling steel coaster - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its miniature railway and a pair of vertical drop roller coasters - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :An old redundant bridge is yours to develop into an amusement park - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Covering land both sides of a highway, this park has several rides already operating - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :This castle is all yours to turn into a theme park - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :The area around a dam is available for you to develop into an amusement park - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :A vast canyon is yours to turn into a theme park - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :The local authority won’t allow you to build above tree height in this park - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centrepiece - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :A four lane steeplechase ride is the centrepiece of this expanding park - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :A large garden park needs turning into a thriving theme park - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :A dormant volcano is the setting of this coaster-building challenge - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :A large lake in an ancient crater is the setting for this park - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :This sea-side cove is the setting for this coaster-building challenge - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :A park which has much of its footpaths and coasters underground - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :A glacier-filled valley is yours to develop into a theme park - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Five coasters require completion in this desert park - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :This historical park is only allowed to build older-styled rides - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Develop this alien park to maximise its profit - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :A scary park with a giant centrepiece coaster - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :In this large park you must design and build ten large coasters - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :An icy landscape needs turning into a thriving theme park - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :A desert park with some cleverly designed coasters is yours to expand - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :In this tiny park you must finish building the five existing coasters - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :A large park with a novel transportation system around its edge - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :This large island is all yours to develop as an amusement park - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :This urban area is all yours to develop into an amusement park - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :A giant park already packed full of rides needs improving - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :On a far-away planet this area of land needs turning into a theme park - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Try to create the world’s smallest profitable park - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official - -[TTPIRF05] -STR_NAME :Roof - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Convert a small mountain ski resort into a snow-themed amusement park - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Build a flying-themed amusement park in this abandoned airport - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Your challenge is to build a high-profit park on this paradise island - - -STR_SCNR :Build your own Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Build your own version of this European Six Flags park - - -STR_SCNR :Build your own Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Use your design skills to recreate this Six Flags park - - -STR_SCNR :Build your own Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Build this European Six Flags park the way you want to - - -STR_SCNR :Build your own Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Create your own version of this massive Six Flags park - - -STR_SCNR :Build your own Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Starting from scratch, build the rides in this Six Flags park - - -STR_SCNR :Build your own Six Flags Park -STR_PARK :Six Flags -STR_DTLS :Build your own design of Six Flags park - either build rides from other Six Flags parks or design and build your own rides - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Starting with a small market bazaar, your challenge is to increase the profit from shops and stalls by building rides and roller coasters to attract more customers - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :You have inherited a large castle. Your job is to convert it into a small theme park. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Situated near a highway junction in the desert, Dusty Greens is an opportunity to develop a small golf resort into a thriving theme park - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :You have inherited a small farm, and your challenge is to build a small theme park amongst the fields and farm buildings - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Free of financial restrictions, your challenge is to expand this desert park to attract people seeking the ultimate thrills - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :An abandoned factory complex is an opportunity to build a mechanical-themed amusement park - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Restricted to only older-style wooden rides, your challenge is to build a thriving theme park in Fungus Woods - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Hired by a large amusement park chain, your task is to build them a giant roller coaster park around an abandoned mining town - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Your challenge is to build a roller coaster park in the beautiful Gravity Gardens. No other rides, just roller coasters! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :A park nestled precariously on lava rock with streams of magma - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :With unlimited funds but a challenging lake location, this park will be a challenge to expand and manage - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Built on a hillside, this park is forbidden from building anything tall. Can you expand the park and make it successful? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to attract more guests to the park! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to repay your loan while keeping the park value up! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to attract more guests to the park! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :You inherited a disused diamond mine, and find a valuable diamond. You decide to invest that money to build a world-famous theme park. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :A desert Oasis has been discovered and would provide a beautiful location for a park. Transport to the oasis has been provided. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :A dam has been built offering abundant, cheap hydroelectric power with which to run a park. You need to reach a high park value to help repay the loan for the dam. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :The environment agency has turned to you to transform an old oil refinery ecological eyesore into a top tourist attraction. Land is cheap but loan interest is high. You can sell the old buildings for salvage. - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :The authorities have decided to enhance tourism around the Great Wall by building a theme park on the adjacent land. Money is no object! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :An existing park has run out of space. Your only option is to build out into the sea, and so you have taken out a loan. Height restrictions on your building are enforced due to foundations and earthquake risk. - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :You have been commissioned by the Maharaja to bring entertainment to the large local population. Build a park inspired by the Maharaja’s palace. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :You are helping Aboriginal people to build a park as part of a cultural awareness program. You need to get a large number of guests to educate them in the unique heritage of the Aboriginal people. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :A local entrepreneur’s sealife park has gone bust. You already operate a small park and buy the other park from the construction company. Develop a big combined park. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :You have been brought in to take over a European Cultural Visitor Attraction and must increase the number of guests in order to pay back the EU subsidy by the end of the current European parliament term. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :An old park has fallen into disrepair. You gain a European Union grant to return this deprived area to its former glory! You need to renovate the park and repay the grant. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :The people of Hawaii are bored of surfing and are looking for something more intense. You need to build a park with this in mind to keep the area’s tourist attraction rating high. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :You have to build a park on limited land either side of this natural treasure - you do have the opportunity to buy neighbouring land from the Native American Indians. You need to complete the objective to sustain the local town’s population. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :You are a successful business tycoon on long sabbatical who desires to use this time transforming the city park into Rollercoaster Heaven. Money is no object! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :To further boost local tourism you must construct a park that is in tune with its surroundings, and has height restrictions. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Space is limited in the precious rainforest - you must cram as much as possible into the existing clearing, in order to provide a viable alternative to the local timber industry. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :You run a small park near Rio but the bank has called in your loan. You need to quickly increase your earning capacity to repay this unexpected debt. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Local members of the battle re-enactment society are rather serious about their hobby. They’ve entrusted you with the job of constructing a Dark Age theme park on the grounds of Cliffside Castle. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :To liberate wealth from the rich and distribute it to the needy, you and your Merry Men have decided to build a theme park in Sherwood Forest. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Life has been discovered on a distant planet Build an alien theme park to cash in on the unprecedented wave of interest. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Show off your inventive, utopian vision of the future - come up with a futuristic park design that incorporates state-of-the-art attractions. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :You have been given the task of running and improving an existing theme park, which has been built on an old film set. Build a tribute to the pioneering stop-motion animators who first brought mythical creatures to life on the silver screen. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :You own an island of particular archaeological value. You’ve decided to fund its preservation by constructing a theme park based on the area’s rich Mythological heritage. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :You own a dusty old meteor crater. In the true entrepreneurial spirit, you’ve decided to construct an asteroid theme park and convert your seemingly worthless land into a sizeable fortune. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :You’ve been given the task of constructing a Jurassic era theme park. To optimize your visitors’ access to the exotic plant and animal exhibits, you will need to build rides going over and into the valley. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :To thwart the highway developers and preserve the mysterious ancient stone circles, you will need to construct a Stone Age theme park and turn a profit. However, attracting visitors may pose a challenge, as the terrain is a tad inhospitable. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :The infamous Prison Island - whose population once swelled with bootleggers and racketeers - is now up for sale. You’ve decided to convert it into a top tourist attraction, and money is no object - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :The 75th anniversary of your grandfather’s Schneider Cup victory is coming up in a few years. You’re going to honour his achievement by building a theme park based on the famous seaplane race. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :You own an empty lot near the low-rise part of town. To squeeze the most out of your urban property, build a skyscraper theme park inspired by the soaring art deco architecture of the twenties. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :A large annual music festival takes place on your land. Build a hip theme park to keep the free-spirited audience entertained. - - -STR_SCNR :Rock ‘n’ Roll Revival -STR_PARK :Rock ‘n’ Roll Revival -STR_DTLS :This aging theme park has seen better days. Help the owner give it a retro rock ‘n’ roll makeover and turn the place into a successful venue. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Світ панд -STR_PARK :Світ панд -STR_DTLS :Додайте більше атракціонів і залучіть більше людей до цього парку на тему панди - - -STR_SCNR :Парк магнату -STR_PARK :Парк магнату -STR_DTLS : - -### - -STR_SCNR :Цвинтарний хребет -STR_PARK :Цвинтарний хребет -STR_DTLS :Це Геловін, Геловін UCES, гарбузи кричать серед ночі! Цей цвинтар у біді, і тільки ти можеш врятувати його, дозволивши мертвим спочивати з миром! Чи зможеш ти утримати привидів у їхніх могилах і нагнати жаху на своїх відвідувачів?{NEWLINE}Автор: Squid - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :Александрійський маяк -STR_PARK :Александрійський маяк -STR_DTLS :Олександр побудував місто, греки, римляни, єгиптяни залишили свій слід. Але найбільшої честі відзначилося Диво Стародавнього Світу — Маяк. Приїжджайте і створіть парк!{NEWLINE}Автор: Katatude - - -STR_SCNR :Луна-парк, Клівленд -STR_PARK :Луна-парк -STR_DTLS :Таким він був у день відкриття — 18 травня 1905 року.{NEWLINE}Автор: Aetherwave - - -STR_SCNR :Гора Везувій -STR_PARK :Гора Везувій -STR_DTLS :Помпеї та Геркуланум були поховані Везувієм у 79 році н.е. Відвідайте розкопки та побудуйте парк!{NEWLINE}Автор: Katatude - - -STR_SCNR :Пісочниця -STR_PARK :Пісочниця -STR_DTLS :Те, чого хоче кожен — пісочниця! Тож беріть своє відерце та лопату і будуйте парк!{NEWLINE}Автор: Katatude - - -STR_SCNR :Ніагарський водоспад та ущелина -STR_PARK :Ніагарський водоспад -STR_DTLS :Американський водоспад, водоспад Брейдл та канадський водоспад Підкова на кордоні Ніагарського водоспаду, 1850 рік.{NEWLINE}Автор: Katatude - - -STR_SCNR :Шахтарі Скелястої гори -STR_PARK :Шахтарі Скелястої гори -STR_DTLS :Обвал гірських порід пошкодив вашу залізницю. Ваші робітники пішли на розвідку. Чи є золото в американських гірках?{NEWLINE}Автори: Squid, Buckone, Fossil - - -STR_SCNR :Машина часу -STR_PARK :Машина часу -STR_DTLS :Машина часу. Будуйте, щоб йти — коли хочете та куди хочете. Вічність чекає. Це все відносно.{NEWLINE}Автор: Katatude - - -STR_SCNR :Вавилонська вежа -STR_PARK :Вавилонська вежа -STR_DTLS :Ого! Подивіться, куди нас занесла машина часу! Куди всі поділися?{NEWLINE}Автор: Fossil - - -STR_SCNR :Перетворення -STR_PARK :Перетворення -STR_DTLS :Ми чекали на тебе…{NEWLINE}Автор: Fossil - - -STR_SCNR :Невпізнаний Урбіс -STR_PARK :Невпізнаний Урбіс -STR_DTLS :Римляни втомилися від нудних гладіаторських боїв. Дайте їм більше гострих відчуттів, перетворіть римське місто на найбільший парк розваг усіх часів!{NEWLINE}Автор: Kaffe - -############################################################################### -## UCES: Katy’s Dreamworld (2003) -############################################################################### - - -STR_SCNR :Під різдвяною ялинкою -STR_PARK :Зимова країна чудес -STR_DTLS :Мама побудувала цю сцену під нашою ялинкою. Тепер вона хоче зробити там парк! Можете допомогти?{NEWLINE}Автор: Katatude - - -STR_SCNR :Вибух Біґрок -STR_PARK :Вибух Біґрок -STR_DTLS :Після вибуху на гірничодобувній компанії Біґрок мешканці міста змушені будувати парк розваг, щоб зберегти своє місто.{NEWLINE}Автори: rbarclay та buckone - - -STR_SCNR :Табір “Пересмішник” -STR_PARK :Табір “Пересмішник” -STR_DTLS :Лише 500$/тиждень у цьому літньому таборі! Відкрий свій банк, а потім розважайся та будуй парк.{NEWLINE}Автор: Katatude - - -STR_SCNR :Місто Чух-Чух -STR_PARK :Місто Чух-Чух -STR_DTLS :Мамо! Татку! Я хочу в місто Чух-Чух!{NEWLINE}Автор: Fossil - - -STR_SCNR :Острови Драконів -STR_PARK :Острови Драконів -STR_DTLS :Острови Драконів? Я не дуже хочу туди.…{NEWLINE}Автор: Fossil - - -STR_SCNR :Дитячий карнавал II -STR_PARK :Дитячий карнавал -STR_DTLS :Привіт, дітки! Нумо розважатися!{NEWLINE}Автори: Piehead та Fossil - - -STR_SCNR :Піщана дюна -STR_PARK :Піщана дюна -STR_DTLS :Як власник невеликого парку, ви купили велику ділянку землі вздовж пляжу, щоб розширити його і привабити більше гостей до прекрасних піщаних дюн, але будьте обережні: ви не можете порушувати ці екологічно крихкі піщані дюни.{NEWLINE}Автор: rbarclay diff --git a/data/language/vi-VN.txt b/data/language/vi-VN.txt index 56124c198e..7428862479 100644 --- a/data/language/vi-VN.txt +++ b/data/language/vi-VN.txt @@ -3500,757 +3500,3 @@ STR_6431 :RMB STR_6432 :Mouse {INT32} STR_6433 :Remove STR_6434 :Remove all bindings for this shortcut. - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :Starting from scratch, build a theme park around a large lake - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :Develop Bumbly Beach’s small amusement park into a thriving theme park - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :Several islands form the basis for this new park - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :A small theme park with a few rides and room for expansion. Your aim is to double the park value. - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :A small, cramped amusement park which requires major expansion - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :A park with some excellent water-based rides requires expansion - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :In the hilly forests of Mystic Mountain, build a theme park from scratch - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :A large park with well-designed but rather old rides. Replace the old rides or add new rides to make the park more popular. - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :Convert this sleepy town’s pier into a thriving attraction - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers. Use the available land to attract a new thrill-seeking clientele. - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :A well-established park, which has a few problems - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Rainbow Valley’s local authority won’t allow any landscape changes or large tree removal, but you must develop the area into a large theme park - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists. Use the available space to build rides to attract more people. - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :Just for fun! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :Develop the seaside cliffs into a thriving amusement park - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :Central to this large developing park is a giant triple-track racing/duelling steel coaster - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its miniature railway and a pair of vertical drop roller coasters - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :An old redundant bridge is yours to develop into an amusement park - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :Covering land both sides of a highway, this park has several rides already operating - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :This castle is all yours to turn into a theme park - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :A series of stepped lakes form the basis for this new park - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :This elderly park has many historical rides but is badly in debt - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :A large area of land has been cleared and partially themed ready for you to develop into a landscaped theme park - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :A thriving fruit farm has built a railroad to boost its income, your job is to develop it into a full-blown amusement park - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :The area around a dam is available for you to develop into an amusement park - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :A vast canyon is yours to turn into a theme park - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :The local authority won’t allow you to build above tree height in this park - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centrepiece - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :A four lane steeplechase ride is the centrepiece of this expanding park - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :A large garden park needs turning into a thriving theme park - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :A dormant volcano is the setting of this coaster-building challenge - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :A large lake in an ancient crater is the setting for this park - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :This sea-side cove is the setting for this coaster-building challenge - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :A park which has much of its footpaths and coasters underground - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :A glacier-filled valley is yours to develop into a theme park - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :Five coasters require completion in this desert park - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :This historical park is only allowed to build older-styled rides - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :Develop this alien park to maximise its profit - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :A scary park with a giant centrepiece coaster - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :In this large park you must design and build ten large coasters - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :An icy landscape needs turning into a thriving theme park - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :A desert park with some cleverly designed coasters is yours to expand - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :In this tiny park you must finish building the five existing coasters - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :A large park with a novel transportation system around its edge - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :This large island is all yours to develop as an amusement park - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :This urban area is all yours to develop into an amusement park - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :A giant park already packed full of rides needs improving - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :On a far-away planet this area of land needs turning into a theme park - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :Try to create the world’s smallest profitable park - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :Alton Towers -STR_PARK :Alton Towers -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official -[TTPIRF05] -STR_NAME :Roof - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Convert a small mountain ski resort into a snow-themed amusement park - - -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Build a flying-themed amusement park in this abandoned airport - - -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Your challenge is to build a high-profit park on this paradise island - - -STR_SCNR :Build your own Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Build your own version of this European Six Flags park - - -STR_SCNR :Build your own Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Use your design skills to recreate this Six Flags park - - -STR_SCNR :Build your own Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Build this European Six Flags park the way you want to - - -STR_SCNR :Build your own Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Create your own version of this massive Six Flags park - - -STR_SCNR :Build your own Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Starting from scratch, build the rides in this Six Flags park - - -STR_SCNR :Build your own Six Flags Park -STR_PARK :Six Flags -STR_DTLS :Build your own design of Six Flags park - either build rides from other Six Flags parks or design and build your own rides - - -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Starting with a small market bazaar, your challenge is to increase the profit from shops and stalls by building rides and roller coasters to attract more customers - - -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :You have inherited a large castle. Your job is to convert it into a small theme park. - - -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Situated near a highway junction in the desert, Dusty Greens is an opportunity to develop a small golf resort into a thriving theme park - - -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :You have inherited a small farm, and your challenge is to build a small theme park amongst the fields and farm buildings - - -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Free of financial restrictions, your challenge is to expand this desert park to attract people seeking the ultimate thrills - - -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :An abandoned factory complex is an opportunity to build a mechanical-themed amusement park - - -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Restricted to only older-style wooden rides, your challenge is to build a thriving theme park in Fungus Woods - - -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Hired by a large amusement park chain, your task is to build them a giant roller coaster park around an abandoned mining town - - -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Your challenge is to build a roller coaster park in the beautiful Gravity Gardens. No other rides, just roller coasters! - - -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :A park nestled precariously on lava rock with streams of magma - - -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :With unlimited funds but a challenging lake location, this park will be a challenge to expand and manage - - -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :Built on a hillside, this park is forbidden from building anything tall. Can you expand the park and make it successful? - - -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to attract more guests to the park! - - -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Try your hand at running and improving this Six Flags park - - -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to repay your loan while keeping the park value up! - - -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Build the missing Six Flags rides, or create your own designs to improve the park! But don’t forget your ultimate aim: to attract more guests to the park! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :You inherited a disused diamond mine, and find a valuable diamond. You decide to invest that money to build a world-famous theme park. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :A desert Oasis has been discovered and would provide a beautiful location for a park. Transport to the oasis has been provided. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :A dam has been built offering abundant, cheap hydroelectric power with which to run a park. You need to reach a high park value to help repay the loan for the dam. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :The environment agency has turned to you to transform an old oil refinery ecological eyesore into a top tourist attraction. Land is cheap but loan interest is high. You can sell the old buildings for salvage. - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :The authorities have decided to enhance tourism around the Great Wall by building a theme park on the adjacent land. Money is no object! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :An existing park has run out of space. Your only option is to build out into the sea, and so you have taken out a loan. Height restrictions on your building are enforced due to foundations and earthquake risk. - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :You have been commissioned by the Maharaja to bring entertainment to the large local population. Build a park inspired by the Maharaja’s palace. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :You are helping Aboriginal people to build a park as part of a cultural awareness program. You need to get a large number of guests to educate them in the unique heritage of the Aboriginal people. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :A local entrepreneur’s sealife park has gone bust. You already operate a small park and buy the other park from the construction company. Develop a big combined park. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :You have been brought in to take over a European Cultural Visitor Attraction and must increase the number of guests in order to pay back the EU subsidy by the end of the current European parliament term. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :An old park has fallen into disrepair. You gain a European Union grant to return this deprived area to its former glory! You need to renovate the park and repay the grant. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :The people of Hawaii are bored of surfing and are looking for something more intense. You need to build a park with this in mind to keep the area’s tourist attraction rating high. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :You have to build a park on limited land either side of this natural treasure - you do have the opportunity to buy neighbouring land from the Native American Indians. You need to complete the objective to sustain the local town’s population. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :You are a successful business tycoon on long sabbatical who desires to use this time transforming the city park into Rollercoaster Heaven. Money is no object! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :To further boost local tourism you must construct a park that is in tune with its surroundings, and has height restrictions. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Space is limited in the precious rainforest - you must cram as much as possible into the existing clearing, in order to provide a viable alternative to the local timber industry. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :You run a small park near Rio but the bank has called in your loan. You need to quickly increase your earning capacity to repay this unexpected debt. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :Cliffside Castle -STR_PARK :Cliffside Castle -STR_DTLS :Local members of the battle re-enactment society are rather serious about their hobby. They’ve entrusted you with the job of constructing a Dark Age theme park on the grounds of Cliffside Castle. - - -STR_SCNR :Sherwood Forest -STR_PARK :Sherwood Forest -STR_DTLS :To liberate wealth from the rich and distribute it to the needy, you and your Merry Men have decided to build a theme park in Sherwood Forest. - - -STR_SCNR :Extraterrestrial Extravaganza -STR_PARK :Extraterrestrial Extravaganza -STR_DTLS :Life has been discovered on a distant planet Build an alien theme park to cash in on the unprecedented wave of interest. - - -STR_SCNR :Gemini City -STR_PARK :Gemini City -STR_DTLS :Show off your inventive, utopian vision of the future - come up with a futuristic park design that incorporates state-of-the-art attractions. - - -STR_SCNR :Animatronic Antics -STR_PARK :Animatronic Antics -STR_DTLS :You have been given the task of running and improving an existing theme park, which has been built on an old film set. Build a tribute to the pioneering stop-motion animators who first brought mythical creatures to life on the silver screen. - - -STR_SCNR :Mythological Madness -STR_PARK :Mythological Madness -STR_DTLS :You own an island of particular archaeological value. You’ve decided to fund its preservation by constructing a theme park based on the area’s rich Mythological heritage. - - -STR_SCNR :Crater Carnage -STR_PARK :Crater Carnage -STR_DTLS :You own a dusty old meteor crater. In the true entrepreneurial spirit, you’ve decided to construct an asteroid theme park and convert your seemingly worthless land into a sizeable fortune. - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :You’ve been given the task of constructing a Jurassic era theme park. To optimize your visitors’ access to the exotic plant and animal exhibits, you will need to build rides going over and into the valley. - - -STR_SCNR :Rocky Rambles -STR_PARK :Rocky Rambles -STR_DTLS :To thwart the highway developers and preserve the mysterious ancient stone circles, you will need to construct a Stone Age theme park and turn a profit. However, attracting visitors may pose a challenge, as the terrain is a tad inhospitable. - - -STR_SCNR :Alcatraz -STR_PARK :Alcatraz -STR_DTLS :The infamous Prison Island - whose population once swelled with bootleggers and racketeers - is now up for sale. You’ve decided to convert it into a top tourist attraction, and money is no object - - -STR_SCNR :Schneider Shores -STR_PARK :Schneider Shores -STR_DTLS :The 75th anniversary of your grandfather’s Schneider Cup victory is coming up in a few years. You’re going to honour his achievement by building a theme park based on the famous seaplane race. - - -STR_SCNR :Metropolis -STR_PARK :Metropolis -STR_DTLS :You own an empty lot near the low-rise part of town. To squeeze the most out of your urban property, build a skyscraper theme park inspired by the soaring art deco architecture of the twenties. - - -STR_SCNR :Woodstock -STR_PARK :Woodstock -STR_DTLS :A large annual music festival takes place on your land. Build a hip theme park to keep the free-spirited audience entertained. - - -STR_SCNR :Rock ‘n’ Roll Revival -STR_PARK :Rock ‘n’ Roll Revival -STR_DTLS :This aging theme park has seen better days. Help the owner give it a retro rock ‘n’ roll makeover and turn the place into a successful venue. - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Panda World -STR_PARK :Panda World -STR_DTLS :Add more rides and attract more people to this panda-themed park diff --git a/data/language/zh-CN.txt b/data/language/zh-CN.txt index 1046b25b30..c41afadb8b 100644 --- a/data/language/zh-CN.txt +++ b/data/language/zh-CN.txt @@ -3714,862 +3714,3 @@ STR_6642 :{STRING}({COMMA32} / {COMMA32}) STR_6643 :{STRING}({COMMA32} / {COMMA32} 千字节) STR_6644 :增强触控模式 STR_6645 :将一些用户界面元素放大,使其更容易点击或触碰。 - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :森之边林 -STR_PARK :森之边林 -STR_DTLS :在隐藏于森林深处的空地中,建造一个繁荣的主题公园 - - -STR_SCNR :炸药山丘 -STR_PARK :炸药山丘 -STR_DTLS :这个坐立于沙漠中的乐园只有一座云霄飞车,但不缺乏可供扩充的空地 - - -STR_SCNR :茂林湖 -STR_PARK :茂林湖 -STR_DTLS :在一个大型湖泊的旁边,从零开始兴建一个主题乐园 - - -STR_SCNR :钻石高地 -STR_PARK :钻石高地 -STR_DTLS :钻石高地已经是一个拥有极佳游乐设施,并且很发展得很成功的乐园——继续发展以让它的价值翻倍 - - -STR_SCNR :常青花园 -STR_PARK :常青花园 -STR_DTLS :将景色优美的常青花园转型成一个很受欢迎的乐园 - - -STR_SCNR :邦布利海滩 -STR_PARK :邦布利海滩 -STR_DTLS :将邦布利海滩这个小型乐园发展成一个繁荣的主题乐园 - - -STR_SCNR :三体群岛 -STR_PARK :三体群岛 -STR_DTLS :几个邻近的岛屿组成了这个新乐园的基本地势 - - -STR_SCNR :凯蒂梦之境 -STR_PARK :凯蒂梦之境 -STR_DTLS :一个只有几个游乐设施但有扩展空间的小型乐园——你的目标是让它的价值翻倍 - - -STR_SCNR :狭窄公园 -STR_PARK :狭窄公园 -STR_DTLS :一个拥挤的小型乐园,它需要大扩张 - - -STR_SCNR :净水公园 -STR_PARK :净水公园 -STR_DTLS :一个附有优良水上类游乐设施的乐园,它需要大扩张 - - -STR_SCNR :千年矿山 -STR_PARK :千年矿山 -STR_DTLS :将一个已被遗弃的大型矿坑由景点转型成一个乐园 - - -STR_SCNR :过山卡丁 -STR_PARK :过山卡丁 -STR_DTLS :一个隐藏在森林的大型乐园,但当中只有小型赛车及木制过山车 - - -STR_SCNR :梅尔的世界 -STR_PARK :梅尔的世界 -STR_DTLS :这个乐园已经有一些既优秀又现代的游乐设施,但它亦有很大的扩充空间 - - -STR_SCNR :神秘山 -STR_PARK :神秘山 -STR_DTLS :在神秘山的丘陵森林中,从零开始建造主题公园 - - -STR_SCNR :太平洋金字塔 -STR_PARK :太平洋金字塔 -STR_DTLS :将埃及遗址旅游景点改造成繁荣的主题公园 - - -STR_SCNR :老废物乐园 -STR_PARK :老废物乐园 -STR_DTLS :一个拥有精心设计但已经相当老旧的游乐设施的大型公园。更换旧的游乐设施或添加新的游乐设施,使公园更受欢迎。 - - -STR_SCNR :天堂码头 -STR_PARK :天堂码头 -STR_DTLS :将这个沉睡小镇的码头变成一个繁荣的景点。 - - -STR_SCNR :闪电峰 -STR_PARK :闪电峰 -STR_DTLS :闪电峰美丽的山脉深受步行者和观光者的欢迎。利用可用土地吸引新的寻求刺激的客户。 - - -STR_SCNR :象牙塔 -STR_PARK :象牙塔 -STR_DTLS :一个完善的但拥有一些小问题的公园。 - - -STR_SCNR :彩虹谷 -STR_PARK :彩虹谷 -STR_DTLS :彩虹谷的地方当局不允许任何景观变化或大树砍伐,但您必须将该地区开发成大型主题公园。 - - -STR_SCNR :雷霆岩 -STR_PARK :雷霆岩 -STR_DTLS :雷霆岩矗立在沙漠中央,吸引了众多游客。利用可用空间建造游乐设施以吸引更多人。 - - -STR_SCNR :超级乐园 -STR_PARK :超级乐园 -STR_DTLS :娱乐至上! - -## Added Attractions - -STR_SCNR :耳语崖 -STR_PARK :耳语崖 -STR_DTLS :将海边悬崖开发成繁华的游乐园 - - -STR_SCNR :三猴乐园 -STR_PARK :三猴乐园 -STR_DTLS :这个大型发展中公园的中心是一个巨大的三轨钢制过山车 - - -STR_SCNR :金丝雀矿 -STR_PARK :金丝雀矿 -STR_DTLS :这个被废弃矿山已经具备了成为旅游景点的条件,它有一条微型铁路和一对垂直坠落过山车 - - -STR_SCNR :男爵之桥 -STR_PARK :男爵之桥 -STR_DTLS :你要将一个多余的老破桥开发成游乐园 - - -STR_SCNR :疯狂快乐城 -STR_PARK :疯狂快乐城 -STR_DTLS :在高速公路两侧的这个公园已经有几个游乐设施在运营 - - -STR_SCNR :闹心港口 -STR_PARK :闹心港口 -STR_DTLS :当地政府同意在保留某些游乐设施的基础上将附近的土地廉价出售给这个小型海滨公园 - - -STR_SCNR :趣味堡垒 -STR_PARK :趣味堡垒 -STR_DTLS :这整个城堡都是你的,快把它改造为主题乐园吧 - - -STR_SCNR :未来之地 -STR_PARK :未来之地 -STR_DTLS :这个未来派的公园有足够的空间供新的游乐设施在其外星景观中使用 - - -STR_SCNR :温柔峡谷 -STR_PARK :温柔峡谷 -STR_DTLS :当地人喜欢温和而轻松的游乐设施,所以你的工作是扩大这个公园以适应他们的口味 - - -STR_SCNR :欢乐丛林 -STR_PARK :欢乐丛林 -STR_DTLS :丛林深处有大片土地准备变成主题公园 - - -STR_SCNR :海德鲁山 -STR_PARK :海德鲁山 -STR_DTLS :这个公园由一系列阶梯状的湖组成 - - -STR_SCNR :活泼公园 -STR_PARK :活泼公园 -STR_DTLS :这个古老的公园有许多历史悠久的游乐设施,但负债累累 - - -STR_SCNR :魔力拼 -STR_PARK :魔力拼 -STR_DTLS :由四等分的不同风情区域组成,大片土地已清理完毕,部分主题已准备好开发成景观主题公园 - - -STR_SCNR :水果农场 -STR_PARK :水果农场 -STR_DTLS :一个繁荣的水果农场修了一条铁路来增加收入,你的工作就是把它发展成一个成熟的游乐园 - - -STR_SCNR :蝴蝶坝 -STR_PARK :蝴蝶坝 -STR_DTLS :大坝周边的区域可以供你开发成一个主题公园 - - -STR_SCNR :过山车峡谷 -STR_PARK :过山车峡谷 -STR_DTLS :一个巨大的峡谷供你开发成一个主题公园 - - -STR_SCNR :雷雨公园 -STR_PARK :雷雨公园 -STR_DTLS :这里的天气非常潮湿,以至于建造了一个巨大的金字塔,以便在掩护下建造一些游乐设施 - - -STR_SCNR :和声山丘 -STR_PARK :和声山丘 -STR_DTLS :这个公园当地的政府不允许建造比树高的设施 - - -STR_SCNR :罗马村庄 -STR_PARK :罗马村庄 -STR_DTLS :通过增加更多的设施和过山车来开发这个罗马主题的公园 - - -STR_SCNR :沼泽湾 -STR_PARK :沼泽湾 -STR_DTLS :这个公园部分建在一系列小岛上,已经有一对大型过山车作为卖点 - - -STR_SCNR :肾上腺素高地 -STR_PARK :肾上腺素高地 -STR_DTLS :建造一个吸引寻求高强度刺激的当地人的公园 - - -STR_SCNR :乌托邦公园 -STR_PARK :乌托邦 -STR_DTLS :沙漠中的绿洲为建造游乐园提供了难得的机会 - - -STR_SCNR :腐烂高地 -STR_PARK :腐烂高地 -STR_DTLS :杂草丛生,破败不堪,你能复活这个曾经伟大的游乐园吗? - - -STR_SCNR :惨淡森林 -STR_PARK :惨淡森林 -STR_DTLS :充满设计不良和危险的游乐设施,您的预算和时间非常有限,解决这些问题并扭转乐园的颓势。 - - -STR_SCNR :腌黄瓜公园 -STR_PARK :腌黄瓜公园 -STR_DTLS :地方政府不允许任何形式的广告或促销,所以这个公园必须靠声誉才能赢得成功。 - - -STR_SCNR :伤心嬉笑 -STR_PARK :伤心嬉笑 -STR_DTLS :四车道障碍赛是这个不断扩大的游乐园的核心 - - -STR_SCNR :采石场公园 -STR_PARK :采石场公园 -STR_DTLS :将这个废弃的采石场变成吸引寻求刺激的游客的地方 - - -STR_SCNR :狂热过山车 -STR_PARK :狂热过山车 -STR_DTLS :用有限的金钱和无限的时间把这个山脚下的地区变成一个巨大的游乐园吧 - - -STR_SCNR :城市公园 -STR_PARK :城市公园 -STR_DTLS :一个小公园与附近的城镇达成了一项协议,允许经过城镇上空向周边进行扩张 - - -STR_SCNR :杰弗里花园 -STR_PARK :杰弗里花园 -STR_DTLS :一个大型花园公园需要变成一个欣欣向荣的主题公园 - - -## Loopy Landscapes - -STR_SCNR :冰山群岛 -STR_PARK :冰山群岛 -STR_DTLS :一系列冰山为这个雄心勃勃的主题公园营造了一个寒冷的环境 - - -STR_SCNR :火焰之域 -STR_PARK :火焰之域 -STR_DTLS :这座休眠的火山就是过山车建造挑战的背景 - - -STR_SCNR :干旱高地 -STR_PARK :干旱高地 -STR_DTLS :你的挑战是在没有任何的财政限制的情况下开发一个一直使游客开心的沙漠公园 - - -STR_SCNR :剃刀岩 -STR_PARK :剃刀岩 -STR_DTLS :你的任务是在一个巨大的岩石群中建造充满过山车的乐园 - - -STR_SCNR :中心湖 -STR_PARK :中心湖 -STR_DTLS :一个坐落于古老火山口中的湖上的主题乐园 - - -STR_SCNR :头晕眼花 -STR_PARK :头晕眼花 -STR_DTLS :这个大型公园已经有一个非常好的超级过山车,但你的任务是大幅增加其利润 - - -STR_SCNR :天堂码头2 -STR_PARK :天堂码头2 -STR_DTLS :天堂码头已经在海上扩展了它的人行道网络,你的任务是扩大公园以利用额外的空间 - - -STR_SCNR :卧龙湾 -STR_PARK :卧龙湾 -STR_DTLS :这个海湾就是过山车建造挑战的背景 - - -STR_SCNR :佳爵公园 -STR_PARK :佳爵公园 -STR_DTLS :一座有过山车的城堡需要发展成一个更大的主题公园 - - -STR_SCNR :狡兔三窟 -STR_PARK :狡兔三窟 -STR_DTLS :一个大多数人行道和过山车都在地下的公园 - - -STR_SCNR :大冰川 -STR_PARK :大冰川 -STR_DTLS :一个充满冰川的山谷等你开发成游乐园 - - -STR_SCNR :疯狂陨石坑 -STR_PARK :疯狂陨石坑 -STR_DTLS :在一个不需要钱的遥远世界里,你必须建造一个娱乐中心来让人们开心 - - -STR_SCNR :飞尘沙漠 -STR_PARK :飞尘沙漠 -STR_DTLS :这个沙漠公园里有五座过山车需要你完成 - - -STR_SCNR :朽木公园 -STR_PARK :朽木公园 -STR_DTLS :这个久经沙场的公园只允许建造老式设施 - - -STR_SCNR :伊卡洛斯公园 -STR_PARK :伊卡洛斯公园 -STR_DTLS :开发这个外星公园并且最大化你的收益 - - -STR_SCNR :阳光沼泽 -STR_PARK :阳光沼泽 -STR_DTLS :这个主题鲜明的游乐园已经有好几部游乐设施,但仍有足够的扩展空间等你来扩张 - - -STR_SCNR :惊魂山丘 -STR_PARK :惊魂山丘 -STR_DTLS :一个在中心有一座巨大过山车的诡异公园 - - -STR_SCNR :雷霆巨石 -STR_PARK :雷霆巨石 -STR_DTLS :在沙漠上的两块巨型岩柱上构建的主题公园 - - -STR_SCNR :八角游乐园 -STR_PARK :八角游乐园 -STR_DTLS :在这个大公园里你需要设计建造十种大型过山车 - - -STR_SCNR :欢悦岛 -STR_PARK :欢悦岛 -STR_DTLS :一个狭长的岛屿使得过山车的建筑变得富有挑战 - - -STR_SCNR :冰封世界 -STR_PARK :冰封世界 -STR_DTLS :一个极地主题乐园等你来把它变得欣欣向荣 - - -STR_SCNR :南方沙漠 -STR_PARK :南方沙漠 -STR_DTLS :一个有着几座设计精明的过山车的沙漠公园等你扩张 - - -STR_SCNR :小方块 -STR_PARK :小方块 -STR_DTLS :在这个小公园里你必须完成五座未完成的过山车 - - -STR_SCNR :永无止境公园 -STR_PARK :永无止境公园 -STR_DTLS :一个有着与众不同的交通系统环绕的大公园 - - -STR_SCNR :太平岛 -STR_PARK :太平岛 -STR_DTLS :你的这个大岛屿需要你来改造成为游乐园 - - -STR_SCNR :都市丛林 -STR_PARK :都市丛林 -STR_DTLS :一座巨大的废弃摩天大楼对主题公园开发商来说是一个难得的机会 - - -STR_SCNR :恐怖镇 -STR_PARK :恐怖镇 -STR_DTLS :你的这个小镇需要你来改造成为游乐园 - - -STR_SCNR :巨型世界公园 -STR_PARK :巨型世界公园 -STR_DTLS :需要你去改进一个有很多过山车的巨大公园 - - -STR_SCNR :金星池塘 -STR_PARK :金星池塘 -STR_DTLS :在一个遥远的星球的土地上创造一个主题公园 - - -STR_SCNR :微型公园 -STR_PARK :微型公园 -STR_DTLS :试着建造一个世界上最小的公园 - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :奥尔顿塔 -STR_PARK :奥尔顿塔 -STR_DTLS : - - -STR_SCNR :海德公园 -STR_PARK :海德公园 -STR_DTLS : - - -STR_SCNR :布莱克浦游乐海滩 -STR_PARK :布莱克浦游乐海滩 -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :时空堡垒 -STR_PARK :时空堡垒 -STR_DTLS : - -########### -# Scenery # -########### - -## Start OpenRCT2 Official - -[TTPIRF05] - -STR_NAME :屋顶 - -## End OpenRCT2 Official - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :阿尔卑斯历险记 -STR_PARK :阿尔卑斯历险记 -STR_DTLS :将一个小滑雪胜地转型为一个以冰雪为主题的游乐园 - - -STR_SCNR :和睦机场 -STR_PARK :和睦机场 -STR_DTLS :在这个被遗弃的飞机场建立一个以飞行为主题的游乐园 - - -STR_SCNR :绿色杀手 -STR_PARK :绿色杀手 -STR_DTLS :你的挑战是在这个天堂岛上建立一个高利润的游乐园 - - -STR_SCNR :建造你自己的 六旗比利时游乐园 -STR_PARK :六旗比利时 -STR_DTLS :建立自己的这个六旗比利时游乐园的版本 - - -STR_SCNR :建造你自己的 六旗大冒险游乐园 -STR_PARK :六旗大冒险 -STR_DTLS :使用您的设计技能来重建这个六旗游乐园 - - -STR_SCNR :建造你自己的 六旗荷兰游乐园 -STR_PARK :六旗荷兰 -STR_DTLS :以你想要的方式建造这个欧洲六旗游乐园 - - -STR_SCNR :建造你自己的 六旗魔法山游乐园 -STR_PARK :六旗魔法山 -STR_DTLS :创建你自己的大型六旗游乐园的版本 - - -STR_SCNR :建造你自己的 六旗降临得克萨斯游乐园 -STR_PARK :六旗降临得克萨斯 -STR_DTLS :从零开始,建造这个六旗游乐园的游乐设施 - - -STR_SCNR :建造你自己的 六旗游乐园 -STR_PARK :六旗游乐园 -STR_DTLS :建造你自己设计的六旗游乐园——你可以从其他六旗游乐园借鉴或者设计建造你自己的游乐设施 - - -STR_SCNR :混乱集市 -STR_PARK :混乱集市 -STR_DTLS :从一个小集市,你的挑战是增加商店利润,建设商店及游乐设施和过山车来吸引更多的顾客 - - -STR_SCNR :疯狂城堡 -STR_PARK :疯狂城堡 -STR_DTLS :你继承了一个大的城堡——你的工作是把它转型成一个小型主题公园。 - - -STR_SCNR :沙尘绿地 -STR_PARK :沙尘绿地 -STR_DTLS :位于沙漠附近的一个公路交界处,是时候把沙尘绿地这个小高尔夫度假村发展成为一个繁荣的主题公园了 - - -STR_SCNR :电气田野 -STR_PARK :电气田野 -STR_DTLS :你继承了一个小农场,你的挑战是在农田和农场建筑之间建立一个小型主题乐园 - - -STR_SCNR :终极高地 -STR_PARK :终极高地 -STR_DTLS :自由的金融限制,你的挑战是如何扩大这个沙漠游乐园吸引人们寻求终极的刺激 - - -STR_SCNR :工厂冒险 -STR_PARK :工厂冒险 -STR_DTLS :一个废弃的工厂是你的机遇,把它建造成一个机械为主题的游乐园 - - -STR_SCNR :真菌森林 -STR_PARK :真菌森林 -STR_DTLS :仅限于老式的木制游乐设施,你的挑战是在真菌森林建造一个蓬勃发展的主题乐园 - - -STR_SCNR :鬼城 -STR_PARK :鬼城 -STR_DTLS :由一个大型的娱乐公园开始,你的任务是在一个废弃的采矿镇周围建造一个巨大的过山车游乐园 - - -STR_SCNR :重力花园 -STR_PARK :重力花园 -STR_DTLS :你的挑战是在重力花园没有其他设施可用的条件下打造过山车游乐园,只能建造过山车! - - -STR_SCNR :炼狱 -STR_PARK :炼狱 -STR_DTLS :公园坐落在炙热的熔岩流和不稳定的岩浆中 - - -STR_SCNR :幸运湖泊 -STR_PARK :幸运湖泊 -STR_DTLS :你有了无限的资金,但湖泊是一个具有挑战性的位置,这个公园将是一个挑战,扩大它并运营它 - - -STR_SCNR :彩虹尽头 -STR_PARK :彩虹尽头 -STR_DTLS :这个游乐园建在一个山坡上,禁止建造任何高的东西。你能扩大游乐园,使它成功吗? - - -STR_SCNR :六旗比利时 -STR_PARK :六旗比利时 -STR_DTLS :尝试用你的手运营并改进这座六旗游乐园 - - -STR_SCNR :六旗大冒险 -STR_PARK :六旗大冒险 -STR_DTLS :建造遗失的六旗乐园游乐设施,或用自己的设计善公园!但别忘了你的最终目标——吸引更多的客人到公园去! - - -STR_SCNR :六旗荷兰 -STR_PARK :六旗荷兰 -STR_DTLS :尝试用你的手运营并改进这座六旗游乐园 - - -STR_SCNR :六旗魔术山 -STR_PARK :六旗魔术山 -STR_DTLS :建造遗失的六旗乐园游乐设施,或用自己的设计善公园!但别忘了你的最终目标——偿还贷款,同时保持公园价值! - - -STR_SCNR :六旗降临得克萨斯 -STR_PARK :六旗降临得克萨斯 -STR_DTLS :建造遗失的六旗乐园游乐设施,或用自己的设计善公园!但别忘了你的最终目标——吸引更多的客人到公园去! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :非洲矿山 -STR_PARK :非洲矿山 -STR_DTLS :你继承了一个废弃的钻石矿,并找到一个珍贵的钻石。你决定用那笔钱去建造一个世界闻名的主题乐园。 - - -STR_SCNR :海市蜃楼狂热 -STR_PARK :海市蜃楼狂热 -STR_DTLS :一个沙漠绿洲被发现了,它为游乐园提供了一个美丽的环境。游乐园已有绿洲运输。 - - -STR_SCNR :大河边缘 -STR_PARK :大河边缘 -STR_DTLS :当地建成了一个大坝,提供了丰富的,廉价的水电,用来运行一个公园。你需要用公园来获得很多的钱,用来偿还建造大坝的贷款。 - - -STR_SCNR :冰冷冒险 -STR_PARK :冰冷冒险 -STR_DTLS :环境署已经把你碍眼的旧炼油厂改造成顶级生态的旅游胜地。土地便宜但贷款利息高。你可以卖掉旧建筑来赚钱。 - - -STR_SCNR :中国长城 -STR_PARK :中国长城 -STR_DTLS :当局已决定在附近的土地上建造主题公园,以加强在长城周边的旅游业发展。 - - -STR_SCNR :冲绳海岸 -STR_PARK :冲绳海岸 -STR_DTLS :一个现有的公园已经用完了空间。你唯一的选择是建立在海上,所以你采取了贷款。你的建筑的高度被地基和地震风险限制。 - - -STR_SCNR :迈索尔公园 -STR_PARK :迈索尔公园 -STR_DTLS :你被委托为当地人建造大型的娱乐设施。由王公的宫殿改建成一个游乐园。 - - -STR_SCNR :艾尔斯冒险 -STR_PARK :艾尔斯冒险 -STR_DTLS :作为文化意识计划的一部分,你要帮助土著人建立一个游乐园。你需要让大量的客人知道土著们具有独特的文化遗产。 - - -STR_SCNR :海滩烧烤风 -STR_PARK :海滩烧烤风 -STR_DTLS :一个本地企业家的海滨游乐园已经破产。你已经经营了一个小游乐园,你要从建筑公司购买另一个游乐园。开发一个大联合游乐园。 - - -STR_SCNR :欧洲盛会 -STR_PARK :欧洲盛会 -STR_DTLS :你被安排接管一个欧洲文化游的景点,必须增加客人的数量,在目前的欧洲议会任期结束前支付加入欧盟的税款。 - - -STR_SCNR :来自灰烬 -STR_PARK :来自灰烬 -STR_DTLS :一个老公园年久失修。你获得一个欧盟的补助金,将这个被剥夺的地区归还给它昔日的荣耀!你需要整修公园并偿还补助金。 - - -STR_SCNR :积极威基基 -STR_PARK :积极威基基 -STR_DTLS :夏威夷的人们厌倦了冲浪,寻找更刺激的东西。你需要建立一个游乐园,以保持该地区的旅游评级。 - - -STR_SCNR :峡谷浩劫 -STR_PARK :峡谷浩劫 -STR_DTLS :你必须在有限的土地上建立一个游乐园,这里有自然财富——从美洲印第安人那里有机会购买邻近的土地。维持当地城镇的人口是你需要完成的目标。 - - -STR_SCNR :过山车天堂 -STR_PARK :过山车天堂 -STR_DTLS :你是在休假想要利用这段时间改造城市公园的过山车的天堂一个成功的商业大亨。金钱是没有目标的! - - -STR_SCNR :失落之城 -STR_PARK :失落之城 -STR_DTLS :为了进一步促进当地旅游业的发展,你需要建设一个与周围环境相协调的公园。 - - -STR_SCNR :嬉闹雨林 -STR_PARK :嬉闹雨林 -STR_DTLS :空间是有限的宝贵的热带雨林——你必须尽可能多地塞进现有的结算,以提供一个可行的替代当地木材业。 - - -STR_SCNR :蜜糖面包海岸 -STR_PARK :蜜糖面包海岸 -STR_DTLS :你在里约附近的一个小公园,但银行已在你的贷款。你需要快速提高你的盈利能力来偿还这意想不到的债务。 - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :悬崖城堡 -STR_PARK :悬崖城堡 -STR_DTLS :战斗的地方成员重新制定的社会是相当严重的他们的爱好。他们委托你在悬崖边的城堡的场地建设一个黑暗时代的主题公园的工作。 - - -STR_SCNR :舍伍德森林 -STR_PARK :舍伍德森林 -STR_DTLS :为了把财富从富人中解放出来并分发给有需要的人,你和你的快乐的人决定在舍伍德森林里建立一个主题公园。 - - -STR_SCNR :外星盛会 -STR_PARK :外星盛会 -STR_DTLS :生命在一个遥远的星球上被发现,建造一个外星人主题公园,以现金在前所未有的兴趣浪潮。 - - -STR_SCNR :双子城 -STR_PARK :双子城 -STR_DTLS :炫耀你的创造性的,乌托邦式的未来愿景——想出一个未来的公园设计,结合国家的最先进的景点。 - - -STR_SCNR :古怪的动画电影 -STR_PARK :古怪的动画电影 -STR_DTLS :你已经被赋予了运行和改进现有的主题公园的任务,它是建立在一个旧的电影集上的。建立一个向创业的定格动画人第一次带来了神秘的生物生活在银幕上。 - - -STR_SCNR :神话狂热 -STR_PARK :神话狂热 -STR_DTLS :你拥有一个特定的考古价值的岛屿。你已经决定采用基于地区丰富的神话遗产建设主题公园的保护基金。 - - -STR_SCNR :陨石坑大战 -STR_PARK :陨石坑大战 -STR_DTLS :你拥有一个布满灰尘的老流星陨石坑。在真正的创业精神,你已经决定建造一个小行星主题公园,并转换你的看似毫无价值的土地变成一个相当大的财富。 - - -STR_SCNR :过山龙 -STR_PARK :过山龙 -STR_DTLS :你被赋予了建设一个侏罗纪时代主题公园的任务。为了优化您的游客访问异国情调的植物和动物的展品,你将需要建立乘坐去到山谷。 - - -STR_SCNR :洛基漫步 -STR_PARK :洛基漫步 -STR_DTLS :为了阻止公路的开发和维护神秘的古老的石头圈,你将需要建造一个石器时代主题公园,并把利润。然而,吸引游客可能会构成挑战,因为地形有点荒凉。 - - -STR_SCNR :恶魔岛 -STR_PARK :恶魔岛 -STR_DTLS :臭名昭著的监狱岛的人口曾经充满了走私犯和诈骗犯——现在出售。你已经决定把它变成一个顶级的旅游景点,钱是没有对象 - - -STR_SCNR :施耐德海岸 -STR_PARK :施耐德海岸 -STR_DTLS :你的祖父的施耐德杯胜利第七十五周年是几年来。你要尊重自己的成就,通过构建一个基于著名的水上飞机比赛主题公园。 - - -STR_SCNR :大都会 -STR_PARK :大都会 -STR_DTLS :你拥有一个空的地段,靠近城镇的低矮的部分。把最贵的城市属性,建立一个主题公园的启发,摩天大楼高耸的建筑装饰艺术的年代。 - - -STR_SCNR :伍德斯托克 -STR_PARK :伍德斯托克 -STR_DTLS :一个大型的年度音乐节在你的土地上。打造一个主题公园,保持自由奔放的观众的娱乐。 - - -STR_SCNR :摇滚复兴 -STR_PARK :摇滚复兴 -STR_DTLS :这个老龄化的主题公园已经看到了更好的日子。帮助主人给它一个复古摇滚的改造,把这个地方变成一个成功的地点。 - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :熊猫世界 -STR_PARK :熊猫世界 -STR_DTLS :增加更多的设施来吸引更多的顾客来到这个熊猫主题的乐园. - - -STR_SCNR :大亨公园 -STR_PARK :大亨公园 -STR_DTLS : - -### - -STR_SCNR :墓地飞车 -STR_PARK :墓地飞车 -STR_DTLS :万圣节到了,UCES万圣节,南瓜在夜深人静时尖叫!这个墓地有麻烦了,由你来拯救它,同时让死者安息!你能把鬼魂留在他们的坟墓里,给你的顾客带来寒意吗? - -############################################################################### -## UCES: The Time Machine (2003) -############################################################################### - -STR_SCNR :亚历山德里亚的灯塔 -STR_PARK :亚历山德里亚的灯塔 -STR_DTLS :亚历山大建造了这座城市;希腊人、罗马人、埃及人纷纷留下了他们的印记。但最大的荣耀是来自古代世界的奇迹——灯塔。建造一个公园!{NEWLINE}作者:Katatude - - -STR_SCNR :克利夫兰的月神公园 -STR_PARK :月神公园 -STR_DTLS :一切就像它开幕当天一样——1905年5月18日。{NEWLINE}作者:Aetherwave - - -STR_SCNR :维苏威火山 -STR_PARK :维苏威火山 -STR_DTLS :维苏威火山在公元79年喷发,庞贝古城和赫库兰尼姆被深埋地下。参观挖掘并建造公园!{NEWLINE}作者:Katatude - - -STR_SCNR :沙盒 -STR_PARK :沙盒 -STR_DTLS :每个人都想拥有的——沙盒!所以拿起你的桶和铲子,建造一个公园吧!{NEWLINE}作者:Katatude - - -STR_SCNR :尼亚加拉大瀑布和峡谷 -STR_PARK :尼亚加拉大瀑布 -STR_DTLS :美国的瀑布,婚纱样的瀑布,加拿大的瀑布,在尼亚加拉丛林旁,1850年。{NEWLINE}作者:Katatude - - -STR_SCNR :落石山矿工 -STR_PARK :落石山矿工 -STR_DTLS :泥石流摧毁了你的铁路。通过工人的勘探,过山车中貌似有黄金?{NEWLINE}作者:Squid,Buckone,Fossil - - -STR_SCNR :时间机器 -STR_PARK :时间机器 -STR_DTLS :时间机器。一个用来去往任何你想去的时间,任何你想去的地点。等待永恒。这都是相对的。{NEWLINE}作者:Katatude - - -STR_SCNR :吵闹之塔 -STR_PARK :吵闹之塔 -STR_DTLS :哇奥!看看这这个时间机器吧我们带到哪里去了!大家都去哪了?{NEWLINE}作者:Fossil - - -STR_SCNR :做出改变 -STR_PARK :做出改变 -STR_DTLS :我们会希望你可以……{NEWLINE}作者:Fossil - - -STR_SCNR :世外桃源 -STR_PARK :世外桃源 -STR_DTLS :罗马人厌倦了无聊的角斗士战斗。给他们更多的刺激,把神秘的罗马城市变成有史以来最伟大的游乐园!{NEWLINE}作者:Kaffe - -############################################################################### -## UCES: Katy's Dreamworld (2003) -############################################################################### - - -STR_SCNR :圣诞树下 -STR_PARK :冬季仙境 -STR_DTLS :妈妈在树下创造了这个场景,现在,她想要在这里创造一个游乐园!你能帮忙吗?{NEWLINE}作者:Katatude - - -STR_SCNR :巨石镇大爆炸 -STR_PARK :巨石镇大爆炸 -STR_DTLS :在巨石镇矿产公司发生爆炸后,巨石镇的人们不得不建造一个游乐园来维持他们的城镇活力。{NEWLINE}作者:rbarclay & buckone - - -STR_SCNR :嘲鸫夏令营 -STR_PARK :嘲鸫夏令营 -STR_DTLS :这个夏令营每个月只有500美元!找银行吧,玩的开心就好!建造一个游乐园。{NEWLINE}作者:Katatude - - -STR_SCNR :呜呜小镇 -STR_PARK :呜呜小镇 -STR_DTLS :妈咪!爸比!我想去呜呜小镇!{NEWLINE}作者:Fossil - - -STR_SCNR :龙之岛 -STR_PARK :龙之岛 -STR_DTLS :龙之岛?我可不确定我会想去那……{NEWLINE}作者:Fossil - - -STR_SCNR :基迪嘉年华2 -STR_PARK :基迪嘉年华 -STR_DTLS :嘿,孩子们!玩的开心!{NEWLINE}作者:Piehead & Fossil - - -STR_SCNR :梦幻沙丘 -STR_PARK :梦幻沙丘 -STR_DTLS :你是一个小公园的拥有者,你买了一大块土地去扩展,希望可以吸引更多的游客来欣赏美丽的沙丘,但是别忘了:你可不能破坏沙丘的生态平衡。{NEWLINE}作者:rbarclay diff --git a/data/language/zh-TW.txt b/data/language/zh-TW.txt index 0332da8bfc..45f3bc32e3 100644 --- a/data/language/zh-TW.txt +++ b/data/language/zh-TW.txt @@ -3608,748 +3608,3 @@ STR_6535 :{WINDOW_COLOUR_2}噁心度加成: {BLACK}-{COMMA16}% STR_6536 :此樂園從較新的OpenRCT2中儲存. 儲存樂園文件版本為v{INT32}. 你目前使用v{INT32}. STR_6537 :容許使用一般道路為輪候區 STR_6538 :於“道路”視窗內的輪候區下拉選單中顯示一般道路. - -############# -# Scenarios # -################ -# RCT Original # -################ - -STR_SCNR :Forest Frontiers -STR_PARK :Forest Frontiers -STR_DTLS :在隱藏於森林深處的清空範圍中, 建造一個很受歡迎的樂園 - - -STR_SCNR :Dynamite Dunes -STR_PARK :Dynamite Dunes -STR_DTLS :這個座立於沙漠中的樂園只有一座雲霄飛車, 但不缺乏可供擴充的區域 - - -STR_SCNR :Leafy Lake -STR_PARK :Leafy Lake -STR_DTLS :在一個大型湖泊的旁邊, 由零開始建造一個樂園 - - -STR_SCNR :Diamond Heights -STR_PARK :Diamond Heights -STR_DTLS :Diamond Heights已經是一個擁有極佳遊樂設施, 並且很發展得很成功的樂園 - 繼續發展它讓它的價值翻倍 - - -STR_SCNR :Evergreen Gardens -STR_PARK :Evergreen Gardens -STR_DTLS :將景色優美的Evergreen Gardens轉型成一個很受歡迎的樂園 - - -STR_SCNR :Bumbly Beach -STR_PARK :Bumbly Beach -STR_DTLS :將Bumbly Beach這個小型樂園發展成一個很受歡迎的樂園 - - -STR_SCNR :Trinity Islands -STR_PARK :Trinity Islands -STR_DTLS :幾個鄰近的島嶼組成了這個新樂園的基本地勢 - - -STR_SCNR :Katie’s Dreamland -STR_PARK :Katie’s Dreamland -STR_DTLS :一個只有幾個遊樂設施但有擴展空間的小型樂園 - 你的目標是讓它的價值翻倍 - - -STR_SCNR :Pokey Park -STR_PARK :Pokey Park -STR_DTLS :一個擠迫的小型樂園, 它需要重大擴張 - - -STR_SCNR :White Water Park -STR_PARK :White Water Park -STR_DTLS :一個附有優良水文類遊樂設施的樂園, 它需要重大擴張 - - -STR_SCNR :Millennium Mines -STR_PARK :Millennium Mines -STR_DTLS :將一個已被遺棄的大型礦坑由景點轉型成一個樂園 - - -STR_SCNR :Karts & Coasters -STR_PARK :Karts & Coasters -STR_DTLS :一個隱藏在森林的大型樂園, 但當中只有小型賽車及木製雲霄飛車 - - -STR_SCNR :Mel’s World -STR_PARK :Mel’s World -STR_DTLS :這個樂園已經有一些既優秀又現代的遊樂設施, 但它亦有很大的擴充空間 - - -STR_SCNR :Mystic Mountain -STR_PARK :Mystic Mountain -STR_DTLS :在Mystic Mountain的崎嶇不平森林中, 由零開始建造一個樂園 - - -STR_SCNR :Pacific Pyramids -STR_PARK :Pacific Pyramids -STR_DTLS :將這個一直為旅遊景點的埃及遺址轉型成一個很受歡迎的樂園 - - -STR_SCNR :Crumbly Woods -STR_PARK :Crumbly Woods -STR_DTLS :一個擁有老舊但設計妥善的遊樂設施的大型樂園 - 取代那些遊樂設施或添加新的遊樂設施來使樂園變得更受歡迎 - - -STR_SCNR :Paradise Pier -STR_PARK :Paradise Pier -STR_DTLS :將這個平凡無奇的小鎮碼頭轉型成一個很受歡迎的樂園 - - -STR_SCNR :Lightning Peaks -STR_PARK :Lightning Peaks -STR_DTLS :雄偉的Lightning Peaks一直都是遊客及觀光客的首選 - 善用可用的土地來吸引尋找刺激的新顧客 - - -STR_SCNR :Ivory Towers -STR_PARK :Ivory Towers -STR_DTLS :一個有數項問題的知名樂園 - - -STR_SCNR :Rainbow Valley -STR_PARK :Rainbow Valley -STR_DTLS :Rainbow Valley的當地政府不容許改變土地或移除樹木, 但你要將此地區發展為一個大型樂園 - - -STR_SCNR :Thunder Rock -STR_PARK :Thunder Rock -STR_DTLS :Thunder Rock豎立一個在沙漠中部, 並因此吸引遊客 - 將可用的空間建造遊樂設施來吸引更多遊客 - - -STR_SCNR :Mega Park -STR_PARK :Mega Park -STR_DTLS :盡情玩吧! - -## Added Attractions - -STR_SCNR :Whispering Cliffs -STR_PARK :Whispering Cliffs -STR_DTLS :將這個海邊懸崖發展成一個很受歡迎的樂園 - - -STR_SCNR :Three Monkeys Park -STR_PARK :Three Monkeys Park -STR_DTLS :此發展中的大型樂園中部有三座互相競賽的鐵架旋轉式雲霄飛車 - - -STR_SCNR :Canary Mines -STR_PARK :Canary Mines -STR_DTLS :因為擁有一條觀光鐵路及兩座垂直雲霄飛車, 這個已荒廢的礦場具有成為旅遊景點的潛力 - - -STR_SCNR :Barony Bridge -STR_PARK :Barony Bridge -STR_DTLS :一條古舊並多餘的橋現可由你任意發展成一個樂園 - - -STR_SCNR :Funtopia -STR_PARK :Funtopia -STR_DTLS :這個被一條高速公路所分開的樂園已擁有幾個已在運行的遊樂設施 - - -STR_SCNR :Haunted Harbour -STR_PARK :Haunted Harbour -STR_DTLS :當地政府已同意將鄰近的土地以低廉的價格販賣給這個小型海邊樂園, 但條件是要保留某些遊樂設施 - - -STR_SCNR :Fun Fortress -STR_PARK :Fun Fortress -STR_DTLS :這個城堡現可由你任意發展成一個樂園 - - -STR_SCNR :Future World -STR_PARK :Future World -STR_DTLS :這個於外星土地上, 並富有未來感的樂園擁有很多建造遊樂設施的空間 - - -STR_SCNR :Gentle Glen -STR_PARK :Gentle Glen -STR_DTLS :當地居民比較喜愛溫和及令人放鬆的遊樂設施, 所以你的任務便是要將這個樂園以他們的口味擴建 - - -STR_SCNR :Jolly Jungle -STR_PARK :Jolly Jungle -STR_DTLS :埋藏在森林深處的一塊巨型土地現已準備改造為一個主題樂園 - - -STR_SCNR :Hydro Hills -STR_PARK :Hydro Hills -STR_DTLS :一連串的梯間湖是這個全新樂園的根基 - - -STR_SCNR :Sprightly Park -STR_PARK :Sprightly Park -STR_DTLS :這個古舊的樂園擁有很多具歷史性的遊樂設施, 但它欠債纍纍 - - -STR_SCNR :Magic Quarters -STR_PARK :Magic Quarters -STR_DTLS :一塊巨型的土地現已清空並部份裝飾好, 可供你發展成一個有特色的主題樂園 - - -STR_SCNR :Fruit Farm -STR_PARK :Fruit Farm -STR_DTLS :一個壯大中的果園已建造一條鐵路來增加收入, 你的任務要將它發展成一個完善的主題樂園 - - -STR_SCNR :Butterfly Dam -STR_PARK :Butterfly Dam -STR_DTLS :這個圍繞水霸的地方現可由你任意發展成一個樂園 - - -STR_SCNR :Coaster Canyon -STR_PARK :Coaster Canyon -STR_DTLS :這個巨大的峽谷現可由你任意發展成一個樂園 - - -STR_SCNR :Thunderstorm Park -STR_PARK :Thunderstorm Park -STR_DTLS :這裡的天氣實在太多雨, 因此一座巨型金字塔的存在可供一些遊樂設施建造於其之中 - - -STR_SCNR :Harmonic Hills -STR_PARK :Harmonic Hills -STR_DTLS :當地政府不會容許你於這個樂園內建造高於樹木的高度 - - -STR_SCNR :Roman Village -STR_PARK :Roman Village -STR_DTLS :以添加遊樂設施及雲霄飛車發展這個羅馬主題的樂園 - - -STR_SCNR :Swamp Cove -STR_PARK :Swamp Cove -STR_DTLS :此樂園已經有一對建造在數個小島嶼上的巨型雲霄飛車作為它的靈魂 - - -STR_SCNR :Adrenaline Heights -STR_PARK :Adrenaline Heights -STR_DTLS :建造一個能吸引喜好高刺激度遊樂設施的當地遊客前往的樂園 - - -STR_SCNR :Utopia Park -STR_PARK :Utopia -STR_DTLS :一個沙漠中的綠洲帶來了一個非比尋常的機會去建造一個主題樂園 - - -STR_SCNR :Rotting Heights -STR_PARK :Rotting Heights -STR_DTLS :你能拯救這個曾經輝煌過, 但現殘破又雜草叢生的主題樂園嗎? - - -STR_SCNR :Fiasco Forest -STR_PARK :Fiasco Forest -STR_DTLS :你只有非常有限的資金及時間去修復這一個充滿不同劣質設計及非常危險的遊樂設施的樂園 - - -STR_SCNR :Pickle Park -STR_PARK :Pickle Park -STR_DTLS :當地政府並不准許任何營銷活動, 所以這個樂園必須要以名譽來達至成功 - - -STR_SCNR :Giggle Downs -STR_PARK :Giggle Downs -STR_DTLS :四座馬術障礙賽式雲霄飛車是這個需要擴張的樂園的靈魂 - - -STR_SCNR :Mineral Park -STR_PARK :Mineral Park -STR_DTLS :將這個已廢棄的石礦轉型成一個能夠吸引喜好剌激的遊客前往的地方 - - -STR_SCNR :Coaster Crazy -STR_PARK :Coaster Crazy -STR_DTLS :你擁有有限的金錢但無限的時間來將這個山區轉變成一個巨大的雲霄飛車樂園 - - -STR_SCNR :Urban Park -STR_PARK :Urban Park -STR_DTLS :這個微小的樂園已與鄰近城鎮商討好使用後者來擴充前者的交易 - - -STR_SCNR :Geoffrey Gardens -STR_PARK :Geoffrey Gardens -STR_DTLS :一個大型的賞花公園需要改造為一個壯大的主題樂園 - - -## Loopy Landscapes - -STR_SCNR :Iceberg Islands -STR_PARK :Iceberg Islands -STR_DTLS :一些冰川為此雄心勃勃的主題樂園帶來了一絲寒意 - - -STR_SCNR :Volcania -STR_PARK :Volcania -STR_DTLS :此建造雲霄飛車挑戰設定於一座沉睡火山之中 - - -STR_SCNR :Arid Heights -STR_PARK :Arid Heights -STR_DTLS :沒有任何財政上的限制, 你的挑戰是要發展這個沙漠中的樂園並讓遊客樂而忘返 - - -STR_SCNR :Razor Rocks -STR_PARK :Razor Rocks -STR_DTLS :你的任務是於Razor Rocks之中建造一個擁有不同雲霄飛車的樂園 - - -STR_SCNR :Crater Lake -STR_PARK :Crater Lake -STR_DTLS :此樂園設定於一個沉睡火山口的湖之上 - - -STR_SCNR :Vertigo Views -STR_PARK :Vertigo Views -STR_DTLS :這個大型的樂園已經擁有一座很棒的超級雲霄飛車, 但你的任務是要將他的利潤大幅增加 - - -STR_SCNR :Paradise Pier 2 -STR_PARK :Paradise Pier 2 -STR_DTLS :Paradise Pier 已向海中心擴張它的道路網絡, 你的任務是讓樂園使用那些新擴張的區域 - - -STR_SCNR :Dragon’s Cove -STR_PARK :Dragon’s Cove -STR_DTLS :此建造雲霄飛車挑戰設定於一個處於海邊的洞穴之中 - - -STR_SCNR :Good Knight Park -STR_PARK :Good Knight Park -STR_DTLS :一個擁有一對雲霄飛車的城堡需要發展成一個更大型的主題樂園 - - -STR_SCNR :Wacky Warren -STR_PARK :Wacky Warren -STR_DTLS :一個擁有很多道路及雲霄飛車於地下的樂園 - - -STR_SCNR :Grand Glacier -STR_PARK :Grand Glacier -STR_DTLS :一個由冰川所填滿的峽谷現可由你任意發展成一個樂園 - - -STR_SCNR :Crazy Craters -STR_PARK :Crazy Craters -STR_DTLS :在一個不用錢的遙遠的世界中, 你需要建造一個娛樂中心來讓遊客開心 - - -STR_SCNR :Dusty Desert -STR_PARK :Dusty Desert -STR_DTLS :你需要在此沙漠中的樂園完成未建好的5座雲霄飛車 - - -STR_SCNR :Woodworm Park -STR_PARK :Woodworm Park -STR_DTLS :這個很有歷史的樂園只能讓你建造一些古舊風格的遊樂設施 - - -STR_SCNR :Icarus Park -STR_PARK :Icarus Park -STR_DTLS :發展此外星樂園並將其利潤最大化 - - -STR_SCNR :Sunny Swamps -STR_PARK :Sunny Swamps -STR_DTLS :這個佈置得很好的主題樂園已經有數項遊樂設施, 但有很多擴張的空間 - - -STR_SCNR :Frightmare Hills -STR_PARK :Frightmare Hills -STR_DTLS :一個在中心擁有一座巨大的雲霄飛車的恐怖樂園 - - -STR_SCNR :Thunder Rocks -STR_PARK :Thunder Rocks -STR_DTLS :兩座屹立在沙地之上的巨型石將會作為建造一個主題樂園的初始環境 - - -STR_SCNR :Octagon Park -STR_PARK :Octagon Park -STR_DTLS :你需要在此大型樂園內建造十座雲霄飛車 - - -STR_SCNR :Pleasure Island -STR_PARK :Pleasure Island -STR_DTLS :一個又長又窄的島嶼令到建造挑選好的雲霄飛車十分有挑戰性 - - -STR_SCNR :Icicle Worlds -STR_PARK :Icicle Worlds -STR_DTLS :一個冰天雪地的地方需要發展成一個主題樂園 - - -STR_SCNR :Southern Sands -STR_PARK :Southern Sands -STR_DTLS :一個已經有些設計妥善的雲霄飛車現可由你任意擴張 - - -STR_SCNR :Tiny Towers -STR_PARK :Tiny Towers -STR_DTLS :你需要在此細小的樂園中完成建設五座雲霄飛車 - - -STR_SCNR :Nevermore Park -STR_PARK :Nevermore Park -STR_DTLS :一個已經四周都擁有童話般的運輸系統的大型樂園 - - -STR_SCNR :Pacifica -STR_PARK :Pacifica -STR_DTLS :此大型島嶼現可由你任意發展成一個樂園 - - -STR_SCNR :Urban Jungle -STR_PARK :Urban Jungle -STR_DTLS :一座被棄置的摩天大樓是發展主題樂園的難得機會 - - -STR_SCNR :Terror Town -STR_PARK :Terror Town -STR_DTLS :此市區現可由你任意發展成一個樂園 - - -STR_SCNR :Megaworld Park -STR_PARK :Megaworld Park -STR_DTLS :一個已經有很多遊樂設施, 但需要改善的大型樂園 - - -STR_SCNR :Venus Ponds -STR_PARK :Venus Ponds -STR_DTLS :在一個遙遠的行星上的此地需要發展成一個主題樂園 - - -STR_SCNR :Micro Park -STR_PARK :Micro Park -STR_DTLS :嘗試建立一個世界上最小的利潤性樂園 - -## Real Parks from RCT1 -# None of them had details - -STR_SCNR :奧爾頓塔 -STR_PARK :奧爾頓塔 -STR_DTLS : - - -STR_SCNR :Heide-Park -STR_PARK :Heide-Park -STR_DTLS : - - -STR_SCNR :Blackpool Pleasure Beach -STR_PARK :Blackpool Pleasure Beach -STR_DTLS : - -## Misc parks from RCT1 -# Had no details - -STR_SCNR :Fort Anachronism -STR_PARK :Fort Anachronism -STR_DTLS : - - -############################################################################### -## RCT2 Scenarios -############################################################################### - -STR_SCNR :高山冒險 -STR_PARK :高山冒險 -STR_DTLS :將一座小型滑雪勝地的山區轉換成一座雪景主題趣味遊樂園 - - -STR_SCNR :亞米提飛機場 -STR_PARK :亞米提飛機場 -STR_DTLS :在這個放棄的機場建一座飛行樂趣的遊樂園 - - -STR_SCNR :植物生態破壞者 -STR_PARK :植物生態破壞者 -STR_DTLS :你的挑戰是在這天堂島建設一座高收益的遊樂園 - - -STR_SCNR :建造屬於你自己的比利時六旗 -STR_PARK :比利時六旗 -STR_DTLS :將這個歐洲的六旗遊樂園建造成屬於你自己的版本 - - -STR_SCNR :建造屬於你的六旗大型規模冒險樂園 -STR_PARK :六旗大型規模冒險樂園 -STR_DTLS :運用你的設計能力使六旗遊樂園具娛樂性 - - -STR_SCNR :建造屬於你自己的荷蘭六旗 -STR_PARK :荷蘭的六旗 -STR_DTLS :在歐洲的六旗遊樂園 運用你想要的方式建造 - - -STR_SCNR :建造屬於你自己的六旗魔術山 -STR_PARK :六旗魔術山 -STR_DTLS :將這個超大的六旗遊樂園建造成屬於你自己的版本 - - -STR_SCNR :建造你自己的六旗遊樂園 -STR_PARK :六旗 -STR_DTLS :建造你自己設計的六旗遊樂園- 從其他的六旗遊樂園建造遊樂設施或是設計及建造你自己擁有的遊樂設施 - - -STR_SCNR :在德州建造屬於你自己的六旗 -STR_PARK :在德州的六旗 -STR_DTLS :從頭開始做起,在六旗遊樂園內建造遊樂設施 - - -STR_SCNR :雜亂的商店街 -STR_PARK :雜亂的商店街 -STR_DTLS :以一個小型的市場商店街開始, 你的挑戰是從商店及攤販增加收入以建設遊樂設施及雲霄飛車以吸引更多的顧客 - - -STR_SCNR :瘋狂城堡 -STR_PARK :瘋狂城堡 -STR_DTLS :你繼承了一座大型城堡 - 你的工作是將它變為一座小型主題樂園. - - -STR_SCNR :枯燥無味的草坪 -STR_PARK :枯燥無味的草坪 -STR_DTLS :在沙漠的高速公路連結附近有一片枯燥無味的草坪,是一個將小型高爾夫勝地轉變為成功主題樂園的發展機會 - - -STR_SCNR :發電牧場 -STR_PARK :發電牧場 -STR_DTLS :你繼承一塊小型農場,你的挑戰是建造一個小型的主題遊樂園介於牧場及農場間的建設 - - -STR_SCNR :高海拔極地 -STR_PARK :高海拔極地 -STR_DTLS :免於財務限制規定, 你的挑戰是擴展這座荒野中的遊樂園以吸引人們來尋找最終的刺激 - - -STR_SCNR :活躍工廠 -STR_PARK :活躍工廠 -STR_DTLS :一座錯綜複雜的被廢棄工廠是去建造一座機械主題的趣味遊樂園的一個機會 - - -STR_SCNR :菌類森林 -STR_PARK :菌類森林 -STR_DTLS :只被老舊所設限-森林式遊樂設施風格, 你的挑戰是在菌類森林中建造一座成功主題遊樂園 - - -STR_SCNR :鬼城 -STR_PARK :鬼城 -STR_DTLS :你被一座超大的遊樂園所僱用,你的任務是在被遺棄的礦業城鎮將它建造成一座大型的雲霄飛車遊樂園 - - -STR_SCNR :地心引力花園 -STR_PARK :地心引力花園 -STR_DTLS :你的挑戰是在美麗的地心引力花園中建造一個雲霄飛車遊樂園介於牧場及農場間的建設- 沒有其他的遊樂設施, 只有雲霄飛車! - - -STR_SCNR :地獄般的景色 -STR_PARK :地獄般的景色 -STR_DTLS :一座遊樂園位於火山岩地會噴出熔岩的危險地帶 - - -STR_SCNR :幸運湖泊 -STR_PARK :幸運湖泊 -STR_DTLS :在沒有資金限制下挑戰湖泊區域,這座遊樂園的開發及管理將是一個挑戰 - - -STR_SCNR :彩虹峰頂 -STR_PARK :彩虹峰頂 -STR_DTLS :在山坡上建造,這個遊樂園被禁止建造高的建物,你可以擴展這個遊樂園獲得勝利? - - -STR_SCNR :比利時的六旗 -STR_PARK :比利時的六旗 -STR_DTLS :試著用你的雙手經營並改善這座六旗遊樂園 - - -STR_SCNR :六旗大型冒險 -STR_PARK :六旗大型冒險 -STR_DTLS :建造缺少的六旗遊樂設施,或建造你自己設計的以改善遊樂園!但不要忘了你最終的目標-吸引更多遊客進入你的遊樂園! - - -STR_SCNR :荷蘭的六旗 -STR_PARK :荷蘭的六旗 -STR_DTLS :試著用你的雙手經營並改善這座六旗遊樂園 - - -STR_SCNR :六旗魔術山 -STR_PARK :六旗魔術山 -STR_DTLS :建造缺少的六旗遊樂設施,或建造你自己設計的以改善遊樂園!但不要忘了你最終的目標-當保持遊樂園價值提昇時要償還你的貸款! - - -STR_SCNR :六旗遍及德州 -STR_PARK :六旗遍及德州 -STR_DTLS :建造缺少的六旗遊樂設施,或建造你自己設計的以改善遊樂園!但不要忘了你最終的目標-吸引更多遊客進入你的遊樂園! - -############################################################################### -## Wacky Worlds Scenarios -############################################################################### - -STR_SCNR :Mines of Africa -STR_PARK :Mines of Africa -STR_DTLS :You inherited a disused diamond mine, and find a valuable diamond. You decide to invest that money to build a world-famous theme park. - - -STR_SCNR :Mirage Madness -STR_PARK :Mirage Madness -STR_DTLS :A desert Oasis has been discovered and would provide a beautiful location for a park. Transport to the oasis has been provided. - - -STR_SCNR :Over The Edge -STR_PARK :Over The Edge -STR_DTLS :A dam has been built offering abundant, cheap hydroelectric power with which to run a park. You need to reach a high park value to help repay the loan for the dam. - - -STR_SCNR :Icy Adventures -STR_PARK :Icy Adventures -STR_DTLS :The environment agency has turned to you to transform an old oil refinery ecological eyesore into a top tourist attraction. Land is cheap but loan interest is high. You can sell the old buildings for salvage. - - -STR_SCNR :Great Wall of China -STR_PARK :Great Wall of China -STR_DTLS :The authorities have decided to enhance tourism around the Great Wall by building a theme park on the adjacent land. Money is no object! - - -STR_SCNR :Okinawa Coast -STR_PARK :Okinawa Coast -STR_DTLS :An existing park has run out of space. Your only option is to build out into the sea, and so you have taken out a loan. Height restrictions on your building are enforced due to foundations and earthquake risk. - - -STR_SCNR :Park Maharaja -STR_PARK :Park Maharaja -STR_DTLS :You have been commissioned by the Maharaja to bring entertainment to the large local population. Build a park inspired by the Maharaja’s palace. - - -STR_SCNR :Ayers Adventure -STR_PARK :Ayers Adventure -STR_DTLS :You are helping Aboriginal people to build a park as part of a cultural awareness program. You need to get a large number of guests to educate them in the unique heritage of the Aboriginal people. - - -STR_SCNR :Beach Barbecue Blast -STR_PARK :Beach Barbecue Blast -STR_DTLS :A local entrepreneur’s sealife park has gone bust. You already operate a small park and buy the other park from the construction company. Develop a big combined park. - - -STR_SCNR :European Extravaganza -STR_PARK :European Extravaganza -STR_DTLS :You have been brought in to take over a European Cultural Visitor Attraction and must increase the number of guests in order to pay back the EU subsidy by the end of the current European parliament term. - - -STR_SCNR :From The Ashes -STR_PARK :From The Ashes -STR_DTLS :An old park has fallen into disrepair. You gain a European Union grant to return this deprived area to its former glory! You need to renovate the park and repay the grant. - - -STR_SCNR :Wacky Waikiki -STR_PARK :Wacky Waikiki -STR_DTLS :The people of Hawaii are bored of surfing and are looking for something more intense. You need to build a park with this in mind to keep the area’s tourist attraction rating high. - - -STR_SCNR :Canyon Calamities -STR_PARK :Canyon Calamities -STR_DTLS :You have to build a park on limited land either side of this natural treasure - you do have the opportunity to buy neighbouring land from the Native American Indians. You need to complete the objective to sustain the local town’s population. - - -STR_SCNR :Rollercoaster Heaven -STR_PARK :Rollercoaster Heaven -STR_DTLS :You are a successful business tycoon on long sabbatical who desires to use this time transforming the city park into Rollercoaster Heaven. Money is no object! - - -STR_SCNR :Lost City Founder -STR_PARK :Lost City Founder -STR_DTLS :To further boost local tourism you must construct a park that is in tune with its surroundings, and has height restrictions. - - -STR_SCNR :Rainforest Romp -STR_PARK :Rainforest Romp -STR_DTLS :Space is limited in the precious rainforest - you must cram as much as possible into the existing clearing, in order to provide a viable alternative to the local timber industry. - - -STR_SCNR :Sugarloaf Shores -STR_PARK :Sugarloaf Shores -STR_DTLS :You run a small park near Rio but the bank has called in your loan. You need to quickly increase your earning capacity to repay this unexpected debt. - -############################################################################### -## Time Twister Scenarios -############################################################################### - -STR_SCNR :克利弗塞德城堡 -STR_PARK :克利弗塞德城堡 -STR_DTLS :本地的戰役重現協會成員對他們的這項嗜好相當認真。他們授權您建造一座以克利弗塞德城堡為主題的黑暗時代主題樂園。 - - -STR_SCNR :舍伍德森林 -STR_PARK :舍伍德森林 -STR_DTLS :為了劫富濟貧,您與您的伙伴們決定要在舍伍德森林中建造一座主題樂園。 - - -STR_SCNR :外星文明博覽會 -STR_PARK :外星文明博覽會 -STR_DTLS :在遙遠的行星上發現了生命 建築一個外星主題樂園,在這個史無前例的風潮中大撈一票。 - - -STR_SCNR :雙子星城市 -STR_PARK :雙子星城市 -STR_DTLS :展現您對於未來的創造力與想像力-設計出以最先進科技為特色的未來主題樂園。 - - -STR_SCNR :機械偶動作 -STR_PARK :機械偶動作 -STR_DTLS :您被賦予經營並改善現有主題樂園的工作,樂園建築在舊片場上。為首先將神話生物帶到銀幕中的定格動畫家們獻上崇高敬意 - - -STR_SCNR :神話狂熱 -STR_PARK :神話狂熱 -STR_DTLS :您擁有一個具有特殊考古價值的小島。您決定透過建造一座以這個區域非常豐富的神話遺產為主題的樂園。 - - -STR_SCNR :隕石坑大屠殺 -STR_PARK :隕石坑大屠殺 -STR_DTLS :您擁有滿是灰塵的老舊隕石坑。您的企業家精神讓您決定建立小行星主題樂園,並將看來毫無價值的土地轉變成巨大的財富。 - - -STR_SCNR :Coastersaurus -STR_PARK :Coastersaurus -STR_DTLS :您被賦予建立侏羅紀主題公園的工作。為了讓您的訪客能更容易接近觀賞各種動植物,您必須在河谷中建立交通工具 - - -STR_SCNR :石間漫步 -STR_PARK :石間漫步 -STR_DTLS :為了阻止高速公路開發者並保存神秘的古代石頭環,您必須建立石器時代主題公園並獲利。但很難吸引到遊客,因為地形荒涼 - - -STR_SCNR :惡魔島 -STR_PARK :惡魔島 -STR_DTLS :惡名昭彰的監獄島-島上居名曾以販賣私酒者或騙徒為主-現在正待價而沽中。您決定要將這個小島轉變為觀光勝地,錢不是問題 - - -STR_SCNR :施耐德海岸 -STR_PARK :施耐德海岸 -STR_DTLS :令祖父在施耐德盃優勝的75週年紀念再過幾年就要到了。您決定建造以著名的水上飛機競速賽為主題的樂園來紀念他的成就。 - - -STR_SCNR :大都會 -STR_PARK :大都會 -STR_DTLS :您在市鎮低層數建築區中擁有空地。為了讓地產發揮最大價值,請建造以喧騰的20年代裝飾藝術為主題的摩天大樓主題樂園 - - -STR_SCNR :伍斯托克音樂會 -STR_PARK :伍斯托克音樂會 -STR_DTLS :您的土地上將舉辦大型的年度音樂嘉年華。請建立一個能讓這些崇尚心靈自由的人們感到愉快的主題樂園。 - - -STR_SCNR :搖滾復興 -STR_PARK :搖滾復興 -STR_DTLS :這個過時的主題樂園曾經有過輝煌的日子。請協助所有者將讓這個主題樂園再次搖滾起來,讓這個地方成為成功的企業。 - -############################################################################### -## Official Custom Content Scenarios -############################################################################### - -STR_SCNR :Panda World -STR_PARK :Panda World -STR_DTLS :在這以熊貓為主題的樂園中增加更多遊樂設施以吸引更多遊客到訪 From 4482a080245688c4e3507a21690d7abd00db3e06 Mon Sep 17 00:00:00 2001 From: mix <167040362+mixiate@users.noreply.github.com> Date: Sat, 2 Nov 2024 12:24:26 +0000 Subject: [PATCH 92/97] Add new Corkscrew Roller Coaster track pieces --- distribution/changelog.txt | 1 + resources/g2/sprites.json | 3920 ++++++++ .../track/corkscrew/barrel_roll_left_1_1.png | Bin 0 -> 1037 bytes .../track/corkscrew/barrel_roll_left_1_2.png | Bin 0 -> 1009 bytes .../track/corkscrew/barrel_roll_left_1_3.png | Bin 0 -> 922 bytes .../track/corkscrew/barrel_roll_left_1_4.png | Bin 0 -> 1386 bytes .../track/corkscrew/barrel_roll_left_1_5.png | Bin 0 -> 903 bytes .../track/corkscrew/barrel_roll_left_1_6.png | Bin 0 -> 1282 bytes .../track/corkscrew/barrel_roll_left_2_1.png | Bin 0 -> 935 bytes .../track/corkscrew/barrel_roll_left_2_2.png | Bin 0 -> 1026 bytes .../track/corkscrew/barrel_roll_left_2_3.png | Bin 0 -> 900 bytes .../track/corkscrew/barrel_roll_left_2_4.png | Bin 0 -> 1111 bytes .../track/corkscrew/barrel_roll_left_2_5.png | Bin 0 -> 935 bytes .../track/corkscrew/barrel_roll_left_2_6.png | Bin 0 -> 1247 bytes .../track/corkscrew/barrel_roll_left_3_1.png | Bin 0 -> 1289 bytes .../track/corkscrew/barrel_roll_left_3_2.png | Bin 0 -> 910 bytes .../track/corkscrew/barrel_roll_left_3_3.png | Bin 0 -> 1117 bytes .../track/corkscrew/barrel_roll_left_3_4.png | Bin 0 -> 994 bytes .../track/corkscrew/barrel_roll_left_3_5.png | Bin 0 -> 885 bytes .../track/corkscrew/barrel_roll_left_3_6.png | Bin 0 -> 1114 bytes .../track/corkscrew/barrel_roll_left_4_1.png | Bin 0 -> 1252 bytes .../track/corkscrew/barrel_roll_left_4_2.png | Bin 0 -> 896 bytes .../track/corkscrew/barrel_roll_left_4_3.png | Bin 0 -> 1162 bytes .../track/corkscrew/barrel_roll_left_4_4.png | Bin 0 -> 944 bytes .../track/corkscrew/barrel_roll_left_4_5.png | Bin 0 -> 923 bytes .../track/corkscrew/barrel_roll_left_4_6.png | Bin 0 -> 1095 bytes .../track/corkscrew/barrel_roll_right_1_1.png | Bin 0 -> 1325 bytes .../track/corkscrew/barrel_roll_right_1_2.png | Bin 0 -> 903 bytes .../track/corkscrew/barrel_roll_right_1_3.png | Bin 0 -> 1253 bytes .../track/corkscrew/barrel_roll_right_1_4.png | Bin 0 -> 953 bytes .../track/corkscrew/barrel_roll_right_1_5.png | Bin 0 -> 940 bytes .../track/corkscrew/barrel_roll_right_1_6.png | Bin 0 -> 1128 bytes .../track/corkscrew/barrel_roll_right_2_1.png | Bin 0 -> 1187 bytes .../track/corkscrew/barrel_roll_right_2_2.png | Bin 0 -> 899 bytes .../track/corkscrew/barrel_roll_right_2_3.png | Bin 0 -> 1082 bytes .../track/corkscrew/barrel_roll_right_2_4.png | Bin 0 -> 988 bytes .../track/corkscrew/barrel_roll_right_2_5.png | Bin 0 -> 885 bytes .../track/corkscrew/barrel_roll_right_2_6.png | Bin 0 -> 1072 bytes .../track/corkscrew/barrel_roll_right_3_1.png | Bin 0 -> 947 bytes .../track/corkscrew/barrel_roll_right_3_2.png | Bin 0 -> 1056 bytes .../track/corkscrew/barrel_roll_right_3_3.png | Bin 0 -> 902 bytes .../track/corkscrew/barrel_roll_right_3_4.png | Bin 0 -> 1142 bytes .../track/corkscrew/barrel_roll_right_3_5.png | Bin 0 -> 934 bytes .../track/corkscrew/barrel_roll_right_3_6.png | Bin 0 -> 1338 bytes .../track/corkscrew/barrel_roll_right_4_1.png | Bin 0 -> 1011 bytes .../track/corkscrew/barrel_roll_right_4_2.png | Bin 0 -> 987 bytes .../track/corkscrew/barrel_roll_right_4_3.png | Bin 0 -> 921 bytes .../track/corkscrew/barrel_roll_right_4_4.png | Bin 0 -> 1269 bytes .../track/corkscrew/barrel_roll_right_4_5.png | Bin 0 -> 902 bytes .../track/corkscrew/barrel_roll_right_4_6.png | Bin 0 -> 1202 bytes .../flat_to_gentle_up_left_bank_1.png | Bin 0 -> 1249 bytes .../flat_to_gentle_up_left_bank_2_1.png | Bin 0 -> 930 bytes .../flat_to_gentle_up_left_bank_2_2.png | Bin 0 -> 1086 bytes .../flat_to_gentle_up_left_bank_3.png | Bin 0 -> 1261 bytes .../flat_to_gentle_up_left_bank_4.png | Bin 0 -> 1267 bytes .../flat_to_gentle_up_left_bank_diag_1_1.png | Bin 0 -> 979 bytes .../flat_to_gentle_up_left_bank_diag_1_2.png | Bin 0 -> 1084 bytes .../flat_to_gentle_up_left_bank_diag_2.png | Bin 0 -> 1192 bytes .../flat_to_gentle_up_left_bank_diag_3.png | Bin 0 -> 1319 bytes .../flat_to_gentle_up_left_bank_diag_4.png | Bin 0 -> 1287 bytes .../flat_to_gentle_up_right_bank_1.png | Bin 0 -> 1354 bytes .../flat_to_gentle_up_right_bank_2.png | Bin 0 -> 1187 bytes .../flat_to_gentle_up_right_bank_3_1.png | Bin 0 -> 949 bytes .../flat_to_gentle_up_right_bank_3_2.png | Bin 0 -> 1120 bytes .../flat_to_gentle_up_right_bank_4.png | Bin 0 -> 1187 bytes .../flat_to_gentle_up_right_bank_diag_1.png | Bin 0 -> 1270 bytes .../flat_to_gentle_up_right_bank_diag_2.png | Bin 0 -> 1185 bytes .../flat_to_gentle_up_right_bank_diag_3_1.png | Bin 0 -> 990 bytes .../flat_to_gentle_up_right_bank_diag_3_2.png | Bin 0 -> 1122 bytes .../flat_to_gentle_up_right_bank_diag_4.png | Bin 0 -> 1316 bytes .../track/corkscrew/gentle_up_left_bank_1.png | Bin 0 -> 1083 bytes .../track/corkscrew/gentle_up_left_bank_2.png | Bin 0 -> 1091 bytes .../track/corkscrew/gentle_up_left_bank_3.png | Bin 0 -> 1164 bytes .../track/corkscrew/gentle_up_left_bank_4.png | Bin 0 -> 1223 bytes .../corkscrew/gentle_up_left_bank_diag_1.png | Bin 0 -> 1042 bytes .../corkscrew/gentle_up_left_bank_diag_2.png | Bin 0 -> 1046 bytes .../corkscrew/gentle_up_left_bank_diag_3.png | Bin 0 -> 1118 bytes .../corkscrew/gentle_up_left_bank_diag_4.png | Bin 0 -> 1044 bytes .../gentle_up_left_bank_to_flat_1.png | Bin 0 -> 1259 bytes .../gentle_up_left_bank_to_flat_2_1.png | Bin 0 -> 1043 bytes .../gentle_up_left_bank_to_flat_2_2.png | Bin 0 -> 996 bytes .../gentle_up_left_bank_to_flat_3.png | Bin 0 -> 1265 bytes .../gentle_up_left_bank_to_flat_4.png | Bin 0 -> 1252 bytes .../gentle_up_left_bank_to_flat_diag_1_1.png | Bin 0 -> 989 bytes .../gentle_up_left_bank_to_flat_diag_1_2.png | Bin 0 -> 1060 bytes .../gentle_up_left_bank_to_flat_diag_2.png | Bin 0 -> 1205 bytes .../gentle_up_left_bank_to_flat_diag_3.png | Bin 0 -> 1278 bytes .../gentle_up_left_bank_to_flat_diag_4.png | Bin 0 -> 1278 bytes .../gentle_up_left_bank_to_gentle_up_1.png | Bin 0 -> 1281 bytes .../gentle_up_left_bank_to_gentle_up_2_1.png | Bin 0 -> 1024 bytes .../gentle_up_left_bank_to_gentle_up_2_2.png | Bin 0 -> 985 bytes .../gentle_up_left_bank_to_gentle_up_3.png | Bin 0 -> 1207 bytes .../gentle_up_left_bank_to_gentle_up_4.png | Bin 0 -> 1298 bytes ...tle_up_left_bank_to_gentle_up_diag_1_1.png | Bin 0 -> 994 bytes ...tle_up_left_bank_to_gentle_up_diag_1_2.png | Bin 0 -> 1083 bytes ...entle_up_left_bank_to_gentle_up_diag_2.png | Bin 0 -> 1143 bytes ...entle_up_left_bank_to_gentle_up_diag_3.png | Bin 0 -> 1329 bytes ...entle_up_left_bank_to_gentle_up_diag_4.png | Bin 0 -> 1328 bytes .../gentle_up_left_bank_to_left_bank_1.png | Bin 0 -> 1199 bytes .../gentle_up_left_bank_to_left_bank_2.png | Bin 0 -> 1115 bytes .../gentle_up_left_bank_to_left_bank_3.png | Bin 0 -> 1294 bytes .../gentle_up_left_bank_to_left_bank_4.png | Bin 0 -> 1262 bytes ...entle_up_left_bank_to_left_bank_diag_1.png | Bin 0 -> 1132 bytes ...entle_up_left_bank_to_left_bank_diag_2.png | Bin 0 -> 1150 bytes ...entle_up_left_bank_to_left_bank_diag_3.png | Bin 0 -> 5435 bytes ...entle_up_left_bank_to_left_bank_diag_4.png | Bin 0 -> 1195 bytes .../corkscrew/gentle_up_right_bank_1.png | Bin 0 -> 1256 bytes .../corkscrew/gentle_up_right_bank_2.png | Bin 0 -> 1146 bytes .../corkscrew/gentle_up_right_bank_3.png | Bin 0 -> 1080 bytes .../corkscrew/gentle_up_right_bank_4.png | Bin 0 -> 1051 bytes .../corkscrew/gentle_up_right_bank_diag_1.png | Bin 0 -> 1130 bytes .../corkscrew/gentle_up_right_bank_diag_2.png | Bin 0 -> 1046 bytes .../corkscrew/gentle_up_right_bank_diag_3.png | Bin 0 -> 1054 bytes .../corkscrew/gentle_up_right_bank_diag_4.png | Bin 0 -> 1048 bytes .../gentle_up_right_bank_to_flat_1.png | Bin 0 -> 1360 bytes .../gentle_up_right_bank_to_flat_2.png | Bin 0 -> 1193 bytes .../gentle_up_right_bank_to_flat_3_1.png | Bin 0 -> 1064 bytes .../gentle_up_right_bank_to_flat_3_2.png | Bin 0 -> 1018 bytes .../gentle_up_right_bank_to_flat_4.png | Bin 0 -> 1179 bytes .../gentle_up_right_bank_to_flat_diag_1.png | Bin 0 -> 1228 bytes .../gentle_up_right_bank_to_flat_diag_2.png | Bin 0 -> 1197 bytes .../gentle_up_right_bank_to_flat_diag_3_1.png | Bin 0 -> 997 bytes .../gentle_up_right_bank_to_flat_diag_3_2.png | Bin 0 -> 1080 bytes .../gentle_up_right_bank_to_flat_diag_4.png | Bin 0 -> 1311 bytes .../gentle_up_right_bank_to_gentle_up_1.png | Bin 0 -> 1362 bytes .../gentle_up_right_bank_to_gentle_up_2.png | Bin 0 -> 1173 bytes .../gentle_up_right_bank_to_gentle_up_3_1.png | Bin 0 -> 1036 bytes .../gentle_up_right_bank_to_gentle_up_3_2.png | Bin 0 -> 1007 bytes .../gentle_up_right_bank_to_gentle_up_4.png | Bin 0 -> 1221 bytes ...ntle_up_right_bank_to_gentle_up_diag_1.png | Bin 0 -> 1257 bytes ...ntle_up_right_bank_to_gentle_up_diag_2.png | Bin 0 -> 1123 bytes ...le_up_right_bank_to_gentle_up_diag_3_1.png | Bin 0 -> 1013 bytes ...le_up_right_bank_to_gentle_up_diag_3_2.png | Bin 0 -> 1132 bytes ...ntle_up_right_bank_to_gentle_up_diag_4.png | Bin 0 -> 1346 bytes .../gentle_up_right_bank_to_right_bank_1.png | Bin 0 -> 1344 bytes .../gentle_up_right_bank_to_right_bank_2.png | Bin 0 -> 1194 bytes .../gentle_up_right_bank_to_right_bank_3.png | Bin 0 -> 1177 bytes .../gentle_up_right_bank_to_right_bank_4.png | Bin 0 -> 1132 bytes ...tle_up_right_bank_to_right_bank_diag_1.png | Bin 0 -> 5395 bytes ...tle_up_right_bank_to_right_bank_diag_2.png | Bin 0 -> 1137 bytes ...tle_up_right_bank_to_right_bank_diag_3.png | Bin 0 -> 1144 bytes ...tle_up_right_bank_to_right_bank_diag_4.png | Bin 0 -> 1208 bytes .../gentle_up_to_gentle_up_left_bank_1.png | Bin 0 -> 1271 bytes .../gentle_up_to_gentle_up_left_bank_2_1.png | Bin 0 -> 891 bytes .../gentle_up_to_gentle_up_left_bank_2_2.png | Bin 0 -> 1100 bytes .../gentle_up_to_gentle_up_left_bank_3.png | Bin 0 -> 1219 bytes .../gentle_up_to_gentle_up_left_bank_4.png | Bin 0 -> 1312 bytes ...tle_up_to_gentle_up_left_bank_diag_1_1.png | Bin 0 -> 1005 bytes ...tle_up_to_gentle_up_left_bank_diag_1_2.png | Bin 0 -> 1113 bytes ...entle_up_to_gentle_up_left_bank_diag_2.png | Bin 0 -> 1115 bytes ...entle_up_to_gentle_up_left_bank_diag_3.png | Bin 0 -> 1349 bytes ...entle_up_to_gentle_up_left_bank_diag_4.png | Bin 0 -> 1342 bytes .../gentle_up_to_gentle_up_right_bank_1.png | Bin 0 -> 1350 bytes .../gentle_up_to_gentle_up_right_bank_2.png | Bin 0 -> 1165 bytes .../gentle_up_to_gentle_up_right_bank_3_1.png | Bin 0 -> 893 bytes .../gentle_up_to_gentle_up_right_bank_3_2.png | Bin 0 -> 1117 bytes .../gentle_up_to_gentle_up_right_bank_4.png | Bin 0 -> 1225 bytes ...ntle_up_to_gentle_up_right_bank_diag_1.png | Bin 0 -> 1285 bytes ...ntle_up_to_gentle_up_right_bank_diag_2.png | Bin 0 -> 1114 bytes ...le_up_to_gentle_up_right_bank_diag_3_1.png | Bin 0 -> 1028 bytes ...le_up_to_gentle_up_right_bank_diag_3_2.png | Bin 0 -> 1164 bytes ...ntle_up_to_gentle_up_right_bank_diag_4.png | Bin 0 -> 1361 bytes .../corkscrew/large_corkscrew_left_1_1.png | Bin 0 -> 1271 bytes .../corkscrew/large_corkscrew_left_1_2.png | Bin 0 -> 1352 bytes .../corkscrew/large_corkscrew_left_1_3.png | Bin 0 -> 1219 bytes .../corkscrew/large_corkscrew_left_1_4.png | Bin 0 -> 1267 bytes .../corkscrew/large_corkscrew_left_1_5.png | Bin 0 -> 1146 bytes .../corkscrew/large_corkscrew_left_2_1.png | Bin 0 -> 1090 bytes .../corkscrew/large_corkscrew_left_2_2.png | Bin 0 -> 1141 bytes .../corkscrew/large_corkscrew_left_2_3.png | Bin 0 -> 1387 bytes .../corkscrew/large_corkscrew_left_2_4.png | Bin 0 -> 1395 bytes .../corkscrew/large_corkscrew_left_2_5.png | Bin 0 -> 1203 bytes .../corkscrew/large_corkscrew_left_3_1.png | Bin 0 -> 1196 bytes .../corkscrew/large_corkscrew_left_3_2.png | Bin 0 -> 1142 bytes .../corkscrew/large_corkscrew_left_3_3.png | Bin 0 -> 4975 bytes .../corkscrew/large_corkscrew_left_3_4.png | Bin 0 -> 5379 bytes .../corkscrew/large_corkscrew_left_3_5.png | Bin 0 -> 5311 bytes .../corkscrew/large_corkscrew_left_4_1.png | Bin 0 -> 1235 bytes .../corkscrew/large_corkscrew_left_4_2.png | Bin 0 -> 1390 bytes .../corkscrew/large_corkscrew_left_4_3.png | Bin 0 -> 1272 bytes .../corkscrew/large_corkscrew_left_4_4.png | Bin 0 -> 1233 bytes .../corkscrew/large_corkscrew_left_4_4_2.png | Bin 0 -> 1152 bytes .../corkscrew/large_corkscrew_left_4_5.png | Bin 0 -> 1216 bytes .../corkscrew/large_corkscrew_right_1_1.png | Bin 0 -> 1297 bytes .../corkscrew/large_corkscrew_right_1_2.png | Bin 0 -> 1361 bytes .../corkscrew/large_corkscrew_right_1_3.png | Bin 0 -> 1214 bytes .../corkscrew/large_corkscrew_right_1_4.png | Bin 0 -> 1205 bytes .../corkscrew/large_corkscrew_right_1_4_2.png | Bin 0 -> 1131 bytes .../corkscrew/large_corkscrew_right_1_5.png | Bin 0 -> 1171 bytes .../corkscrew/large_corkscrew_right_2_1.png | Bin 0 -> 1141 bytes .../corkscrew/large_corkscrew_right_2_2.png | Bin 0 -> 1166 bytes .../corkscrew/large_corkscrew_right_2_3.png | Bin 0 -> 873 bytes .../corkscrew/large_corkscrew_right_2_4.png | Bin 0 -> 1272 bytes .../corkscrew/large_corkscrew_right_2_5.png | Bin 0 -> 1275 bytes .../corkscrew/large_corkscrew_right_3_1.png | Bin 0 -> 1114 bytes .../corkscrew/large_corkscrew_right_3_2.png | Bin 0 -> 1185 bytes .../corkscrew/large_corkscrew_right_3_3.png | Bin 0 -> 1477 bytes .../corkscrew/large_corkscrew_right_3_4.png | Bin 0 -> 1406 bytes .../corkscrew/large_corkscrew_right_3_5.png | Bin 0 -> 1153 bytes .../corkscrew/large_corkscrew_right_4_1.png | Bin 0 -> 1215 bytes .../corkscrew/large_corkscrew_right_4_2.png | Bin 0 -> 1370 bytes .../corkscrew/large_corkscrew_right_4_3.png | Bin 0 -> 1179 bytes .../corkscrew/large_corkscrew_right_4_4.png | Bin 0 -> 1278 bytes .../corkscrew/large_corkscrew_right_4_5.png | Bin 0 -> 1207 bytes .../corkscrew/large_half_loop_left_1_1.png | Bin 0 -> 1402 bytes .../corkscrew/large_half_loop_left_1_2.png | Bin 0 -> 5444 bytes .../corkscrew/large_half_loop_left_1_3.png | Bin 0 -> 5724 bytes .../corkscrew/large_half_loop_left_1_4.png | Bin 0 -> 5567 bytes .../corkscrew/large_half_loop_left_1_5.png | Bin 0 -> 1391 bytes .../corkscrew/large_half_loop_left_1_6.png | Bin 0 -> 1245 bytes .../corkscrew/large_half_loop_left_1_6_2.png | Bin 0 -> 5270 bytes .../corkscrew/large_half_loop_left_1_7.png | Bin 0 -> 1172 bytes .../corkscrew/large_half_loop_left_2_1.png | Bin 0 -> 1084 bytes .../corkscrew/large_half_loop_left_2_2.png | Bin 0 -> 1065 bytes .../corkscrew/large_half_loop_left_2_2_2.png | Bin 0 -> 5136 bytes .../corkscrew/large_half_loop_left_2_3.png | Bin 0 -> 1091 bytes .../corkscrew/large_half_loop_left_2_3_2.png | Bin 0 -> 5264 bytes .../corkscrew/large_half_loop_left_2_4.png | Bin 0 -> 1435 bytes .../corkscrew/large_half_loop_left_2_5.png | Bin 0 -> 1584 bytes .../corkscrew/large_half_loop_left_2_6.png | Bin 0 -> 1400 bytes .../corkscrew/large_half_loop_left_2_7.png | Bin 0 -> 1238 bytes .../corkscrew/large_half_loop_left_3_1.png | Bin 0 -> 1139 bytes .../corkscrew/large_half_loop_left_3_2.png | Bin 0 -> 1143 bytes .../corkscrew/large_half_loop_left_3_3.png | Bin 0 -> 1158 bytes .../corkscrew/large_half_loop_left_3_3_2.png | Bin 0 -> 5458 bytes .../corkscrew/large_half_loop_left_3_4.png | Bin 0 -> 5476 bytes .../corkscrew/large_half_loop_left_3_5.png | Bin 0 -> 1521 bytes .../corkscrew/large_half_loop_left_3_6.png | Bin 0 -> 1288 bytes .../corkscrew/large_half_loop_left_3_7.png | Bin 0 -> 1284 bytes .../corkscrew/large_half_loop_left_4_1.png | Bin 0 -> 1236 bytes .../corkscrew/large_half_loop_left_4_2.png | Bin 0 -> 1304 bytes .../corkscrew/large_half_loop_left_4_3.png | Bin 0 -> 1487 bytes .../corkscrew/large_half_loop_left_4_4.png | Bin 0 -> 1655 bytes .../corkscrew/large_half_loop_left_4_5.png | Bin 0 -> 1360 bytes .../corkscrew/large_half_loop_left_4_6.png | Bin 0 -> 1422 bytes .../corkscrew/large_half_loop_left_4_7.png | Bin 0 -> 5301 bytes .../corkscrew/large_half_loop_right_1_1.png | Bin 0 -> 1279 bytes .../corkscrew/large_half_loop_right_1_2.png | Bin 0 -> 1309 bytes .../corkscrew/large_half_loop_right_1_3.png | Bin 0 -> 1410 bytes .../corkscrew/large_half_loop_right_1_4.png | Bin 0 -> 1487 bytes .../corkscrew/large_half_loop_right_1_5.png | Bin 0 -> 1282 bytes .../corkscrew/large_half_loop_right_1_6.png | Bin 0 -> 1402 bytes .../corkscrew/large_half_loop_right_1_7.png | Bin 0 -> 5351 bytes .../corkscrew/large_half_loop_right_2_1.png | Bin 0 -> 1141 bytes .../corkscrew/large_half_loop_right_2_2.png | Bin 0 -> 1133 bytes .../corkscrew/large_half_loop_right_2_3.png | Bin 0 -> 5257 bytes .../corkscrew/large_half_loop_right_2_3_2.png | Bin 0 -> 5611 bytes .../corkscrew/large_half_loop_right_2_4.png | Bin 0 -> 5476 bytes .../corkscrew/large_half_loop_right_2_5.png | Bin 0 -> 1634 bytes .../corkscrew/large_half_loop_right_2_6.png | Bin 0 -> 1324 bytes .../corkscrew/large_half_loop_right_2_7.png | Bin 0 -> 1244 bytes .../corkscrew/large_half_loop_right_3_1.png | Bin 0 -> 1133 bytes .../corkscrew/large_half_loop_right_3_2.png | Bin 0 -> 1101 bytes .../corkscrew/large_half_loop_right_3_2_2.png | Bin 0 -> 5165 bytes .../corkscrew/large_half_loop_right_3_3.png | Bin 0 -> 1140 bytes .../corkscrew/large_half_loop_right_3_3_2.png | Bin 0 -> 5223 bytes .../corkscrew/large_half_loop_right_3_4.png | Bin 0 -> 1463 bytes .../corkscrew/large_half_loop_right_3_5.png | Bin 0 -> 1538 bytes .../corkscrew/large_half_loop_right_3_6.png | Bin 0 -> 1391 bytes .../corkscrew/large_half_loop_right_3_7.png | Bin 0 -> 1304 bytes .../corkscrew/large_half_loop_right_4_1.png | Bin 0 -> 1334 bytes .../corkscrew/large_half_loop_right_4_2.png | Bin 0 -> 5387 bytes .../corkscrew/large_half_loop_right_4_3.png | Bin 0 -> 5553 bytes .../corkscrew/large_half_loop_right_4_4.png | Bin 0 -> 5701 bytes .../corkscrew/large_half_loop_right_4_5.png | Bin 0 -> 1428 bytes .../corkscrew/large_half_loop_right_4_6.png | Bin 0 -> 1192 bytes .../corkscrew/large_half_loop_right_4_6_2.png | Bin 0 -> 5211 bytes .../corkscrew/large_half_loop_right_4_7.png | Bin 0 -> 1118 bytes ...e_turn_left_bank_to_diag_gentle_up_1_1.png | Bin 0 -> 1179 bytes ...e_turn_left_bank_to_diag_gentle_up_1_2.png | Bin 0 -> 1191 bytes ...e_turn_left_bank_to_diag_gentle_up_1_3.png | Bin 0 -> 993 bytes ...e_turn_left_bank_to_diag_gentle_up_1_4.png | Bin 0 -> 1154 bytes ...e_turn_left_bank_to_diag_gentle_up_2_1.png | Bin 0 -> 1028 bytes ...e_turn_left_bank_to_diag_gentle_up_2_2.png | Bin 0 -> 1081 bytes ...e_turn_left_bank_to_diag_gentle_up_2_3.png | Bin 0 -> 1009 bytes ...e_turn_left_bank_to_diag_gentle_up_2_4.png | Bin 0 -> 1034 bytes ...e_turn_left_bank_to_diag_gentle_up_3_1.png | Bin 0 -> 1082 bytes ...e_turn_left_bank_to_diag_gentle_up_3_2.png | Bin 0 -> 1050 bytes ...e_turn_left_bank_to_diag_gentle_up_3_3.png | Bin 0 -> 1016 bytes ...e_turn_left_bank_to_diag_gentle_up_3_4.png | Bin 0 -> 1073 bytes ...e_turn_left_bank_to_diag_gentle_up_4_1.png | Bin 0 -> 1300 bytes ...e_turn_left_bank_to_diag_gentle_up_4_2.png | Bin 0 -> 1265 bytes ...e_turn_left_bank_to_diag_gentle_up_4_3.png | Bin 0 -> 990 bytes ...e_turn_left_bank_to_diag_gentle_up_4_4.png | Bin 0 -> 1194 bytes ..._left_bank_to_orthogonal_gentle_up_1_1.png | Bin 0 -> 1074 bytes ..._left_bank_to_orthogonal_gentle_up_1_2.png | Bin 0 -> 860 bytes ..._left_bank_to_orthogonal_gentle_up_1_3.png | Bin 0 -> 5290 bytes ..._left_bank_to_orthogonal_gentle_up_1_4.png | Bin 0 -> 1214 bytes ..._left_bank_to_orthogonal_gentle_up_2_1.png | Bin 0 -> 932 bytes ..._left_bank_to_orthogonal_gentle_up_2_2.png | Bin 0 -> 860 bytes ..._left_bank_to_orthogonal_gentle_up_2_3.png | Bin 0 -> 1039 bytes ..._left_bank_to_orthogonal_gentle_up_2_4.png | Bin 0 -> 1093 bytes ..._left_bank_to_orthogonal_gentle_up_3_1.png | Bin 0 -> 1232 bytes ..._left_bank_to_orthogonal_gentle_up_3_2.png | Bin 0 -> 860 bytes ..._left_bank_to_orthogonal_gentle_up_3_3.png | Bin 0 -> 1321 bytes ..._left_bank_to_orthogonal_gentle_up_3_4.png | Bin 0 -> 1314 bytes ..._left_bank_to_orthogonal_gentle_up_4_1.png | Bin 0 -> 1058 bytes ..._left_bank_to_orthogonal_gentle_up_4_2.png | Bin 0 -> 860 bytes ..._left_bank_to_orthogonal_gentle_up_4_3.png | Bin 0 -> 1319 bytes ..._left_bank_to_orthogonal_gentle_up_4_4.png | Bin 0 -> 1424 bytes .../large_turn_left_to_diag_gentle_up_1_1.png | Bin 0 -> 1311 bytes .../large_turn_left_to_diag_gentle_up_1_2.png | Bin 0 -> 1284 bytes .../large_turn_left_to_diag_gentle_up_1_3.png | Bin 0 -> 1017 bytes .../large_turn_left_to_diag_gentle_up_1_4.png | Bin 0 -> 1170 bytes .../large_turn_left_to_diag_gentle_up_2_1.png | Bin 0 -> 1009 bytes .../large_turn_left_to_diag_gentle_up_2_2.png | Bin 0 -> 1113 bytes .../large_turn_left_to_diag_gentle_up_2_3.png | Bin 0 -> 1026 bytes .../large_turn_left_to_diag_gentle_up_2_4.png | Bin 0 -> 1071 bytes .../large_turn_left_to_diag_gentle_up_3_1.png | Bin 0 -> 1005 bytes .../large_turn_left_to_diag_gentle_up_3_2.png | Bin 0 -> 981 bytes .../large_turn_left_to_diag_gentle_up_3_3.png | Bin 0 -> 981 bytes .../large_turn_left_to_diag_gentle_up_3_4.png | Bin 0 -> 1011 bytes .../large_turn_left_to_diag_gentle_up_4_1.png | Bin 0 -> 1245 bytes .../large_turn_left_to_diag_gentle_up_4_2.png | Bin 0 -> 1195 bytes .../large_turn_left_to_diag_gentle_up_4_3.png | Bin 0 -> 958 bytes .../large_turn_left_to_diag_gentle_up_4_4.png | Bin 0 -> 1117 bytes ..._turn_left_to_orthogonal_gentle_up_1_1.png | Bin 0 -> 1093 bytes ..._turn_left_to_orthogonal_gentle_up_1_2.png | Bin 0 -> 860 bytes ..._turn_left_to_orthogonal_gentle_up_1_3.png | Bin 0 -> 1196 bytes ..._turn_left_to_orthogonal_gentle_up_1_4.png | Bin 0 -> 1300 bytes ..._turn_left_to_orthogonal_gentle_up_2_1.png | Bin 0 -> 895 bytes ..._turn_left_to_orthogonal_gentle_up_2_2.png | Bin 0 -> 860 bytes ..._turn_left_to_orthogonal_gentle_up_2_3.png | Bin 0 -> 1037 bytes ..._turn_left_to_orthogonal_gentle_up_2_4.png | Bin 0 -> 1100 bytes ..._turn_left_to_orthogonal_gentle_up_3_1.png | Bin 0 -> 1123 bytes ..._turn_left_to_orthogonal_gentle_up_3_2.png | Bin 0 -> 860 bytes ..._turn_left_to_orthogonal_gentle_up_3_3.png | Bin 0 -> 1194 bytes ..._turn_left_to_orthogonal_gentle_up_3_4.png | Bin 0 -> 1177 bytes ..._turn_left_to_orthogonal_gentle_up_4_1.png | Bin 0 -> 1081 bytes ..._turn_left_to_orthogonal_gentle_up_4_2.png | Bin 0 -> 860 bytes ..._turn_left_to_orthogonal_gentle_up_4_3.png | Bin 0 -> 1311 bytes ..._turn_left_to_orthogonal_gentle_up_4_4.png | Bin 0 -> 1367 bytes ..._turn_right_bank_to_diag_gentle_up_1_1.png | Bin 0 -> 1353 bytes ..._turn_right_bank_to_diag_gentle_up_1_2.png | Bin 0 -> 1252 bytes ..._turn_right_bank_to_diag_gentle_up_1_3.png | Bin 0 -> 978 bytes ..._turn_right_bank_to_diag_gentle_up_1_4.png | Bin 0 -> 1144 bytes ..._turn_right_bank_to_diag_gentle_up_2_1.png | Bin 0 -> 1058 bytes ..._turn_right_bank_to_diag_gentle_up_2_2.png | Bin 0 -> 1049 bytes ..._turn_right_bank_to_diag_gentle_up_2_3.png | Bin 0 -> 1023 bytes ..._turn_right_bank_to_diag_gentle_up_2_4.png | Bin 0 -> 1053 bytes ..._turn_right_bank_to_diag_gentle_up_3_1.png | Bin 0 -> 1061 bytes ..._turn_right_bank_to_diag_gentle_up_3_2.png | Bin 0 -> 1130 bytes ..._turn_right_bank_to_diag_gentle_up_3_3.png | Bin 0 -> 1058 bytes ..._turn_right_bank_to_diag_gentle_up_3_4.png | Bin 0 -> 1091 bytes ..._turn_right_bank_to_diag_gentle_up_4_1.png | Bin 0 -> 1119 bytes ..._turn_right_bank_to_diag_gentle_up_4_2.png | Bin 0 -> 1164 bytes ..._turn_right_bank_to_diag_gentle_up_4_3.png | Bin 0 -> 973 bytes ..._turn_right_bank_to_diag_gentle_up_4_4.png | Bin 0 -> 1136 bytes ...right_bank_to_orthogonal_gentle_up_1_1.png | Bin 0 -> 1128 bytes ...right_bank_to_orthogonal_gentle_up_1_2.png | Bin 0 -> 860 bytes ...right_bank_to_orthogonal_gentle_up_1_3.png | Bin 0 -> 1225 bytes ...right_bank_to_orthogonal_gentle_up_1_4.png | Bin 0 -> 1235 bytes ...right_bank_to_orthogonal_gentle_up_2_1.png | Bin 0 -> 925 bytes ...right_bank_to_orthogonal_gentle_up_2_2.png | Bin 0 -> 860 bytes ...right_bank_to_orthogonal_gentle_up_2_3.png | Bin 0 -> 1026 bytes ...right_bank_to_orthogonal_gentle_up_2_4.png | Bin 0 -> 1086 bytes ...right_bank_to_orthogonal_gentle_up_3_1.png | Bin 0 -> 1099 bytes ...right_bank_to_orthogonal_gentle_up_3_2.png | Bin 0 -> 860 bytes ...right_bank_to_orthogonal_gentle_up_3_3.png | Bin 0 -> 5321 bytes ...right_bank_to_orthogonal_gentle_up_3_4.png | Bin 0 -> 1179 bytes ...right_bank_to_orthogonal_gentle_up_4_1.png | Bin 0 -> 1092 bytes ...right_bank_to_orthogonal_gentle_up_4_2.png | Bin 0 -> 860 bytes ...right_bank_to_orthogonal_gentle_up_4_3.png | Bin 0 -> 1395 bytes ...right_bank_to_orthogonal_gentle_up_4_4.png | Bin 0 -> 1526 bytes ...large_turn_right_to_diag_gentle_up_1_1.png | Bin 0 -> 1276 bytes ...large_turn_right_to_diag_gentle_up_1_2.png | Bin 0 -> 1168 bytes ...large_turn_right_to_diag_gentle_up_1_3.png | Bin 0 -> 950 bytes ...large_turn_right_to_diag_gentle_up_1_4.png | Bin 0 -> 1085 bytes ...large_turn_right_to_diag_gentle_up_2_1.png | Bin 0 -> 995 bytes ...large_turn_right_to_diag_gentle_up_2_2.png | Bin 0 -> 992 bytes ...large_turn_right_to_diag_gentle_up_2_3.png | Bin 0 -> 987 bytes ...large_turn_right_to_diag_gentle_up_2_4.png | Bin 0 -> 1008 bytes ...large_turn_right_to_diag_gentle_up_3_1.png | Bin 0 -> 1025 bytes ...large_turn_right_to_diag_gentle_up_3_2.png | Bin 0 -> 1148 bytes ...large_turn_right_to_diag_gentle_up_3_3.png | Bin 0 -> 1061 bytes ...large_turn_right_to_diag_gentle_up_3_4.png | Bin 0 -> 1125 bytes ...large_turn_right_to_diag_gentle_up_4_1.png | Bin 0 -> 1255 bytes ...large_turn_right_to_diag_gentle_up_4_2.png | Bin 0 -> 1272 bytes ...large_turn_right_to_diag_gentle_up_4_3.png | Bin 0 -> 991 bytes ...large_turn_right_to_diag_gentle_up_4_4.png | Bin 0 -> 1142 bytes ...turn_right_to_orthogonal_gentle_up_1_1.png | Bin 0 -> 1066 bytes ...turn_right_to_orthogonal_gentle_up_1_2.png | Bin 0 -> 860 bytes ...turn_right_to_orthogonal_gentle_up_1_3.png | Bin 0 -> 1135 bytes ...turn_right_to_orthogonal_gentle_up_1_4.png | Bin 0 -> 1150 bytes ...turn_right_to_orthogonal_gentle_up_2_1.png | Bin 0 -> 892 bytes ...turn_right_to_orthogonal_gentle_up_2_2.png | Bin 0 -> 860 bytes ...turn_right_to_orthogonal_gentle_up_2_3.png | Bin 0 -> 1027 bytes ...turn_right_to_orthogonal_gentle_up_2_4.png | Bin 0 -> 1100 bytes ...turn_right_to_orthogonal_gentle_up_3_1.png | Bin 0 -> 1119 bytes ...turn_right_to_orthogonal_gentle_up_3_2.png | Bin 0 -> 860 bytes ...turn_right_to_orthogonal_gentle_up_3_3.png | Bin 0 -> 1230 bytes ...turn_right_to_orthogonal_gentle_up_3_4.png | Bin 0 -> 1264 bytes ...turn_right_to_orthogonal_gentle_up_4_1.png | Bin 0 -> 1094 bytes ...turn_right_to_orthogonal_gentle_up_4_2.png | Bin 0 -> 860 bytes ...turn_right_to_orthogonal_gentle_up_4_3.png | Bin 0 -> 1372 bytes ...turn_right_to_orthogonal_gentle_up_4_4.png | Bin 0 -> 1468 bytes .../corkscrew/large_zero_g_roll_left_1_1.png | Bin 0 -> 1386 bytes .../corkscrew/large_zero_g_roll_left_1_2.png | Bin 0 -> 1175 bytes .../corkscrew/large_zero_g_roll_left_1_3.png | Bin 0 -> 1330 bytes .../corkscrew/large_zero_g_roll_left_1_4.png | Bin 0 -> 1004 bytes .../corkscrew/large_zero_g_roll_left_1_5.png | Bin 0 -> 1392 bytes .../corkscrew/large_zero_g_roll_left_1_6.png | Bin 0 -> 4975 bytes .../corkscrew/large_zero_g_roll_left_1_7.png | Bin 0 -> 5442 bytes .../corkscrew/large_zero_g_roll_left_2_1.png | Bin 0 -> 4975 bytes .../corkscrew/large_zero_g_roll_left_2_2.png | Bin 0 -> 5381 bytes .../corkscrew/large_zero_g_roll_left_2_3.png | Bin 0 -> 860 bytes .../corkscrew/large_zero_g_roll_left_2_4.png | Bin 0 -> 1321 bytes .../corkscrew/large_zero_g_roll_left_2_5.png | Bin 0 -> 860 bytes .../corkscrew/large_zero_g_roll_left_2_6.png | Bin 0 -> 1237 bytes .../corkscrew/large_zero_g_roll_left_2_7.png | Bin 0 -> 860 bytes .../corkscrew/large_zero_g_roll_left_2_8.png | Bin 0 -> 1245 bytes .../corkscrew/large_zero_g_roll_left_3_1.png | Bin 0 -> 963 bytes .../corkscrew/large_zero_g_roll_left_3_2.png | Bin 0 -> 1138 bytes .../corkscrew/large_zero_g_roll_left_3_3.png | Bin 0 -> 5419 bytes .../corkscrew/large_zero_g_roll_left_3_4.png | Bin 0 -> 5200 bytes .../corkscrew/large_zero_g_roll_left_3_5.png | Bin 0 -> 5346 bytes .../corkscrew/large_zero_g_roll_left_3_6.png | Bin 0 -> 5271 bytes .../corkscrew/large_zero_g_roll_left_3_7.png | Bin 0 -> 938 bytes .../corkscrew/large_zero_g_roll_left_3_8.png | Bin 0 -> 5273 bytes .../corkscrew/large_zero_g_roll_left_4_1.png | Bin 0 -> 1534 bytes .../corkscrew/large_zero_g_roll_left_4_2.png | Bin 0 -> 1669 bytes .../corkscrew/large_zero_g_roll_left_4_3.png | Bin 0 -> 1185 bytes .../corkscrew/large_zero_g_roll_left_4_4.png | Bin 0 -> 5358 bytes .../corkscrew/large_zero_g_roll_left_4_5.png | Bin 0 -> 963 bytes .../corkscrew/large_zero_g_roll_left_4_6.png | Bin 0 -> 1166 bytes .../corkscrew/large_zero_g_roll_right_1_1.png | Bin 0 -> 1474 bytes .../corkscrew/large_zero_g_roll_right_1_2.png | Bin 0 -> 1649 bytes .../corkscrew/large_zero_g_roll_right_1_3.png | Bin 0 -> 1177 bytes .../corkscrew/large_zero_g_roll_right_1_4.png | Bin 0 -> 5371 bytes .../corkscrew/large_zero_g_roll_right_1_5.png | Bin 0 -> 971 bytes .../corkscrew/large_zero_g_roll_right_1_6.png | Bin 0 -> 1240 bytes .../corkscrew/large_zero_g_roll_right_2_1.png | Bin 0 -> 952 bytes .../corkscrew/large_zero_g_roll_right_2_2.png | Bin 0 -> 1133 bytes .../corkscrew/large_zero_g_roll_right_2_3.png | Bin 0 -> 5401 bytes .../corkscrew/large_zero_g_roll_right_2_4.png | Bin 0 -> 5204 bytes .../corkscrew/large_zero_g_roll_right_2_5.png | Bin 0 -> 5331 bytes .../corkscrew/large_zero_g_roll_right_2_6.png | Bin 0 -> 5039 bytes .../corkscrew/large_zero_g_roll_right_2_7.png | Bin 0 -> 933 bytes .../corkscrew/large_zero_g_roll_right_2_8.png | Bin 0 -> 5230 bytes .../corkscrew/large_zero_g_roll_right_3_1.png | Bin 0 -> 860 bytes .../corkscrew/large_zero_g_roll_right_3_2.png | Bin 0 -> 1310 bytes .../corkscrew/large_zero_g_roll_right_3_3.png | Bin 0 -> 860 bytes .../corkscrew/large_zero_g_roll_right_3_4.png | Bin 0 -> 1307 bytes .../corkscrew/large_zero_g_roll_right_3_5.png | Bin 0 -> 860 bytes .../corkscrew/large_zero_g_roll_right_3_6.png | Bin 0 -> 1289 bytes .../corkscrew/large_zero_g_roll_right_3_7.png | Bin 0 -> 860 bytes .../corkscrew/large_zero_g_roll_right_3_8.png | Bin 0 -> 1357 bytes .../corkscrew/large_zero_g_roll_right_4_1.png | Bin 0 -> 1464 bytes .../corkscrew/large_zero_g_roll_right_4_2.png | Bin 0 -> 1192 bytes .../corkscrew/large_zero_g_roll_right_4_3.png | Bin 0 -> 1373 bytes .../corkscrew/large_zero_g_roll_right_4_4.png | Bin 0 -> 1024 bytes .../corkscrew/large_zero_g_roll_right_4_5.png | Bin 0 -> 1360 bytes .../corkscrew/large_zero_g_roll_right_4_6.png | Bin 0 -> 4976 bytes .../corkscrew/large_zero_g_roll_right_4_7.png | Bin 0 -> 5581 bytes .../left_bank_to_gentle_up_left_bank_1.png | Bin 0 -> 1203 bytes .../left_bank_to_gentle_up_left_bank_2.png | Bin 0 -> 1137 bytes .../left_bank_to_gentle_up_left_bank_3.png | Bin 0 -> 1298 bytes .../left_bank_to_gentle_up_left_bank_4.png | Bin 0 -> 1272 bytes ...eft_bank_to_gentle_up_left_bank_diag_1.png | Bin 0 -> 1145 bytes ...eft_bank_to_gentle_up_left_bank_diag_2.png | Bin 0 -> 1149 bytes ...eft_bank_to_gentle_up_left_bank_diag_3.png | Bin 0 -> 5415 bytes ...eft_bank_to_gentle_up_left_bank_diag_4.png | Bin 0 -> 1201 bytes .../corkscrew/medium_half_loop_left_1_1.png | Bin 0 -> 1455 bytes .../corkscrew/medium_half_loop_left_1_2.png | Bin 0 -> 5463 bytes .../corkscrew/medium_half_loop_left_1_3.png | Bin 0 -> 5601 bytes .../corkscrew/medium_half_loop_left_1_4.png | Bin 0 -> 1435 bytes .../corkscrew/medium_half_loop_left_1_4_2.png | Bin 0 -> 5299 bytes .../corkscrew/medium_half_loop_left_1_5.png | Bin 0 -> 1225 bytes .../corkscrew/medium_half_loop_left_2_1.png | Bin 0 -> 1173 bytes .../corkscrew/medium_half_loop_left_2_1_2.png | Bin 0 -> 5242 bytes .../corkscrew/medium_half_loop_left_2_2.png | Bin 0 -> 1107 bytes .../corkscrew/medium_half_loop_left_2_2_2.png | Bin 0 -> 1255 bytes .../corkscrew/medium_half_loop_left_2_3.png | Bin 0 -> 5704 bytes .../corkscrew/medium_half_loop_left_2_4.png | Bin 0 -> 1836 bytes .../corkscrew/medium_half_loop_left_2_5.png | Bin 0 -> 1151 bytes .../corkscrew/medium_half_loop_left_3_1.png | Bin 0 -> 1063 bytes .../corkscrew/medium_half_loop_left_3_2.png | Bin 0 -> 1062 bytes .../corkscrew/medium_half_loop_left_3_3.png | Bin 0 -> 1546 bytes .../corkscrew/medium_half_loop_left_3_4.png | Bin 0 -> 5962 bytes .../corkscrew/medium_half_loop_left_3_5.png | Bin 0 -> 1185 bytes .../corkscrew/medium_half_loop_left_4_1.png | Bin 0 -> 1241 bytes .../corkscrew/medium_half_loop_left_4_2.png | Bin 0 -> 1355 bytes .../corkscrew/medium_half_loop_left_4_3.png | Bin 0 -> 1571 bytes .../corkscrew/medium_half_loop_left_4_4.png | Bin 0 -> 1710 bytes .../corkscrew/medium_half_loop_left_4_4_2.png | Bin 0 -> 1304 bytes .../corkscrew/medium_half_loop_left_4_5.png | Bin 0 -> 1141 bytes .../corkscrew/medium_half_loop_right_1_1.png | Bin 0 -> 1267 bytes .../corkscrew/medium_half_loop_right_1_2.png | Bin 0 -> 1290 bytes .../corkscrew/medium_half_loop_right_1_3.png | Bin 0 -> 1415 bytes .../corkscrew/medium_half_loop_right_1_4.png | Bin 0 -> 1610 bytes .../medium_half_loop_right_1_4_2.png | Bin 0 -> 1364 bytes .../corkscrew/medium_half_loop_right_1_5.png | Bin 0 -> 1181 bytes .../corkscrew/medium_half_loop_right_2_1.png | Bin 0 -> 1055 bytes .../corkscrew/medium_half_loop_right_2_2.png | Bin 0 -> 1047 bytes .../corkscrew/medium_half_loop_right_2_3.png | Bin 0 -> 1565 bytes .../corkscrew/medium_half_loop_right_2_4.png | Bin 0 -> 6068 bytes .../corkscrew/medium_half_loop_right_2_5.png | Bin 0 -> 1132 bytes .../corkscrew/medium_half_loop_right_3_1.png | Bin 0 -> 1195 bytes .../medium_half_loop_right_3_1_2.png | Bin 0 -> 1147 bytes .../corkscrew/medium_half_loop_right_3_2.png | Bin 0 -> 1133 bytes .../medium_half_loop_right_3_2_2.png | Bin 0 -> 1195 bytes .../corkscrew/medium_half_loop_right_3_3.png | Bin 0 -> 5704 bytes .../corkscrew/medium_half_loop_right_3_4.png | Bin 0 -> 1784 bytes .../corkscrew/medium_half_loop_right_3_5.png | Bin 0 -> 1213 bytes .../corkscrew/medium_half_loop_right_4_1.png | Bin 0 -> 1410 bytes .../corkscrew/medium_half_loop_right_4_2.png | Bin 0 -> 1415 bytes .../corkscrew/medium_half_loop_right_4_3.png | Bin 0 -> 5750 bytes .../corkscrew/medium_half_loop_right_4_4.png | Bin 0 -> 1454 bytes .../medium_half_loop_right_4_4_2.png | Bin 0 -> 1165 bytes .../corkscrew/medium_half_loop_right_4_5.png | Bin 0 -> 1148 bytes .../medium_turn_left_bank_gentle_up_1_1.png | Bin 0 -> 1226 bytes .../medium_turn_left_bank_gentle_up_1_2.png | Bin 0 -> 1144 bytes .../medium_turn_left_bank_gentle_up_1_3.png | Bin 0 -> 860 bytes .../medium_turn_left_bank_gentle_up_1_4.png | Bin 0 -> 1305 bytes .../medium_turn_left_bank_gentle_up_1_5.png | Bin 0 -> 1329 bytes .../medium_turn_left_bank_gentle_up_2_1.png | Bin 0 -> 1172 bytes .../medium_turn_left_bank_gentle_up_2_2.png | Bin 0 -> 1045 bytes .../medium_turn_left_bank_gentle_up_2_3.png | Bin 0 -> 1012 bytes .../medium_turn_left_bank_gentle_up_2_4.png | Bin 0 -> 1060 bytes .../medium_turn_left_bank_gentle_up_2_5.png | Bin 0 -> 1150 bytes .../medium_turn_left_bank_gentle_up_3_1.png | Bin 0 -> 1219 bytes .../medium_turn_left_bank_gentle_up_3_2.png | Bin 0 -> 860 bytes .../medium_turn_left_bank_gentle_up_3_3.png | Bin 0 -> 953 bytes .../medium_turn_left_bank_gentle_up_3_4.png | Bin 0 -> 860 bytes .../medium_turn_left_bank_gentle_up_3_5.png | Bin 0 -> 1156 bytes .../medium_turn_left_bank_gentle_up_4_1.png | Bin 0 -> 1345 bytes .../medium_turn_left_bank_gentle_up_4_2.png | Bin 0 -> 1312 bytes .../medium_turn_left_bank_gentle_up_4_3.png | Bin 0 -> 1087 bytes .../medium_turn_left_bank_gentle_up_4_4.png | Bin 0 -> 1187 bytes .../medium_turn_left_bank_gentle_up_4_5.png | Bin 0 -> 1286 bytes .../medium_turn_right_bank_gentle_up_1_1.png | Bin 0 -> 1401 bytes .../medium_turn_right_bank_gentle_up_1_2.png | Bin 0 -> 1242 bytes .../medium_turn_right_bank_gentle_up_1_3.png | Bin 0 -> 1035 bytes .../medium_turn_right_bank_gentle_up_1_4.png | Bin 0 -> 1115 bytes .../medium_turn_right_bank_gentle_up_1_5.png | Bin 0 -> 1220 bytes .../medium_turn_right_bank_gentle_up_2_1.png | Bin 0 -> 1205 bytes .../medium_turn_right_bank_gentle_up_2_2.png | Bin 0 -> 860 bytes .../medium_turn_right_bank_gentle_up_2_3.png | Bin 0 -> 950 bytes .../medium_turn_right_bank_gentle_up_2_4.png | Bin 0 -> 860 bytes .../medium_turn_right_bank_gentle_up_2_5.png | Bin 0 -> 1138 bytes .../medium_turn_right_bank_gentle_up_3_1.png | Bin 0 -> 1238 bytes .../medium_turn_right_bank_gentle_up_3_2.png | Bin 0 -> 5431 bytes .../medium_turn_right_bank_gentle_up_3_3.png | Bin 0 -> 1033 bytes .../medium_turn_right_bank_gentle_up_3_4.png | Bin 0 -> 1076 bytes .../medium_turn_right_bank_gentle_up_3_5.png | Bin 0 -> 1121 bytes .../medium_turn_right_bank_gentle_up_4_1.png | Bin 0 -> 1143 bytes .../medium_turn_right_bank_gentle_up_4_2.png | Bin 0 -> 1121 bytes .../medium_turn_right_bank_gentle_up_4_3.png | Bin 0 -> 860 bytes .../medium_turn_right_bank_gentle_up_4_4.png | Bin 0 -> 1363 bytes .../medium_turn_right_bank_gentle_up_4_5.png | Bin 0 -> 1434 bytes .../track/corkscrew/quarter_loop_up_1_1.png | Bin 0 -> 1378 bytes .../track/corkscrew/quarter_loop_up_1_2.png | Bin 0 -> 5192 bytes .../track/corkscrew/quarter_loop_up_1_2_2.png | Bin 0 -> 5313 bytes .../track/corkscrew/quarter_loop_up_1_3.png | Bin 0 -> 5359 bytes .../track/corkscrew/quarter_loop_up_2_1.png | Bin 0 -> 1636 bytes .../track/corkscrew/quarter_loop_up_2_2.png | Bin 0 -> 1507 bytes .../track/corkscrew/quarter_loop_up_2_3.png | Bin 0 -> 1084 bytes .../track/corkscrew/quarter_loop_up_3_1.png | Bin 0 -> 1534 bytes .../track/corkscrew/quarter_loop_up_3_2.png | Bin 0 -> 1553 bytes .../track/corkscrew/quarter_loop_up_3_3.png | Bin 0 -> 1121 bytes .../track/corkscrew/quarter_loop_up_4_1.png | Bin 0 -> 1402 bytes .../track/corkscrew/quarter_loop_up_4_2.png | Bin 0 -> 1061 bytes .../track/corkscrew/quarter_loop_up_4_2_2.png | Bin 0 -> 1287 bytes .../track/corkscrew/quarter_loop_up_4_3.png | Bin 0 -> 1180 bytes .../right_bank_to_gentle_up_right_bank_1.png | Bin 0 -> 1411 bytes .../right_bank_to_gentle_up_right_bank_2.png | Bin 0 -> 1237 bytes .../right_bank_to_gentle_up_right_bank_3.png | Bin 0 -> 1175 bytes .../right_bank_to_gentle_up_right_bank_4.png | Bin 0 -> 1108 bytes ...ht_bank_to_gentle_up_right_bank_diag_1.png | Bin 0 -> 5386 bytes ...ht_bank_to_gentle_up_right_bank_diag_2.png | Bin 0 -> 1139 bytes ...ht_bank_to_gentle_up_right_bank_diag_3.png | Bin 0 -> 1159 bytes ...ht_bank_to_gentle_up_right_bank_diag_4.png | Bin 0 -> 1200 bytes .../corkscrew/small_flat_to_steep_up_1.png | Bin 0 -> 1424 bytes .../corkscrew/small_flat_to_steep_up_2_1.png | Bin 0 -> 948 bytes .../corkscrew/small_flat_to_steep_up_2_2.png | Bin 0 -> 1104 bytes .../corkscrew/small_flat_to_steep_up_3_1.png | Bin 0 -> 976 bytes .../corkscrew/small_flat_to_steep_up_3_2.png | Bin 0 -> 1129 bytes .../corkscrew/small_flat_to_steep_up_4.png | Bin 0 -> 1416 bytes .../small_flat_to_steep_up_diag_1.png | Bin 0 -> 1313 bytes .../small_flat_to_steep_up_diag_2.png | Bin 0 -> 1063 bytes .../small_flat_to_steep_up_diag_3.png | Bin 0 -> 1367 bytes .../small_flat_to_steep_up_diag_4.png | Bin 0 -> 1294 bytes .../corkscrew/small_steep_to_flat_up_1.png | Bin 0 -> 1383 bytes .../corkscrew/small_steep_to_flat_up_2_1.png | Bin 0 -> 1044 bytes .../corkscrew/small_steep_to_flat_up_2_2.png | Bin 0 -> 1032 bytes .../corkscrew/small_steep_to_flat_up_3_1.png | Bin 0 -> 1070 bytes .../corkscrew/small_steep_to_flat_up_3_2.png | Bin 0 -> 1042 bytes .../corkscrew/small_steep_to_flat_up_4.png | Bin 0 -> 1412 bytes .../small_steep_to_flat_up_diag_1.png | Bin 0 -> 1328 bytes .../small_steep_to_flat_up_diag_2.png | Bin 0 -> 1051 bytes .../small_steep_to_flat_up_diag_3.png | Bin 0 -> 1403 bytes .../small_steep_to_flat_up_diag_4.png | Bin 0 -> 1289 bytes .../small_turn_left_bank_gentle_up_1_1.png | Bin 0 -> 5361 bytes .../small_turn_left_bank_gentle_up_1_2.png | Bin 0 -> 5500 bytes .../small_turn_left_bank_gentle_up_2_1.png | Bin 0 -> 1137 bytes .../small_turn_left_bank_gentle_up_2_2.png | Bin 0 -> 1244 bytes .../small_turn_left_bank_gentle_up_3_1.png | Bin 0 -> 5382 bytes .../small_turn_left_bank_gentle_up_3_2.png | Bin 0 -> 5220 bytes .../small_turn_left_bank_gentle_up_4_1.png | Bin 0 -> 1259 bytes .../small_turn_left_bank_gentle_up_4_2.png | Bin 0 -> 1238 bytes .../small_turn_left_bank_gentle_up_4_3.png | Bin 0 -> 1193 bytes .../small_turn_left_bank_to_gentle_up_1_1.png | Bin 0 -> 1289 bytes .../small_turn_left_bank_to_gentle_up_1_2.png | Bin 0 -> 1324 bytes .../small_turn_left_bank_to_gentle_up_2_1.png | Bin 0 -> 963 bytes .../small_turn_left_bank_to_gentle_up_2_2.png | Bin 0 -> 1082 bytes .../small_turn_left_bank_to_gentle_up_2_3.png | Bin 0 -> 1271 bytes .../small_turn_left_bank_to_gentle_up_2_4.png | Bin 0 -> 1119 bytes .../small_turn_left_bank_to_gentle_up_3_1.png | Bin 0 -> 1214 bytes .../small_turn_left_bank_to_gentle_up_3_2.png | Bin 0 -> 1136 bytes .../small_turn_left_bank_to_gentle_up_4_1.png | Bin 0 -> 5294 bytes .../small_turn_left_bank_to_gentle_up_4_2.png | Bin 0 -> 5275 bytes .../small_turn_left_bank_to_gentle_up_4_3.png | Bin 0 -> 5259 bytes .../small_turn_right_bank_gentle_up_1_1.png | Bin 0 -> 1311 bytes .../small_turn_right_bank_gentle_up_1_2.png | Bin 0 -> 1177 bytes .../small_turn_right_bank_gentle_up_1_3.png | Bin 0 -> 1136 bytes .../small_turn_right_bank_gentle_up_2_1.png | Bin 0 -> 1159 bytes .../small_turn_right_bank_gentle_up_2_2.png | Bin 0 -> 1114 bytes .../small_turn_right_bank_gentle_up_3_1.png | Bin 0 -> 1216 bytes .../small_turn_right_bank_gentle_up_3_2.png | Bin 0 -> 1218 bytes .../small_turn_right_bank_gentle_up_4_1.png | Bin 0 -> 5248 bytes .../small_turn_right_bank_gentle_up_4_2.png | Bin 0 -> 5645 bytes ...small_turn_right_bank_to_gentle_up_1_1.png | Bin 0 -> 5383 bytes ...small_turn_right_bank_to_gentle_up_1_2.png | Bin 0 -> 5242 bytes ...small_turn_right_bank_to_gentle_up_1_3.png | Bin 0 -> 5194 bytes ...small_turn_right_bank_to_gentle_up_2_1.png | Bin 0 -> 1159 bytes ...small_turn_right_bank_to_gentle_up_2_2.png | Bin 0 -> 1136 bytes ...small_turn_right_bank_to_gentle_up_3_1.png | Bin 0 -> 977 bytes ...small_turn_right_bank_to_gentle_up_3_2.png | Bin 0 -> 1139 bytes ...small_turn_right_bank_to_gentle_up_3_3.png | Bin 0 -> 1256 bytes ...small_turn_right_bank_to_gentle_up_3_4.png | Bin 0 -> 5199 bytes ...small_turn_right_bank_to_gentle_up_4_1.png | Bin 0 -> 1245 bytes ...small_turn_right_bank_to_gentle_up_4_2.png | Bin 0 -> 1406 bytes .../corkscrew/steep_to_vertical_up_1.png | Bin 0 -> 1403 bytes .../corkscrew/steep_to_vertical_up_2.png | Bin 0 -> 5407 bytes .../corkscrew/steep_to_vertical_up_3.png | Bin 0 -> 5404 bytes .../corkscrew/steep_to_vertical_up_4.png | Bin 0 -> 1579 bytes resources/g2/track/corkscrew/vertical_1.png | Bin 0 -> 1011 bytes resources/g2/track/corkscrew/vertical_2.png | Bin 0 -> 999 bytes resources/g2/track/corkscrew/vertical_3.png | Bin 0 -> 1002 bytes resources/g2/track/corkscrew/vertical_4.png | Bin 0 -> 1014 bytes .../corkscrew/vertical_to_steep_up_1.png | Bin 0 -> 1383 bytes .../corkscrew/vertical_to_steep_up_2.png | Bin 0 -> 5402 bytes .../corkscrew/vertical_to_steep_up_3.png | Bin 0 -> 5403 bytes .../corkscrew/vertical_to_steep_up_4.png | Bin 0 -> 1528 bytes .../corkscrew/vertical_twist_left_up_1.png | Bin 0 -> 1673 bytes .../corkscrew/vertical_twist_left_up_2_1.png | Bin 0 -> 5265 bytes .../corkscrew/vertical_twist_left_up_2_2.png | Bin 0 -> 5438 bytes .../corkscrew/vertical_twist_left_up_3.png | Bin 0 -> 1640 bytes .../corkscrew/vertical_twist_left_up_4_1.png | Bin 0 -> 5218 bytes .../corkscrew/vertical_twist_left_up_4_2.png | Bin 0 -> 5679 bytes .../corkscrew/vertical_twist_right_up_1_1.png | Bin 0 -> 5218 bytes .../corkscrew/vertical_twist_right_up_1_2.png | Bin 0 -> 5479 bytes .../corkscrew/vertical_twist_right_up_2.png | Bin 0 -> 5742 bytes .../corkscrew/vertical_twist_right_up_3_1.png | Bin 0 -> 5256 bytes .../corkscrew/vertical_twist_right_up_3_2.png | Bin 0 -> 5438 bytes .../corkscrew/vertical_twist_right_up_4.png | Bin 0 -> 1686 bytes .../track/corkscrew/zero_g_roll_left_1_1.png | Bin 0 -> 5474 bytes .../track/corkscrew/zero_g_roll_left_1_2.png | Bin 0 -> 1064 bytes .../track/corkscrew/zero_g_roll_left_1_3.png | Bin 0 -> 4976 bytes .../track/corkscrew/zero_g_roll_left_1_4.png | Bin 0 -> 5794 bytes .../track/corkscrew/zero_g_roll_left_1_5.png | Bin 0 -> 4975 bytes .../track/corkscrew/zero_g_roll_left_1_6.png | Bin 0 -> 5545 bytes .../track/corkscrew/zero_g_roll_left_2_1.png | Bin 0 -> 933 bytes .../track/corkscrew/zero_g_roll_left_2_2.png | Bin 0 -> 1052 bytes .../track/corkscrew/zero_g_roll_left_2_3.png | Bin 0 -> 4975 bytes .../track/corkscrew/zero_g_roll_left_2_4.png | Bin 0 -> 5321 bytes .../track/corkscrew/zero_g_roll_left_2_5.png | Bin 0 -> 4975 bytes .../track/corkscrew/zero_g_roll_left_2_6.png | Bin 0 -> 5530 bytes .../track/corkscrew/zero_g_roll_left_3_1.png | Bin 0 -> 1200 bytes .../track/corkscrew/zero_g_roll_left_3_2.png | Bin 0 -> 1289 bytes .../track/corkscrew/zero_g_roll_left_3_3.png | Bin 0 -> 983 bytes .../track/corkscrew/zero_g_roll_left_3_4.png | Bin 0 -> 5287 bytes .../track/corkscrew/zero_g_roll_left_4_1.png | Bin 0 -> 1384 bytes .../track/corkscrew/zero_g_roll_left_4_2.png | Bin 0 -> 1325 bytes .../track/corkscrew/zero_g_roll_left_4_3.png | Bin 0 -> 969 bytes .../track/corkscrew/zero_g_roll_left_4_4.png | Bin 0 -> 5328 bytes .../track/corkscrew/zero_g_roll_right_1_1.png | Bin 0 -> 1423 bytes .../track/corkscrew/zero_g_roll_right_1_2.png | Bin 0 -> 1373 bytes .../track/corkscrew/zero_g_roll_right_1_3.png | Bin 0 -> 971 bytes .../track/corkscrew/zero_g_roll_right_1_4.png | Bin 0 -> 5336 bytes .../track/corkscrew/zero_g_roll_right_2_1.png | Bin 0 -> 1137 bytes .../track/corkscrew/zero_g_roll_right_2_2.png | Bin 0 -> 1230 bytes .../track/corkscrew/zero_g_roll_right_2_3.png | Bin 0 -> 976 bytes .../track/corkscrew/zero_g_roll_right_2_4.png | Bin 0 -> 5257 bytes .../track/corkscrew/zero_g_roll_right_3_1.png | Bin 0 -> 932 bytes .../track/corkscrew/zero_g_roll_right_3_2.png | Bin 0 -> 1065 bytes .../track/corkscrew/zero_g_roll_right_3_3.png | Bin 0 -> 4976 bytes .../track/corkscrew/zero_g_roll_right_3_4.png | Bin 0 -> 5375 bytes .../track/corkscrew/zero_g_roll_right_3_5.png | Bin 0 -> 4977 bytes .../track/corkscrew/zero_g_roll_right_3_6.png | Bin 0 -> 5423 bytes .../track/corkscrew/zero_g_roll_right_4_1.png | Bin 0 -> 1127 bytes .../track/corkscrew/zero_g_roll_right_4_2.png | Bin 0 -> 1043 bytes .../track/corkscrew/zero_g_roll_right_4_3.png | Bin 0 -> 4976 bytes .../track/corkscrew/zero_g_roll_right_4_4.png | Bin 0 -> 5473 bytes .../track/corkscrew/zero_g_roll_right_4_5.png | Bin 0 -> 4976 bytes .../track/corkscrew/zero_g_roll_right_4_6.png | Bin 0 -> 5443 bytes src/openrct2/network/NetworkBase.cpp | 2 +- .../track/coaster/CorkscrewRollerCoaster.cpp | 8640 +++++++++++++++++ src/openrct2/park/Legacy.cpp | 140 + src/openrct2/park/ParkFile.h | 3 +- .../ride/rtd/coaster/CorkscrewRollerCoaster.h | 4 +- src/openrct2/ride/rtd/coaster/Hypercoaster.h | 2 +- .../ride/rtd/coaster/LayDownRollerCoaster.h | 2 +- src/openrct2/sprites.h | 18 +- 704 files changed, 12725 insertions(+), 7 deletions(-) create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_1_1.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_1_2.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_1_3.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_1_4.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_1_5.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_1_6.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_2_1.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_2_2.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_2_3.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_2_4.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_2_5.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_2_6.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_3_1.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_3_2.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_3_3.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_3_4.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_3_5.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_3_6.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_4_1.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_4_2.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_4_3.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_4_4.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_4_5.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_left_4_6.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_1_1.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_1_2.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_1_3.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_1_4.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_1_5.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_1_6.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_2_1.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_2_2.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_2_3.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_2_4.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_2_5.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_2_6.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_3_1.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_3_2.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_3_3.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_3_4.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_3_5.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_3_6.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_4_1.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_4_2.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_4_3.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_4_4.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_4_5.png create mode 100644 resources/g2/track/corkscrew/barrel_roll_right_4_6.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_1.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_2_1.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_2_2.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_3.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_4.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_1_1.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_1_2.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_3.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_1.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_2.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_3_1.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_3_2.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_4.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_1.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_3_1.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_3_2.png create mode 100644 resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_diag_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_diag_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_2_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_2_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_1_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_1_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_1_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_1_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_diag_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_diag_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_3_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_3_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_3_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_3_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_3_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_3_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_2_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_2_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_1_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_1_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_3.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_3_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_3_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_4.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_3_1.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_3_2.png create mode 100644 resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_1_1.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_1_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_1_3.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_1_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_1_5.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_2_1.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_2_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_2_3.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_2_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_2_5.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_3_1.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_3_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_3_3.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_3_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_3_5.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_4_1.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_4_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_4_3.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_4_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_4_4_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_left_4_5.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_1_1.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_1_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_1_3.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_1_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_1_4_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_1_5.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_2_1.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_2_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_2_3.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_2_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_2_5.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_3_1.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_3_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_3_3.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_3_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_3_5.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_4_1.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_4_2.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_4_3.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_4_4.png create mode 100644 resources/g2/track/corkscrew/large_corkscrew_right_4_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_1_1.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_1_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_1_3.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_1_4.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_1_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_1_6.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_1_6_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_1_7.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_1.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_2_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_3.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_3_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_4.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_6.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_2_7.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_3_1.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_3_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_3_3.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_3_3_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_3_4.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_3_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_3_6.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_3_7.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_4_1.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_4_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_4_3.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_4_4.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_4_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_4_6.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_left_4_7.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_1_1.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_1_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_1_3.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_1_4.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_1_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_1_6.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_1_7.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_2_1.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_2_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_2_3.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_2_3_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_2_4.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_2_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_2_6.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_2_7.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_1.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_2_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_3.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_3_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_4.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_6.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_3_7.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_4_1.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_4_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_4_3.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_4_4.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_4_5.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_4_6.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_4_6_2.png create mode 100644 resources/g2/track/corkscrew/large_half_loop_right_4_7.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_diag_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_diag_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_left_to_orthogonal_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_diag_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_diag_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/large_turn_right_to_orthogonal_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_1_1.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_1_2.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_1_3.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_1_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_1_5.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_1_6.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_1_7.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_2_1.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_2_2.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_2_3.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_2_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_2_5.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_2_6.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_2_7.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_2_8.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_3_1.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_3_2.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_3_3.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_3_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_3_5.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_3_6.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_3_7.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_3_8.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_4_1.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_4_2.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_4_3.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_4_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_4_5.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_left_4_6.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_1_1.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_1_2.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_1_3.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_1_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_1_5.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_1_6.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_2_1.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_2_2.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_2_3.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_2_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_2_5.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_2_6.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_2_7.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_2_8.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_3_1.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_3_2.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_3_3.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_3_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_3_5.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_3_6.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_3_7.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_3_8.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_4_1.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_4_2.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_4_3.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_4_4.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_4_5.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_4_6.png create mode 100644 resources/g2/track/corkscrew/large_zero_g_roll_right_4_7.png create mode 100644 resources/g2/track/corkscrew/left_bank_to_gentle_up_left_bank_1.png create mode 100644 resources/g2/track/corkscrew/left_bank_to_gentle_up_left_bank_2.png create mode 100644 resources/g2/track/corkscrew/left_bank_to_gentle_up_left_bank_3.png create mode 100644 resources/g2/track/corkscrew/left_bank_to_gentle_up_left_bank_4.png create mode 100644 resources/g2/track/corkscrew/left_bank_to_gentle_up_left_bank_diag_1.png create mode 100644 resources/g2/track/corkscrew/left_bank_to_gentle_up_left_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/left_bank_to_gentle_up_left_bank_diag_3.png create mode 100644 resources/g2/track/corkscrew/left_bank_to_gentle_up_left_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_1_1.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_1_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_1_3.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_1_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_1_4_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_1_5.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_2_1.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_2_1_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_2_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_2_2_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_2_3.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_2_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_2_5.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_3_1.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_3_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_3_3.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_3_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_3_5.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_4_1.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_4_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_4_3.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_4_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_4_4_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_left_4_5.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_1_1.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_1_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_1_3.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_1_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_1_4_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_1_5.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_2_1.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_2_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_2_3.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_2_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_2_5.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_3_1.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_3_1_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_3_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_3_2_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_3_3.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_3_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_3_5.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_4_1.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_4_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_4_3.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_4_4.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_4_4_2.png create mode 100644 resources/g2/track/corkscrew/medium_half_loop_right_4_5.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_1_5.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_2_5.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_3_5.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/medium_turn_left_bank_gentle_up_4_5.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_1_4.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_1_5.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_2_5.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_3_5.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_4_4.png create mode 100644 resources/g2/track/corkscrew/medium_turn_right_bank_gentle_up_4_5.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_1_1.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_1_2.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_1_2_2.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_1_3.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_2_1.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_2_2.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_2_3.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_3_1.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_3_2.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_3_3.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_4_1.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_4_2.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_4_2_2.png create mode 100644 resources/g2/track/corkscrew/quarter_loop_up_4_3.png create mode 100644 resources/g2/track/corkscrew/right_bank_to_gentle_up_right_bank_1.png create mode 100644 resources/g2/track/corkscrew/right_bank_to_gentle_up_right_bank_2.png create mode 100644 resources/g2/track/corkscrew/right_bank_to_gentle_up_right_bank_3.png create mode 100644 resources/g2/track/corkscrew/right_bank_to_gentle_up_right_bank_4.png create mode 100644 resources/g2/track/corkscrew/right_bank_to_gentle_up_right_bank_diag_1.png create mode 100644 resources/g2/track/corkscrew/right_bank_to_gentle_up_right_bank_diag_2.png create mode 100644 resources/g2/track/corkscrew/right_bank_to_gentle_up_right_bank_diag_3.png create mode 100644 resources/g2/track/corkscrew/right_bank_to_gentle_up_right_bank_diag_4.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_1.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_2_1.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_2_2.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_3_1.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_3_2.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_4.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_diag_1.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_diag_2.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_diag_3.png create mode 100644 resources/g2/track/corkscrew/small_flat_to_steep_up_diag_4.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_1.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_2_1.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_2_2.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_3_1.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_3_2.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_4.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_diag_1.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_diag_2.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_diag_3.png create mode 100644 resources/g2/track/corkscrew/small_steep_to_flat_up_diag_4.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_2_3.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_2_4.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_left_bank_to_gentle_up_4_3.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_1_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_1_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_1_3.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_2_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_2_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_3_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_3_2.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_3_3.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_3_4.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_4_1.png create mode 100644 resources/g2/track/corkscrew/small_turn_right_bank_to_gentle_up_4_2.png create mode 100644 resources/g2/track/corkscrew/steep_to_vertical_up_1.png create mode 100644 resources/g2/track/corkscrew/steep_to_vertical_up_2.png create mode 100644 resources/g2/track/corkscrew/steep_to_vertical_up_3.png create mode 100644 resources/g2/track/corkscrew/steep_to_vertical_up_4.png create mode 100644 resources/g2/track/corkscrew/vertical_1.png create mode 100644 resources/g2/track/corkscrew/vertical_2.png create mode 100644 resources/g2/track/corkscrew/vertical_3.png create mode 100644 resources/g2/track/corkscrew/vertical_4.png create mode 100644 resources/g2/track/corkscrew/vertical_to_steep_up_1.png create mode 100644 resources/g2/track/corkscrew/vertical_to_steep_up_2.png create mode 100644 resources/g2/track/corkscrew/vertical_to_steep_up_3.png create mode 100644 resources/g2/track/corkscrew/vertical_to_steep_up_4.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_left_up_1.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_left_up_2_1.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_left_up_2_2.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_left_up_3.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_left_up_4_1.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_left_up_4_2.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_right_up_1_1.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_right_up_1_2.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_right_up_2.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_right_up_3_1.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_right_up_3_2.png create mode 100644 resources/g2/track/corkscrew/vertical_twist_right_up_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_1_1.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_1_2.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_1_3.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_1_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_1_5.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_1_6.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_2_1.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_2_2.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_2_3.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_2_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_2_5.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_2_6.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_3_1.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_3_2.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_3_3.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_3_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_4_1.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_4_2.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_4_3.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_left_4_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_1_1.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_1_2.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_1_3.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_1_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_2_1.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_2_2.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_2_3.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_2_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_3_1.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_3_2.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_3_3.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_3_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_3_5.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_3_6.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_4_1.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_4_2.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_4_3.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_4_4.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_4_5.png create mode 100644 resources/g2/track/corkscrew/zero_g_roll_right_4_6.png diff --git a/distribution/changelog.txt b/distribution/changelog.txt index c69bf19bbc..cc81bb8a0c 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.4.16 (in development) ------------------------------------------------------------------------ +- Improved: [#22937] Add banked sloped turns and many other pieces to the Corkscrew, Hypercoaster and Lay-down Roller Coaster. - Improved: [#22967] Add medium and large half loops to the Wooden and Classic Wooden Roller Coasters. - Improved: [#23010] Make AppImage compatible with Ubuntu 22.04 and Debian Bookworm again. - Fix: [#21221] Trains use unbanked sprites on flat to gentle diagonal banked track pieces. diff --git a/resources/g2/sprites.json b/resources/g2/sprites.json index fa6b492fef..4282107096 100644 --- a/resources/g2/sprites.json +++ b/resources/g2/sprites.json @@ -8302,6 +8302,3926 @@ "y": -8, "palette": "keep" }, + { + "path": "track/corkscrew/small_flat_to_steep_up_1.png", + "x": -24, + "y": -28, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_2_1.png", + "x": -24, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_2_2.png", + "x": -22, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_3_1.png", + "x": -20, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_3_2.png", + "x": -26, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_4.png", + "x": -26, + "y": -26, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_1.png", + "x": -25, + "y": -28, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_2_1.png", + "x": -22, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_2_2.png", + "x": -25, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_3_1.png", + "x": -24, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_3_2.png", + "x": -15, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_4.png", + "x": -24, + "y": -28, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_diag_1.png", + "x": -32, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_diag_2.png", + "x": -14, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_diag_3.png", + "x": -32, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_flat_to_steep_up_diag_4.png", + "x": -14, + "y": -32, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_diag_1.png", + "x": -32, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_diag_2.png", + "x": -14, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_diag_3.png", + "x": -32, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_steep_to_flat_up_diag_4.png", + "x": -14, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/steep_to_vertical_up_1.png", + "x": -25, + "y": -51 + }, + { + "path": "track/corkscrew/steep_to_vertical_up_2.png", + "x": -26, + "y": -52 + }, + { + "path": "track/corkscrew/steep_to_vertical_up_3.png", + "x": -13, + "y": -51 + }, + { + "path": "track/corkscrew/steep_to_vertical_up_4.png", + "x": -13, + "y": -52 + }, + { + "path": "track/corkscrew/vertical_to_steep_up_1.png", + "x": -11, + "y": -60 + }, + { + "path": "track/corkscrew/vertical_to_steep_up_2.png", + "x": -10, + "y": -44 + }, + { + "path": "track/corkscrew/vertical_to_steep_up_3.png", + "x": -26, + "y": -44 + }, + { + "path": "track/corkscrew/vertical_to_steep_up_4.png", + "x": -27, + "y": -60 + }, + { + "path": "track/corkscrew/vertical_twist_left_up_1.png", + "x": -15, + "y": -92 + }, + { + "path": "track/corkscrew/vertical_twist_left_up_2_1.png", + "x": -10, + "y": -92 + }, + { + "path": "track/corkscrew/vertical_twist_left_up_2_2.png", + "x": -10, + "y": -84 + }, + { + "path": "track/corkscrew/vertical_twist_left_up_3.png", + "x": -15, + "y": -92 + }, + { + "path": "track/corkscrew/vertical_twist_left_up_4_1.png", + "x": -7, + "y": -91 + }, + { + "path": "track/corkscrew/vertical_twist_left_up_4_2.png", + "x": -13, + "y": -91 + }, + { + "path": "track/corkscrew/vertical_twist_right_up_1_1.png", + "x": -10, + "y": -89 + }, + { + "path": "track/corkscrew/vertical_twist_right_up_1_2.png", + "x": -10, + "y": -92 + }, + { + "path": "track/corkscrew/vertical_twist_right_up_2.png", + "x": -15, + "y": -91 + }, + { + "path": "track/corkscrew/vertical_twist_right_up_3_1.png", + "x": -7, + "y": -92 + }, + { + "path": "track/corkscrew/vertical_twist_right_up_3_2.png", + "x": -13, + "y": -90 + }, + { + "path": "track/corkscrew/vertical_twist_right_up_4.png", + "x": -15, + "y": -92 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_1.png", + "x": -24, + "y": -19 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_2_1.png", + "x": -10, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_2_2.png", + "x": -24, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_3.png", + "x": -23, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_4.png", + "x": -24, + "y": -24 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_1.png", + "x": -24, + "y": -24 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_2.png", + "x": -24, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_3_1.png", + "x": -8, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_3_2.png", + "x": -24, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_4.png", + "x": -23, + "y": -19 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_1.png", + "x": -20, + "y": -19 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_2_1.png", + "x": -22, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_2_2.png", + "x": -24, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_3.png", + "x": -24, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_4.png", + "x": -24, + "y": -19 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_1.png", + "x": -24, + "y": -19 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_2.png", + "x": -20, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_3_1.png", + "x": -24, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_3_2.png", + "x": 0, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_4.png", + "x": -24, + "y": -19 + }, + { + "path": "track/corkscrew/left_bank_to_gentle_up_left_bank_1.png", + "x": -22, + "y": -11 + }, + { + "path": "track/corkscrew/left_bank_to_gentle_up_left_bank_2.png", + "x": -23, + "y": -4 + }, + { + "path": "track/corkscrew/left_bank_to_gentle_up_left_bank_3.png", + "x": -23, + "y": -9 + }, + { + "path": "track/corkscrew/left_bank_to_gentle_up_left_bank_4.png", + "x": -24, + "y": -16 + }, + { + "path": "track/corkscrew/right_bank_to_gentle_up_right_bank_1.png", + "x": -23, + "y": -16 + }, + { + "path": "track/corkscrew/right_bank_to_gentle_up_right_bank_2.png", + "x": -22, + "y": -9 + }, + { + "path": "track/corkscrew/right_bank_to_gentle_up_right_bank_3.png", + "x": -24, + "y": -4 + }, + { + "path": "track/corkscrew/right_bank_to_gentle_up_right_bank_4.png", + "x": -23, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_left_bank_1.png", + "x": -20, + "y": -12 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_left_bank_2.png", + "x": -24, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_left_bank_3.png", + "x": -23, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_left_bank_4.png", + "x": -22, + "y": -17 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_right_bank_1.png", + "x": -24, + "y": -17 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_right_bank_2.png", + "x": -20, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_right_bank_3.png", + "x": -22, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_right_bank_4.png", + "x": -23, + "y": -12 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_1.png", + "x": -20, + "y": -19 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_2.png", + "x": -24, + "y": -6 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_3.png", + "x": -23, + "y": -12 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_4.png", + "x": -24, + "y": -24 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_1.png", + "x": -24, + "y": -24 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_2.png", + "x": -20, + "y": -12 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_3.png", + "x": -24, + "y": -6 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_4.png", + "x": -23, + "y": -19 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_1.png", + "x": -24, + "y": -11 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_2_1.png", + "x": -24, + "y": -4 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_2_2.png", + "x": -24, + "y": 3 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_3.png", + "x": -23, + "y": -4 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_4.png", + "x": -24, + "y": -16 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_1.png", + "x": -24, + "y": -16 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_2.png", + "x": -24, + "y": -4 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_3_1.png", + "x": -10, + "y": -4 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_3_2.png", + "x": -24, + "y": 3 + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_4.png", + "x": -23, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_1.png", + "x": -20, + "y": -12 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_2_1.png", + "x": -22, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_2_2.png", + "x": -24, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_3.png", + "x": -24, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_4.png", + "x": -24, + "y": -12 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_1.png", + "x": -24, + "y": -12 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_2.png", + "x": -20, + "y": -11 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_3_1.png", + "x": -24, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_3_2.png", + "x": -2, + "y": -5 + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_4.png", + "x": -24, + "y": -12 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_1_1.png", + "x": -26, + "y": -34 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_1_2.png", + "x": -17, + "y": -27 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_2_1.png", + "x": -17, + "y": -13 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_2_2.png", + "x": -38, + "y": -22 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_3_1.png", + "x": -23, + "y": -14 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_3_2.png", + "x": -26, + "y": -32 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_4_1.png", + "x": -26, + "y": -25 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_4_2.png", + "x": -28, + "y": -15 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_1_1.png", + "x": -29, + "y": -25 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_1_2.png", + "x": -26, + "y": -15 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_2_1.png", + "x": -17, + "y": -14 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_2_2.png", + "x": -29, + "y": -19 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_3_1.png", + "x": -38, + "y": -13 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_3_2.png", + "x": -16, + "y": -22 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_4_1.png", + "x": -9, + "y": -27 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_4_2.png", + "x": -23, + "y": -27 + }, + { + "path": "track/corkscrew/small_turn_left_bank_gentle_up_4_3.png", + "x": -16, + "y": -12 + }, + { + "path": "track/corkscrew/small_turn_right_bank_gentle_up_1_3.png", + "x": -16, + "y": -10 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_1_1.png", + "x": -20, + "y": -15 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_1_2.png", + "x": -30, + "y": -13 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_1_3.png", + "x": 0, + "y": 0 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_1_4.png", + "x": -32, + "y": -10 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_1_5.png", + "x": -24, + "y": -24 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_2_1.png", + "x": -24, + "y": -11 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_2_2.png", + "x": 0, + "y": -19 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_2_3.png", + "x": 0, + "y": -2 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_2_4.png", + "x": -13, + "y": -24 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_2_5.png", + "x": -17, + "y": -18 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_3_1.png", + "x": -26, + "y": -12 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_3_2.png", + "x": 0, + "y": 0 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_3_3.png", + "x": -30, + "y": -10 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_3_4.png", + "x": 0, + "y": 0 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_3_5.png", + "x": -24, + "y": -9 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_4_1.png", + "x": -31, + "y": -22 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_4_2.png", + "x": -32, + "y": -13 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_4_3.png", + "x": -19, + "y": -25 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_4_4.png", + "x": -23, + "y": -10 + }, + { + "path": "track/corkscrew/medium_turn_left_bank_gentle_up_4_5.png", + "x": -23, + "y": -12 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_1_1.png", + "x": -24, + "y": -22 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_1_2.png", + "x": -16, + "y": -13 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_1_3.png", + "x": -9, + "y": -25 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_1_4.png", + "x": -19, + "y": -10 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_1_5.png", + "x": -25, + "y": -12 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_2_1.png", + "x": -20, + "y": -12 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_2_2.png", + "x": 0, + "y": 0 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_2_3.png", + "x": 16, + "y": -10 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_2_4.png", + "x": 0, + "y": 0 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_2_5.png", + "x": -24, + "y": -9 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_3_1.png", + "x": -32, + "y": -11 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_3_2.png", + "x": -32, + "y": -19 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_3_3.png", + "x": -26, + "y": -2 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_3_4.png", + "x": -22, + "y": -24 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_3_5.png", + "x": -23, + "y": -18 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_4_1.png", + "x": -17, + "y": -15 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_4_2.png", + "x": 5, + "y": -13 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_4_3.png", + "x": 0, + "y": 0 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_4_4.png", + "x": 2, + "y": -10 + }, + { + "path": "track/corkscrew/medium_turn_right_bank_gentle_up_4_5.png", + "x": -23, + "y": -24 + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_1_1.png", + "x": -24, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_1_2.png", + "x": -32, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_1_3.png", + "x": 10, + "y": 8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_1_4.png", + "x": -19, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_2_1.png", + "x": -24, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_2_2.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_2_3.png", + "x": -24, + "y": 13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_2_4.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_3_1.png", + "x": -5, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_3_2.png", + "x": 8, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_3_3.png", + "x": -32, + "y": -1, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_3_4.png", + "x": -14, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_4_1.png", + "x": -25, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_4_2.png", + "x": -26, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_4_3.png", + "x": 0, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_diag_gentle_up_4_4.png", + "x": 0, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_1_1.png", + "x": -24, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_1_2.png", + "x": -18, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_1_3.png", + "x": -13, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_1_4.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_2_1.png", + "x": -24, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_2_2.png", + "x": -33, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_2_3.png", + "x": 2, + "y": -1, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_2_4.png", + "x": -12, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_3_1.png", + "x": -7, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_3_2.png", + "x": -8, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_3_3.png", + "x": 0, + "y": 13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_3_4.png", + "x": 0, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_4_1.png", + "x": -19, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_4_2.png", + "x": -10, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_4_3.png", + "x": -32, + "y": 8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_diag_gentle_up_4_4.png", + "x": -14, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_1_1.png", + "x": 0, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_1_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_1_3.png", + "x": -32, + "y": -17, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_1_4.png", + "x": -32, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_2_1.png", + "x": -14, + "y": 7, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_2_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_2_3.png", + "x": -14, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_2_4.png", + "x": -16, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_3_1.png", + "x": -32, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_3_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_3_3.png", + "x": -17, + "y": -1, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_3_4.png", + "x": -24, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_4_1.png", + "x": -16, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_4_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_4_3.png", + "x": -25, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_to_orthogonal_gentle_up_4_4.png", + "x": -24, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_1_1.png", + "x": 0, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_1_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_1_3.png", + "x": -32, + "y": -1, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_1_4.png", + "x": -31, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_2_1.png", + "x": 7, + "y": 7, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_2_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_2_3.png", + "x": -16, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_2_4.png", + "x": -24, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_3_1.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_3_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_3_3.png", + "x": -11, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_3_4.png", + "x": -24, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_4_1.png", + "x": -14, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_4_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_4_3.png", + "x": -11, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_to_orthogonal_gentle_up_4_4.png", + "x": -28, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_1_1.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_1_2.png", + "x": -32, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_2.png", + "x": -15, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_3.png", + "x": -32, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_4.png", + "x": -14, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_1.png", + "x": -32, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_2.png", + "x": -14, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_3_1.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_3_2.png", + "x": -32, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_4.png", + "x": -16, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_1_1.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_1_2.png", + "x": -32, + "y": -1, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_2.png", + "x": -15, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_3.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_4.png", + "x": -14, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_1.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_2.png", + "x": -14, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_3_1.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_3_2.png", + "x": -32, + "y": -1, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_4.png", + "x": -16, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/left_bank_to_gentle_up_left_bank_diag_1.png", + "x": -32, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/left_bank_to_gentle_up_left_bank_diag_2.png", + "x": -15, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/left_bank_to_gentle_up_left_bank_diag_3.png", + "x": -32, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/left_bank_to_gentle_up_left_bank_diag_4.png", + "x": -9, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/right_bank_to_gentle_up_right_bank_diag_1.png", + "x": -32, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/right_bank_to_gentle_up_right_bank_diag_2.png", + "x": -9, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/right_bank_to_gentle_up_right_bank_diag_3.png", + "x": -32, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/right_bank_to_gentle_up_right_bank_diag_4.png", + "x": -15, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_left_bank_diag_1.png", + "x": -32, + "y": -3, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_left_bank_diag_2.png", + "x": -15, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_left_bank_diag_3.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_left_bank_diag_4.png", + "x": -9, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_right_bank_diag_1.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_right_bank_diag_2.png", + "x": -9, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_right_bank_diag_3.png", + "x": -32, + "y": -3, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_right_bank_diag_4.png", + "x": -15, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_diag_1.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_diag_2.png", + "x": -15, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_diag_3.png", + "x": -32, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_diag_4.png", + "x": -9, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_diag_1.png", + "x": -32, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_diag_2.png", + "x": -9, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_diag_3.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_diag_4.png", + "x": -15, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_diag_1_1.png", + "x": -32, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_diag_1_2.png", + "x": -32, + "y": -3, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_diag_2.png", + "x": -15, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_diag_3.png", + "x": -32, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_left_bank_diag_4.png", + "x": -14, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_diag_1.png", + "x": -32, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_diag_2.png", + "x": -14, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_diag_3_1.png", + "x": -32, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_diag_3_2.png", + "x": -32, + "y": -3, + "palette": "keep" + }, + { + "path": "track/corkscrew/flat_to_gentle_up_right_bank_diag_4.png", + "x": -15, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_diag_1_1.png", + "x": -32, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_diag_1_2.png", + "x": -32, + "y": 3, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_diag_2.png", + "x": -15, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_diag_3.png", + "x": -32, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_left_bank_to_flat_diag_4.png", + "x": -14, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_diag_1.png", + "x": -32, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_diag_2.png", + "x": -14, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_diag_3_1.png", + "x": -32, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_diag_3_2.png", + "x": -32, + "y": 3, + "palette": "keep" + }, + { + "path": "track/corkscrew/gentle_up_right_bank_to_flat_diag_4.png", + "x": -15, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_1_1.png", + "x": -20, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_1_2.png", + "x": -28, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_1_3.png", + "x": 15, + "y": 8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_1_4.png", + "x": -11, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_2_1.png", + "x": -24, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_2_2.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_2_3.png", + "x": -24, + "y": 14, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_2_4.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_3_1.png", + "x": -8, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_3_2.png", + "x": 0, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_3_3.png", + "x": -32, + "y": -2, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_3_4.png", + "x": -14, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_4_1.png", + "x": -26, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_4_2.png", + "x": -26, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_4_3.png", + "x": 0, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_diag_gentle_up_4_4.png", + "x": 0, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_1_1.png", + "x": -24, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_1_2.png", + "x": -21, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_1_3.png", + "x": -15, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_1_4.png", + "x": -32, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_2_1.png", + "x": -20, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_2_2.png", + "x": -34, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_2_3.png", + "x": -1, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_2_4.png", + "x": -14, + "y": -23, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_3_1.png", + "x": -8, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_3_2.png", + "x": -8, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_3_3.png", + "x": 0, + "y": 14, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_3_4.png", + "x": 0, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_4_1.png", + "x": -16, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_4_2.png", + "x": -5, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_4_3.png", + "x": -32, + "y": 8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_diag_gentle_up_4_4.png", + "x": -15, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_1_1.png", + "x": 0, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_1_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_1_3.png", + "x": -32, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_1_4.png", + "x": -29, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_2_1.png", + "x": -15, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_2_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_2_3.png", + "x": -9, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_2_4.png", + "x": -16, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_3_1.png", + "x": -32, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_3_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_3_3.png", + "x": -24, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_3_4.png", + "x": -23, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_4_1.png", + "x": -11, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_4_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_4_3.png", + "x": -26, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_left_bank_to_orthogonal_gentle_up_4_4.png", + "x": -24, + "y": -23, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_1_1.png", + "x": 0, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_1_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_1_3.png", + "x": -32, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_1_4.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_2_1.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_2_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_2_3.png", + "x": -16, + "y": -10, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_2_4.png", + "x": -24, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_3_1.png", + "x": -32, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_3_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_3_3.png", + "x": -15, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_3_4.png", + "x": -23, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_4_1.png", + "x": -15, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_4_2.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_4_3.png", + "x": -14, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_turn_right_bank_to_orthogonal_gentle_up_4_4.png", + "x": -29, + "y": -23, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_1_1.png", + "x": -27, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_1_2.png", + "x": -18, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_2_1.png", + "x": -17, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_2_2.png", + "x": -18, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_2_3.png", + "x": -38, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_3_1.png", + "x": -25, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_3_2.png", + "x": -11, + "y": -2, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_4_1.png", + "x": -10, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_4_2.png", + "x": -30, + "y": -1, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_1_1.png", + "x": -29, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_1_2.png", + "x": -10, + "y": -1, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_2_1.png", + "x": -15, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_2_2.png", + "x": -30, + "y": -2, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_3_1.png", + "x": -38, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_3_2.png", + "x": -38, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_3_3.png", + "x": -18, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_4_1.png", + "x": -11, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_4_2.png", + "x": -25, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_4_3.png", + "x": -16, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_1_3.png", + "x": -16, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_left_bank_to_gentle_up_2_4.png", + "x": -38, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/small_turn_right_bank_to_gentle_up_3_4.png", + "x": -18, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_1_1.png", + "x": -24, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_1_2.png", + "x": -23, + "y": -71, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_1_3.png", + "x": -28, + "y": -36, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_1_4.png", + "x": -25, + "y": -48, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_1_5.png", + "x": -24, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_2_1.png", + "x": -24, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_2_2.png", + "x": -32, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_2_3.png", + "x": -25, + "y": -50, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_2_4.png", + "x": -20, + "y": -58, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_2_5.png", + "x": -15, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_3_1.png", + "x": -16, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_3_2.png", + "x": -17, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_3_3.png", + "x": 13, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_3_4.png", + "x": -19, + "y": -38, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_3_5.png", + "x": -26, + "y": -31, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_4_1.png", + "x": -26, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_4_2.png", + "x": -25, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_4_3.png", + "x": -16, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_4_4.png", + "x": -37, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_4_5.png", + "x": -24, + "y": -26, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_1_1.png", + "x": -24, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_1_2.png", + "x": -25, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_1_3.png", + "x": -24, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_1_4.png", + "x": -30, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_1_5.png", + "x": -32, + "y": -26, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_2_1.png", + "x": -24, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_2_2.png", + "x": -16, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_2_3.png", + "x": -24, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_2_4.png", + "x": -16, + "y": -38, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_2_5.png", + "x": -24, + "y": -31, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_3_1.png", + "x": -35, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_3_2.png", + "x": -16, + "y": -15, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_3_3.png", + "x": -27, + "y": -50, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_3_4.png", + "x": -32, + "y": -58, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_3_5.png", + "x": -24, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_4_1.png", + "x": -23, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_4_2.png", + "x": -11, + "y": -71, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_4_3.png", + "x": 13, + "y": -36, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_4_4.png", + "x": -14, + "y": -48, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_4_5.png", + "x": -21, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_left_4_4_2.png", + "x": -37, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_corkscrew_right_1_4_2.png", + "x": -20, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/quarter_loop_up_1_1.png", + "x": -22, + "y": -53 + }, + { + "path": "track/corkscrew/quarter_loop_up_1_2.png", + "x": -4, + "y": -35 + }, + { + "path": "track/corkscrew/quarter_loop_up_1_3.png", + "x": -24, + "y": -17 + }, + { + "path": "track/corkscrew/quarter_loop_up_2_1.png", + "x": -28, + "y": -78 + }, + { + "path": "track/corkscrew/quarter_loop_up_2_2.png", + "x": -32, + "y": -66 + }, + { + "path": "track/corkscrew/quarter_loop_up_2_3.png", + "x": -24, + "y": -25 + }, + { + "path": "track/corkscrew/quarter_loop_up_3_1.png", + "x": -13, + "y": -78 + }, + { + "path": "track/corkscrew/quarter_loop_up_3_2.png", + "x": -23, + "y": -68 + }, + { + "path": "track/corkscrew/quarter_loop_up_3_3.png", + "x": -10, + "y": -25 + }, + { + "path": "track/corkscrew/quarter_loop_up_4_1.png", + "x": -13, + "y": -54 + }, + { + "path": "track/corkscrew/quarter_loop_up_4_2.png", + "x": -24, + "y": -36 + }, + { + "path": "track/corkscrew/quarter_loop_up_4_3.png", + "x": -32, + "y": -17 + }, + { + "path": "track/corkscrew/quarter_loop_up_1_2_2.png", + "x": 0, + "y": -35 + }, + { + "path": "track/corkscrew/quarter_loop_up_4_2_2.png", + "x": -45, + "y": -36 + }, + { + "path": "track/corkscrew/medium_half_loop_left_1_1.png", + "x": -24, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_1_2.png", + "x": -24, + "y": -50, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_1_3.png", + "x": -32, + "y": -98, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_1_4.png", + "x": -40, + "y": -121, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_1_5.png", + "x": -23, + "y": -31, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_2_1.png", + "x": -24, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_2_2.png", + "x": 0, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_2_3.png", + "x": -32, + "y": -85, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_2_4.png", + "x": -33, + "y": -148, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_2_5.png", + "x": -24, + "y": -41, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_3_1.png", + "x": -24, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_3_2.png", + "x": 0, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_3_3.png", + "x": -7, + "y": -72, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_3_4.png", + "x": -39, + "y": -152, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_3_5.png", + "x": -16, + "y": -41, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_4_1.png", + "x": -23, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_4_2.png", + "x": -25, + "y": -26, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_4_3.png", + "x": -32, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_4_4.png", + "x": -14, + "y": -123, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_4_5.png", + "x": -25, + "y": -34, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_1_1.png", + "x": -24, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_1_2.png", + "x": -21, + "y": -26, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_1_3.png", + "x": -19, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_1_4.png", + "x": -37, + "y": -123, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_1_5.png", + "x": -24, + "y": -34, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_2_1.png", + "x": -24, + "y": -7, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_2_2.png", + "x": -32, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_2_3.png", + "x": -32, + "y": -72, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_2_4.png", + "x": -28, + "y": -152, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_2_5.png", + "x": -23, + "y": -41, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_3_1.png", + "x": -32, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_3_2.png", + "x": -32, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_3_3.png", + "x": -32, + "y": -85, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_3_4.png", + "x": -14, + "y": -148, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_3_5.png", + "x": -12, + "y": -41, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_4_1.png", + "x": -24, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_4_2.png", + "x": -20, + "y": -50, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_4_3.png", + "x": -7, + "y": -98, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_4_4.png", + "x": -32, + "y": -121, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_4_5.png", + "x": -32, + "y": -31, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_1_4_2.png", + "x": -40, + "y": -121, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_2_1_2.png", + "x": -24, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_2_2_2.png", + "x": -32, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_left_4_4_2.png", + "x": -14, + "y": -123, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_1_4_2.png", + "x": -37, + "y": -123, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_3_1_2.png", + "x": -32, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_3_2_2.png", + "x": -32, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/medium_half_loop_right_4_4_2.png", + "x": -32, + "y": -121, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_half_loop_left_1_1.png", + "x": -24, + "y": -29 + }, + { + "path": "track/corkscrew/large_half_loop_left_1_2.png", + "x": -20, + "y": -42 + }, + { + "path": "track/corkscrew/large_half_loop_left_1_3.png", + "x": -32, + "y": -69 + }, + { + "path": "track/corkscrew/large_half_loop_left_1_4.png", + "x": -32, + "y": -84 + }, + { + "path": "track/corkscrew/large_half_loop_left_1_5.png", + "x": -18, + "y": -68 + }, + { + "path": "track/corkscrew/large_half_loop_left_1_6.png", + "x": -11, + "y": -177 + }, + { + "path": "track/corkscrew/large_half_loop_left_1_7.png", + "x": -23, + "y": -14 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_1.png", + "x": -24, + "y": -6 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_2.png", + "x": -6, + "y": -8 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_3.png", + "x": -9, + "y": -25 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_4.png", + "x": -9, + "y": -116 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_5.png", + "x": -32, + "y": -136 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_6.png", + "x": -28, + "y": -195 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_7.png", + "x": -25, + "y": -25 + }, + { + "path": "track/corkscrew/large_half_loop_left_3_1.png", + "x": -25, + "y": -4 + }, + { + "path": "track/corkscrew/large_half_loop_left_3_2.png", + "x": -31, + "y": -9 + }, + { + "path": "track/corkscrew/large_half_loop_left_3_3.png", + "x": -28, + "y": -37 + }, + { + "path": "track/corkscrew/large_half_loop_left_3_4.png", + "x": -10, + "y": -59 + }, + { + "path": "track/corkscrew/large_half_loop_left_3_5.png", + "x": -11, + "y": -117 + }, + { + "path": "track/corkscrew/large_half_loop_left_3_6.png", + "x": -23, + "y": -196 + }, + { + "path": "track/corkscrew/large_half_loop_left_3_7.png", + "x": -26, + "y": -25 + }, + { + "path": "track/corkscrew/large_half_loop_left_4_1.png", + "x": -24, + "y": -17 + }, + { + "path": "track/corkscrew/large_half_loop_left_4_2.png", + "x": -32, + "y": -21 + }, + { + "path": "track/corkscrew/large_half_loop_left_4_3.png", + "x": -32, + "y": -55 + }, + { + "path": "track/corkscrew/large_half_loop_left_4_4.png", + "x": -32, + "y": -82 + }, + { + "path": "track/corkscrew/large_half_loop_left_4_5.png", + "x": 12, + "y": -60 + }, + { + "path": "track/corkscrew/large_half_loop_left_4_6.png", + "x": -19, + "y": -181 + }, + { + "path": "track/corkscrew/large_half_loop_left_4_7.png", + "x": -32, + "y": -16 + }, + { + "path": "track/corkscrew/large_half_loop_right_1_1.png", + "x": -24, + "y": -18 + }, + { + "path": "track/corkscrew/large_half_loop_right_1_2.png", + "x": -20, + "y": -21 + }, + { + "path": "track/corkscrew/large_half_loop_right_1_3.png", + "x": -14, + "y": -55 + }, + { + "path": "track/corkscrew/large_half_loop_right_1_4.png", + "x": 0, + "y": -82 + }, + { + "path": "track/corkscrew/large_half_loop_right_1_5.png", + "x": -32, + "y": -60 + }, + { + "path": "track/corkscrew/large_half_loop_right_1_6.png", + "x": -21, + "y": -181 + }, + { + "path": "track/corkscrew/large_half_loop_right_1_7.png", + "x": -25, + "y": -16 + }, + { + "path": "track/corkscrew/large_half_loop_right_2_1.png", + "x": -24, + "y": -4 + }, + { + "path": "track/corkscrew/large_half_loop_right_2_2.png", + "x": -12, + "y": -9 + }, + { + "path": "track/corkscrew/large_half_loop_right_2_3.png", + "x": -6, + "y": -37 + }, + { + "path": "track/corkscrew/large_half_loop_right_2_4.png", + "x": -28, + "y": -59 + }, + { + "path": "track/corkscrew/large_half_loop_right_2_5.png", + "x": -26, + "y": -117 + }, + { + "path": "track/corkscrew/large_half_loop_right_2_6.png", + "x": -20, + "y": -196 + }, + { + "path": "track/corkscrew/large_half_loop_right_2_7.png", + "x": -23, + "y": -25 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_1.png", + "x": -26, + "y": -6 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_2.png", + "x": -28, + "y": -8 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_3.png", + "x": -29, + "y": -25 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_4.png", + "x": -32, + "y": -116 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_5.png", + "x": 12, + "y": -136 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_6.png", + "x": 0, + "y": -195 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_7.png", + "x": -19, + "y": -25 + }, + { + "path": "track/corkscrew/large_half_loop_right_4_1.png", + "x": -27, + "y": -29 + }, + { + "path": "track/corkscrew/large_half_loop_right_4_2.png", + "x": -28, + "y": -41 + }, + { + "path": "track/corkscrew/large_half_loop_right_4_3.png", + "x": -23, + "y": -69 + }, + { + "path": "track/corkscrew/large_half_loop_right_4_4.png", + "x": -10, + "y": -84 + }, + { + "path": "track/corkscrew/large_half_loop_right_4_5.png", + "x": -11, + "y": -68 + }, + { + "path": "track/corkscrew/large_half_loop_right_4_6.png", + "x": -31, + "y": -177 + }, + { + "path": "track/corkscrew/large_half_loop_right_4_7.png", + "x": -28, + "y": -14 + }, + { + "path": "track/corkscrew/large_half_loop_left_1_6_2.png", + "x": -11, + "y": -177 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_2_2.png", + "x": -6, + "y": -8 + }, + { + "path": "track/corkscrew/large_half_loop_left_2_3_2.png", + "x": -19, + "y": -25 + }, + { + "path": "track/corkscrew/large_half_loop_left_3_3_2.png", + "x": -28, + "y": -37 + }, + { + "path": "track/corkscrew/large_half_loop_right_2_3_2.png", + "x": -32, + "y": -37 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_2_2.png", + "x": -28, + "y": -8 + }, + { + "path": "track/corkscrew/large_half_loop_right_3_3_2.png", + "x": -29, + "y": -25 + }, + { + "path": "track/corkscrew/large_half_loop_right_4_6_2.png", + "x": -31, + "y": -177 + }, + { + "path": "track/corkscrew/barrel_roll_left_1_1.png", + "x": -24, + "y": 6, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_1_2.png", + "x": -15, + "y": 6, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_1_3.png", + "x": -22, + "y": -17, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_1_4.png", + "x": -21, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_1_5.png", + "x": -14, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_1_6.png", + "x": -13, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_2_1.png", + "x": -24, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_2_2.png", + "x": -25, + "y": 4, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_2_3.png", + "x": -28, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_2_4.png", + "x": -28, + "y": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_2_5.png", + "x": -30, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_2_6.png", + "x": -32, + "y": -23, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_3_1.png", + "x": -30, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_3_2.png", + "x": -31, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_3_3.png", + "x": -25, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_3_4.png", + "x": -28, + "y": -20, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_3_5.png", + "x": -3, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_3_6.png", + "x": -25, + "y": -23, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_4_1.png", + "x": -17, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_4_2.png", + "x": -7, + "y": 14, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_4_3.png", + "x": -13, + "y": -20, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_4_4.png", + "x": -10, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_4_5.png", + "x": -22, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_left_4_6.png", + "x": -24, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_1_1.png", + "x": -25, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_1_2.png", + "x": -15, + "y": 15, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_1_3.png", + "x": -28, + "y": -20, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_1_4.png", + "x": -27, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_1_5.png", + "x": -22, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_1_6.png", + "x": -24, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_2_1.png", + "x": -24, + "y": -5, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_2_2.png", + "x": -17, + "y": 10, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_2_3.png", + "x": -8, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_2_4.png", + "x": -1, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_2_5.png", + "x": -8, + "y": -12, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_2_6.png", + "x": -7, + "y": -23, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_3_1.png", + "x": -4, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_3_2.png", + "x": -4, + "y": 4, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_3_3.png", + "x": 2, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_3_4.png", + "x": 0, + "y": -9, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_3_5.png", + "x": -10, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_3_6.png", + "x": -24, + "y": -24, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_4_1.png", + "x": -11, + "y": 6, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_4_2.png", + "x": -21, + "y": 6, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_4_3.png", + "x": -28, + "y": -18, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_4_4.png", + "x": -29, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_4_5.png", + "x": -23, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/barrel_roll_right_4_6.png", + "x": -24, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_1_1.png", + "x": -24, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_1_2.png", + "x": -10, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_1_3.png", + "x": -10, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_1_4.png", + "x": -11, + "y": -35, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_1_5.png", + "x": -19, + "y": -20, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_1_6.png", + "x": -21, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_2_1.png", + "x": -14, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_2_2.png", + "x": -24, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_2_3.png", + "x": -23, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_2_4.png", + "x": -23, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_2_5.png", + "x": -21, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_2_6.png", + "x": -26, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_3_1.png", + "x": -21, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_3_2.png", + "x": -22, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_3_3.png", + "x": -25, + "y": -20, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_3_4.png", + "x": -24, + "y": -27, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_4_1.png", + "x": -18, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_4_2.png", + "x": -12, + "y": -39, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_4_3.png", + "x": -22, + "y": -17, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_left_4_4.png", + "x": -22, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_1_1.png", + "x": -24, + "y": -30, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_1_2.png", + "x": -29, + "y": -39, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_1_3.png", + "x": -23, + "y": -17, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_1_4.png", + "x": -35, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_2_1.png", + "x": -24, + "y": -13, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_2_2.png", + "x": -17, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_2_3.png", + "x": -14, + "y": -20, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_2_4.png", + "x": -23, + "y": -28, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_3_1.png", + "x": -9, + "y": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_3_2.png", + "x": -9, + "y": -6, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_3_3.png", + "x": -11, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_3_4.png", + "x": -11, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_3_5.png", + "x": -22, + "y": -16, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_3_6.png", + "x": -22, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_4_1.png", + "x": -25, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_4_2.png", + "x": -31, + "y": -14, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_4_3.png", + "x": -25, + "y": -22, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_4_4.png", + "x": -39, + "y": -35, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_4_5.png", + "x": -19, + "y": -20, + "palette": "keep" + }, + { + "path": "track/corkscrew/zero_g_roll_right_4_6.png", + "x": -25, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_1_1.png", + "x": -25, + "y": -46, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_1_2.png", + "x": -26, + "y": -48, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_1_3.png", + "x": -17, + "y": -51, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_1_4.png", + "x": -11, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_1_5.png", + "x": -15, + "y": -40, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_1_6.png", + "x": -14, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_1_7.png", + "x": -19, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_2_1.png", + "x": -26, + "y": -17, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_2_2.png", + "x": -26, + "y": -43, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_2_3.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_2_4.png", + "x": -28, + "y": -34, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_2_5.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_2_6.png", + "x": -32, + "y": -26, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_2_7.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_2_8.png", + "x": -30, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_3_1.png", + "x": -11, + "y": -32, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_3_2.png", + "x": -15, + "y": -31, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_3_3.png", + "x": -31, + "y": -41, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_3_4.png", + "x": -32, + "y": -23, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_3_5.png", + "x": -24, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_3_6.png", + "x": -24, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_3_7.png", + "x": -24, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_3_8.png", + "x": -23, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_4_1.png", + "x": -17, + "y": -52, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_4_2.png", + "x": -16, + "y": -47, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_4_3.png", + "x": -11, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_4_4.png", + "x": -30, + "y": -57, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_4_5.png", + "x": -20, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_left_4_6.png", + "x": -23, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_1_1.png", + "x": -25, + "y": -54, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_1_2.png", + "x": -32, + "y": -47, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_1_3.png", + "x": -29, + "y": -33, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_1_4.png", + "x": -31, + "y": -57, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_1_5.png", + "x": -25, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_1_6.png", + "x": -28, + "y": -25, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_2_1.png", + "x": -18, + "y": -32, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_2_2.png", + "x": -26, + "y": -31, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_2_3.png", + "x": -25, + "y": -41, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_2_4.png", + "x": -23, + "y": -23, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_2_5.png", + "x": -18, + "y": -29, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_2_6.png", + "x": 15, + "y": -27, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_2_7.png", + "x": -8, + "y": -11, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_2_8.png", + "x": -28, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_3_1.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_3_2.png", + "x": -19, + "y": -43, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_3_3.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_3_4.png", + "x": -15, + "y": -34, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_3_5.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_3_6.png", + "x": -5, + "y": -26, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_3_7.png", + "x": 0, + "y": 0, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_3_8.png", + "x": -23, + "y": -21, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_4_1.png", + "x": -21, + "y": -46, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_4_2.png", + "x": -23, + "y": -50, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_4_3.png", + "x": -32, + "y": -51, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_4_4.png", + "x": -27, + "y": -36, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_4_5.png", + "x": -29, + "y": -40, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_4_6.png", + "x": -18, + "y": -19, + "palette": "keep" + }, + { + "path": "track/corkscrew/large_zero_g_roll_right_4_7.png", + "x": -25, + "y": -25, + "palette": "keep" + }, { "path": "track/lim/barrel_roll_left_1_1.png", "x": -22, diff --git a/resources/g2/track/corkscrew/barrel_roll_left_1_1.png b/resources/g2/track/corkscrew/barrel_roll_left_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..300d3ea5e627860cff37895ae7e84c8083e811a2 GIT binary patch literal 1037 zcmX9-Z;0D;7=G_>?sl8qtXyIJkj=_vE|W}x3lc_d%gye{xQu1c4+S%bTCihLqU(o# z2s5Xh6wS1|744v~p!JBX>J7sv7`%W7>t@88b~8vliWWSfxFUCYAAV*Gp7(uuzPt|) z&-=c6axS@J+wN@uuw(Z4%&Blb8CG;`DD2BFwFxi;Cr_L{7Se%%fx*GSp`oGS;o*^y zkU6TV~Iq9rYWB1BuP+|w5F+sVU)|&dfoB7)gb8g`!od{3!*TQPDis@ zJeQ{mMYdcKYjwHdYE8e`?pQpDrPv8oi0LWZREVlZFB!aBPBrUluu|v-)<(}u#z7__ z$AKwfH5GG2NUCH?rxlacD!gF}rG{iRWhcnsOq@z4Scw!ACav;nK`d0|s-rr-?gb^k zTWfE)5e}jf#4>>AfiN+q8cWuRw9Bb}s@T@7p6Q__k&G%#JeMSkDYmBY4NdY5rB&8C zw$XFT8@`P?UL?v8WQt}o9G{bVfC?+Z@OOrb!W9 z#?35Q$#Zr=YE&{Sw%&3p-ImwyuOkj11)u?#05-r1KnDX9LgZ0iL$-y2mPmj~Lx}?? z34sVm0;I-Jkw%t?oGfY=NcR3=9be&tsW5t2FH?AB+cPjiOy#PQ_or@ybDs| zKn|b)5DK#>gmRA%H}aKEhpChwL2EYobXv-0m3&^MDTATP9BuQoD^RN<*-a&oj3b>u z6&g7l@`dpDnP(>ce)t1#oSKth`j30BgrqS$bL8~C58l3%ecafyef}o;Y3GA$#M9Kv ze?D=bb7TJ@ZmB(0+4oQVx4FBc7hn5qYI<_l_py%;P2OBwp5HvI+`2#b^)>U=_kKS9 zYi9AItJ;re$IeVGT>1P!j=klLYj;LI-JNG9XYQvC{xVDA%e}?F-hZ~b_rLl}&;9W4 z<(-|!E?j-#?C<>T#Utlm-2Cv~`A;riI#}Mdw!VMQ+P6*S@WRn^Gk0(7z4GRri?5%U q|LU6uYtJX2x}BTOoV)Pd_66q4(ifyLq`ec`fZ1bnGuMxvdFy{w4#FS+ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_1_2.png b/resources/g2/track/corkscrew/barrel_roll_left_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..f05203dc8f35645d29a71bd2e0186bf8149067ca GIT binary patch literal 1009 zcmX9-Ux?#$5T5;;{o@+F9u%w)-J&^+M;3w`Bw+4L*WMc4++OymT)?O~t`AiLM(knG z=oPI}FiM3WeJEU%E(YwwD#7hT;41c@LOk}NVvvdj`*2{8;uYM7pE(Y`nc;hxZ-#H? zlk+?IwUvif0AOwVT<$_rvq_|u=8}B+-P}(Ab8!BJy{&}K%*@Qr&d$xv&Cky-EG#T8 zE@BwAw6wImyqwNvvkXHE0x!#=rYVM@S1J|9X|~&bw|f*t@npi#z;hsptBR5;m58!Q zS8JTpkXmiE6BzxlHXOMEg%!9}T})dA!q&*9!5mbCz$x_Gdep0qBX=5i^BGVnDDz;; zSWCx(8a`;HCjAT=(`cfiV;iAvvV#PmVwjHORwiSUq|0#!lGG~}2bOia*+fB*VNzK> zO-lr)l6jpfSd3ArSx%-zja76(uS(UX+Vpilw7O9}9Jhwk z0OuhkL%Ilr38am&&2+v^Dgm#Dh1$??W4ntEBr2t`nR1@06}XlrbPPGHXamO>d6hVD zrlE&MT|C8-RDofOyik_qnx-|%<#w$WG@GIC508%GI7X1sfpjpYg$tdG+^32|p*m9B zak&%QN0avWcrZn)6ppj$be_n{6s>WbAxc#>X=b)-^R7W z_o{NIQS5ovAZUyS-O1!O;sFW(27nFV0rUVy7@!1_fJ_5&auJU$TatYNZ z^@y`$#ha8nQ>TCI578hdQ@|2fp2iiPD9Maj6m6^I)~$|L54+wt>Y~Yz6-DF&iU6U+ zi)tcw51ESD7>(G5a}P$pFDQy!Dru&vGjxTe9iH(7CJ^Z(i5eHONF|U(q6UL}9))6Z z{Osw~fA0RkTNid@IP=%9R}#|P&Yj&m_4$XNZJ)TYao_yEC^)BnxYzdV0KQyC-)`U%oibEnk{O!H-}4@w|y$ C)2iD5 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_1_3.png b/resources/g2/track/corkscrew/barrel_roll_left_1_3.png new file mode 100644 index 0000000000000000000000000000000000000000..d495e75e0202d67e188fbd5d6b969f2796bee212 GIT binary patch literal 922 zcmX9-L5SmI82x5CGwEy@awtR8z{I789D)Rl5HW|iW|qvDWwLG-a_AuoLAzKXLWF`{ z4A_Mt!OcJqJ#^U~!qP*)3Ui23qwR(7XNHiJ^j$9 zgO)8ucR14%?2*(9ltHBVb0f@J6i>2pL(mw-8DvI!QK2^T}!(<08~G zAX-3mf%Y(dOvqEZ8H-k`yDQt@cnP{vnYzi79hq@;VPZ;=t))G4IkeY7Zxau=lGT=bu`U2%~7W_b=`P8PQ!4uSZp>M1f&J@5aTAe6p`ATX|1IGy6NYgXyYx4 zX@0ZZq8fwaJVD4*Lt|J|5Nt*58>Lux>JDa;X_lnLN(4i}Yz=n|%4;*Dt{C*SXw;eo z&N3e5%cLl-kqDpz*Z>|tS%VqC8Us{9l~C74fseAKN`uA0K!i|+Oa-I?vIyjI$X8L= zM)N+(e0UW+4~hi3inUF`=`aINp7>@I_0lxR^Awd{WDB@%P4o!Wr;L!cGQrz4gQ62{ zhx40og_aw-4m^d)EZ!8Uw#Ic^is!WbffEITGzs!7LB)z!6chr=0HHFAerfj_WUo6~ zuldpNHSGCZYBsfY+w68Nj_vX6P~-xMixqaEGP&MB28A3NjW`sFC{@bx^Y7IDdG!Nd zJ-E=|!$1G{tR!dWr*|H{|GoL>?StpHKR(`la{H72s#xp%_dB0I{cZor$z$xY`Xwg( z^^5ZJv&By@&s4l|{QTtUr@ub_`{=zl?!9ch_~KdR^2IlBd2;l@@sFo(mYQ&W_u}-2 Ij~;#dKa#V74gdfE literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_1_4.png b/resources/g2/track/corkscrew/barrel_roll_left_1_4.png new file mode 100644 index 0000000000000000000000000000000000000000..b8454b91008d6f8e6b91388a39af73348b7a36d0 GIT binary patch literal 1386 zcmXAoeQZ)^6vp3v-hL?!Y@>=w9V$-du)SJTTu^Tt+FtF|UKKZDSj34+=2fps8)|W- zN;_QdEK`=SiHa2`S+RAKMO55y*5tOK+HGjq#E6x4nqtSaE}g!^nEcK;IscsJkLNk9 zt7?=J@+Rj2047vbme;0cX{zSsWTg70ckZ+RkO5Y$SW}T&)6&w?)6+9DGBPtWv$C?X zv$GKd$;rvd&CTVDL?RTGVwi#?ajjNO)0Ek4w%eUvuP+!Jh(r>}Bq{|8IUw+SwVJ2b z3k^o8#VWTu2)9?`572DL8jZOy38IqcQ#jwG5;9t`lSa>*v4CC0dZ|c{B_45&C4x!; z&`5wm0T>c-Q%Jzd3A=eoRsiEtnAE^=2Ew2S00ICFf>0ceNg!avVwYTgo*;U3y0FRg z$mxWEfB@x*6nrTmlxxIFN}@8MT1HMgFtZ1@`AHY6@kMk(nLw%($w>*Wm8mI=vJe)h z#_6McAyY773&q{hu>eN_cqHKKfY1oU3?g&#m0qzrprAr3Ym{~+m>@h)NO)SAz@U^^ zRdTl$^V4L=tPR`gn8%z5*vCR17z=WEGO3?#kr@$eYTmvA^TK3^#mkrJs^E~jzAqDdVy zdabq|w>J_DC8G+U!4aC|m^4C0FL4+Z9t-Jr=z2V+aKI4{2b0N1Pyv7n02%-W01p5? z0K^agQxF(5($M3AkuV_!6bft#;8TJK0U!w=#fMfDx(MjgL)HQ#F7V2D8Ne~1A`rcn zZ!$=1jMDAW`u*lm$PMPWE0<^h=y zQA#;#g-}nTMjg(W^e&sp@3Dn~o_Hh(lTjItLmz+<0Ab1tOG@rF0<+N(i^&}J*U&7B zsnw)juQeJeRBDz$5!48wNemq*^eJEnPlaDLH-Gfi5A3e3A;Hpz zw>JZjUQ|`SY)xhBkt4(1r-};>?1L%+zi?ms!7t9Or>_p){dVWpBs+2+6)(yy>$8_M z7@t_?QLT4-|HL3DCbuMlV7K87{UI=$1lt6>D>jLm=qV3}=k#p9VcGac?zS5i7LWBTZ!bEHOKuL=x7S_SHZSI8CT{KbTs7A&MivQ+nCnxnJ+y4;SR8M?b!T>L4?-7i{^UDa z_rv}zB~9CH>suERFY50c=`Sv8-n;Rl|Cem^!qX=;4`w&`FPlpSyI&St=SFIC0-s$H z?{69F<~|-NTzLC;V-Sew^RY%{M!b98F6<__=9m=_&oN#;E{WTx5 zBQfFb>6bFVhOD|XH0nIuB}N022@qlly@%w GsOf)-ByIZu literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_1_5.png b/resources/g2/track/corkscrew/barrel_roll_left_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..90f9c9ca649bbdc06706da99752025b8564c86bd GIT binary patch literal 903 zcmX9-F=*pv82u6_Q4$kG>p|^_A`VkDh^q>s=!&>1trFB!z34by@t{Emf{NlngIYXz z5Y$j#5k-RsQC#qW1{DPLkU@h64WfAPpuvL+8cZ=%Lk3Yiq>$mSj)V7oA8&bYc<=l9 z*|mIj`rs4*&aS?^c;4I(oB80l)$9k~ee*9s3!Z)b;j^%;Nal!@bKv9 z2*a@B0mJTylgfrl4P@5)pd=4w1EyVF2bdh)Rv63k;Yp+tOjZAuXgk5 zetn19436^zAyZwAVNF4B6m@JgV#B#NSw!p@ZTOm1~s-n}dl6i43I*NCRXO$m39`qNI zeX>F8n(hEkVKR&BBGuQpp{4k4Kb*K}JSpIg`@*J~1zW51$tl*c?`=7NQ{_yDGSD$`#UcL9^sd4)|_UbhH j`?n{rTCe~6^PN)=pPs$j&R_r92*B0l^~E1wy!`QhDe8AT literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_1_6.png b/resources/g2/track/corkscrew/barrel_roll_left_1_6.png new file mode 100644 index 0000000000000000000000000000000000000000..86423387b3d6a7f5f1bc42e3cabf5978a9220636 GIT binary patch literal 1282 zcmX9-e{2(F82(td-F|wIG8<{MvJMIyq{4{@c5tvOspOU(?1+U_Qo=99zZqLp+|rI4wo7OAFc37sBLpu)vfC|JXUX4Guz9G@j5&-?R__xa;_-rXzA zrsjqz4FG`VnVz4S(@Xlg1~z`o?tK>kBg~PR+dZUGOh=t0Wfr<)v9zjG)|Y^ z>oWvHOf+swB!!IR%NHUPhFA=ZJgstDG=5GO7Vv%#l?+-kab8Y)i*jVNlrpJ-4FgUR z_*o>%BS{~ciz>?*H7x33*#^h_5T>*MFaX#Pghx@gTJ6{AA_hZ0!=&x@oZCGV4#Q+p zjVraJO3!EvHl2ybEN-0h8-x($iP3=s8_C#2*{&hfdXv_`Vl+osd5ZTk-mon!@}lHU z$pNVt&5tHg5-3@qvIC6^===x~R+-{DYm($8i!U!kO8yk=XD}s4sGTOvXE8)MDj~3v zhsyJ%u27*sgo5`WWHOZ1$~qjJ%f;h*51|i| zc#Oi6v_8vVMT-{NG|;VsAsmV%l<122i8+nK_kQ4&E;9?3{Qk>^N`HL0ap|fBd%AlY z&&M8Z>bVTByjWwj+zCv4WFFBzw0b`N!Ie8p&F0pQcI0g4S{=Q3F#g-dM0sivIiq|# z{nGWq1OHOS*3HKMZm~aKeY)YvyBF52Z2E3d&y0OkwdK$*^ycBNO_Q2V^i3Xrby4q8 za^Uol_n-N4-Gf})k$tnsLo-b$*KeQLae@Bz+_E*5wMTbnu*Gno@0wm149sJA9tOnJ1esnKX=j*jjNm0Lzz|jmJ9Hz4<@y$2W8U literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_2_1.png b/resources/g2/track/corkscrew/barrel_roll_left_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..6b4a1bf450eba1856ca9b238089d815ee4e9f48e GIT binary patch literal 935 zcmXAoL5SmY6vkhtGn3BNwMq{WGZLYPfI*@YG>06rYi6lKbh1o#DcD1lfE9blAxaNL zqvlYS9C9dQ7J8_VL)CyijBCUS0VDKK)__GTMk!b^$SP3^+r!}g&9d;l_xLXFclh4B zarL-<@xtR50N~=$i-#xq+|TQgQZerbk7mCD6yfSi*RJHYP$+C|Z54~f?d|QIot@p? zT@1rYrPAKs9$u@}Se6k*K~W@4YZ``bS(fV#$KxQ1=1G#R*DM1953*ElHmmJ6+37Mp zn|BBDXsk{`V;0-Xl_%0zgD>k6ZZ=3qqlN~1W{IKOn2q&h+Dj8}lSOp`R2n)0I0`n> zvCyt8M%DF;mOr+z_visb(nXal>93UgkvTOs1I5Cvi(iX0<@~td%H?faa zQKiaJbc5wug4j_MThj)e&e*oY;V=$@<$RuH83IBF%Ej1GMVt`IjBYK(-m2-Pok`}* z*W>hju|Z|JQsHpCPSzBf(RkjFyGXIbTm$)c)b)rl`uo8m@4VC=|NZUd&*?c zn)>D<9HfhAy}pA4fChj8-~jjlQ-Bo)D3>gvu7P|HB@3AXorS&tK^+nqkOD}@kI>e?mP97r%fhS9Q$b+qnt&wfbEtA2bVok4JbX~ovi7v zJClt&I}eszO=`04fBTt7OzeC@H*Ti;!N_`PRJ+n4U4FHY_)ZFfy8G^z{{AaJ|MkP|zrRnv`FMQl-n#kex2OO8^73md c!Fpo)+w&j&^LFd08~{gGjt@V3;nffR2ODUV6aWAK literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_2_2.png b/resources/g2/track/corkscrew/barrel_roll_left_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..ccba38e00bb8e4b2b88439ad9a62f22909ee67f8 GIT binary patch literal 1026 zcmX9-e~8<36n}TUyW9_ss{Nz7Fe_B;SUf8Pi4ZWl+>srbm+f*;M`iJdTgIwJ$e@!V z85f~w(M*bzQCQXdQ6zKSaj?LZ5h2K_1p_PCNs#_gT>rRvWs7*i{qZ$p@Okg?`R9Ee z@AKYgCs(-n*+a7cFu#0!aW$%kqex80qMYaceG4E4Cr_*`MRaUzYe_=pC}Yk z#ZtChp=))a*^=6>*6}O-fyEM7j-FHbq@GKea;Bk?TL$aaa-EhM?39OrwLkJW93%pY z445L;R57;_?==%)2S>v!3MF)4BIKn31ON%c)OcLSaWj*#XnIQ!b`+(j>${Bxa$THE zq?u$^NYPS;Q;D2T$|kMVS;OY5ZPDsTPN1YHJjF)2ud-@cC^w{rqdLCs1yz68 z?C-mA1`;A96-bpJV`5Yz$+a?hmr?y(rLS2d(?eSVk&r38$Ptws-IUq3Ci;flt7!w< z7`e55-$ny3o}e;Bj-(WZEsA1Amg~i0t5R_r4c~G4-R@{KLV&A~sbOR@&bD!}LnwW= zJjh$aVtZtE!`ASiw~ywCc$`Wmxl~#tvNBC;yik^+W~El8y3=e0o*(uZka$cJOF&Kmb;>BP;F0kZ@GRs6tRN@#B2hKDrX{!AhVR?Mp^qXhTmiB)$CydM zN=Z&e4QO+ex5Hw4zt%Z$`lvU`B!Eg`TsEF(QU#GLDZHr{tg7C&tG;Is0}q9Lisz97 zC;)^aFUpbJW8g-qJ{VB-+GA*)4x7)5g@RlvsbtomvNeXZS<>aRU4aU+(pE#vd?2g-|AHaEW6`{UNs z{HHIipW6E1&*%1DyMFP>53kR>FkE!MUFdA<_}O2c*?ec>_L&>G^FL7CrypJxUq5ka z>7VWXnP2bjeZ1QE?)y6*{XKhI>BhhOQF*?0f42S8#?@;N&G7VZ`uU$Zk31Y+)$d%m a6uWlre)rbSq4j8XSYBFLym9Q^jsF2)xV?G+ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_2_3.png b/resources/g2/track/corkscrew/barrel_roll_left_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..2d820a308fca3505d66e7c014f02e4cf66d9081d GIT binary patch literal 900 zcmX9-F^Jn{6n=NUJKdcdG?+x!s#H)@l%f_vHE0k;ZFE6BR8AoZc<`WrpdLKvKmiYi zDnx@R8btA+!KE5Bcui^^@O&m5O$C93_7s5Ye&lb-Xb>3o5{8ecU3NvpffNM!PBt0 ziDfRnns@32iMA}Nb#&_?ly?DC03E|j9Jfi*qv=o(u2uDBFj(34>mWc`Msl65NU$m; z=(KDyJ)1K;!J0`s%yMo3j2H!U&bD~ZHJxI)?u=8?SZ0GA;hKtbA zfEWNZ2HL~;fRJOlpNVGCbJtc_c{#dPnU2AeBbjk~!rYKjODh~>3)Fa#1K`GO(IeE5(i7S&1+VHy^(fu> zi`!(4Ru$a=p2B1n?~Bw>oHvREVBhf{-Q zBe=8+U6fl9 z?>jR-=IPzEV-o=Mjtmb@H0#cd=xS@`p%Qfwpbf?k92{znEiEmrt*vcsZSC#t9UUE= zot+qlb#--hcXvBnE*DKx9LI_xFUvkvRU(l{B9Y2wjY6ShS@lMPrhs*W!1wrk_CUZH z3{laTJCPL9St*xSi)O4+)j1OLx_cDf5%xMYnMkShe1yvl@paiE|B0LJ|4b!sbR+C&L!^d-?UX%>W?__Yw<8q56FEc)cQ=&pNC8Z3-FvA5a zZr0M3)x3=by9f?HI72{a7?W~%vV4N~LhPWCTz#iYy&AjAwx7z$;(@*%1zsam|y~zpHO>+o*lHzcD91I7}~|y+n9-zO{e4+Y<*R3> zuRpwHJCI)A{PPbl{&j3&D&9VEWqj+m)vp7;Prm%kldqiNO4iiO#5Mcemxq4JX{8Oz@z9pc*^~s(@QO zs5zII!xTYXFu^GvG#IK z@BHLgy1IXD9{{c%-9EUJ-Rs$0+s$SBudiSH1CWE0k4_IWy0x{ny}g~wf zHZ-xIgD-}qbVi^xgHjD$I0%Im00lt9FcZgZf^aCx<@vFqObugU+s_9B6a)lYst9F9 zA$g6GOuA~by2D$2vE|9#iR#WYKQ>5?V5ADK(z4FgOwnvB?SVG%O+T{3xErm9%T0g_ zP*S060NDh}!MH(L8d0@CFr#W`X}O6LqOn4kbdG39bf?M>b#Y>;QA=O+td-YFg5D}B97R`I&Je_gs&;g}-)M|FonSDCe1AEgCrN^UFoEh}><||xggT>*rPyB8+;wA; zIP-M0zF2Hfk;ZYZT$ad+N;5joTe8yDvS-avr#l^v;xI~=0%$U3skp6?PMz*I1+T46 z`o`3=7eRl$2-EaA5&)_I7Jvib0Zai_7@!P_h?*AiTof-93QQKd0{9Zd3Lq7bSwCG;#`P@hGO;q2*^!{47heR=nt-|jyC^_L%? z-T3bF{Hup2ufF|Edi?J9U*6De!TE!m``0n!{QSfG+tkC`;|GN=o_zE78;`7iUp^XN Zfzwal{BP>Mby+|-Iy^r3;e&f;{{v-uj#dBw literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_2_6.png b/resources/g2/track/corkscrew/barrel_roll_left_2_6.png new file mode 100644 index 0000000000000000000000000000000000000000..9023a2345031e7750bdec602ac268f2fe74866e6 GIT binary patch literal 1247 zcmX9-acmQH6#i}Nc7txIQq3tvODv?yi3N{PV%1ZxSm(iR+cAQ;Js8Vae(!SY25bRzjyGDY!s`C#j^cQw!@@|Cpm-H5Iq;vxMY(-}l}>@B8C> zZ+}~>t$FVJxd4FXmRGFns=BIL3mWUHT=&)|O;rYMYu2x>jx{wkwY9Z%b#*G0s=mIy zp`igmkjBQwIdkTq27>{|O(aP$48?H{LEyb!Z!j2+#}nyvR#8gjGHwEd1<;h*;n2EV zdbh{q^IL);IvQt_DIp{K^MweBA$E(Jr%=(ZmpEfsz=ynKDrnEdd1cgBR3ep9+NJ|6 z2HXUY7$nLgDZeHc)s{0lSTw;h3uhz<(*^)&09XX!H5yT;lZ?iQ#WFHkS z$YNRv$i-;BlF|@B%K+2~^d4Z85OWx{#f^>>!OM1kUWk;WG#sKaEoaubZJ6I~iE?C8 zU}P_s3krppx0DK2%xoJn1VqB1LzyBxTF-;!Lgr)tE+OMp2vIz+fiMVi73X$5xkl;{L#BG_IuO za-IMzg$RsBWc88@3wel`k4c7{qcJg;3Ketda(N080N4Q#0FVHP0Wb}f!MlCSw5t~WlAoMN<_c$p@ zbVUMUG8T~2v7(ZO<-D1qU;;n|Kv>PfSGBtbo!1j86wIOEJqVc$>2NSE7w7TtxXEia z1qnPx;wj3MrLm&j09id0jWC461Oa8Ldi>_4>RWezVCTA42D~tN`R!`o-C})l{i^Om z2d55r7dGwdfcB~J>l+uDXNQoQZb$D2E3@wm{&jut-bKf6%shH$3n;%|Gz|WzI{W&$ zp>m*1EsIkpI(op`=||3OBzq?tFlW2wJU4OqO7Qe+JFZ3Vpe@78(TOkCt(+Q1o;>o^ z=;4k}9bYn*6J56ged1@A`yV*|@zVcP^E!-IinW~;t?zKoGig0@>CBq*rp3>Uuk7XD zSP*-6$L>S(cC}`=`t%n&|2V(t!0fi4_dST^cl1v@Jkqi4;N^e1j%N4%UcczT zjW;iz`Z`EleR+DKzx6p~!>e6`N4MT=kKYdT?;O~5``GhmW+qu;y6@0qofj(Alt9bs LR_nk^oA>+=LpC#H literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_3_1.png b/resources/g2/track/corkscrew/barrel_roll_left_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..bc461e9faf91d6d73c575513d2dc0855d3de41dc GIT binary patch literal 1289 zcmXAoeQXnT7{`C??KTFU&}btymZh6zG^NHvu4dIC@3f_EG#N2DlRTA zDJek^q_niOtgK8dlgThlMG!be>1f)(vW(qsce}m8ARmd0Bodiy7E=LS14v!D!5}i5 zr53Bo;ncW2q(5j3h1r>836oSUQE6owN};3G28Li9q{D0U z@(eH7A_5Ogsn66)36}i?vc2rBKlt4XYy^#{4pC(CLc$ zgNcZcP2#|)Ls$y68Ks`BKX+3Y050nh`$0>A+f03ZrL3IQ-L zl7Lng27E9PC*^>_fC~q_79>ajDF7KUbYjp)Lf#Bx4w&$P`{30;M*uyEm}#-iqHu9q zzmE=u?1B(Trv;ezl9&KyEyp=A>603HIg`+E8ABjz3FX|e89oW)8Mz3krHEFA8gQwZ z!mK78XEXa;wot$&L;~qV1ZIK?|Qtc;fIY|uKZ_iC1$5P_LS2t ztKBu*56`r18`ytfe{=QmbEmY+erlh1ZP6=>*Bdp;X7lmx?&f#z#gv~ODjU*zlmlm! zrVn!%v|t{hqoJ(S?t(9XHTRmHK~`ed8Yuel@Ly!s)f4W;dUk`EAtoQfd-4y_uaPjHoy_z-}jlI3SX0y4!zkhIWaCmr# zVc5~p(ed#y(dl$Jj+G=)(-hOxZQJrZFASsUG|ls6SysCp$ATz;sy-S1NahaLJt zI94Z9W0u*A!e4J&LQraqopwg4wV0IHO zZqqedRdgG83X@q}7pcC+IXxwC`|-$~C8Huwwq=fXYhF=M3aA8x>MVw}-7AouGu~|Y zarg@MVj=0e*6*8+V{xps|7=G`wcTAY)Vg?M|!IUD6G+L9IYp|z197oL+>B*u?oTiCOTw;+TOPo4j zkeyCwaCi$D$^Pgc3pOy!2^AM?pt+oJCY2mGauo(Q;xt4jEb$^A{v08B-mib&CwZRt z{dDtKaPgw$ivVEp=*E#P?YgoZEBdj1i7^DE;U+G9sYM`veeS65eecXv-u zPj7E8hGBhuef|CY-asHgQ6$H)qR2~9SW)CuDwWF>N+rXxW*w*5YEdMx3<$g{9QMRw z{&<2+XP8`GD3&5+Q>oaQT3zD^EX25E-kS{hRS7RB)KrQybD>H}c4pEIM_XuGK_5g2 zh_j%ISW(8zjJsO&v?@N-AW3TN)TqE(P}bzqfkJm z>7zUW)=LV0CV~fLB9x>gl~M9sO6Rj>QL97@C+eqtWH7*p1TWEHnUm8(x)3QCvSBAJ zCu=u~wFT47f=2{z6#NOmRg5lpgC#s{va%h@)D*3$T4+ijJQD4T2Z>CGDN0;f5$%*z z%_(&~)iiSpwvOtS+e70-h@zt`7Z=5hB<17rQYK>-3btX?W@nqtCIX)fcn+hAZm#ST zD@3%$rR!m>5id8@*;c7>r@DY#gxgJfy+MCKBuI&26kbS2+RGB9Om?PNaxA-5VUf8476vGGeHbMveyeji-U z3RJ?ys$N0!M+{tc7_}MJTk-Nju5!nyp=uNN0PV+uq&v*|VB5 zu~4f<^E@&DIe<{xi*%dr0eq=MzFw#Exd%`x6)qeWV=*a_kSQ`nlR1{sIm+b8S%GMT z0x04~NgU-VWU$EQ+s98o?YepY2X<^36JhwbOYgLM*XYQL<7*D?%f`OgJNVGv)9B)g z>wkwvtyHY zJFc!>rtg~&h>JU^`RN0j&#gGIwJ`nIPyK7nQ}n9&?u{>hk9Qt=?&x3#H&NU}9)7$q zGWNpcE$a6r<9O|sd)1jovHin?|GxTE_3N&Q;d56Htj3OBXneeK$?YSXK8o|*Z~Ddg zrTyNaYs|pyGebky$awnZiR0Gvm7fm;c5nUrwRf#;Ykqy>^~n#u+!W>)woOgGO?f|= zoBL+hBihLy51LC4U!Plk;rxZ+MQ2BsY`?ry`S7dno?!o4_UHRIdhTsM>3aUO`QBaQ cpXOcfjsbp}-M{r%TO%0VFg9}hrMLF{4-38My#N3J literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_3_4.png b/resources/g2/track/corkscrew/barrel_roll_left_3_4.png new file mode 100644 index 0000000000000000000000000000000000000000..27c52409503ffd07f13f73b1a85062066e6d2654 GIT binary patch literal 994 zcmX9-U#Q!36h8NFdT+gSu3%+xWKbkRkURv;L(u5b(Osf9mz!PkP)3Gf>!e7KO!`nE zTnnqSXf`@5tVod{eTc5;MFRFAjy&8+9|G3VL69n)1{qRDrWG#UpBaPioWu8Wz7M{0 zu5E7>H`Y(A1Hi`S*}_gTPbT$TYANaIkIP2@OR)Xsxibk}SXfwGTwGdOT3%jWSy@?K zUBxggl}fFxt>yChJj2j}z{|3zX(hwZ>-BoO-R<{X-yenHERGo(cn%~nT`FZO6{1?B z8%?g=k$Qb~;2Fc9Ihoo5g(+NG7jvdUSQ^oZ@X2!j2Jj78%qgX|U7D9d=Kmt%POwVLY9Jff)=D2-HIw+UNrunejMV^N<**u@4 zC4y7QqE0C$qgkBM5$cZE8p!rgb;B~j;&d_3$&{$EC0)=PQlqPOUEK{#KWqh2Z!-5X zJY;3am4T=MX<=+PSL~A|kJkgGIWg>+<)eLx%4#fLEmBQ|>uJKkkb}B5ZW~jlKJ(i1 zz(G?#lVwRtVc0S+RAsrTX`O1d-)wr_Zs59;(P%cCA;5JY+ZfZ!2m@RmQss%zn3n9Q zI+$6bxE~#k=O|5OGHfnaB=RyvYaC~YQbSFa)%wlWL9ZYBK|J9>6){83m?~jas7{S{ z8uFl1K5)#j*NMh{96v-nfC69uSO5;d0l*Xklt2y$ z_T}`WCqHmyXG@0H|G0lCA=ftxZ=8GS#^*Qg9QRM93jZNfymy_y_SLb`*1bR9y8A`# z*B|h!=Tmo--^i3R+#xPKzx(r-@IZTf@n-g)Q&%20KloGe5ObCte&qYwYgb%H5)WeDK=u kg;$iLn@3moKKOU#SbgvGx9{gKB;H{2%vRy{=?fqJ5C0UbG5`Po literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_3_5.png b/resources/g2/track/corkscrew/barrel_roll_left_3_5.png new file mode 100644 index 0000000000000000000000000000000000000000..f41ba8469816335220963610a481b7a099fc2b40 GIT binary patch literal 885 zcmX9-F^HsQ6n?uiyUy;gOkfHj1}r9EA;Cg|g@w6u53?B7c&j2mB`{>z|MxLCUoSvSxTCH}weRg(setwQ& zSf|suxVXRvg8|Djq9~}Utm`AwG#tnA{b03tg zyJf%L5U6BOt)T}Gp=y(1O^Ab2}^MdAZyl)1Cl*74R{T z7Em6>1-P`LMyX)rLw9e6m6xG=h3@MdF_ma{$S-ve9U)hvO1CP-#Zzc~e$qTC>brx%2gMRb+X+7eJFSQ|;Lr=}qW`B}6kdS&Y|_y-OG6 zF01QTNB|fDm;fF?1h57;V1ODZBC<>rg{asm6c{Yb1&Adm6hJB<14k~4LIuSWw3(qI zgxA4yAd4_mu!)Y_Q+n=6%TP}eC(om@%u(Y-jDfYff`=<1sl}90@Ln~F>S=QHHxKb1 z?JBAd9EnLxZzPZtm9@sQXHUYpoka6Ii^?KH^`4Vu6ay*%p(cx2WA_GxV=WE`ZsEUy zx!H)Lkvf^^mSwPv!!f?VMk1Ta%vPbx;Q(nQvMID+Q7oWbZjPUOulw)oA9(TfR)r7# z`u)>J3~sI;J?ng@KmY1w_1SN^i$D7Hled2Q{Ljm8e{BB|2=+gJe*wSTU48t{_y2v_ PjKj^7+v^`5KmYoFQN(uj literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_3_6.png b/resources/g2/track/corkscrew/barrel_roll_left_3_6.png new file mode 100644 index 0000000000000000000000000000000000000000..d414d96b066cc0d877807bb34c2027c315c9b1b4 GIT binary patch literal 1114 zcmX9-eP|nX7=HVC{WQfWamysdAg3N%#ADuQ95;8ZSvlJ)z1dJB-0FcT3wXmD%O9~G z8b(^;cAY_@L<|xk!p#O&_1Lm{XoeLtIJC|TZZ>pLGpQO&gl@L=XU5=pzy5h2c%Jv2 z8yofYcJ1y0fZpLFgX4|b-w0<%OCvwAYvvPx78rZ}=ul&9YHDh3ZfDz7Yinz7 zZ^tmKqobpryGhc+Ff`Azq8N~6DH@F?lj&SeFBDcRt5&a*9-zIzvE6}yJrr_< zBc52?n@n-poRBx~0JMamiW5plmaD>8YRH=|-H zDOa>;%}8#V8mbg*b_yr_Bo(BYFwe(DF%=Hy;&CILHg&zcvQn$n5I7~klNgz`F?lCn zB!XooRtaRP;e1V9spqO&rA^dL*ld);;d8lp!XtXUGRwt;#z z%-a;frG|)9gw|qwJ{4Tnl#-FEmJ0RyI-&vm05X6IpaCocR4_mda14sbNXsCr#Ni;3 zkf1^LfyDvh0Z9%NCsBq&dI%L`$jZQ7<0)Vn@N-y5bSPmWq585JF`ti`rdF+*sKMn7 z0vYM1RR@=G2|6xWUbPm`>f!umvbd#}QK^R8fpTF!k1asELOdA>vZ@lwB$T|CFbi7M zDxi9qVp*gEvH+om7qJH2JvgJ0RHZ_tlJ_7Ni%cNEheBc`B9WdbcGP z-;D$pQgDAn8*I#M$9m9jq9)0ZG%sZX0Ug_@{x`?g~ zjPy^9j$eLr?)db;+=a=m`=3#^#G5x};NYR;?E8O_^LzU?7M^DJoe}Wu`KeFaei`_v z7`pa$^ZdfEFUR|ue_}6Ae6|0x53a^v$o-stH}(?u@9M)7s8jp!_V|?p|3sVE)f2~G zpZu}synWBX*Qiy;^p0cyQsIZoGrcR@!SlN=+I=UXel~*-;4d)i09GiohO%nC->}LN`Kz>?J4(Ft7mDb@(8WW~aKa65v&;i-?goVvcFxPFrof?{mT-h( z3wEO+hZJZ`!)mBfOaq4_Qnf-2mpP!o1&35trO^T>VrZa=BO>`(Lh`-$z4y=i{`kJv z-@eQ?VcfKF0DuW?i(5L%+*qy`YBlBF+fNMxpaJbmI$O(YMMXtrWu-==sj8}~uCA`B zsX-8=wzjseu1;? z#n&O>rq|nyCdOjraNJGN0k(WhkbO#EJ(iGYi^sTB z%C9I1RaIbF%isj4P)~?@I%Z^(Wmx~hw9<};0 zYnVV2B$}qIBeX@en;>h1UNelKFiAj#Du*ANQ-Al-5A=2{V?guGU)GlAJ#8(EI$znf zYaexD`?KR)uEHzRcARWpc)n}msZr_DlFNmcIvXnvI0_pj(*S=K{qg?(1$&21-~Zv3 zVC0%_o^}jAotb1p?@n%*JG8+!^U#sX)mPWQ*XM8T_8jWz3GUaNQ3tBK8|JJ%d#CHz z;+ZqQi>{mT{?f0ee(+zWBQ=X0S}xo>ckSVYz}R?Tw19 zt?v%rYiwHD87bg(`)-_leWU%#(QTmp#@iz^_BZHP?DVa>GjY}E>}=`cUt9W??_OQp zKD+*(p#{?1mX*sJLeys`x3yk7y!zgU$b~g4_RRg_GI&xeZyFr9`{&+Mz8yn71Cf-x zWqs?^b>}t=9?{8Lq`ybU^$-Wv&H`Sv2GRP~amZ^Mf7 zU(TP^z3sPeeEsZ|JeyAFaQ7m literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_4_2.png b/resources/g2/track/corkscrew/barrel_roll_left_4_2.png new file mode 100644 index 0000000000000000000000000000000000000000..50d3a74fe2df24514cf2103d3d88ab71f860da9e GIT binary patch literal 896 zcmX9-F^J@36n?w2yP4hLj4(yS6cMIK5i~-O6e*%+m)sKB9G8P2DIx?MaEcTW2Mik7 zDF#WAVv0eg7$wCB0jJm^Mc`5dnPP;1Q;d*eicwP>OE^-DvchkUgYUhMuXyh(zW2U= zaw9*wc>4kX9$i1aeA@6EO`W$}P5)qWZveF5$tTaQ8hLbdbbNf=YPC*IPEJox&(6*; z3~RUB=jZ1{uh-)^R+2T@8pn zP%h8`#?J|PNgJtX=eoah!Yatnoyv4Ao*c@IuL}!HN*pa8S=*_zk49BGJ>(JEXLy&V z8J*+%qBPVr-?C=I;nMfh`8S+vX34)`jW3yT2F8#@Bu`IH@-icr;n4{sINd*ID=8Dl+OJ@C5G~nw zp>0KXfu}H;#SM`fXq?+u0&fsbyd;|BSyUDos&~AipcqgA2sK%Z8@tyaNA7ID=V#N` zaMo+dFtowIa$TEaM?5QcRMd%{lJ$`Z#4Mu z?>|0o#CzA5A3baTVEyykcNfopdYOKE^;Z~Sx9rbfKmYNIfB(D3-hAg%`12cd`#!=R a^PvCw*2(?htKXYRxW2l%{N>}%ZvO|x{C%MS literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_4_3.png b/resources/g2/track/corkscrew/barrel_roll_left_4_3.png new file mode 100644 index 0000000000000000000000000000000000000000..2733e28088b2b7de8dcb1e6bb39a49240d863851 GIT binary patch literal 1162 zcmX9-e{2(V6o32GTN$L9LaH`eLxF;a6nDbSoblXlO_^m};TUz)rN|)#i{6qmHlaXe z7t>%}PAIH@G+IJ21x{#me>7O|3{|Q&a+*a;I7nkktN~&%jZR$jYYEBcz0Z69yw4w> z_c`R<;9fBAv3UTnU})XorWUVg)za>cR{w3^Y89XZyz4i+T5DTdTYGzZM@L6zXJ=Pe zm%(7bFs!?~+h{ae>~=drI2nfKI1kVJMNyC>DVa>?a`|F$M%Nq7CgB8{0@l;x_nSi@ zTR7s3#i?Y9&E^6HRV-`qYAwUyn2+iaJeH`>Ci9N8NK8wNn)H=(f?kT%^~`Le=(a)t zhcFE?hh+s!jhiZ2bF*wkbth^D(434=(GI`@1Tai6nW9#!>~Lf#YMNzB!C)mCy`4@Y zRkadkJ8f~YHY(t73%D;z@G>Q)7)kLY3S6cf$m>BHX?42o6o-3w(l0PVjE$uO>AaBF zqD4KS)w9)E)kK4t14|HW5pc*DnYOrd4!=qZnlD}zGYz?jrdiy~lh&{skNc=B&lE&X zllV$ftSM4MP0nfxsufLU(t-O3GDtIFj*IhrDjd$m<7zss<@427 zQ?PPnJXmF7HGifaE;QtsX0AS0nMFOg$wXQ#ZkwIMojgT}9yS(e9gF1RiBdMF7qw=U zhJXhXIa4%XlS6naLMt(@kP4QRXhlucE5&B>HlhK103v`4pa7HrY8apvSO!Hzq-2m@ zVI3e4kf0&&2Au`O0TL`IPM{2n@*z}?Aw2{4jVHmwfRDvOyd@gO6S6y-;R^*x)0BE$ zLoF?95Qs<*EnC=(Es%EzIwd#!N;6!TO_t~KRa9v>%s|>Ox6|aOZ6S_`1U+&zlu1Mj zNL+#R& z^IhlBPiMXyTOt*fy*l3hto7`L0|yM_S6s%~73(%$b}lJ=?cVEKX4wDtBh@{F>Ga*p zPlSy7S5IN5J~_9@HIEn@eWlmvefiQCZ;ssfVB^5^4|Sb9bjv{PIezErK>r)8Yx>4( z@1HpKvv>2_`4<peSh;rb6%g9)zMb0QA{-yX! z1ByhQ&hB`)7kL*R#!4ICzO-dgXl3Ky-NSodxHdjsUh;JJZq6aNE+I`_!{ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_4_4.png b/resources/g2/track/corkscrew/barrel_roll_left_4_4.png new file mode 100644 index 0000000000000000000000000000000000000000..81ffdc09b3b9b8598a5690d1959c59248484ea06 GIT binary patch literal 944 zcmXAoL5SmY6vp37XC|E~OTeN3Y>PjaIAG?e>R5KMco7vPe^w0f7fuDpae*dYx=E znYPV$d-7nYjRG@@?di-FX-wq{hE%dt($T5D$sV`FpsPkhBROf$6L+}?D+FjXGz4%I zY+zu4jZX%}G$PQPL8*pL9fZO%fDE8vn1SOKK{yoU^8B$ZpVVp-%evq1qaYyIVp%9L zGRbRH#h_J-)g9jKi7ij+j1)K0{G>*51XC&V3N7he)ew!g-0o|A-|%BAOgiy=FkJ?? z07V5#H6WWnIT+V3RfbeG5R6#0r>47bLUb(CMV%uW71~z$fi8|rC2r}Ht~v8si=exV zJv0mPB1h3G%hd$2p(wVl_Zp3%Z3q2+?EBO4c(GU@APk_o7(2kl5urqMZ7Q~BRd?PP zEu3*WoS#mXs6gX5S1MJ=vO+UD&zq9m*0N>Iq1`zd43jWUrvhjaW-7R)kxrfNH3hG& zjC!>b&zc0i`6Nu!`$zy#0Zae~zymk|m|=i2$s%f+$a7ILktr}(=m_9fAdvwnfQ%Bd zS>(#ducN4q5*Ho>&w(U@Dr0rMWHsoHQyIAWXw-^hZ$6Jv#v*FKHVcANl3h~sDI?*X zMb%3iqh&Wb^`~gEpo+keScSo>0$EqsW=(Rey4$fvUMCK{c@m;@%1ILP0VRM?mPI?m zJrvPu_GUA#*L^56io|MFsn_*p(_onv$8-hO6WKsw#xgxu%Sa=UMWG&xd;!H$cKqBk zh2J0iz}1WU3cUF14{v7X^}U^!4xhU5^^J3neerC5`wsf$Zj`@$?~k{yUwh*}e676w z`0?Sbn;*QN`{p{_{_X1dcfSAf{J|%?7e4&wxpS``eg5OU&+0c{`}d=#uf28or#t}{(SlFrL$k5E#}H2``=#r_=VMs1be&tJD+Y}dG~+Y5SK#$ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_4_5.png b/resources/g2/track/corkscrew/barrel_roll_left_4_5.png new file mode 100644 index 0000000000000000000000000000000000000000..bb5ca9c55c9450dfbde3735a5c16d1ac8a7a9965 GIT binary patch literal 923 zcmX9-L5SmI6n-}5sDkwz(yz-AxaK81c{K<%#t1APR7k(4>@EZV1yoWh)x$G z2JE3|!5~F@C~T1kJp}Aw&;z2W=*!e|wl?R(5kx4KZXp7)$*x1J6 z9zGw}*C~lsELt1r%10<^0H^>4hS@mok)%)4fgqf#>V;*^J@0ZfLUBxT^@d2WDkT`S zY%@)dGkw7sN}W*YPqiR5qTHf*l9d~R#waGQ+mhW?yCY*1*-_>tc|Ti?7n>Ltp{@a8 z0p$YiWBiDaC$t`mcGm1IoS^U%bgnXWlPB9U(`yQ2Q<^$j)-mS;XBl>ic(BPrv`p|i zPcu!9w?wI}X+6^%w%e0lFCLAuC|b;BMNuFiZJ-AjH^!wYsilmykh)7fShc5xKU+^$ zSMv?3F*wc>giJLwhBXDjQPi$cin)_s|6)AJlWe^Z!B8+q!##uYTg=cE!>%?RS{I== zkB6&yvR+>z5ugd+0QdkQzy-h(15`qlkn5l@K>1vy!RDYZLL@`30@4841nO}pP*K!E zX&2=ITnEpCB0*EdS|;JOnZ7TN19LjVP$Z&EDUY9jt@iKr4}9?8 zSc5x%{qbH&j*brBJbmSh?|w}W;H7Hi&=J|WI-;&oqzjbQ8`pZwB-Tdc`AAi7}fd2Gl^0}MumzyqC?;an1 J`_{ux{s)3%hOGbq literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_left_4_6.png b/resources/g2/track/corkscrew/barrel_roll_left_4_6.png new file mode 100644 index 0000000000000000000000000000000000000000..1f13667eb9f2ac4996f2d01bc2ebf731f2022b60 GIT binary patch literal 1095 zcmX9-acCQL82zdel5PiK=CPj`q19C&JWe}{H;b#-@ldpw?=o}S*` z-oCy*1VQ@y`v(RF0^x9&AaI7E1%VUAs4PpWs^)Tqa=BtzRo88`+XN113h>-uH0nRi?kigv8x#zSNfXTy|$aUvO&7%9!C3$a2)syK?} zW}RlKzG?bs;1@t34niq_Y6w{fuw^uA(vlO&)a7DJv*03+`9(6AWU)+yDv69C3yvz* za&kjgTV`(4(P6{#`AHOu5M-QYl7f&C#e6bZ&ScC&!Kqa0)oQENf*>dXG=~r+A7cas z8;jSObR$}9CXJR>ZI_!{wM{sP`Fvy`z=pyChKm#>b9_41d6p_?vdg8iYdP&Y4PqQ3 z3qB=B74bobGFNR_jRB|b;71i5GV>4%ORqC+TLj8aYAuR5T(xHSvq~e^WB#K$Z(6f%E zH(d+1>me3qf>`ZS-ZWHOYo;r zPxAa%x1Z*|^Uv(Wf5$(+lKr}O;nUfrTVulqpE>S5Z;uFP#`b7$9$mTo_dTDSOA6|b z#t1d+zy8_>N4yuFPqfdj=2tiFy7%h9zvB;ne02!dkL--TssQ{*i^7AAY$pH?h`zD2m*e7PIQF&$7AsZuXCZ z$1ZJMNS}C&K6d!@sJCw=^3usCzqx;Y@5rck*UajR4`{RXVefP9#L7E8%4HZhM_fB3 z?d~74*M4~Qx-d46{kKZ&zT5cc%*pYETV2;~yuI?Uadf3)0GQf8J^97sN8b7$%X!|Y literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_1_1.png b/resources/g2/track/corkscrew/barrel_roll_right_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..607ac9ce4abe73e7221ed07b6e41308823e2bfde GIT binary patch literal 1325 zcmX9-e{2(F82+HJ?gvn^Di_vC)dEFMXz+*yE1c{$>bSYvxGkL&yu}-o=C_(o#HEE-B@mePjXv3213*YbcG=rcIkZeY!*|RKjFR+ia75 zKa9l`m|TS;8cL~S)Orpz*f3Vm@jk*HB0W($kYpmFNvTz6^eP>VlC0Lq5uAf^_!)nM zi==FE(UZyrGsTz;2XY!9CZMzewIJ2{5q(%~jNx3$;LPxWyby;Y6e?%63X2|f8gxOH zi1KvG&ZfP5He}Doyv0-qX5%usR*f1ktqCVAH0@+rpT!b(I%9r+DiX^O2Lf!ta!*lM}4M5$d-=za_M-XFbQ!03;^%|2mpitC^;c31+WB) zfL0!c0#Hm-YQSN@gM)}3h!lV{fE)sy7z|J_Vuncv6a(Oq@LE6;z(7gOEMl{u9zh=r zu+gYJl?vr@DOloCm;h$2!Ucp1D4B?w6Lmt~7%EtzMQ?H{l7Z>GS`M^Isa_*9;z~1( zSxuy1GY34jXvmX_hjL;Z7BX6rgb@Hm0AWcBM~Ut+6n3jGo7MWfkHIICgwaTw&8*eR zVH&$u|s|I@P?et|azCFMi)y|d~rfX_R&vxTikgKnR1@1bj@3v)srv*hWnPPZ)l z*~I2!$hYSmKZ50zSML?k4L!#n@*|oJhmZAFPriwqs5@O(gPdD(be{=S&%bGLH?C`P z^_{W0=Df5pv17BV!!3+)d)!06v7_$W?+&hLzuMK&yP)TTyOqa63lH3?tDdOeHdq#I zbHC;3S?fLC`7*mWf7s;>^17`x*0!r>SJm8pqj7oSz~u$)+kP6W*>%n{GWSMw=}OPU z6T3EbMdxCO{e@rsb)Mpv^8GGyKK8>G*FRZSHxii8t-0x_rCldp%x`aG_FQBJ!^*w_wY`f6hMm_~71CTVA`t43ALHC|ZZH z;X&NDxZPhn&(y!{B)R`y=mJ`K`F@#`uMv?B@?cYoSy;kq<=NquMSdgI0Jq1D|hO{3)KP>jbb zvG=LxKRTnRlKi>j>kGb(=M(WOi-NbNBKsa(G!M*KF(DaiJyN+ze(lQI-iHNip!t6C j`-g1+FIyBg_z&4!O^dd_)7$i4NpsNH&|H72u5;i2Z~aQ( literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_1_2.png b/resources/g2/track/corkscrew/barrel_roll_right_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..1683853fe64d8ef8068a34d79baebcf95c059ff3 GIT binary patch literal 903 zcmX9-F^Jn{82#>iXZg+vrZvU18kFKeP*F69qCtb2>VkTxoI(`v;6VjJJvbn!N*tm= z5K&AJMT04#Xwaa7p(=IZAcA@jMS}+oD%{|L1`nncGzB#nYRCdi{Q%VQ4|%6-Cmtp<(E@ZF^p@Sj1_1RTR~3$I!rYAWQAxusa?T6O*1g zoaf8)g}O|PEO$2BP@u2@*Vd(;H6UD#3=HPd77}leE%ahFEsJnpr6LY01rr`z1)J+w z;&j&Y?k>YoNu!;Lu3d!EK7b6MVwm3PSUB#IWXN%svb-9N)|T}$2vCyXOt;VXXqn(t zQq-w|#b_>P_<|itv!xPdYFvy67N^BNr%;l{4s}7F%F{p%Vm;2Sw3y}Pe6vqFJaiT4 zjeszLbTKyQi3@U=@OnOQHbz*vDY}%YuEydMk#YvyToaatlH1zaGq#akCEh-d&^GOK zS&|ws?1&d8isERRKbb5XCkcW)jyG3VRaGItbs#;AnRkRGu4L3`BTTo$u$(L__iDE& zuh)CjraB$A*At1pLeUz>8In9z>u2V|nXTrFBF%Rj9#jc4l#Znm?wImTKAI{^f3%9M zb>f%nbhmqncz^+b0pJ2e04snk2B?NCAk#omh>EpLg3iED5H3c zvMDM;xG|muNq~WjjkTUNp=Pc)54Gje&hw}&b5v{LBVf!n@Al-7P-9XrIJX)`yUB9z zW!Lcrtt+w%EP;u1XUG#{g)v8xYmLL1wTxzY8kI$gb{kfbPzhQB4w_n|K;F|{* z3VizapI_DFlk>B?4_iNc``z7BxN|H0A636S_U}B2kIh>@KL6vL=CkHcPhb4{;p^{z l|LDczcOUKj;Pu!49Txw--~9PicGD<0zjtx=%V%FcdjpKPfWiO( literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_1_3.png b/resources/g2/track/corkscrew/barrel_roll_right_1_3.png new file mode 100644 index 0000000000000000000000000000000000000000..cd16e1c2bdbd93d04c942e15cbbd5ea87efd9fec GIT binary patch literal 1253 zcmXAoe{2(F7{}kOW!G)Y#&x7X4TV%GShdqbk9ooY1@6bdYA$Y7Af&EODtK{MQdo50)>oFbqg8rT0-)De*N=&|M)!5 z#~tm?hPs(`0Dy+pmCHLTb$%rt*J&!*GP^hv01fD9>snD6tE#H1tE)8{jaI9jGG$6l zO$~w|I-Rbzw$^B|SWwjNa1a#bVp%uObAlj5BC%vLmCcSQN~v5%?SQ}m>8f|T4PLL= z=eGw#cqB^3lT13p=j2eKC^>8hjn{K7V}Le`tTo1?1A-$Hp>s)2849Y3G*QYrO@Ofh z9|1%PiE~IMq|e6<<(vtsc35WMqzGZw0ssjBgCLwQ22S}TN#Y{e@EkxsS){*8Z zSzz-KzL*e7naG5kfW@rdfLU!cig^f!kD@{>8}<2;p-?6klT)d}$VjPFg22Q9YXm{# zdPmws2rDdt6}yKr3I1rYh(#k0#piMkx0~{MS-+n{?E+?x z5NN`IW?c3W(x%cD$e3Zk3Zp1Y5m0tjjvsrv{?>yZc&D?S0!#iH-B9Vnt;?5oE&O!X zp4ay6oIQ2LukhkGS}pz62hAr(mJatEyS=@3?XugA)5g{e{%{Y!!vFYkE8NlA*YtP0 zZcC1i3s>kxTiQ4EFSDFDdViy2nto~*I{%QeL;=HU_rh0>)8E&A z)*s&3Mm7nW15b{g>D+((>PzZJ+cwRavB%e6?77-~Z0wV)bvG7V`_HBB({tzDS$D0u ztE27QtEtEC+>CrVd~omEha0MbSo7D7-`V;o(9eh zKD+p-aTU~Ey6~@_nJ%%+reczRg?tyYuQ+_io=u56RWK=MOI!H+I)-YdEtW zyVtU@uIb%_vAZo#>}L1xixoHCZ;FEp>nX-y^e_`&DE3z)!`U StBe&^pmjz2^8RIS?D!u#KPrs? literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_1_4.png b/resources/g2/track/corkscrew/barrel_roll_right_1_4.png new file mode 100644 index 0000000000000000000000000000000000000000..566af467db343a4e5dd8f1b4c0b1f83352502561 GIT binary patch literal 953 zcmXAoL5SmY6vp37XC|E~Gd)x(nnMnC$ZF861PPc!Rx?Yd8<{Mdks?8&1})e_4iTzE z3~LW%C=!-BR;W@i3q1t4=qM3-h!U3~1%p=ULSV~Mu?qu6DNNBh{LQlPz4!Po?|1m# zJGy#M+}?V83jnrD`+L`txtr9Z=~U9so}YXMkb>>S`*LT3cINUtizY z*uXF>olb9VZsrSx0>jXPz{|3zX^LU!^?JSC?)Lj$5R9WJUMv_Icn%~nqbRv*m8h9? zqsg^9Qm?NLd}9n(1%t>AF+vQPTkA{tTO~cT#pz;!lPOVS63hfAZms4-gN0_ zdC19-uK-~JX=7|RU+j~L&+B2iIW?Tv4$z52uJKkki)t*X&W=Q9{cTO z=%QJW&9Nj^X4ncZ)MUA-X`NcF-)#EbZs>W_@i>lS1h@`l8)JG|VSvjcsxlQCGsT(L z2C+R}^ylZ3CCX6QESt|4iGobg8pj!;)KHUUX201Q_WDr}E~Y%FB4)^0OC{_o)iHUu zArCs0p=(Y2&U_Lq7N>{@C<7P(Hh>E-1ejrf5=jCw4dgl~nn)z*477OgiV#VFWI%cz zH5uec$g84J14Rxz2%ZH|fU<;DwY*iMT6VGLXoEpL4Bh!WLXCZH z*|Fj-YJ+8abnZ>jBqnpf5?GPWDm+n@8M7kVR@G@)1Gg0h?mP<6V# z!95gSH#@T#+i5?PF&YVqB3G-LY3dAJXX!T2xB}yg^jMfU* zbmpH2Kk&}A0~s#;dFQRfR7!g<9A3Eb`!7Fie}6HZx^y;u=GEOFKfQT;88^u?WbkM}?R_TPK=f1=KgcE0|vbT4!Ka_Ou4w~rr7kWjjOuy^al*FO9oPWG9t literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_1_5.png b/resources/g2/track/corkscrew/barrel_roll_right_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..69859643b68cae3c2034bc46e20195933df445e2 GIT binary patch literal 940 zcmXAoL5SmY6vp37XC^aKhaP$;Y``ErWS1xrBjgY?YG&yUk;yVyjBJIh1PpA!AQ5_q z7%?nm4U*BK5sOreP&Hr=bI74!Tmp_zFozzxYjk_4yA}3OBuK$I{LQfN@!tC`?|1m# zyM6VrvA26+7XbDSuIwKb{ps_0yHwN%KfL!fKnbqCdhK#y*Vfk7*Vjv>(#FQd=H}+s z))t0g+uPeaJ3F;{z0NSSAn>v*YFg7Y4aaeOzdsyCNixZ@Wu7xM@Ek~Dx!J6?T14BT zJ1*zwJxt z2u>v%2Bp}H=5c0Ea6+*=l7q1tWjev)bfeD6l&G;yLohm0r?2)SBTDTg>!yprY!z2{ zsLD{&fv|w|Ft%T749RB98>!;X%wXvy=tQEb8jH6Zl&f$9O&FPS>S$BnoQKXb_E%|$ z=1HZ>l9a-*IxnxZh8sXf~NFmrDe=0i=&HgNiW1d)fz-yrf7}hOi}8n#WHK?c25VxEJ^bj52}cna>Z5&uSNANKJ3V& zo_-qI)3~>oCVBn{@c;^d3E%;Q0H*+R3{W9SK$eNZ0A*8&1cQMt4^aa$36KoPs3Dg@ zfrO$K8h20@z7!>g+6^r9%pDF)y z{sZqG9m??1!@F-4=K8_@%hxV`^6~MVy$_y!qI8089{+Oi#pZ3|QvA_t|Gp4}53c{^ z9lrgQ`3`aaxljMT^ZN5|{4xLOzk65U*Sq?|&))p~__uGr`TWxKyWLw)UC{3z-TMB| f_(_Og{P|0I@czYA+hvG?0tc55_kVol#)tm{Q@@k( literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_1_6.png b/resources/g2/track/corkscrew/barrel_roll_right_1_6.png new file mode 100644 index 0000000000000000000000000000000000000000..081da33671311c0b729afc45ffc60e4a08661af0 GIT binary patch literal 1128 zcmX9-Z;aD)7=DlAuJY ztsDu@>ASxV0Omwq99rG3kGJEVp3Zju_u|N2fKFIByk>cO?C9v2HEUL9XXotMv%9*w zy1TnE4D0FX>Fw?H`2Bu@2+}mgaf~3uWLZk5)A@X%R5DC++_qbeLj-{e0n7BqV(xg{ zmq-RP*-&0(izU8Xk*ij=-q2_qi-!6o#*>Qr6d_QMi6d#cl8;tPl0BAb+S+u>410mc zAwhw{VMPh6WL>qQ+o^g{Gl(1>%_s<&egGDL$1us|N_o9XAfSapM_6`D6ln~YPAq}B?#m(qUfT_ zUapFZbvo0CY0X5rrHnhJ=1grG_2VuV>G6bpehv=`p^(h58NR(NS<2?diY42$oH_+O zgUOsL#ru>vt|lox!yT%4U zA|OYB5eAzD!~v2#C`%xXMMfM|GsxE9w(%q|G(=e}E_hN2Jg0<1~|feZ>+O#ArBNBgI4|G)>UM>tq^`RrTmeqLng`89)I?A#sSot{7U)9=u) zcdtM8S7gAM`};)qPUV{`6V#M?;OgNGH@5%u-lnyy&b&K3j=p-I*f{Fk>Yvu#`%XOhNPf}i#Pyfz^GGpra@V1S1{!>(K6Uo^;?vDDPrUNnmT#{%&aFoOynJKb zj!4(o@e@VliV0*Pu^=3<*Y|90aGtyt6Fn#PSAXR%n?+S=ON+dDcs#*ZJ5 zAV_CtXIEF3&Eas6q?2VCLEt1wR1`TF3`V2zR4Sdz6-~2Nuai!|(17Q9MA7Q=+5G`$ zC`?CVd?Mw^WR-#uE?0DxK-_eX%-K}8U6b&*LXHL5Y}8#y$!0!OHT6a<=fZ%80DcB& z0+NuCY#1#itn~s0t4>(=z@`Ra&H(@qfCoWj6jd=y!*QLa$9O*P^_EoidOQxZS&Xzg z7@L!~(;nO<6K<81G+K$V!6X;S2ztSjHobNVbGjU~KyVTz%B&pXLvc?$EvF4NXGV-_ zqTI-$46q8o<^}cuz%_)5+gvGJ%rdg!4wn_Zrsd!mPgo@i^Sg+!n@&h2k4HtJNUDWPnEzGJ&!gOehfE zG8?Lhdext)X~lY~+AK9-4}qeT&E~Q@1i~rNw8HTrPit8q6^`T+DKlr(%M9>vh$5h> z$FBK^Sb#}}giOqvPpYMCtXj&|>(?OzfExe>01bd70C@l^2!Ji{EDR_xsYA2G<3J`s zgaK(6FnIt40A(8tlThbj+6N0EXzJjm@f6@#;N}sZWK;b_L~|u{DU%5rMzUHpV2ca$ z0y5CUXf|HAd(yaU(ppVS*8Q1Aw9rhKVX1~&0cA&APE=&vl{{VG zq_Tfr^{d&ZJBUeFo}I~UnDSGecI>Pk_HLZUN-rFHZsPHC2Z{&RAG9Kw)Zaf4zpQ)n zl_5+_zrW?e@;3%njzw&)cQ2ipTwHhU)oxQ9?L9MjQt!swcO06#=k9s=qwM09-?Ez) zM5dCLAABS`>ySlSyF{AmA34A2+{=IZD#*;m)Y@4O^ezprDzCWMHn!)8R69Ij?}-Kf zcn@rQd)er)(RlRfk53Jsy1Y7m+#$`MbL3v+x0Cyhp54+u<`2xCTw0+?s>5F5FcGKE3pP|#focz{( x3$LC>KWa9cSC>6m`qhy4H$Fc)>5}X5zYrOr=lo|Tx>`zuf&Rh1(WUFR{||^_1Zw~Q literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_2_2.png b/resources/g2/track/corkscrew/barrel_roll_right_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..7366c8899f044fb3cd02ddfc53bd8a3726a4dbb3 GIT binary patch literal 899 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 Ma&z_P;}<{u4;#yN#{d8T literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_2_6.png b/resources/g2/track/corkscrew/barrel_roll_right_2_6.png new file mode 100644 index 0000000000000000000000000000000000000000..5db309e34bf6687ce92d4ebd1c8a5e6db94fba1e GIT binary patch literal 1072 zcmX9-acCQL6n<^mUb@mH4d++i6^FBVl z_ZALM28OrXwFLl%Ck~Du>CVw^d7O@JAKQNNBLD{+K6G?{m-h7Z^!D~T9FD%ezW)CH zfq?-G!<)cWaVYmx-)Ouf(}hTB;TlyOLVHj7Fn z5AE`?Zc6a_LqtF!C5@JKznbCV2A?X5xoXI?!(PTi1$=&ytha-YMZMxI}P=!5afY$C#`;P#}UOROpL?f7MMvE%-()gxpk#u^E+m;mwwv1cE9tLStNGSK)?r|NuaG>Oz8TsS;_aLmJU71%;3@^-|+gSSGpzquIoqKL9e{$n7{@&M5 z%}(JGHTv`O>fMt+KC}GA+-cw9Humz=%4*Nt?z6_i$gzJ`i8EuLUHa?o*B-sOWAwlI fo3TrkkMRq?-uL-Ce~vY}PGMsI(l^l~nPJ_N}mXdf!%A%hA* zGObv*GJ@0@w2VFk=|kX(+$3nhF!FE@W#pk?C&6`4u*kroc_?xZe=`Q(-|xrw<@b5` z{(jdF_QmZ}&z%B*?Y*~lFJ<%jtWFnlS^s15#T+092k%_InAx?pwe|J&TrQW-=QlPs zHa9mh3@a20TU%R|YPHHRv>@<`BI&wnnntVDa^3!L7(~$|NtS8K(7EB(U2;3jc|0bZ!$+MA#`iwp^+T77m2r8Mj{Rx1x+3t z1sfPx*eOj1<#ddr1&vY-oj3?ZRR9@4!!V;%vT@uYNsr@>Wcj#WpW61LejkM)&XlWs zg_a3UBSnL%*^KURW>0AOQg@_yV=YMP1dG#Rl~X85XH`Qm+H$+E^#db_?I`KSi@|Ia zmUt*DP^kl90qJ0DzakDvHRO%B)|r{!(uvTKOqF#OZ;Di>#tn2~WGZn>pStGUZ!JT2 z75iu&mC7th)fl$U3r$7o=z6c&9CkWkzaIy|Y%*Ccmk4kJNEc%UC1HdsW2!zA+H=)g zG)GHkk`5Oq(-kUGr4n1Ih(uMPXr1FsNp5S|GHclB9uI~|6sI#DGzl}6lC2R=gX&ql z-&RJw`mt|M!`@;VrRgKY1JnRa00+PaI0l$wfHKJfvP|TAD4EJ67z}iI2t-I^KnftE zf;tTHWE3>exQ!AI9tY2YBtT8Z8hXWUQe8(Jc=~A6ierDVh*8GE>%dq=-l@nQp#`Lo zaL!Wo)8=U9j!%Lanl8yQummR3C6y-{3S-qJ$8LCCd*pZH$X_H8N@uJjp#V?<2xVEc zGu#v5Evq-5vpx5T%<))IRi)9;Ez4l&7E8N4;|okE(G!_k)T&4$kWHcbNQKDKYhLP)U}rj`TtPz)%m;b{cnEj-h6Me``5iU zU-|5I{@M#4pWgiN=9wEmd~$1W@al!%&wP3C;A62N9fdBvi literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_3_2.png b/resources/g2/track/corkscrew/barrel_roll_right_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..e120b69e62f88c8502d8e470cb56cbfaa98db9f1 GIT binary patch literal 1056 zcmX9-acCQL6n<^mUfZ+_BTA%EZW83gv&3@D`{U4?yLPdj>&@OEV$f3$8b<~P-b$3H zfkugK{y1I!2ogrXLo>P2z$!g4V8CNWx#1}RGdUzeU_m2fTb%tP)1Nm6-+PbmpZD?j zzPEj9EjB;9Fbe?ltIsa4d-FlBg3~^)fBC@$6~G6lonrT@r*BuOpR1{bS1m2%W1XC$I zor&fPOsOnXYf``N3f3qD+STCD4x?Ta4J9uqn#p84o9$OBsL=>h z!3Z0Q3OFMXF@=n0DOqFGGM6*>VqMg2$#j!A9gfB#j7ah_olrO>FXSsy#Z*iuYq>?I zSM3}$0xSeY2qgi}0HI-YB^0X>i3Y1U@j^${2bzWU1TrYo;dG2F#F?th)m72S$?cNb zHFASS>A*2i*9rt_f{asilI7B(Sdis%I$bLi8kLG;nw?f_Fc=^RD?pSmsv6+xVbLa& z9WLKZ=)H7(ptXjz-l%nPyA|NG%3KY@>WTudvN3ITcji-U*lhfdq@EL@JZywQNc+X6r`Lv5cN;p<##S zd1L}|0U^(eyeD@L;asNN?b7AaJ*c+LB@$vPC1)}U70uDn5=$8z)!?Hof$YU2NWxK; zKxGP-X~b#Ug>=r_R~=a25|g`K~54u8M9 zfAPlErSTu;4?lHCeCK-jM1EUoUSMtqe{Jn+AHD|{h5pt3Rq6%rGFV+%Ti!kX>em0{ C;mv;l literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_3_3.png b/resources/g2/track/corkscrew/barrel_roll_right_3_3.png new file mode 100644 index 0000000000000000000000000000000000000000..296ae3a9093244d03606565161bb50805b1efc29 GIT binary patch literal 902 zcmX9-F^HsQ6n?w2yYAj(F))S6T38Ih5D69@ctlu}xXWZQtjBpU#S|V08MrA7F?SXc zJWdh`2IQE+VggfGOd(_fTUb~~u$W@tgiJ93izxAkai0C0Ns)y1Qxo;C5|ajVH6!0V>bf`?x}zHI2;-roNHeyi0wI5;>wJUlu& z!Z7Uk`1s`Hgy?p=9LGwMsH(EA4@}c=T{jG;^LdiztFqkHHOGP|fFidCgU)C~SvKqW zLO4-ob1luxW#MnOk;Gtqp>4>7)29NRo|@c^D`jDSIXB9MSC!H2F7J_`F<^-hsMyTF zG9O>hI`xu76^m*O-318cT>u3@!!QHK9g+-aIue8%MOh4oYsYyrouVuwxlUIkScMWa zx@RzbhtmVWoJejgk5e^TYDqbyc#`dP1(lI?eqcz3r+8Csnixsp7iT(VNqQOf-tVzcHg-kfR%g>F7LZ^%%b|%ycO=)xy=+p}CFST^8OJG1}&M zho_l7#}7rxQdM8qCzdt${cJidl4P@5?RGl^qycn@aWh;>Np;B#Hk}Q z?$)=c&EPms5Iw4^GOR8LrmT2cv&^3R-r560r~(YKmZT}EC99`pazPBY!k&1D%T1P1_xsik{*-_AQg~7AfH2#f|3zh zdZ>)xt?@j_67&^pq!W(CjDy}R($mx}inyu@)M$}I;Ow>-5K2U832l@@up7j+mEMNS zyJUmbJGuirh4ol`AW|chvxjovjH0oV#^WN7t1?IRhL>fO04f2Y#tW~Jdk50BC)+JQ z3E#n7E~UXh9gTF`HaOPh*-+$SiOXbmr7%^$i!=&3G@5WI5m6yG$IpM-{`c(zjt$zqkD6`AcFu^Wy_Q&S^wcXx8!=l?j4q60yFq3n z+-8(mvT?ZJLJ1{cwuNzY0n?g7Hc~jDu3)g))AuhpzXWK5gKrG=H_Mimme$tRwzjr4Yu2>4 zx368h7Q?WPj*fNf*4Z2m2SqtqmJtL_6uq)6g~Q=^JekSlbbY}zYxO$i1jYqC*Xi|I z0|9$5bm9jhgPp z!AC-n0ad`#5>|*>N@;7oh@+|#)qUuZijeLA-~oIXCRr>Bj;jQba=EfRKj-(C6lFP? zM1=xQSsjec$=h8%!Yz>=g%VYloM6Km7t0H&qAzFq?KJLmJ6rlHrM#;#WYptIi)>yN zjIdaW%M~qLE5sXyhAO(nN)x1qqWugT6ojZKCW66CG+Ia|ja;t0uu!Yj5a1FJag0h^ z*gP&2Nq?D*RJ^HbFke#_>Y3`JQUi6877J~&x$O>tbc!yQ%<&Olvsow;jm@Pqrf$^B z4EQ)q7A%U-t_H|Nh|wZKKH;C!lu{v4E$Q|8GGYKc05X6IpaIMQR4_nI@GJ_+NJ}BJ z#1kM<5MvGiwTLw7o&pbt5|s*_h(Co~EV5p&5D18&kVHAdv@_078cP*8 z=K@bwJr3lvBZWW-3gsANaLwbVdpiGm@&oT59u#2j{oALS`3nPm`-Wb;{LZJ|_w+4Y z{nKdjiw&FZUAgsZ`v=>Px1Rj1Ub(zuboSNRo`DCBzL8Pv(&yJMZhdy!wHvFiTqU;k zY`k;**hu5ViTQ4^!@NHs@4xp}`Hzz`BP0Kf?!G%Q)^bN)9O=5KPtE*!VV7s>@4L#S zvqPItclSgfE<*8^Wo z_m1EC;q0NnM|I}29gE#JhsW{B$xW|C_8#4}d+ULv(?{NI&VAv#Jxi-gd*){n->zT$ z_vKHtY*%*i*yb~DZ;7uy{P^7TjWhU%!#|(vS`nw*y?c%vs%(C|GBGnge!AzvH-+=r z$p_NPFm~`4ZP6_*Uzv|9_kWzYZEn0fHX8f=aqB;!vBvku1MSV_!9f3D-`Blwp8p?J C75$D7X+t*x!Eua`=tjg5`X&CRW? zEeyl9x3_n8c8F@V%5khDiK;4_rtUa)tJUiD2BT4!B$F)5mrITXQ2<3Q>w2YLry5PR z-4S|yWjHdT*cqpt+1!^HOcTnsOt>25ne@Qn&RSC3)5aq^J8v&Cf0ZXS5)1|!B6un` zw6VB@PluJ|m_!Q}Ee&+xA(T`B6aWLmY#et<(xYi#5Y80k+_I*w`)DvgaZGZRsz|U3 zB^Y$gW;B;GJ;CWqtw8QZsy{Zu%%XUbtyKk;kxgE=CA+P(2gV?@!_-Z(Zn_xGRxvI@ zMFqkFstL4*@dKhZqV-s`Q>`;|{M<{>nZi^|o@~^ZjwTFEDRR`bWlnp}JZR-{Zw9n7sG@{&_ zEJurr=?aw@9Ont5MpadYH3h+um9|lcHAkK9`EZma>2fB5A!Ck;y9VXenSN6Y+G^Cd z&I5NE_ZQP-xqO5~01dza@BjjUbAUMpsDL7&rh@_>WmAO)n}e3X%HZ$?ooO@qZEMTHk>0oN>x9-;V@5z=-hc)1=d z8_}vaz6fV%n$s2FDXhlgx=7Vku4&1hTlc$e6m-)hSY!!W&UjfyA)pKpDza!7c27XI zn*I5l@Asa-8IL7hSL=1N*|a&f#j`z;3nVU<*@?m|v??+vixp1%IMdE@!rk6w8Dck9nf)xG;~$R|5DpLuxetDj!{aQ~Mt z&#a%n-+k@l+xPB%vls6FcjpSklWVWO_w=Qw4(|N=HTUDo`0XG5{rleJr3ZTtzBss2 Z0{=VW{r%5Y?-u%SboKb~+qZ7q{U6!4i0uFX literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_3_6.png b/resources/g2/track/corkscrew/barrel_roll_right_3_6.png new file mode 100644 index 0000000000000000000000000000000000000000..8f53d91e5ed3a6e088a10eff94d40d0d9a85c0c6 GIT binary patch literal 1338 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_4_3.png b/resources/g2/track/corkscrew/barrel_roll_right_4_3.png new file mode 100644 index 0000000000000000000000000000000000000000..785f64a45b592b801a9a138e793e1e1ef6086020 GIT binary patch literal 921 zcmX9-Pl)4m82x5CGns#D4@Dy85F|pBpc#!4A&0DHmN-Nv%Vwd69x@QHNDmPrREQEa zhagp=6t;&TJwzxHFo#*lp-R9UDiqA2LX{kfTi71<5F|nmbNHEM;eFr7yS#UJ@B8}h zrF`r7#bW@tb@BfBz52dU&nt(GdS3;PJ_l&P-4E{Hsp-zn&hGARqtV#g+uPsYKR7tR zFzoQ~@aX6Wrznc!SVh;LJ&3Xf2 z6sVI}pQhG4AFS4)#9(dV#8hynP5K5swzz9oN=NN^Y!)+bQ-s?xlL^on=!@WM*u=!r zL3252RdWJuSXAlg#z!cl08{`S!^~#WAqbzQLqWJ!)mgW@bet#SF-lW{Yf&Q3s-&RP zvdOd^&hP~*klaWaPPK5ZCq zo@Uw{-xa04rVR`u==bBnARUkMBv~yMWmzI1OrS>?H)%>!LYp()mE^5E;if+={Y4dT zZkAhg!Ze#aj>{yaF{~j7mZExkEoR4q;cOBYSzfI~&=t(mnvPETJtnZl$kV1lcNRIz zG}tV&s(OM%fHr^y-~&VeGk`S)sD>&b+d@%@ils_}$-z*BM212IqyaKvdIrjSk|heiR15)tJ}U4H(xlYgK7z$f=E zHMsrwuMcY?U!1>t|DA7*tJ_~(pT699^WoXqXOz4++xhQ!{r%}5|2+8Z`3KVL-{hwc z8^6Qqr;lFvVHdo&!@oa0cNahQUZQ?|^y=*6FDp>u=YILl`tz+?5-#psp8x#b)mQ%m Db<~AS literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_4_4.png b/resources/g2/track/corkscrew/barrel_roll_right_4_4.png new file mode 100644 index 0000000000000000000000000000000000000000..b515bc70a87be25d4bd23151af4acfe8c2eb7f61 GIT binary patch literal 1269 zcmX9-Z)_8F82;@~cN-m+r6C=ZP+2oNazKF#xo9P)+(tJmyTMJHQDTvk71Q9MXDC=r zWd(1nEQc0Ww3!V#NW~gE8OwoXIbFqqH91T_R4B2s8X6taNDU=f!p{g(%O zDpf;61A-upjg3uBO**5|h+$@uBxu^kFbBWHOV>mC9wz3vkJFUNaxCgu+xb?o7yBS_$L}B8eh)i<-6Re0GDtm?9iD=_looJsoFrDZZE!E2X4W z51c6Q5I~@jD2vDeO*X16r}eOChGi$57a&X;0iXbIA_%L|`1E?gWD+fwNs3CjTv?xQ zE)s#VtjDxQLT9E77N^O|qIMs~2o^3(`eU|Wf)>+GDd#fadb8DNp-~%yJ6MwCDL&$i zNUWszlDVK#jOHt{h5%X`=v=_y1ttN(BRXr`5cfZY;h z$OK0#ekL2@3Ne344po#GEF?8r+=SXO+(nQcnhr2b*yD)@0&*mxNK!tNDV0hP=viP2 zAy`yHCiHX~b>&IE;1G+RL`le$`3f09-W&0K@=D0Z>2ytb!t; zmxD18=CYItuowsuK(c}y1t1L|tAhayiWHRGFwMi92%Z>^0~-nK6yj!dJ`WlctWl9k zB>ajJD;5=4)zZ5F=2a7djuH({$;9R?Ldg*;dlHpUdS1%IY{{erxB;=6H4ehyrZKO} zCivW9(3gk>m1L}#OTuyTz*0DUGH#-Kz%#a0bJzDE7;lOK3*doK-My!+c=bryR%U+V8Z zHa=#5H@U94^AL>P96P9MS>qg-xEj2+`UgJM#e#dat^AGI=0uCI^^e8UC&r()&Jx$o zKiuPO44l6Ye*Ee}*F^X2zg4SdxNS`D!JgG8_YI)@%++&8+eeoiZvOm1l&iV3?Db6B zETzWIJyg|;Egy{?{&GK@ePfVubQo`Q6WR^dKKp#f`_Jq+Hnmn5nP}d4AgG-->aG}? zK92OhedOfQ_U4vfRFki5S+Z)RK|FK(^n+W0)(5{XUfI2S)YUO?JH7IrtA6m2F#Xxx zp`~}~NCVuwx*WWtm zMcKKwaOuw#{Vi-hwP)nbI~#WICzP9K*Bw7|@#kABg_cKD|DvP!x-PD$9rAVu4;|SB z8_VI$i34fj(K}^&)8_xyVzcc*W*dI_`m&+n4_nibOC#914e~~{N45_R-JfA<&Y!xx zabW6baOZ_*M=xCZo;z}Oec$tAr%!e53r&x!+IF5v{58Dx@uBM``pWoJans9h%_;oO c9p3qc4LA0pqwx>;s&}BLtGDx;&AW#F2U*81=l}o! literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_4_5.png b/resources/g2/track/corkscrew/barrel_roll_right_4_5.png new file mode 100644 index 0000000000000000000000000000000000000000..a481433bc5cb1c045c0757a9c2c1a12259aa72ee GIT binary patch literal 902 zcmX9-L5SmI6n-}IaDYbF^3{Sg5(e(3pqs1EOm@bhRr~P95N8JU>C9wr3*a- zH(*zS1T2z6g&cC|A!3m^NDmcqs8FznMZyxWhe3X`EPU^Me24eG!}s3z zSC_rBdvDzXfU}EF&L7tNZe8y*8+HHrKS~E^z}08h4{CXEaBz5d*l0A4j*gCxk55ic zFbr!po2RFzoo=_wvWzGSiXs_?W?81=IKCgu=W&*;ilVG4mH~kWS!!uodoUn}BWCRK z{#2gL^(3{Hxx3khB8{nh%al5{N_qwrSnRDMroOtIo5fW+n^RgUn7Qh1tg!SlbSu+sgCmAL+Ew|PAtsiRJI30#wvkh&{yvY;HpAN- zMXM~=7sR2WxP~zu4(G0$20o{ofQtR&O^BC^-% zbhpl`>NyesQ~(RW1Bd_?09y=D4Ov7Z3q>I+)-nYq3ljn29uzVl1(4Z6E{j4L#RIe) zqauWt!E+#qpvu_5=-5Mg;`L^skt9x@N4s5)YA>P>?5HJp9XTZRm@*6AE48Q^CVPK* z7jMwIq}srdSdYOqfgC98s4sc;Ae`7qG|97QS7fN#aFT>#Km{OFXECnrUV(5%)9sd< z`mbOum!hUAgMl#`nJnXQj4!Z}$fgprlIfk=MLLOW3QbuQ3n-WBT|5f@_~`(?`RBE-p0JPqt>@w5!R7g{AKyIvAF4-tR{#J2 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/barrel_roll_right_4_6.png b/resources/g2/track/corkscrew/barrel_roll_right_4_6.png new file mode 100644 index 0000000000000000000000000000000000000000..e6f2762d5a5b1409b51b7280098d11de4e4ad268 GIT binary patch literal 1202 zcmX9-e{2(F82+|(yFpzFHqt@C3n_TuK?+{#q17C4BV`=h5e_`?NN(XGRl0b89N2^s zDi&?Dk`rrEppj;DP@zg8lbo}XqNj|c#$!zE;37>Zp#g*r8yyk#v&7_ifBo}5$@9GL z`|Emr9aCpb1pst(ukKpksPh}KpuMG$d#~#?09wGhwHsD7#-^sG=H}*>mKKY}(%RbE z*4Bm~NPBzxlqpjjE|-fS+%!#b93x4BqR5d*B#}tva+nP#nCC)|MY0+z7~f;|vG zgCTb`=1nBoOis)fl%f$USJE_&@LsFTIKn)tN?1xEh9Yz!!54F~ITEd!>B*Yza{>_u zK?qRH5x?x>}k5mYC7XT~(B7(>^TiEGTF)Z!%4zcWr-(L!c@1|0) zP;e4<7v*rXs8_^%GR}tyN%bm8I+A7Lc`jWPHPerhPPfnH<#0wK1(}wkY&0dNG+8sk zx*0dBnet@8Mgcnq9Daa?0Hz{j%HhjlLV=PEK2}!JHC2a0EN+)bXV8bocyC6c^9pA~ zq*6kuWFxggV$#UMif*%$7|s)td@NG50MM!ie{ zkwFyB78X%8fG0y#Hp=Cb{*i3BR7h4!dcA%ZQULG(C;+GcWC0ifpn?F{087J=0<&po zmRJnP1c*~W^8u3ukONS5z!(A3EYt$97=>mUJT{&L3=Mb|2}q7`5Ra?AOj^q4BZiT! zRt?zTa{2)gvQnypO{1cQ$);DW3E6ruKba^#(#o(@!|Z@W5ue*8P-uW7LViXK2h#Cy zJ{vdmY}M3Zy-YF;)BrRAgbgpE4Z8o~jD(Vv3Ykp&52aY71%V3$q)-=jAUm@~?m!5c6 zTz&!H&i>fM-SDj1+2_03)xY?|W8K8A89%@3uzE|o-#q{C%HOc>pDQ)>OIJ$6H!dBy zymfqN_6M^f4=xV8e0IfQ@}r3tdpZw(%~}u640s~ZQRd;i-@o*{HDpfvN!Z-~#d}}v z{WjUN$p2^e#2U|$(9r0io1QtBo|$prRwGCM8DiMhvK;vA`8Mt7N8gsmTwoy6R~ z#xJbw!v+qXoO!z4cj(q^-Sg|ZZ9UhP9UU2*W_jv_-aL3l8`Lg$mX=Nqzdf<%>AiIe zI(({g$&UMS@zWo!e=eQv7It6UwDI<)bN#ojEIojp-gBZzsptO=oEVimJZm=*D8FIL z+_ncDH~H5$UzHawU%dK{8SC$z`DS3^-1Zla-I*F+Q$F)qdBNcn`cKQkdmYnnR;Ld% Pga_TLdb>`o?0e@w7%~x* literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_1.png b/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_1.png new file mode 100644 index 0000000000000000000000000000000000000000..76c74fee724fcd5cb2adc62d682ef73291536f0e GIT binary patch literal 1249 zcmXAoZ)_8F7{`D6!)|3@foe+D#1bo%?BWWZ@sv|exj}{MZtj*9XrN;!Hqek`J4lfR z8!4{AI#21K!-iG3K{W?dg67aB7U{Ic5>F^l!Xb53C^|wzI<~-G{462)KL6f4-xr_f z+1u7?ojJX6Isjni%C}nDE7eko=j&@Kxp`@59RM|;?d^``m9eU-s=B(mrlzL0wszXI zX?1mV2!hnt*K0Hyy~$+4FbhSI3}a(i2hVeUzdsy~#^Z7-l~vVJxr|u=NdVf`;Be^N zZllL*2?U97gpS3Xi6oy+Kwyvx{SENVl@#AYGZK+M{xl<5Oqdn zPF8#=HKY_{`N^b~1Ud%jUBKuCW&y#YdTZS5NRpgl59WEXB&6VJ8r8A5!DB^(b|S`7 z37%2>Y%a_fB!4Lxo>U}QNNIJr8MR}$i=;dZ6J*(l#}f|*lhLRm%lT}!R4PGW;D9-d zU@x4Igi_HPzF#15LQ?ODt1p~@OvYL0v-uJ5ueFW4hQ3QvtBQUS^T&q zOkxs+C2f{0jTY@D=rlr~8AdQDlTfi$jvs%a;r`|c%^^; zfP3Gbc{BF>058|gpEuN^nboz~za&v!Jun*HxNB4Pog=gULLOb1nVTR!Y|oG0Mz4>1 zu-$E&8;MOCAZlCYJ{qYSu0H?qbKCbyYyF1@26*Aj=hr^Hk#6t(#5Mly-iE^`R%{!5 z@z5x~sP47ifh&vp7iSNSURaGyzkTVY4-QOj>(gFayGz%-;d;|QI+43LXMwvf?K+zt zSlC^&esIVrzdE=kJ@W3$J;%q{IY(C^_r5%Ie!{bO_-1GCFNWs*2TvSJc7H8*H2!=k zQ#*flZsVGf1GC?Ir1zX$agJXd?IBkw3);Tgw{)wbp6$P@Y5q+4jN5)|%WuQogQhR& zQm4||^z7DMV=L$xW4T*BRZaKi!tXY9bpXk5xlo>O;0LzaR~HHv~?bv z{d(<<;T=Dn2=Y@;@4NDAY}uCkv14ak6WkGUUBAe+{9bkUIQ92Ae&;v;{X5kE{n@9Q zAMQMQYyGV8JDn4~47{kh=Qk$bp=^p~4BQ NT;AGpa#`2z{{fdTG8_N^ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_2_1.png b/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..b8792a1b7fbb75c1a5be8b8cfe756b00d330d4b0 GIT binary patch literal 930 zcmX9-L5SmI82x5CGikRw#-(V*9D;N(hqy$@NDe`=npxrynT(T#9(u?^z#ekQAwmy5 z1hz=g9-@>rLJt*!_7Jebph1E}jWCBEB2?^3WP2!V4!aU}yU@dkzmbLaeIM`g-r>FP zqtg><|H{i(0AT<4oujkj9u#x6Tq^dPujG#bN^tt_t(yhi+S=OQ-Y%6&J3BkOySsaP zdl-h5%jHU?Qg1XGEX#5K$y5s?YnBX_D^H}cCSNt>y4@rlof=#0c~6Yo=4@)F7yT^tHhC-&pwZ9~z)`V@ ziA4i^F{!O*1j-n+*3hMcP}~4e05l9Uaoi>dhoU^5KUb8Cc6(vl565E^MFd-G2z5pw zd5w}xx@ohz!&@V<=gY%T^=4X-wn>g)qz13jvd*x8*8 zUr)2k#RgSr9OvqFiEOAeqw~BaD}AjH>rMy5i^(*Nll4*nO~x!0w>8o+=uubj`)W99 zU-!rJQKly3@$JfiHKkRRx|NF4=&&R)gbvDGF-lx(VPrp>3 z`{Mfpc=FAQpMCdU#Y$fL{nvxP9^J#?#JK(8kmt+5rc~wN31tEMl8oX^`NJ_cClXRm0mT|3{E^|7=a!092pC8 zWwDDA@tmnYwfk51E-wRg!Sv+pc$;=~baZxhc6D`icX#*n z^laO<4a2bB-rl~xK9Aq;C&>WIGJ?QKQdm*sL?V&Nj zDtSq_pYa5EA1&fRnFy(*q|r*2O&DCdDCiZ@bRs^=8wmPof#4)6EVFWwPv*p&DVw%x zIcd9*uWgiE47dgGM8FpZT*IiGCs@G4B}TSGshXlUH482Bgj=G#u^^EO(Rqn2DuSJm zsu`tjB$}nnhHap_<#JOv5hAGw!^Q+5B}v&>tdL5Tayi>HYbz_wW)p!|20Vk2c^6ys z3Kb$!W0Uo;-iQ^O+Dfa?*sN}#0m9{?Jf5J>FAxEVrWKA)itT0bLMmO(7aYrO)ff;t zOc7kF=+mM^HqIDHp_q-74YgXzHmX*uwT2jg5P$-p0T=*ffI0@K4W31D1sOVWsyq%d z326q*AUHfA0g&uLDH7>CGNY)HM2-#*f~SCEA;e=*$)m=Iv=+?kQn8q@ZKKh!QCrI! z0Wv4s>z!heEQGtv{I8BY}X|-siZOdpl z7HZWfjzcCO2M}s!k!;I7gf|h-*6UO@^AJjDDvq)wG8trZ?c=9*4gC4w2R@vc65!Q4zrWumcPGYPo85VG{^Y)D~PkC5?Z z_w}cSR|7*wo}iD+>&Ko;X?NByWDYD%UlCtkospLo{`&6}adT#t`{V1!Cay~I{^8&D zU%mM8{kL8`e{?lAdHDXw=}+b!(R&-8o%#Ex$;y{|f9~6N%d?w2!7Y@Bv*jOl9DHNw z)UsuFo@IO0Fza4GfczpJoCr95&EbX~8e{nT?%d@<3_E+}k z-d^XP_Vm`i%g3B&ZjO}thu+)1Jb0GedHfo7CCz-X``lJ)>~phf?7Gg3{?hU2`oWR! qPAsT%)Q_CCw%++~V)XV)TX45y_S&V}hrVz7hKcd1v2XXhd;EVey4>#o literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_3.png b/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_3.png new file mode 100644 index 0000000000000000000000000000000000000000..04f5315d95a8c00fa99201cee1057f7c4bf589bc GIT binary patch literal 1261 zcmXAoeQXnT7{`BOFV`_<83jA3p9;`x%Wfo~jC3RFBTO|z?DLA2oGj34yCY?-a*n$Nrbju(=OGv)Y+dt3ukI(ab z+EA~roIG+iM#Pz)MgSzlKei;9XSO`23(TwGF8Qd(MC zR#t`}h)gCcFE3YWG#VVoXqsYK1IL+cHs0lO`Fw#$B$`O{OHwwM!!baSfH72@(|4N9j`EpXa^4exf*ai1|6;iW!zMhfP$3B3xK zQDCQlz#<_YiF@R!kRq29bf;PUmPK z0ON5LuFz0Qj8T(jt)54XPMi}+o1b=t4c-_VOq!#TMNOzMy@q5_14o#6ns+nqfH@H5 zqoOk*dBsd9osY{YpkRU00@Mzm6%Znz)JL?YIK_)bPudpD3JKWFpbCyq+4ZQ$NQO8% zW@AMcm-5+$!>(-HmlwluI3ZUMTGWUW7K*mBtcT%g9^LZnBUSDcBbO~Oe&GfjY0|lBLFr41OUPS^Z_u809X)1 zLx&B9gHTE_TEOGLOM$2!NDP21fV>iVa2RA@)C!YsCz{nt0PU*CxUO^uU za&{;-j|$+reP|pRRBVb=rOs8Qd?Qv zVKE3!YtZYAg}q`ToRJbRmnIAb7zI!Q5EfXt3wDpBayk6N!-U`WNVa5>Hknwfm2)_F z9CHzvkHW(=9yeh944N@&pji!_TIk1Nl!Bt6aQwux6}KP$z`N_}Sx|fZ%A1AWze@Mg z`kMB3uc@PJ_LRC#I8dM4yIWTN*T!uP-`reqBAPd@e*E0hxyd_Ew>DM%F&^p$H$J;I z*0yGr%!A1<~Iq>A7Av&EZ7w)RZN>i1m!x!Q5A`cT`{)`+wB zuG#crK-l%pfKWRzdZSCE$BsUZS*Ef9M`uF;_dKg>B;a_2xPH4BPMPM^8=`*U;bT@yFvXp{4M8jpXR zX=|%_|DNlam$#0r_j>R8UO$Q literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_4.png b/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_4.png new file mode 100644 index 0000000000000000000000000000000000000000..ee7e037dc5522139d637de017d5b44c38c8b6e39 GIT binary patch literal 1267 zcmXAoe{2(F7{}kX+iqLgno&j*s+Q5XgPfzxBNl1o*xIGcTXuv4s}?=AU=urYNEaF@ z+GVYFq~ZaMG|)kZHEG6~HDksKbyO{+!73LrO($j4tw2Qr6${ib@wJ5H`~3Rn`Tp^F zp1m7;jScln>Hz=^-5U&>Ds@#QR@6!=*--uJbpRw_W6$QU$|w?v#A2~TBB`pXs;;iC zsi{E_q_(!UuC7j@R;zJbqt_EOORKhiY&;g2+n$2>X zP33TEygpqZNJXMdJYi1@zFa=6#}JcF%909~NyS;vkR6|J>k|P}I?85K-aFhzhne7TlIhz@F#b#YCVi@Gzg0$+akE!nIaH@1SX)#S(NlqCQ_D6cS>w+|*RDScE{y z0yKc&5t%-&q|=x+r}yT~;esPxLb^tg4cmPrW;1PH&AoajRAvTM`<-q)$ zF%q`K<8DFV3k3mIyp&deJEa7tpu#F9hO${5S2Xh_N4y+J&&P5wQ$*!Jt3r$#nVC@8 zXxwQfIhQT$cg1P##T{G`B%*2}sqBwAeIQ!41 zwRhw%Uu$ma@?2>;kn`-A+uIx1`OLodbvrKftUh(@TK9rw;)C}_mAC68hVyqnNtDm_ zdFm&&p;X-;h1)F$)(@>b{Q_toI@W)0`08_uugI6ZTjw~iLdm>i9$C7(e!OWvS|0Zg z4Be2v`QY%9!TgqsM^`<(I(m}Xjx_$z+_8}8Id-A*uM>%$qG3_&V$b1$XFJ&AyUC*H zyU|(0#?FTKCq5j$>k;v7lM6SKzX#`AJTo)XU!EP?_VwtcpKb~F$FPgrPF7!jZ3q2L zRo~ji!STLbKPRWnYk!M-%yV0t77t54_`9`ZWc2p(Uf-?BA;oxVLubp6{UfcrPR+jF zC*oT=%jcfIuw4*aQ>fz5p2k!8mpb>HJhSzq^L&S_6>wam@gw$SP|3!hju$DbJ! zef<6OCk2*2^{jidBsrBR%`Y=?Xc}-PLOt>wIJIf9HKMumAu6 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_1_1.png b/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2bfa6be1f0307540be162579895ddfb2d20cc2 GIT binary patch literal 979 zcmX9-Pl()f6n^_RyB*h2M@ea*DGqJ61PLWVs*$EPTjHA1ludPnQL`n~0jCmZgaLC% z?NA08G~$R+<}imG1_?NY1;a9j9CFx&VF|d%R3pq`&_Na*N)Fqy;Lnu8_uk{XyzhhW zy)Uj^l~#_OI0gVK>u;@XWb-@vHcg{mue)xi*9)R(KS`!($}%AEpvbv$xlpZ= zHH&F9dAF@}ds;s<2XS*W_Cy*h@i{}r?GoweRL5ku>SE}Y20bI$X-pFDa2iPjXf)IW za8#^oU|};q>=x1ifhG(}HFV@46cqs!01d;8eBLGqhoU^5-%^yFN@Zx<2b~TILxL?7 z1)NbxUZW&~F4?T^@Mc@A`*N$VdIK#;DkMiRQju3_S?9`zXf%{YN9zPe5Zh7GiYMLC zVVD=7paNb2(gMoCxDGD$sB$P6aj7{ny{QwSErl-V98r_#W{L0WV&7Ebx;}Kxv0tBt z?qTesag;A`6kTGuiXhfhwW;gvTCLY?hMi6v1f%`^>2!*KFo1F~wwo9GggT%rBe5|q zdy`s!>g=bz$-8#!*Pi$sx+hXyeTUUEn8;wnysB~FNxxGB!DJkrkb}k(y7vI zOYj?Nzg^k!?P1uS45KtXKmtGszyxpre1IK*F$O4uA|lH~zK4>bLV>|TOMpOvL;<7% zGH}#nk*A=biUtjoc<>~64rCEZ3Rcx|yGFMhsq5+eem#!;$s|UZ7EuA#$_Wmxc%&9k zM#4MOvY*!ahwk7g7@^^mDgZ}f5|b|rWL0IYitN}`uVwfBRvh`0Btq$klVubDN&ulO zi$*5*6hz%>kH=iweF}3h5X)t?TGcJfV3|6{xB}~oY$!AP3Oy+mkwzk$LTwfW0*dAA z__b>*fiPg=RIofS>yD_mihr{}q3G=hllazx&~%AO71oySFRdeJ!{@ Z6R&-HW|BV&tK(uI<%{+tGm0~X0!G5^w{n8 z-rime!}|LA`uqFcKA(>y{VdA}0w+l!MUmt2csiXe6pH0?)v{XcHt7e32A*?-Las=} z8;$uBNjjb3a|O{TDHStWZ|E$61!;%Oxz(UolkluUF2~tYI#?;l)>@)z={v1*zyl%y zQ3f;t%gI8#~k?TQCA{irRXT@9hK4}b>{F-&$kRgXu*ah;}@d44S%uBqyFHj7Fn z59#tTZa?p(MLZxAL6wv=TFJ2SJeM*Ay&@K^u$S`q13p?HIEf0$teoHzSutCbi>6w( zQf4z(-zhm6a0%cJgEt1ahEZ8}pn!);jBEyzbwzJ!Wwgu_E{XC)14J@N=Oorp1T!wx z(n=#AZCBYdbQeWwGen@z|$C+bFzj< zs1V^gn`ngeX4GhD)pnt|TiZbn!s(>k?ts@P5PpfK6^>7con^5?GPRZ~SY@+aXF%jI zMR2O3SBnst7?V#3Mkc(LS8JtAvsP}mw-Eyn1W*7pfIPq&Km!BR0nehCg7P}DYCH}y z2`L7O0kC*L0wCFqk|ff3RE(fX0$Dmd44wjxg&>bbB)1wRQd%IVONJ3Q&3vx1+{Ry0TlWqgo4h0p-O4erJgBMg%ez<}@{;r&J@KGRyg< zRYvVP#c`+z$O42qStL4gkKl>NGK~h6Nk4*8sj#7t5Q#{!m`wWPlt0aod6q13{why2 zgFYmBk&2@XiHZy|xz6!ZFFXEy_yaSiCj=P&`{p|xa(8@mWb(Dki=T%EFFpSldkg(> z{H55b=?9s6OIxRo_cpW(E8_zvs-Djj|Md34?e&kJ(=Wd=J+ydW<=Xs*LmOWlp8fBa zxmVZMr=d&L`fzCHNl2On)&$CrOw@O^Vm pjemd0k#=n_A6YV9U~e9r?Yi>f{Y_(RX1?PZ#*a;m{&;li;{W9L)=~ff literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_2.png b/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..6a3593f5670b8af9ff593635724788f24de14e25 GIT binary patch literal 1192 zcmX9-e~i;)82;|Yt@lIHko_^jh?AS4hDK+uNQFr%6qskt^`yI-I>IU6{q@iLB+v7{ zyZigRvpeT?0svN@a36tx%XW&04)qxB=w>EYlST*ur6F zL~_Ryo>ZF6=7M@&EE{E4!t)Z_vjV{sc#IwD>?;rC>DS{FGZ z#+OoJMUB<+sfMA#N&&Tz815&?5Jg8gF2VEZNFRwOS1VhXAk?LS#`| zcW^~KRHoyVfKrXh0tIm`funR{~(r))UT^#P_Jsy!^Fw|<* zfK4t(2oO>iCEHoW8PqVr^vJb*AlB%`{T zGzx0fEWmo1WEiLcXaWeEUc{Sp_u+_1=}Lu6r|v^67U@8M3x|105(syUbf+jnrHMS_ zo@DW=-vxtC7{y?kfEoo2rg{A2qg{XB`+@Ci`#A9QZ&RC_{b28^6~0IIk9;t6qVRZo z>>T{@%$f6J56`_4BtF0W)fQ>=C3U3rRjj)ky_+?aB>*pPK$`8QkR= zzA&dPcj&K{y2WZ;uw>xi?!_y$vk$@6jiX5TSIhXC(QiHtVZMJYb2|sWJkc@4c5c1+ z>?t;c(&`cIvF=YlkEy3w;``Ou~fr+o{@Bi7d!%|Cqo z=XFbuH7@_>8+lOP`NQU~Ih07hxn=muCyP>3H>WNwKX&xuQyD*+KfdFOZ@qTV_vgSMcKgm- z`*vRHY1QPb=dS&+aYrh*dK>lP^aXa|FB3Cuj@yk5H#WV{+msvhuI^iPV&#Un{|8nN B5%2&2 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_3.png b/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_3.png new file mode 100644 index 0000000000000000000000000000000000000000..71517ec9eb3deff6597f84fe6cfd961ae91372c5 GIT binary patch literal 1319 zcmXAoe{2$G7{^~|%TdwM1sy6&XvK)l#W8o$i;{WTv%z}WGd&$q8qwVp6V!7&k~$^J~HP%L6PK73EpfjM52gMFXJes)2QZIZP14Gy2ymzn2K_lK6gG78Z9IZDqu!| zod7(8ggGSPm8ZjsVoC+`I#@KraUQ~?1^^lWGlFn(xl^U$wc3zg-%Hbd7E9Xcd=?DC zL_&orG=x$|tMz8BfkTZ>jOF#V0O^WQzBm&~nPVA?8dvEI8a;zjENIf3LsV-@5S(E2W^JJYpMPbZ7TXOIBE2!IU$9)Jh{eE{ST0864t z=&->^2xii>7H}Bw5g=v&85%$aKu!t07!1)cW`!v?%!I&O@Hn7IV5AW%t905?A8!bU z*m&F}2$6hVfF&=L1z-*t!7J&I+8onz89iSxMT++Ls6RCx%ffU)s{ptfG3ewbLTzO* zhlS#u){xH`kNAXSB%evbViu<;7y~c^AS|(Pm+an2<#GgaIXvKhCtE5-noNw<$~qhz zrgPysKY>L^EJ5k|X*6%tK(iV;wJ?Ce7y$*Ubo}@n*^9S7u(PR=0gImuZZ7rr8{rtwMV$Uyo+Xh2;jj}xD0AJkOda8Z+Ob(~S?GNSQDk{G_GV9~{ zU$#7lr-Pr}toiWGZNs_hM=R^&oi{5yJ8x`%G`Dtt;nKYyhg=Jz?dxk7_&%TN{5iYp z{PY!5!r=-n%iX~b?`Yld?~#iYo~zic+8*(Rl&+#M#lSSPp!UPEN`B&F%j$PZtDQwe6swQeC4KQ zQRS0<^3;a919v+vUB`Ak{<`kZtA95S!OpfN?e3~M)BGnSEw9d4jhm~^_S`?PdBrQm z_wPCWk}UePyGnHZq;OcYc4PUV=hodBW7iJed_XQbGWV;I&dCF77F_gax8=uX|Im4~ z2`n4vMkVXE$ks9Q?Q7@VQk?62x&DruyfG>bDK5-p_uh`QUh6vh-^)F_Cv9nY3F_xP zoOOKliH{bDS57%LL4Pz5d;j%Mi-vj|YKKnm?^!eaAQazRZWjmJb*mi{xsgg hi8ghd8n-@vQKq>(a;S3n4^N3UXsB;oda-Up>;JCDMxX!y literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_4.png b/resources/g2/track/corkscrew/flat_to_gentle_up_left_bank_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..adabbc32e429c758235f0921d3b9d760261049fc GIT binary patch literal 1287 zcmX9-acmQH6#i}Pb}JicM>UEXxI%;xtU^)?S^F>?gj@|ELh;kik5h~BXpq& zrz=uN0~aY!v6Je$q)LsAgLz2N0!0TD(uC=X98jdNLclay-9Qq5mXLh!eeeDAzCXV2 z^>ubwr%stM1pqL$eQDduGCy0cg*A$D&)-%}0H6S!%U3NauN4&)m6eqWg+i%RR#jD1 zS63qlQd3i-QmJ%CqY=YUk|Y?0Vp%)Sb6&4E7!1ebQYtkn%f(U&Ljhp{G*xT2Yh5mb z+k^W2mSBjE#vO?ypU(Jm`3Px7Y?fM%(g`+$$eO}DcGOEIgSK>>lSh07IWk#HS@pnS z25tg~3=-v#q+gwlYD;N7ETFLDfR9B8Q$_%202~OysnvpBFPcmdi{&Uyk2sxKLAW0d z!(>vAX^n&qr41H`$;z2+0>+9KK16zBR3O1b(hf;>8gM;oHCh-m#o~63d5D;gNrapuF(I1_6|$*P={_U?umQjWAOa8rV5FP}1i&(A z5_)(Ti$FO`n*fJ_00AT`kZAxJ0687>V=zKP$pzCsC`Z5(<8eTdz(yl3Rwua40nr+b zu!)2>lZh1y8CcfRI|1gYB}5$^F*qa>CtJj#JyvojCWGn6QVwQ|CN01Xh!s`a34@El zJWfg!T#}t6Op%jvbkHZTIYoapyizAN|hxaA}&`!;GQ_r&BPVL&=iN`eO?#yZ4Hn4S} z=dVjM8@}(k*w|L}>!zQl&PJQ&&#Jux6x6Hb}ao&Em@fLdG+RMAv z%%A&rf5j_ZFAO)g@J*UR@9~Zh==rDA+45p~!g+k)Kx#S@;`^*_qN{Ldv98s#CLyuxNUvoSbw(u*nye*W(+K9>2CPtgV(#4 zPN9l>X6r8W$#wjt6Zo3BvhKJGk%hZ6-gu2(aijO*x=_Q=@(o*`nNS@YUafqzdcn_! z>NdVA^qJ}(UYu@T_v7O2NvV2}(-<00*5-u&D!<$wH^z^2lVvwS`;v~fZ(7&){tuCe BG?V}U literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_1.png b/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c0f89bd1bb5afec37c6d15bcca9ff0d56df0d232 GIT binary patch literal 1354 zcmX9-acmNI6#ijtue5eJnL$gp)8eEJao6p(oDSFPyef9op6j(EktowM!-;xMv}8et zlPNJby(lW%(BUMOOwzGMCuUS}AzGDAwh)UeDjKX9yNVT4aO!@;n0)Vj@BQ<>Kfdqn zT->Iqs;I62093UsY;G@dL$T`1ONza@bjck6O2FdQj`_t^Bod7qH?E|lWc>K?rKP21 zWn~D0l$V!_#bTL4p}=vBqDY3(vaH^0=InO6%jF3Kf{{o(nat*LI0i^HptY5Hz0_nv zEmq9It6gr|7chjv=4gyhrM;92(Wxsrt<0uF1y<=Xcb=#)A1>@H!DQoaatv13Ash1;&o~t zONGo#%+4lU=Ct3Q4ZHF&KTJm?QbMWH;e?T-EDXc5tlMG<@O;?gi3NkHcs!fULLldW z(uLqY2^EqvQI#=8InsJ>#uCa3@mwJDB$0=eDv5-U$uy{fQDLlFZPwBbL-Ck3z&rbV zfn+3>OOe2!Ma+!EW;&c_aX*EJwOE{1WpoN?K%q?u-8c-AFs3brpO{rS`uqnrwzn~$>CV+pigTf* z`TdUByY}x}zSll&!uHef%D|GQxjSbxH5<_nu52>(JkIpH3J>=#?v#z1OKXk{jLiD) zhn_PLV(?gC`AZvkOU=1!H&qpvu4eL^JFgFU&abY&x4E#58&OPXFU;N?(LFo(7hZUC z%boqD!r+DVl_>de@W7U7E5E8^CqYp_*BISX_vzfsAz|13{(l!WZbdIIt=-)n_dSi* zNDF^=CEq=@9bGwO#KuI{lcQr(nyQ_`>*=aMPv@S2)T|vVsvLy_flY~l8b!A7;i-G| z4eWuDFS-6Tl5=-0y@uWg#}++wX+r#a1!T>|%C~n>Q$gFWlW&Dbx{fZ@Oy6-Wd!oAH zM%|6`n(24f4X?U9@j-i`_ul0ACG|&ZgQ)oNskE)beY(qixO&4_AOCFP34Ouw3u3+5 zy>|E08RwSmBYRud`#M7-M|xxN3k}hsb%LvBy5r^??kQ-TgcEfrJhXeq+1J*-L0(LM z_a`={&@ZQ|1@X~_g@U_(?C=>k!fiU4-!gB0VW(%Pwf@o6Z0ksGCZ7KNO#hJbR`r67 zGp*ttU*g;AEwy4|b(v||KyGSy8)w8};iB_OpZLRFgcw!*{ZD8G+4ZW?=<#J7$G^wqvt-Zayqobp< zvlBs(uCA`hlP7!qem_YPEXxQ2CrP5B$caQElgXK;RVs}+PNUf*3Bb^R=ekAF6OH;} zaUz+bGg&@wh6_cdY^SO_?GD_J&SaOr}em&2A5@lhxd@Y4d$Nt7tFa*|Kx!Z}N}Y_;U1 z?RvgCQFJrFBLHs%_~HQ55Gv;ln3z~(WIL3qDtbdJ!81JWktj44z*8YQFR=whuoF@x zqtuKkJuXIoZvY^>2}K!C~s%OGUl%@$Ch zj7O?$vL@>FSfQbfHO>0n$^`7j-EPY34fy;5PDnJZaC|b{S{64`>CwFDl7!6 z7a9R%yqnRyyzUEInC#G6Lo}MP!bGNg*Q&xw1M>jNhXe?>$oQfH8IN$98r9Qk!ARRB zqwbVovr2Isv;cGfge@vm~?_XmhROrxtaOKlp(i>w^MV@yDett^TFeJuhrndf@P(=#j*{se`}5 zi%(u%Q}C?1-fu71z2fAKpvm;y+rII`m0!QO&-~)xp&i?4=G;~Dolh$B7s=en%5U7) zcEPWLk6*a9?8f-fBfZ9YqmotU}l-o}~3vp(N@WA1O;cOIL)d`_(SB_4e17G;r-1!Z!d5SpkPkN@^|;`>^s|teMCLI?U(1p+vf(R|4Yx> zGWh8(7qw~sLRW3%Xzc7in+FH(yuS3mCE~z%``+G1e7ld=Hct&44vivLZv8oQ>$8{F x@4CP3(&?ou)H~AAy~*1h!J$X*C;Q$XxsRl+&V8iPYqgXHt9yezr&hkU=YND_3)KJs literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_3_1.png b/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..512aebf4578d199fb1587f4d878271e94f49fdc0 GIT binary patch literal 949 zcmXAoL5SmY6vkhtok?fQ7?vs(a|l{6hag#r5HLt~%?#Zk>tvX$1St|Bi)AR7LxdiR zM9rZr5u=nPN)J5*>>*%3oBJo(d@-w1F`xBc_nzGY$iwli+XtD=<#JnFTlsvxP$+C~Z}05v zU>H^`7I$}dE7fY1Wf@Tv6h+eYx@j7=ZF^pSI1J->nx?Dunq@%XL6%DOdb!yoTWzM} z@Lo?I47E{YP7-In@I@L^`H~@3ER}S1s&BGqwitQpWN4)0&NB5ktGGshMng*gSHT7b z7CHEAP+m_6v}Dj)LzgZ>aTP!Y&@jxvaf={ait>5>OqR!u#>}!V`h65d1Y52O6-Fj` zjj9>6YO%V@n?2DEr0z)ZCt8>`NRD7?RbHVbovRz7(UCiStsfd;V#R4USq|o#2p6EN zK&1g>8z>j!`jy&{sz-v6sLtHWmc^Esu#Sx)Q=*C>^Eb9KUHCnmT z^>BGP+n^GS<6NauBdZF{=sa&qa!1RSwTDi3JQ${NvYrc|NtmhNmPWcwy4Mzhjxy>s z#(_19ddpe7USA*qKm{-XTz~*z46wieWs*hIHc{ZCbS6_^u+SACtU)RRQUDnh zQP@P24oZD^5!XpKB*Ai-po~Q{fNhrqw<7zb7E(sayQ_Mz zZjCnHTVcQMKwVHm{8U@`X4wh+*)^kphPzWdmgt9C;8SbeF zyWLwXxSsb^=42w)>q@h!x7!BG*c{^tY#_3c#7t#+saBCjB8x&j7KH*zr0n>)S4xkc z{J@7NM+#j3=lAzBqaW_yxc&USkK`NAe0;6AKw9qu`)BFFt8d)BA3yl)xc?kn`{Ysar&}+*_SZMTzq!Bli?`mH+&czwz3(#|93C9)fBWWppZ*WKi~s6j&O@bFXSW_Y+_B$cxZ*j z9kIp=jhtAaN)sEcq=rkZI%k6iHgLlc8*}2EUASm5)ip@4lKxQ>oL@^wKJV8*?~{B! z?;YMb9vWPJ?{WYb9DRIbSEp|1guBnx$;bab`#pdQcJ7$i-Wj{Py1Ki&T`t$MWy^Yc zdU|_%F%0YL>+A3D_xk;QiVCnSBM6)j(55{XPES1gt+YtC_+triskh6bJ+5JgWk z>Wjq#$rPQ*@`a*gmeq=#s@3x>iG}F_h4X4*pDq(Qm6}Shm1%jR0y%=$4L<bK6wl8_B2`Vhp39+f z8K*pc#v9;$v_ymyGOSUuPODiqVQ^_v$XBG26Y&M{K*&!EBqs+&g;kP#GAHFqO3BtN zCv7(hwRYLffJXpt1blHIbS#+jhKht(W)wS|s;T*=ZlNij^vFRx79vw&x*)TrD%c6R zno;XUqFK(gZ3ERUwkaw*0vV8LTIKkp)L9lUrqZ*8qGQ>u8UqrC zse)URe0r43#u+0inAymzp;gP-M%8Myt|JB@44?w&00zJ;Kpg|r0nehiii|vRsyqP- z1!)FKA#iv=0wBeUQWVPbs1!w&By#d_+xQ@GEQEP1DtomUnbt#vylk2Y+cp{v8+Eww z2vG3>M)&f0pHw0ght`{-(TbVvOyyRohN?}%13@1a3b;ka7Zs>@gwwTXKCPKX+O~{_ zW1&_p$Z@Cy$N_{pUL-qocYr72*?K*g&D?=nsj#9bM5A&%u26wQFpyy=gQdz`V2&pn zVLy_5NFz{|LL~;-T<7?M4-MSB{R8`VjSH}CapBocfA{FfBNM~Nj=vo}YOT5J^)qPx zi{JKM8XbE6*Qc{zo_^;m^2WdY!?gu#_@!e%|EYENou|LMLB3$(@_m~xeBSf&!RD^T zm3!qgSI(bouiSd*@)+aUsj=Ki<9|KSa7`SgL+Ps|L}r+3e8dC`1jW@7y8^pQV)e}C&=^Se)NWNu#l z_+0zQ!ngMfWrvA_R$;~bjy+=Z%*2y3?+#sD@~`i`Hul`+i>rnvKUmr{b8YSAb=Tbg goLUkOr6#*_)8oGs9{8r&kqJh(kB@x%=rgbV52d^8ZvX%Q literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_4.png b/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_4.png new file mode 100644 index 0000000000000000000000000000000000000000..d6b4ed8e3b88ff981ddf0662599cda85ddf3026a GIT binary patch literal 1187 zcmX9-Z)_8F82)YDb{oy;pqLsiSheUOCzNnm4!ppDH&*5?yU8&dsY@45X+lj7bJI?1 za?BH&<$^b@T4KeLRMSYsX6{3gf+gOEK^nQ3C3aF{2@PD#!~;)U;-WuGNS^oKm-k7Y z=Y6M!hXUOz)~)~mbPw$9+t;lAW~}dYH1p=2$x#3tV0duTo#P+S=ON z+dDcs5CrM$?Ck35^7wo{g77m8&GW1vgd|B+6eX3)6beOMpRd&{+a~;grU1t}Lm_uG z>W#(y36)Bvxm+P!DoYhZtv9j^jsz*E$a>_UR}-*|M9eBoITfrF#M)fKtYw!hJ%EBR z4q`OWcqAtxWz|*9x$O!HO+U25a9M*;_W{5G5JnKu<&sfU!>}wx&2rpaBvO^-#Y_g4 z%P8UY(H=kNrNUT1#Dg*+Xq1#@lsua(@!3kaSc`Z`)F1FsJkAPaNMytWm&k-OMX_ke zdM#;~x%yJsMFTevJQ3iH15886j3-dQLSWb30qI2oepiV0MtLG0VKq6LP0FQw z($Mo}O^0@!WLa1Qum&J(dXZ?-Jpii2(~Sn1PCbBBsW71sAB_s}xJdXF(x0MvBPm_V#9Ez^-j;0!0_)e>#OI^ zoIiPaJonQ6srIq0V^=CuCkGxLoB5^xiJN=h=&K%StnNilj`v=&f1N(kKGV}O-9Fj( z{X@?TpLqJG4d<@j2CDPu*i-!BGw-|KdVAvP;PxJ7p&WAamSbV_f1jQ^a%z>s>(=6}wGH~S?rp1HbsqZe_zXMSKXPm%`r`#> z z46N_6)z5C64FIU`Xm9H-*Vb~(*Ho4BXXGar0H^}%*Y&I^j};Xam6erMRaMp1)ipIW zwY9Yff@n0FS+i#8jYcDeSxAy#7>Z>bJkR<4{%|;&Op3BRrmDqK39|qK2Q*dZaOm7_ zgU4$L1o3c$jwhW`iq9y)Ts}sc5j$STQF@=Wa0GtTIX|+BS6-=fWjt|px+U3gnd=t?q zOr=mvXC(9%+JHMvHqLDKVXT1j5z?QaLJ||pI7QWEu%Z^55ogR4YjtoW7oY=CXH?`w z#V4yFr4Y|er?dpnF+lGE1}`uPh&8IWB~6YL!727&j*k@u84lBC9cx8BHgnL9$5~S1 z8O6_L!+bvBFQ&rNN&@C(t zQjP#l3gH>8&uI|c=7^U_1Q;peN+*2TRHTrVOQi`&0AL4z2S5NI0YDmnJOW@@Gzq;t zOvIp?rA>gtK!^aM4X8AL41k;-1~C|;q3DL0090e(33w}@NMNTCH>>w~%pt)RkFk>E zSCmAdpun;h>H?Uzju7;8%-|GFoQexYN227Bro)*TF$c3nlMYx7h|QvP5C%7cd0mv? zbH_qHDG^fSL_w8dDQBf9C<3Sg2+J%2WxJNI-=uAHTJ!?*5Y>c&EFI0j+HPI0r>|Qv*>!_h;7h|WRyT8)R zKk_e??OVX(FP`Go)V+FX)y;{^XHG2r{`SO@Pe;8Ub^px25L2LUqZ)T;&mBMSIJ2!o+S+1Q*{E!&2yrhr~ e=kim{d%@%0($W1*?Wr<6(6Oeg?cC}u{r>|Djx^W+ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_2.png b/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..4688a1c2d113a955f28d8aebc3776036c000660b GIT binary patch literal 1185 zcmX9-e{2(F82-lA-NrT>Q%&b;azGJJnyf6-Y0pU z_Z=JD&9G1Okpw z2n|Q@c*3is*i4o;a#F!el*%fNA%1U%$T*{ZR2DpGiI|AdImKVdiq=%TVyX3N-sb{5 z2Er7OIV2+@xrDu#anuSfSixb9hxcU&^KJlG0C)ru?e?h4C3`%o*E_+oQ^8;{8eK@I zVJ_z)9B#^qv#6K%_(aSfB?Q?krRbQ(Bn?h2@VXU5Nf+*OdpV2|$bd+TaWZYP~iAL`~XT=04&hK=)$Wsz(mIhDy;d9zlc z0M8&2XOHrz9Kuo&N{e$wDmbM@i@8*#n6K3qAO(OQ00{sY01bdC0Lln}4X`wfNKjLu zRb)LtBtVh^x(`?^fE<9L6DA0#vQQ7fLL6EucwjsU7#jFlBqTVaVJs>8GOA!0G1Js4 z6%#hNTtPrYIw;x6swl5}M9V8z16nO?)Rn@0y#$L@j{}e>;=}C$3Jq~YB*@6okeZAd zTGGsG6)O*GC6ZyF4xj}fY-Do^o{!IY;x@->8mX>qrXq@ESwtZyK_TZ{_~#hxp}Pf zWWp^ew`~3k>9OlJ=CNI8UVZ)frSp@_BkQ{iKXJZvZSQ|W^0cvi$DOx#FWwg$ w9PebYTW3yBZvXLD?PYy`r{ms=+rEEn#|_wJtx8{Q=nMwdZR-F2r5y+U2Qi2W!~g&Q literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_3_1.png b/resources/g2/track/corkscrew/flat_to_gentle_up_right_bank_diag_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..80c2bfb032a378fadd935e5fba3bbb64967d897f GIT binary patch literal 990 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_1.png b/resources/g2/track/corkscrew/gentle_up_left_bank_1.png new file mode 100644 index 0000000000000000000000000000000000000000..9422ff97d9282364f308d97acbafccab265a47b5 GIT binary patch literal 1083 zcmX9-VQ3p=7=F97yLR0SU3AgKnrW(G-bTcmoO0-G-ny*4(OY+u%tkoNjRpyNKdull z>QS>T(@YKwEJ}W4+bLllEYqR~i;`;W`Xl1a#V*sM1c@{otsD}hvWlNK2G9FGJb&Kj z$Md}JA07*D*|dEV0BjjKxc`X5xHC`ox|}`OJQ4wL!Qn$khaK6~)wN;62A9j#-QC^O z)3b5oMhwGxdwcu(`n-WafFME)L-RZ9(b<+10QQ z1RN4Hs61Abuu8_=D0(_IA8LnCM?mW;Le&5O2OwaW!xA1*2vMcvJd@JdY?;?;f?>t{q%RZ>P(03xWK?3LG?y+21w%4S zrD|o(cCoouans=8!5agA5`rp57QEq7Fj}D{Gm>e_nypsREQfnU(w7M1nFv)BnX=5A zDY220TYAc_AtjVNXQLUXQ+iJa2YOgoeP(SW=lU{GwAK>wjNKrD&r3L3$vXsd#6iZgs>@;Z* zSWM>Kir`n{cs@z%X}+9~E$B+4l5aPvoz4oP0i5(@02M$7SO92YfE;iPO3Fyrkk#OV zAQ6zI!3cxJ0pbBkUX&q_#vvn)YH4I?a5s1oSOy{-78kur0?(@9q9&HhDbv*3Z4)_O zz8Db6ep>Z%nqM%2l0~U@RPQ9pYq{FG(L@b9=mFA?g+uNr?T_PTNnUsi7iVWpwLT88y8>(}7 zI}$*GA1OhUCy+rSlXc2Z?(YBV?hi~K8RKE^^35qn+#cD#@9481&M&g}rJmY6JZ>wm z@7Q{4Y;^VJPv@4k&k6d#-~aTUd}ZtDb2}fTZr^!pZ=1e;ao5uL#IdE*J?CeZUb^z= z^o6-8@%Z%86Bo9GO=Z`Pklrw?Ejmf|x|(sPghHuKJBna94m v_22yJnQO^C<)`1h`o}i|mtWic?J_-g=<2USXVOj+07iz#_FsDO)%X4fhHTl> literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_2.png b/resources/g2/track/corkscrew/gentle_up_left_bank_2.png new file mode 100644 index 0000000000000000000000000000000000000000..8c3c739c121a0dd335ca28da461c006702df283b GIT binary patch literal 1091 zcmX9-e~8<36o2<)m%H6Y)w)$zG>26?E*lXu7Ff_sv$H#MUgok#>Mybm8f z@4dNWIaBy(N ziWNgcLl}k)4-b!wj08fV5Jiz3$BH5^%Q00|QmIrfS16V2YPIgV9nYgkU>Okj(OAr% zNZ?70OlO!}UMQBNaz(8ri)Kx--8fDM$w-J130|gS3a6xnbU`ZEitXrC zH|w;E&2GiVf?tF{9B>W721XYGky1ETVHGEuX{u(&sG>Q6@XK^C86h%JrYLh|RdiBv zBd4~kRHu^bIu>eGeSSJjL@7GXa!FCl$Z|fJEM+p4Lcy`^X1(6&bPxm;2S&(>4 z6@9vd8wnz>u~u3v=i`f(-l*i;jjHD@Ar>GCpaK{G7QiAv3j@@Hz#&aVmWkYk5C(;U zEDLr7Tmg^>NC}_}g-ik22~gh!jn^TuwQT)oweerxlC? zrH!&iKrnI14l6EWbYhm5EO&FYWxI(Qovg%FN{jP`o-ng|*~&UqtL;{i z*Q9wK*??R?sFy{$CwBwEl$LL`=zQ)5)LM;;#l%EH)-;78Q#6@lDT|{jJXsfrb~J<} z9O+?{r;yDehwmLfy>ayF^&fa?=d=i0fBAk-k6fMH_Ry~N$6n1YolT9cdi@}ZTi8B) zVsdN`g^lmfE?kS8zdcFaeOldp`Hh#q{_VAzw)S*$Vy`!?4}P=mPW-={`mKLI&Wycv zeC*pT`q0Hq$EF_Jun-zyEuR!WdMk6w8S=^LJ?s14`QzwIA0R%Qx!=AtKlAvpF)@22 z_{kOT(z*Gi1@@6cpI+I%diUWU+shYACue6iKX>AuA8tGR)3xlW7oI&=Jw7{g=xo=% xgT&5E&YN5J{(N@-yUdyoF8unZ_Iu$gcHe?|e*c3{9q5^d$%*N0vkyOgsbD#;*rV~fZA>-H01hGv z5e9St%PLqY;jCm`%`%SaKGYP^jE<1$1>gZh3{#v=4aaqYFlc&&=SRcgil*JnWKgMu zQ!X##_VFHCBmxQ<)F?@()ifK+amk`!l*NJ__V{sMz)K4xC;3APtHk+uM$8nHf~A>u z(yC{xQza(@E&<$O@I-;oF@MG#$P=LwqgcU2RW%yAiAH$RCHe74fJ_AGti%>o!HP+h zlv>Nh8l}{fl|wbt>GBg~kn)EaHX;ZKNlHf|`9z|W$ykL#b$qR%6UotR-Zrgfl>w2% zRKcl<9$hBWQ6?7`is|rZPOFsC^@`bS-b4&Q5I_ac0dfGN05uFy3p|UWD#{tiuJ8mX z6eJla1iIq)Q9(xKII<0RV7wnV7J@t`OKvSfCiOtpkc!2aW##I13$?WH zFi=qkqq}*-BNhn7ru9ZB*NhaWQstRK6;&F93;Z4|;B$r;k1SBpFsEy>k<^O0q-Eyn zwuzcmKgXd0AR7>Bc@b~PJp>+$rfW5SI`t50xy*(_f-FnXs6zQ-eqV~Aax7KieB(S> z4|Yv-Z@x{UQpM9F#`)zFb+}?Xg zV=vz2mpkk+bJZu?Zrs^#jQ+d&r~WUmFTA?4=aKI3p1;1}=km6(eV;F4hBwUJ*K^qOZ1ZZ(Lk^Xx+63%v!zsfVX}&wKDbOBKdvmO!tcGXw|l}CkF2w zvC{*g8)L_R=zC(Byu?8*IJfxVd#BGG>m0Z+d1a<|>xG`d9Z!F8_rDj`E$d%@>8;&s ztMi9<#@Eq5PueF=HZMnx4BdJuJCTyHtGiy!-@N_fc7uIQnmqNv_va7%`idm1A&w9I zGx3)?vIfo0ylu~>O_g`gu0MEr>%5)}{?U#t&f50vu``b8{o2JX XOBVKY?b_K|DQxcT+jzX^^*#Rsf>Q=^ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_4.png b/resources/g2/track/corkscrew/gentle_up_left_bank_4.png new file mode 100644 index 0000000000000000000000000000000000000000..6f7012680f551d1753f6391fe7003a820e4ef739 GIT binary patch literal 1223 zcmX9-acmQH6#i{1yTP1gYhr~e$1JtNfd!A{BxiEe8+P-^Ztfs8Hh7XtsHA2`azcf& z6m7C@7C23D&8$$cGbLVPVUsl4kQy2pr0RtYEaAXvN_K`3t5#BUBtJ_?zW2WO{(0XY z-}grQ`&?~HmM;MSwDtCM57c>my*9Ko)w^=&#!>*9K>yZlTk2~=LqlU@V^dR;!C+Xl zXi;->GlC#3EiH=|FE(4PRvdTGG{td@Ab2E64243mSR$Ry&4;0Y^AO#^P)$&1Z8`L5-BkNg6}kWUI)SgKkt7>9DRPYn8mq z0(cDgDIjx5NfM@mw%BIn^0izR^F|Y4$J{vKrD#9LMFb)4_opL~Tq2=nGNswsN~HpUMFjR3 zf~Smh*1{DqZ;1|BM`1b|#m0szwhlo0^yU}+eT zppt}Ik+lO62T=-STtH(1?S~HUrWCVsy;w03ate$Dsz>u|IsG4$b| zmq@jp{1Hrkxp!g^PH3N_H#TiJ+cC0n20PZt7<*ov*|9oxzkUAlk=qU9J#BYP@s94p zgTuehDBb;>&ZwtsA1!B|;9I^M9vR#7^nuRJZ(Ln^;>?@eGZQNgZ(la{T<1N{d1A#=&C%l5jo~Oz3qAX^}vzdxi#0E{quK*3}v@IRvf8Mpud literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_diag_1.png b/resources/g2/track/corkscrew/gentle_up_left_bank_diag_1.png new file mode 100644 index 0000000000000000000000000000000000000000..962a4cd8ccda16763dd4070de17ed52cd463b800 GIT binary patch literal 1042 zcmX9-afsV=6n=NTyY%ihd)PmU3mBzp!RR`OnqmIPX>Rn6xXW0kWmJe(rM5G5BZrf_}+Vb|GbaK z_r0@67E^nt_Duo6-i7(OqrsdF>cMa*=oa-`4j=?aUO09rpd%wAqobptP-tvyY0~?$8^M<}pC4pr?;HNX0Xf8+O z3&~=MsZ@n}Lu$5E$1U~xCP!jvW?JE6TADEAL`|jEb*@!OI}OF_6bGKUGi;}DkVwe0 zV2D^UrJiaIjW${r$f!)?`4m}7Gj*A3s-mmQ-HO_` z^kJ*A<65ZSjzsAMnWpG0%jHF}B+J!&zELW*YBkrkdz+iX;Sd3?K%#RvFSGkyWJf$O-3SgES4hTBAJvKM&*T~6f7$=O65+y;k8}A$AZLTsurkOFaGfAKhDDbXy>-S9$RYcD%YL4i>~_J zaKF7V|Hxm}+9^7IE4{M(#@8!PZ=W3f^~3k>|NYW`%Ws|-ox%SYu^u3gAD(>*dv+uI z^7&8Rxqd~aKG>R?xw-NASFfGfdg*J-2!%R6Kj(+iSO$P6xNZ!lA{vPoIBf?SI5V$W{OV literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_diag_2.png b/resources/g2/track/corkscrew/gentle_up_left_bank_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..961ca5620d6cdeb53269b9eef30b231ad9b8a509 GIT binary patch literal 1046 zcmX9-acCQL6n<^mUb{Mi4J_7xaSIah*zS*GJLH6OUQ4W3d)uxWN?_M<(x9;%^d_+e zcj$>hPkPlL`6JWF4jSaxQdjJ$5l)HNxroQeA8{NQFksYm#F0M=mihC>;Ct`!{qsIP zzW3fcHJ3Pe;Nb%RaB$|?sWbjO*iH}0GyhgpZ4j%z`)?(U?30}8X6iN z9v&GP!7yxebaZTNEF6o)NRnV#Mi4kjN-2u0XjoU z6V2v`yiONOe5ESZ9Hrsv?T*RfSdt!>xv-jy8dAKhkXst-6qAjr?Cs>cp1IenCn6x? zkY&ISu!@X1dazXq^&1h?B~V{P`vyYw7yu6-VwfBZs*#8hkDD~T#q&GqbW2rlmCML+ zB4jAWgb6-Mi}8evCsk51Xr;tz7FVbVW<#{Sbd-t^i5M;5oJ6H$R?hSJvRJld+g0mc z!R=PsdrpvnkO1K{L~{@~Fsd9*RO2a!k=>-;R?MDJM_W7|lBh^Ff$K@SBC$0^a5bq_ zR63T{bBcSeg*x?Mh>GJ$l1ejdRuFVaDrK`(U3bc5*S6cuX0O*n5RoBX#K=mJtwn?e zo^G@GPRi_NYdxdcuXguaduSXF2B~m35se8rAxgnPkLz_F0zv5XW}vv|QsR7|N>(_Gi;c3tFaMbbd# z#u+2bn^Dn@%N}j?QdU1(+bcHq?KW!l;vt}-Sb_+qm}o{Ib7{^{GiE`pSp~Olb-g<3 zw<(T8HXsiW^0UbMa`zF@a-~j(Di!ZTX*AeWO2}lSTuvqljUtK+X|bfk5ltTNCSyp9 zA~lXmB(fRga{lpCN5}8n`+@Uk<^*{9k6)L3^25y3$@#}WT)uI7LVNUq=^MLh=Jw*D zz|23^>N_X7#UIP~r=Lwcc>J%~myf^D;jbLIxDq;i{p;tnPu8EQ*0 x^V)0n-Gv2b{p{*d^%~-?zux(Fa{unX1FuBVXD9TfhkQRUGd(wT<(b8|{|9~T&uRbw literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_diag_3.png b/resources/g2/track/corkscrew/gentle_up_left_bank_diag_3.png new file mode 100644 index 0000000000000000000000000000000000000000..abe3379c706682bfeb70d778b0ea785d83b757f3 GIT binary patch literal 1118 zcmX9-e`p(Z6n|~nUHWUWM2&d5(*<&jV}|W)PYrmTmoDwD>($;QV1($d7+k7HJ!cp} zQyL|$soWsLbW2MZnM8>*uukHPYn0%sM0V2(DVz{AWl<{zjkRi#uNi~S`}NQJz~}Sc z+}NnAr}N%U0O%PWa*j9aKr=|Ap_yk7uj~dez}U#K!RFY~($d=6YA_hu+S=ON+js5S zg<+V{Xzb|duvo2DnznNsD~h}%c@#wshr{uBGMmj6i)*@GZ!~B-unrLTE|16T_Y;Aj zJrZ@q6GA%c%@>rC7OhlM9EG_ZT{3S8xd~MwlM1~Y<_d9lDJ$!%k(!>`t`}W6cqs_5 zpo&;p#tKnWIc;u~a8$FSh8OLq2otQF(zqoWl2wgl{I&?qNM6-5iJXpSz_>ji;B7(X^G1#q866Q zaiy9G*9-A&ErY5>lbInYH_iB1E+C3gNlF9)*=V$oOlrAYWo@lquOq-^AmbRFHgS1e zEK$A+7pZzuwLreEt~Ii?o$@y7qD&^nVsQ~xk+Mq;hr$aHZ*y5N8;z}|vwBf$R9Nux zm?D}&UPAR#i6EPai1~zXH4`cq618%%(bz;RfEz#oPysRks{mCDP!j@&f(pu{kX{x@ zkZFjqkaK}901^So78IpXNJGlxf*GV%l1m?1vJS^cC>7b8SL;h4Ol+VPp zVy31SQKQ1}Jjwym0imWBktW@3;Nf7RT4fUP+fYg+&f^jNekmA~X?vKl$5}eV(FNYV zCQvoE6?q91B2j`yITmSr^Z1$lUBBP@fmg;yMHslb{(Q6V9(Eo&HZ=F{jVJG(dEkyW zpW80!a0x|f9@x+gnZ_K|KlW8VEUI00BV4FvaiJaNHmWlVR2bp_WKAHEp|CMAa%z z1;T7FB7_);h$>`Eqhy0o3tYzHa~097OSYE?(Rd^pW<-*g>A1ovSs`1Line0An&ai% zPN}t1^|KHVA(((r8VCcUi@|7_h*w#~jp;4b>>3VQ6Ucx}^67MIO+G(!C*8L7RiXrFe)!(rT(&XSAG z3Z4K+1f&F!P9al3b`sUI$TQ(a@HFro!~`rU2elNLGomF^u2eFvYjrv<>TBT%pwi>4 z5fsdjWD|Y{O=n-uyAr#gu_>Ve5FsmnVFtCHF@rj#?&pDdnOLA|AJmW_QvIh zKOCNKeD==QtG_SYUnhn(UEhKI69?x0#jig?U47x=nX|8MtR6c5!}d>$s~aKVgG;wo z=dMle|4P61?njruUwzQI@X5#RbBlAop1$~PWuO1^<$ngw-?4so{I|`Y&#YHYlh3Xk z_c{EbFXo>QOw=Erx@&3c&&k&wn?MKOTKccNSewf&d)ku+AHpv!E$l1Y{^ju}ya$%P zTiz&ab>5y&-uG$q&Fd>Kn$JX@-qN=>{~D04oDGcJYroug12acvr&peO>An8}%y-JN literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_1.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_1.png new file mode 100644 index 0000000000000000000000000000000000000000..cdd60b12a518a176d91fc16bb9c4f40342a7c900 GIT binary patch literal 1259 zcmXAoe{2(F7{_1e#udiwOof8YET))4Z?otHj@aMh0~b@^0u2;b<4C&Ez$61+OGv)YuYaEJAD`#> zVp+4TdeXC#007lZOB$A!Yh5|aT1`1$o;+<301a5SbVXx%95-&<`0?X48cjt-MP+5> zgb5Q61kq}>6DLkIn9XJ!w@?(xFm{%83Igx*`9h&cJf29W2UN9KD&ZDDS^;gZays=K zXYzP0{(vKDiv~M;=J1LFR0PcV%lZ| zE(~}`ATdacM^XV@Hl{CSjIdyVB^Ml%AWWM9paF0p2(QzLMx%tHQLD9&ru*IQtSAme zA~2OQ;(9Y_u+S!}3$^i>L&RChDugMYY!4=xXvURL-6q0lv6-z5W@iZ}Pw{@*A8|zz zd_ob^YEUV}a-%673G@swxPi$FPzfO-23s6;rbu3K1ad;OD5YT^jpeupHeD(WK@tE500ICK05Smm0OSz>%c3dh z6`&l2YL-R;kAoly5;maH05Smb1{lC$l!gfoX8cf%g2&(qV5fkCMmW|Wda$5mi$&RF z(x)hLp`gIBm(dMyZxtyS=%~q+KzY?F6`gX)lN=3Y#u7Q0Euwlrm=K#q=Oj%WgL~a} zN#vqIF)0U?v|Lcru#_Y0c9;NA1rU~5_{(-rWb}E%`8*L0J&};fP);Yqaje(N;}#!b z36Z!=;VHXifW`_AGjy4th{7-q6C_mZ<>M#nt41FGK-=@(lOFw>xIEUE8-Y=KlGwkq7&F?`WEvzdP5-ZQDF@FR?h%nw~pT zlxFVgxIKT<`=Ohg2ex0WCN5pLeu6uH;NX-8Hx9)wm=;ItYJ|bASY73e1JCGMnU(B2 zd*->%?5%uv_}~^#&Fn&?za2Cj1eQE#HD-TnV2mh*I{_E@Mo-YTN=t7?aw{+j#HLYvS z;r9P(=J*0nRXx2b_RrZ>-=9z>Z~AQ0lGAU#+`zAQ$Y`(NZGUA!Vb81e_d8C49%bR@ zzpDFRGon+^Ylkn^)}5S%arJk)hcNB7WBk!mCzlTO9of*?apjjSvDVYIM^CJd9O>+M zd+Wks^N!im*Q|ERhTiV!Z8Z;Drq)&*{$Q-Lw#z+o@vZ9pD^In|x$)eGruz2|cK5g3 z+ws-M{PcL}_D>txOIMHYzBPxN`y-5RI3yl>V|49rUGqQs-O{v*@9UXuIORXAjo-X> aSNCW*`Dp#EMN`VeKvQFL!w-vEw*L>Gj5inn literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_2_1.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..0cb46c551926358555c122ddf35ebcc04faa7ad2 GIT binary patch literal 1043 zcmX9-afsV=6n=NTyYyCOVU<-a(m~OHnTtml8D`m*cWou)|COE3-n7oEE7V zFuG1VjZ#LD3I)T~KZ5HY#|Ron(Ww2SoS9VYX8x$!X_XU-7AbObKQjj3dyns*_wn() z_x9RqdiSpTb^*Zdl_!_hgLxpRz2Q*M&#pfAH9!c~jviYM=+xBI^z?Kn6q=ctnVp@T zo14QhEF2Ec&(FtGsT4(#9LI_xFUwg~RdijiR_o2C?YdpxAC1Qp2`mEwAIWB8`Fyfa zBuizcS`!*g$!Vz_uiPJ)9D!w+h{DIUOwy3?x=L;8T&tStG!?&H8v5pBk z5V3}WwaU?6BR1|N(2zu93GEmNxhVhvK*BI38r2dB1IJB<*%X9!F4xnv?Rp)xS_vwa zV&kNcWF$PT5E+e<4MweTy2V!<(dXf|u#6!YL)8RF~?uVtbnFSG-}P zKWRl-h=~x-L9z(AfzkDNx`}67tm0+LebpQpF4`1`m`o=MX`-BA8ZzgoqNmHfsyeXr zQL8%fEHrSVF&ZZ_6rE$af+&_{xmGAN%jH(R?%8&~+Z~NY2oeh5Rg7vxIVT}@h+Lm5 z4YKC2;Eas!xH;VEO;Ci0M(KDwolJ=YDKm`93neL7R&16l?MBmgy>XufiN{nis!2&B zPt=O6RT7k0mASy<>Vakr9d!98MdMMCJWHr7`~c>K3(rvmcD%F^PoL+@^Vu(d~jB>d+1R`cS&r=<(i{FS@+ z{Bw2TrNbK+i(lTzUORdA=j6-u@fDW7QG0D=VR+)M>*;f1`1^w&J#~3A;_za3zjse} zVSoM6n;##K{P4_C_447*LcbhYIyZTJ>FTG>A>{$5{NnaIo9wq|;ECw-?GG;;;0_<0TYUD!-=Cjxgnja@UtisNKmUr`zW<+KZF- p^gkZ@@3C*Rz27a5Nldobo9BPu@a})>r@#!XEUzwII&$)j{{e*m#Ss7i literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_2_2.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..1c5f6467acfe016cb1a93eecc94c31bcbbb8b156 GIT binary patch literal 996 zcmX9-Z;0D;7=G_>?p9~Of^kO3pql~XC=w+|K19vkx-)V)FDJ$8hbVz7tOr4(bkYyu zj8Y^YB3GnH!NLMo2(IW&!pNW>0=p08h;l;JfEB7%*sv!N4!LbVGX~H5zC2&v=Yi*a zKUrHXoIdsBDF8UVa%pKjooCW|Y+)wtpC5g^3orv~uWc-+bZTm9dU|?hW@dJFc5ZHN zetsUqu!V(%#l=M;m&>tiUK9mIkueH^>TldwR7%0N{B zN5MKe*0b?JC!6$1G|r<$MJEnIVGckBP%%u$ag!t+ns#}9PnP$~<$-D5ZnsgdN3z+R zK;&hLSLuSz6irrhc%vm+p412wx3Btfnc~QNA;&9>q;Vx()a!D+t+svLkIXP`MB~oz zxQ7dnRe&f1RRh|=xHeJf(xslDM@4&RxDzKtdoq*NII>z`>>}UM#K2G@OB*zek!MYM z&Ev>JqY%$>G*e``vLIF!#n!Y|wc54qUb`Ln{_yZ{GMOMCb)cIV+rh)P_PzFkjF~`RZ-YlS#r#Z+b{#K5ry734pB1XBnkO|Vn8U( zqMph<1ZmY;qY>9?K7`Tli=~oMsc5yD&gLyH-xOF+WP4KnP-e!(98xJ{(x}BEUqF$R z9zS;>^Us4HcyE1GftUXLX)7hWD@!kLJn`B4-|swXoqc3>?LHcQdDs5;m-R~*m;IeP z&)@p}gU)jwUAVil{qq~e>&rh}e&@~eOu)6L#Va=sK0Q0Qv%PrkUS{+4r}sABrM6m+ z-}v$J*9!;XIq2-3c_xg1+h9gF-~JWb`AS{+mcIWg{>Szg!NsK`w{WnDuIA2PbrRz5 pr|vCYPyWkBJ6qC=FWj6uy7t{)v(H}nCUplZ%d1P*UU}=o{{hNsuT%g4 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_3.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_3.png new file mode 100644 index 0000000000000000000000000000000000000000..2d731babb0cfad0a7bc04e910670f1a51cd0510e GIT binary patch literal 1265 zcmXAoe{2(F7{^~2>;~IXMujexP-2N4JC@E|@D?s|j2kQC%x-XKfock#tYL*5=Fqwn zY@lkv6HY9qVhIgasCpYURH#r~!!9zk;we>1c9@#gteB|<8<_&;wS?sR{QBql{_%O9 z{XN~b`k9Z;1OU``t?F1?sf#NyucoS!TNVr+1E31@JiTsZWt=i)%G9Y-tE#G|O`A4- z`t<7RY6L-QYHDW8m|-xR%@}5-D3WDqj&leC@Avydp-4QQRFtfymC9wz3P=Jlbgjdo zce_mWu|x?X!7w8(SI*~~ zh(usIZN&6u(qLswgwtZkO3G0pnw2a5ko<* z0Ocsua*PG=7zmOeX#*MqAPXRGfFcH?3{1LVCIGc4cmN&;GzIJo;^quK4;qwgu_%{H z`Bhae7FAgBGP(ffttBM`6E!)L7G5Kyl0zu$;$f8YThM0E875fr{Nj8U5aHp@4@&4<%$Wl*7Tg-JI9UV^%+I z4Uw2kVQJc$WzeGC44o$Ev%oM0lO$B>%JJhZwYMMqz|OVZELc8%y|>awx;om|wHGqmocXZ-?GgXV+|P$&sjRz!{`35h=~8KN zpv^HcchGvX)p6ozqW9RcJJ;ereDU)0M~_^x!3})j{m#UIj1?Nkb_+8<{cU{rM?J%X zYf=MZe?7A(f4uqbKdC#B6LZc4FaIkQlUHxlS2x`i=(2IEx)wr1z8_VyjjuD(TS*Q#qBTgR_A zG7Vq0AMa~EcVxKkW>az2{6F?IfBan2>{Ev}jX7U>Yjo)3{ecDCulNT3f~fR;Gdh3S z!s?R;UOlbAE9D){jXs;Z_sR0M0peM>ew)zQxmw)VGWU_Q>+q#p+=K0N0tB=EO6Q*8 z(B9{;KfK@a>8JmMqf{-d0RU4wm)lp?>VjI#R;y|m9sJ}d04mVa)!SYh>+0(2>+4l2RYOC=q)C$+ z8ygV>QLEKWO-*`}$%LX-g1~8-WLX!_bAG=+9F8UusZ1uXD3xjzwF2A*D6-k*(s?{a zug@9?+QJbkmSEB{pUnk}C5f;gPFpia>IJ7!WX(|?9q-FbKkFG=jk(n$42UHb7B>Zg)WtMx#+E z%LY_u!u3|lXk*L{&f*kMRI%{zki9pFEmA&bTn6DJiC}0jmQXUe zY7qwviSV>WV2q;267k{j0G*Dw2jfCPj+6_TYIPLi05}2Q0T2O*1270c2?4Msihw>I z#wDl}C^O(t5W+#q0Tc>A8bD4DgD8|JnDW4E04frA1Ret<0h|=#VfBL75)vITiA|^d zxm>(l&cT|O!3|JfGcM{W$;hP4oMICzu6Wg(9uH?HQbky(m~{X%A`Yv@g&RFI>T{E# z;E_T?Iv&bp;$AP}$RMK{RJb(P!;?dQ}YHHDDdsoxkvN!z3 ze+$Ujy<0l43)0tE1(Fy|c2TeCR~x{ij|fvcdj$d-VO? zouiYdHY}dIXP|G&XWYXBXY2pIIt~2#=Ivqi)rIoDb?5fpZ921Uc+2LdxbLB++*u@%wN@_RTFEDUC<_9KC|%86tJ#-V zSmn#=lRI~+j$GTOoxW#L+iMSkg^_bZ$*~nnmaOV8pF~KquUJ_>YgpKwTqCxgzvFdo zTIslVqm5gYKGW0jFyHs@$h?b2X6sq)59iN(^IJ^a=9{=ZbJueZp8fgIUr=-N7zwf#D$v>9Z9lzi-R}PZ-h3>f literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_1_1.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..8b884d17a174c4411ae5d81da557df12ea0dfe8f GIT binary patch literal 989 zcmX9-QHa}g82_%lyYzOR8TO%I9wKxQG0eiE=0+ZJGk4S@av95wqMb&GtPgz%m_e03 z1T9)5)95M&)T-3fyPSQswU=)5^1SaM`sQiLf20CmiY;GuhKd(eNR}uR^PEhJDqGeBttmA-O2^Z@&n2?;OlbOP)D{taT~L~ zJr7+p3GggS(Itkh@Ip)^mT#?MnbV21fU6h(ivaH@STZ3*d3c`5IgCb(Oj2jARRq1w} zcbl@`t_)mb)NfBmK^z|;9-suE16TkqzyM%^0ZJeVsIDW|LD5K}Kx3fAgI9z|0we>{ za>!(mBO$MfhD{VX@Gy85L;*??R#kIGjc!@RuA};XBMjZ?G(?FOQ30mD%3C?fAr+6( zBF>tX-MHq@?cuREMxz;(1(w8$1-#6YRhg+*M9Zi;EyH(PVc<@q0L5cg6p;rg0)&z* znu**a5RH0!GGW{HBk04SP%g{Ws#>pWOrgORY@TrirY{x_C3;%QBZWi;h1v}Acod4s z@w2B_??3#3D;IWT*tqxG<%F2qo9A|){_KZq;^W^x^_XxQ{rW`quQSi>`ENcr_woMz z2e14h-qEjaWz;kIjZ-%lzBoyLcZBbrO8xWsH|b|mFZ}s?^mFEQ{NKHWz0;pOd+Sx~ z(){k1B>VN-0{hPJ#`FHWXNi-qvDfcja$7fRf6wk+{wZY5=z95d1b&w0YlT}M_=d)uxfVw_P}^Wjb74~+xBrn$Yd2L^N3pgg0lK^HIYJP6=|ea|lJ8BmAA;dDA(F4xe|(D3l^ z$jAtWVWXp?V`F2!Kp;SpA(mwXffL23qR6RKDwiviN@lIrwC!HMPlkY@f#=-Os8^Ek zL^71l(78NcEX68SrD0{-9i1hx2kzeuxo} zU_cYFqKs8Do>tM@Z}?F+g!(bGp&?WY0Pp}Y43j+`)$iAWL7k?{JYSE;TdI1yP(anH zpY#S8Ux>%)STHOT5tS4*TFJ91gUeO~y%96*I8OOP;Q%cVoJd7wR!;NjLaboQrlr>G ztko^H*Q*`|yaM>*fF~iSVN}5vE(N1iMz$iEwxaj68Y=UISET%jFp-JSMUky2f|U|m zIi+Kydez*zWuQ*YOTW>B_itrs==iOPDev0=7Rs~7YFg=686C(7WGKqljyrb>ENtr%IWW_0Zu z>bEJ5Lna^_5E^8W9?0E;Kb6dPI#fP)4@#rKMx%lxiOHl)hEh~0$B+g~R=H4Nt7qjTQ2- zZC{@_Gr9S*iPPV_S6*2>_0`18=Btah{3lnw{N9*y(v^|p>%!@dd}5N7gPp{Q02| z63Ox_YdOjB?lb3?&Rv@RXyHQpg>Alq^!)NKT#d>m1UKUO!w}JNnMlpVvE2E=STQ@X5E`|FjM+UHZ;z{_Q-nyk{`%*AlIMBf z4|=-YGiS`50RWiUwZ5abQJ-qWv!<3tp1t+U^8mDfo>%)i8)H*bQ*(23OH0eNY15`p zpWfQqiXe!|WHOu0R)@nu5Kfw=IF8|YuP6%Pa5x@MrqfzBn=cltwHo0Blnby-o7Zaz z1nj|(GZJ;h6KpE&%jjaxh?dFiw8x{gx7!U3xv*h2u55i)6Yr!lWi35F+H5|yf)g(EC(;YnN2jYmDM6i;VF z&It2`xL8)hRXtueR9McU781if1nH;fAjd^{J`oJ2qftGXG&HT0&sVEe2y6nt;s}vK z>5Prb;r)z^mW9&M*jOrE%o?>4 z1$+!5a;W69%K0>M8&Uvx01yF?0Z;)L1E7om*Z@nzkO)-; z77Hu}1Omh;pt(Vj1&{+!u)-(-6&7j%n2W%o0v;Jp0)_@2776fHDTv2pcS_+inXqA~ zm5KoyTsA)-LT!|6Wfi+m!-S$su6os4FjJ4`rnC|)R51%6?TFindMSH=BSL;gmI6vl z%BV3Tt5%9xSSyhX12q7P0K$eBkp|sk*utSixlAVFk0IuAwAaf80(>YW5Y8~^j8lY4 z6FTF}vv|ehfId5vFqj~qMnQvV96$Md+h31<;O*XS4y?I(ZF{5VyE@kPz3|bVL;YWb zmzv%ifkRgp_cIer^6r{bS4GSG>q_$Lr9B&3=WUyPrF-hb<14P;Jac;S4}n=5|Lt7v zKh=8!H;o707#*D1_RrqepL^!y_MJC4bk&)2=5LN20I9yimeX2QS~1>}Vb<8Iw~o%3 zxa1s2jlJu(jb2#CF_XJ2=#IOy2A3S)@XpWo*Ij#JnSN0EzIXR`U87wm*WWXBR{q`y z%CW)mR&`^Kw#PELYSF>BZuM{4iG9B1YW?2oH&@R2__IY%N6!7W>O_Y)q`yW^cF@%7 z{R{m0m;DPTe*fykr<41VJ?hEJ{o@l`E|?d*f4}#W_UQE&=WNSY7y z!Lx&NS8hMQciO+_1Qdbf&_=Zd=)^JGMib(YS(_P_UANRIO06 z0-ZEiwnI8-vWi7-(wHKJ3^_-|5(_M$F{kOUhKqEgjG_xEQnZALKTAly&)YxG_m9u> z99-XKm|3}?5&$r>WnE)Ov92k`!t&B$ULG2_0zfHP|N4fe;wY2JN=iyfOG~Fsn^sm< zHhubZ1VPHn%PT4>6l%2^$F(F$(6o_Z%yv8LcDw!lU?d{M<4H-%<@2}}5PCovtITG( z&8BiVwH~kDAD}`JOEhLrh~9LDCo#mNuVRe~mr2DjnxGvYa+5K?DG_0%5l>d)3%R&K z2`m_J5P+kR5R1gTXeuPnCzLR&g?S5{;vkHx0iXb|AP9@1E~S#wXn4JTh@wWU)|AUN z84SW$Oo_|YghETH^cIbQ#Y`@o;q>+Z=?)uxQJPO!1j(w>DYXW*p2m!f&didmhw=n1 zL4g%SS6uRm*-*L=LkS?Kfx-$@PN3lsT~J|&Xv{H!6;0l>ozHP`I7DG`MyGTbFt14; zV#uhS7TrwBZ_k9?xtPBohG8a-%5@sdgzKyX>7Z#Z!vq|Th}Rnn21P+gCzH8c4gw_$ zG=2mRp=4A^CopT8^kmF@))CEd$$TU`l`6n03`KPcg+ZmJF)gFl+l`dRQe5VYczq+G zh!hv|X#!Y`h@D1V78Pg10!||Ap`!uoNZ6H%1+uAlK0gTw089Yb0pI`#126(W1_7`r ziiA!(4D(P*Q5wMFz()YV03-@P8bDS7y*T74DA-`a10^0j1+N1}5|}8&#wc74%*Po* zJQIz&MKPSsim>RVv;y2&MQ{p=S6KuNE9tqMIh=Py3;x8EkcO$8Mh4c zxYn)H`UyNt;xVH(Nnu%&8d_A)rGWt)3Ir65#pBm4ulnoh54_jWMuRnXe%o5?Pqj3z z-B90qyuWjx=Y<(P7vc5(ucns0TS582mR$$BPJVQs92b^Va}0mZdA7a3%zCt;wjjIw zUFV+9{T(+pF`eiS-3Pli|C)L=;{D?0JuMlPM{A6Qk|Gpprn6EpY7Ps49) zo5eO6cPg`W`)>W&y69?td+*~n8|SB6=Wf}(^To4jYV4mYQ}vC)p|_f^&co2b#nD}@ z-DP(q#ZB3Y^upiky3xby_C2S5yS8=W6IsoM>zzv;%>G(==1~`TxNmg(jOY6vxAWT< zZF*30>~8hc__|}vMP=#1?AYbNw&BVeruF*z(E+q>4e@Ydn=mlAw0i7NP4$nzymR!# zk><(jX3xf3puA!7vupL=7y9Px$G*&*p0lgI?4myWh}#ugetpR1%&X8QnVG{L;fyCA&90DZ3Qu)CPu^ik^$B-yicgu3mfLL)Ts5 u(Z{_NKYzd_|3z2KJ|4NVW8&nh|6~h$3rjZE?yV?71T9T%ji(zn@Bbe^nKf|$ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_4.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_flat_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..5551b4b43a8a699876f16b3624f1d3627acee1f0 GIT binary patch literal 1278 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_2_1.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e016902d7f0393f4255699337c8263fa82a08970 GIT binary patch literal 1024 zcmX9-Z)oFm7=HIR+jYCbRVZ4udc{QzTMi@UG+^$`Mx8m9b2%uO4>=dT3RN=6Ns%H! zixlmLY!>W!g;fYg!FVe;B}mZ-6{-}MgTd92!yZriqiWXmKiDp-}y=;10YINQGfEUMR`ovO=?5=`@;N+YS0G$ULTrQC&_N zIiglzt&-TPWjmJMb85q0I|vRC3y=ZO01N;NpaU?#0EG}ZRM3!RBCjXlpi)p_!A^rG z01^SIaa5*|DIhzCx+Ub9a5s1wcn&fGmQ&(-o~RhM@2dSwX&aSnVF!ebn>u7|=;9O-3a)nG>l(mN)dAS=W6oG`srI2=Yr{W%w2x$tNR}Mec`2`Ilq2s{@RU=XRfRr9rt5vC)e(` zi0^wd-(KJRu=6vq^~BqYGqc&v(ph5ri)SBv`jb=aBK>M?Zsxm_*7N)HACb(~e=oC? X|H~UoTW@_9I)~+@mBsBBE`IPodtkX( literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_2_2.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..651ebb0c1d8ad1af682f5f33af7f9e79aa3d4cb6 GIT binary patch literal 985 zcmX9-Ux?du9RJ?m^j7YocG|JZB6OIC-~tOHY92Dp9res{8Ox*(eTWdT4^;z~9TkH{ zS0s#pLF(v3k%B>ri&*d;f)|UD-(K+}zy!{QSbg!s6oM($doM z@-l{DnM`J7WhGxM78!;X1YVX!Rjuf{)@U?Ztxm7!hv6`er?VMD1J8jZW-FCktwz)h z+OoM;Tk7_dexMH`dpvOk3M+G2P0X8R!cobN&g?aWpj969w0Pf2V)tkomI|OyQ0Kvs zv95*%Ha_a+W`hDsXf#vMv4c=p1dsp}4AXGjEEF7)bUAKMlJ=|Bk!jxPbWji!m|T(1 z(-OfcWJ#mSCZjr>-WD33*zC*hK=I=$!4~LJk&`J=Wh#z!>V#-dqH-!*sFx_a%ym_vugg(G9kuj{*O&&a zqsT*(5YMqBRc6>KFVtn(R@HXB-m~qX(}{e4JRDA^Qv?MK$QH(QaiL$32UK+|Sd)sI z)caFsIO`?Hqa&21aGcHOOGHtoXqDr1QL>bDnbEVG``um~Mzb*wiiqhlZYqRRquK`V zS#rN!-S^B<&`w6-Y<36n0A&Cjzya_8_5mgspcImT3>|qciboO&8Usxp{1U_xAQ_OB zM>d083HdcNuu$y6z2I381t?2cP0gEis_B%vuG;T6qR2~<2&GzuDlkTtck+@;C_bsh zoHMO>vwHuiH8}RiXf!2rz!F%A#w$EglNqBbI%dsnntiVsgHVCr{UYIV?VS zIFP>n;@5vJzI)-dEjVuoKcBrlfAzl|EV+C49RGRd?7wSt=K#*U^U98OPkt3- z_)eDH<-WVTb^f7SUt%xZeE)|}Kf0NmJot&XpT~zMv)z|Y&zq}<5A06X{{Az3^4pI; dcyD?8+=XKJ*6y2Uo=Ppj=EnB=XV1QP?SJRxq@Vx* literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_3.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_3.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d2c6ee7d479c67662701a6e81f74f09b359ad0 GIT binary patch literal 1207 zcmX9-e{2(V6o3198wE>Jv}7e#R<*>#G&_E!tWdYI$-?cMzZfR(ADt*2cQJy88P1hK7d5#>S?mrsn2m z48vMlT3TCMjTVcAAZ#>Ev8q_a_1E+rI4LRv8~QBfQw;BfF! zAhB3dz_MX|A!(@QOh~h#Du*T|gcJ(^1HfUJpw|aXCdq0|*zH3MGve_S0)fl%ILc;C zguy}?ZH(E@SseoI3J|`9)^h^!jq z3sJEw2P@g=ges%5qBoFM+(nQciuSQ=nCD|YUn(5V#^Y)_UCQSxl?nor0M;l*B=vO0 z#O82Mi4K+B3C)+ONcn0?n=DKq9j@1tMx(=QVR0L8w~J0D#MPGhQ{l)+GF4R6YKa2Q ziHWQ}z?mg49`jRjh|R=2BXXdSjcEm?TD^=Y02hD=AOXk#BLHO#Pz?-?{34PQs90dE zAP^9tAnkx61BeAA7*Uu&2?nLTC>KJ-1l%>A1SbtH2J`a9fDeyIj%0$*WP++HYnqB` zTqX|?ejOzlnS_~3TZN)ss<`EoVVLDdrJbfPq%A|O=rB2=Th2UE}=E0@Vw^d7`qj&{3Qub21x1;Q32ZBdGlX(H>i zNSv!96aox4MKk)jhZWb0_99vuKUs>LSQx`lsyH#B<5|HkP0(K*`87cc%ftrdRUeqrNLw(j~K?&@2!@&}VI%w5ob``5Ae zbgyj+4>pf}b0KA$9p6~@>Q^rp8l#W&K08i&53fEp+}x$^`g!2__y3-U&C!^>Eq!Ct zZ5NMk*z(`@o;CE7U9&vn54NxESU>aJ?cNJ#2DS0MZI7D2zOV1fPVrFwB@xrfr*lTDjw? z;muR~PaL`ZOYZ~NZ(Y4cN8Nz%;Rihj7Ofq1i)Y)1H|S=6{>A)bi`ZEGfpuqgE7RlW zW#6X0PtL{eumkfeOFxR5R$sk!b+PG7nEB~m_l+a_3tipU@9a69^hR!=L&`1V!MA@n Vx8%z4v6}j@ytBLG@Y3FQ{s**P9M1p% literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_4.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_4.png new file mode 100644 index 0000000000000000000000000000000000000000..39169932b8bab1d7f9b5aadbdb0fa371806b47df GIT binary patch literal 1298 zcmXAoe{2$G7{_01D`@Mk6&+I+u|1V7r&4=HVwj%mwZ-<9o_Z=~n4J@qq%@x9H0X$u z6*taHAF*XE8F%wp)S=bEu8Ocq%GUW;#bIcHOM{4rB6te*N=&|M)yl z*P2%2w5hYF0sy8puWndZthL2hs3dkAe4-t}x||F~KAom8=@QT4zKJ3`SY>W{%|Cv^&5C zqFglP6eVve7s`ys5dtU~pt1su186;ReL!W5Xw7kgOPPcWAIy71c#g)D7QNbT!~~Ne zWFccblX6+oK0X_E<>S8bR2XJOM5)(eCR}eNNISy_7K`6*j|f6M5J*L%nc?AlJ`aJK z16rRP4w9JLdHm zLqSU{=1Qf)xm*esz0_8KJIV=6#E~W z8$MjWy6eOS(@}A5#lu%7p?syVwvcXFs@nYJL(~h9$1^+m+`xsQ`!DPMsooL)?LgJL@#^#6s|MP87Hm`gw4{}&sk~O%o(L+o z*C1b292}iheUg1=sPpi}qgCqaFY1UD(|cdky<;$?oFjw$MMHa zeKW7k-+ia8@xj@$!I$07&-}oAKREa1txvz(dH_BBw|)7pCs%7L7FP|-{#iTl^kaZCX*W-`PD{v8sQqqW9v;Gmy4>UfpXs zs5!Ow)c#LCIJM>Y(6hVUvakND2uzGE8Q47bf~@Ivoq*rM`e(A+`KJ>|PoEXr_^4-E P5iDqKY;EYT-_r3v*aahz zRGGTPH(PS2tM+`OA6lcaBhpxbPwNtH7D!v8+6H@26a8kP-_@hT`Xq8@(;!cPN<&2e zTfsUy=3ALzCmZ((G+|Jzq9YrjAO|1=s2HYaGA2RT6y@;zfh-@EN<-6p*lr`=C)jLG zz!{n3RVuI31(Vfm-e`$6S8DVWr>}ZZiR1_-pW_u;(zv27>UFu^R@n!bxW| z^D_cu6~IeCR)MlHu8rrrRM8jouwac0XKDxNK&G=AM^y5(Rp2|C*fW%{rVX3M*sV?d z<}7s4ILKrO znN)gHdk}XgN5dIP)0qs1<9RZt(2U0Oh9uY3WLdRqH4Z!7CyIQR_KPE?>JhoR|`XTG6_+lMU;T8rUe_99a8lu zJ>u z7WG8#DTrFNH6C-V=2IB`zE~_O<+4_->MT>^n5MwGBI`@cK&B^!98yVSQmDluPe7rR z96$F$`q7gg*xT7wVEvz8-$=+uTbnQMu3f!x6;;Ef8BoR%&X34pWmOkZ0DI1Tbn2MZrrl&z5d%z_V=HhetZ4> ztN*Sxzf5gE%5Q!1_?=JJ%I{uWx$;GQZ=c!ucGdXf(%-qW1@6s_RPQ?e^S#p>b@J@j pkMA}f{7wu19jy5u$Pcd1fBaVC&l~G|gTxzbo!j30ZsXE>{{!-ot-}BS literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_1_2.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..8c770bc14f261e292d34dc35055c1769ddcbe5a5 GIT binary patch literal 1083 zcmX9-acCQL6n<^mUfNm%=8v03j2iU@r=0F6R~N=ruO-Iodb2mkAm|AoveTi8E8phH7L!^6WamuqBXWOQ_N zY-|j}Ft^)1K0b~I0s)$)IF1!XUY4V(s-#k>T&_^57^c~@ZKv0xDPV&j@RQM~Hy-yV zG%B45=JGDw;eO&1BrwL z3%ZDv6s(rPe`tBV+~u1ON%c6pttA^XUXp3Cwn~vik@F_s#FuLU7sy?wn z#@bxE6D@WVRY!03D&2l-8%>fP4};?&e?TNDIT%!VAuSD-X_ZX2UaHup)oZgL@t7)l zl9FGKlX;CTr^RYMRxc-8wS2c__IfuF3lITN0d#;eKpmii0UAKykfx$?5!o$)0ELDu z3q}ZR0gwnt!BK`rMFAOc)JP+{2)Bc0faf40U~w5wCdjNFDi!5wHDy`lZr4HsEnf_1 zZIab-q3D+kLa~Fo6D{`=)$LrPZ?sX%A-ur&u@L2nvi`V8YcXC=#*5ixwVbuga@RId zug&m0G630t&>)NSK<*BFDJ|dWF!|gasEq~}jf(NOtZ52Or5Gy5(q)dW@l;bFyO98r z{3uDFJdF$%S^VJmnI|Uyy!``5mKH^r-TLX!fczewduIR4JEy-3-(x;_*U0RDXgYtL z8hdqfe)#fxYfBrnvG()#Zux<))Vm*g)46qVJn&0u=-sUk-6tPAu?t^a2>RUGsZ_ZrVv3tH* zafs)eSHFnL2WOY2H+FR{@yfj)6Q5pIPgM7!51ii0>pv))>8oV*#iN%lJ}vxXZ#}xx zwYIY7!j2~;^YqFaYHYddt@}6kJiPOTm#ELrU6_I&zfGJw6FGW(dQLg({JK1=RkU08 j|8ej&OFGb7`}-8G<^CnFd?UR*Fb(1P#ko(OefjwR@%h_S literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_2.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..614d3002c8b3c44d605b67200c71b3b3dc99c221 GIT binary patch literal 1143 zcmX9-acCQL6#i{(dTF~FB+j65hApfo93#`iop_E@uQe@KdhM?EhSA-&n+BWdi8l!2 z+>R~7umwD4l(5E{j;lm^vcpxE&8SgMRwe4evXN~kM3=gNV?>GAVa1;rgYUiXy?@^K z$M?OXW251|p8I~Aq7lI&ex4XN$+ZPN5aXduR6vr{57?EWukw|1RInyjyR>g6etri{v6bV?SHxlv2 zVu834N~Xw6md%?&u_Tx6RIRSl7{Zgi65~_(fF`0j8DB`yr3_y-C1)|&aP;M-74`!G z191vy9FmuiQp!`!ds}5cY=mG-fGZk=RuBLd00BWHk4N?UH5AoJa)D(RqtU9W-pJ)( zspQAKLCP0m1Ehe4C5%^bQ6uFnoiLbmk<-gU!HEV4e<&OzIgAmBh(t?CHklK01*u@G zmXo#{`Py>HLjf-bd{Gck0IDHG&KEY(NQshcK2?+Tre?tf7W0aPKOV+XJee2iqRiO| zv6_+VMxt5DEZYXGTOKcgVmwYnDLT$^DN)SE<7O&V%H`}rp;oChn@tG(5sa0BLW2L$bdohoP@cF`lAcuuSl9U-XDYTC%W-7gyHyz7v)hHk^ zh|GCZA)v*utU?({u9%H38fvwaZB(sR>jtC%-~o^U&;T$1SOlPs0N4ggLq&#$4xK8C z0tp9c3KYV?VFBa-lzcFSL!E_%7%V5Dql4SV6M&%s&mu9=r^d0g7S8Kpv6!%JqtUQo zTgx8>xYA2$K2{G11ypiKtr;;|@#1o(yi%yaY7_MWB7lTLo(L6)akvs?G&QED)uNHM zEu-OBuvH@%1{MHx0EBHXl5M#=@F$dPy-s8^cOaL`bR@#XVxpo*cql=HG8Asmc!>#B zSggSZp%8#73bQyYP|#-D;U_lr{(1Wc_H7&Gz?0W6zto;L4i7vv@zC)D?~K1?ZFUcw zgO|=6y|VD_nzO>Xq0{3VmGQa$gKyq9yJ79sJ$J7=xpM4W@~g=;r#>I*T#CB-`kf2f z`m3iuo?Gg9@a4bbC)}5|yfLypzy8_fhx;$id!skIUAsA#dS00%CVu>-ezSV~p!J$Q zH8AsOw0~&m``M3t2e!Uqoq6QlgZuOR{I&UM{n7Bz3){_$H>VFZFK%Agd;WN8XZ`p5 z9KZITP2=v0;~IRTZ}8R&na}>1J5w3E+IP=;GvUcsukgw0+n3EHa@X9hzow?2dHwJg zyT6=#e{10D9p2%R`26(Hhdb0C?)~>CwCDP)erW7*p*j0v`LVmU>@!b}?CHw2ruP4r z3a*=zYe%>V>o7z<*?sPaX?lMC%{UvMxX=y~0Kw Cy82!K literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_3.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_3.png new file mode 100644 index 0000000000000000000000000000000000000000..95e364aa3c8fb442b88eae34c687ae0e2164ad36 GIT binary patch literal 1329 zcmXAoeQXnT7{`BG$F5Lj!9ofvt{YXFd4Vd298%Z~Z%eloc9SbsQnbjyDil3PNvbr^ zN!6~Dc#HxaX{7224V0{!nbgohm9h*{;mih>(Tz@qD?*@=q9eThEFt+mZ~r{sKR(an zX=&D#O)8%R04Qs0s9Ra6wS|~178UXpujUj0BG9tjP+u5}ii(Phi$x+)NlD3s2@^_7 zOA!PSi^UTsPL!)uDh$(*Btg@9hB4V}tjp!{`-724G?5rcr*ru{rU8T&P zD6kWNqmdAc#J$o~NS043U{(Y3X84GMFrfl~0>F$QtW@e$C^)s6*J`^ds?TCcIi0tI zK^TuKFqw*wYbd4Gtk$up(TOpf))pXLVZAR#^GS0wZBgP1jZUSdQ9Xm3Sdw*9?w~ms zWut;Kk@gAMP-Z+XC4h_uatly8fSN<_pj;PGo8km37`+)ApW_m+n?hv_uCVJ+uTdLf z$e4{5TujPu8x6a1asRjwhNB6o3|FH@47U)Zou<7E6R_JOUT-`Y6r$10z(6jSgFwLo zwI9JkQZlBXlc*&_x<^fX)*j1o1NlhyQED7YP^lD`%XLZ>jcORJ)~2W2=E5>Z#Ovz| zMbZf&pCN!*kJxCb)2!sIXuv^)-E=Hq=?gnk@jy0}$mefE0stcbHUKyP!T|IEFp2Upr9`tKR#FT&$A!cwz8Q9wPROW3w@@s zZkeIMbL8OgzC@+?iyhFI434cbO!=?%?FF8NgBxRO);Besu6UvI*y`;0$LP@M+{KU2 z-uAa$Xj&AS<+$ZhzIJp&bth_>^Rxl^4jnUs7cI)pquM7Lq#mxez@ckex z{b*_5N##RHZ6bPl_}o)Nb4PatiToU9r+yPSv%q9k%)t*RKX_&Byd6bgnUmk2>M~63 z-o5pnr(fK#q;r?>64A>nBB%C#^ka3C+E8bPdY4)J`A&_i$-_M|Je4 z)uMN=UVV?5_M5o2V#VS=W;gxP>iN9NxVSoXc*`1I{H;f_OniOakG+HY``bSo>i_-B zNMqfh){2h#Qw}-y+!$_sa7k2GH??~~sciP~87H^9rppj&TFbikFVkMow!2Z@e$jFN z<+EGPAMJfHx%tkkcWeJ_ketHhZ`eEbE*$2{?scx;UEjRDcS!X8rOqSs-;uQ++oLES zyFXSj#i}3NyZN|nWJi1X%*4>8CE#M!g$*bFy3$}+zOnK0lIolNz4NVDdCk^Mo9-5o zB~8axM8(xCvMOHzUcWgQ?yC88T)b%Khu3ZeZak6i{A$LNLk8o93pJGwY7SiPvW#I> wy2_EN8))r`P-X1lOCz(c`JMCT9e!NwZF?}&9sKfMfjeldZ?5ZlYwfQ80XD8nQvd(} literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_4.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_gentle_up_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..f200848bee425b17780ae0753545c1215aa65b61 GIT binary patch literal 1328 zcmX9-acmNI6#lieUTdXj&@#n{9Xht%9GjO7Gpc93R;rj@?R8>hit~(2soqjpP+5jb z9aUy7hDExug(};yp%t~8ticUaw($o}%y826R@tNx*P5ZAlCIf)!{@)YiejM^1@=hUcoE&^myfC0C=EfLtA5UEh#A}EiL8ocx7c}<>low zX3Rhkq@tptva(Vnl}a&8P7pXnscBkkG%_}u&E@h00>MZm!ExDq9+LxH2}pI7Rx30Z zBxZ};?ohhiq%WWgg^jVeBbD|ND56nTF=~-jBVlQo$A}Huh_Fi&3ou;Np5eTOY(ymn zIuw|3z*2~hLBb9}(kINv#4sa=c^#Z)A&f`?AOX-J2qO?!#bQ<_^D32tBpKD~lUD1b z#{SQVg)mSl_RT|xd&98QbC~r&`v<$)6NxMhq z2{OUBHNrXL8DFXp7T`cg0g)a^EI`I03Xez?kZHp>6W2IWMsJplz(Eof(h9Lzg*r4! zA5DaeRNO`I-m@cs_*#ofVG9Q z^Q#j`+ot_j);>IR_WT?Dt`Aq7J3sYF(^>bAboONb{TznX{F~aoYI^;y9cL<3_3g*X zUbyhl#aV~D+cj%S`Mu|sOf`*sIlhpp8~n+XbmWI7=8lAYFAhy4x_TCWd+Ojfvfo=f zn^Lnk?QicMebm*yJ+wa6-|7`?9yz_@24%54xK{mJ@1C32x3=3lO>Ny{Q}d2r*yHK2 zOl;fn_uGAs_ZJw?#2+KOXW!nkzD8H4>XMF@-rJHhwVfKi@cHtKH(VQHUCYNb%f6U% zC)F~1vhOuJcjFgFjj;BB^i~w@7#*;zzOPv2KEv>o={^s51 zf_>G~!&|vp6M5*a>GApZd~-K1|1-xQik#uU`cm#*|2tzV$wDQ%d*i-ktw)nRecOJP z_22*Q%JAGp@2+}&$DF{d0Y_(`JGD`gJJ?b0Szy>2@*0SIW8k-x=t=WF$e^7c_b^rhX literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_1.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_1.png new file mode 100644 index 0000000000000000000000000000000000000000..160fd5113927fad2e8730120f27b5ed8af3ab74a GIT binary patch literal 1199 zcmX9-e`phD82Y@u8S?m zrsn2m1VLI_S{5x@WVPGv1mR#9n&(+Ta7&UH3K541sP*`%niU%$z5N7QFZ~%A^L^PXa6jd-RK~Ym2H{4Ph1l< zUCtU2y_76eGiDlCcwqGcTL54RLdLDm6z0y*qV5V8q(oWC!YK~72qfxv;$at+6qvNc z>p>wOm5OSxoQYO-6&AB*3yI+_g7ngipXbAZ5cB&};czA%*EOv$H&-r~AwWfdMG+!t zX3{91!@UJ2RCFgw{&ZQHtE5T``6@KwW;1EEI&F3ycL)?Ev0TVgTNX%#BQwdAk<}{& z8hBVl;?1(hrugt!fL23%I_8~G<$NYq%4aK;2apE91%L#A0)Ps@3;;z0z#2FP1|+B^ zppoY=AQB)#1I-Bx4nQ72(F(%^OmI;1!CVL$3Gmc-60i(#afnZ_%6>eeIFkt>oet`{ zS}N(V#)WzT5irq;l}p$>8YUW)Qg*8qf4UmYEocRpFJl%!+7PG1?51r#o(OnZMfN2k za$1e(S+!(jVWmK_EYtur0E9I!LN&T)K!br;u}H?E&miS;jN8rod_o`~5{@A0h|+}0 z5E<4n$KfTH9eQj~#$b$q8Vz-}cKqZErbkbIV0fUP2b<@A+f(az_4RBSeC6cH2s;+s z(Ax6>R9BDucXw6Y?_>1F&Y>4iUFmX+TvZRez6Fsx4*Uj(5}l}%X8}wKi+!gyVjxJmsU*E)co0dM-Bv5eP8EqxxCPuX`j5^7{D$p z>92I(ys2Lt`FNb`>)8M0@S1mzH2rXEuX6nK3zKCgmH1&)L;1N zSku1o8;Ac|vT5&%@v(z*E2%qsIuCwQ{pf2h>32-G9sal3J32AkJ+X!s2hbDe=0DTk z<9}ZN`DveX`fcvUZ2RO__dBc`%RAOu8{4IoORwHKFnjEq4d_z$*e!9kZKU$Xz`9pm zqYuwyj<%MrT;Fo&m%{E(m%-6Hr?z+R+_oh-RUO0&VY%T; Lzvsf%-5>rBt)~oS literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_2.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_2.png new file mode 100644 index 0000000000000000000000000000000000000000..0d8a707f2974754eb35ef7994dc506bb3fe631e3 GIT binary patch literal 1115 zcmX9-Z)_8F7=HKnwpDTo9aOAXlSZpKNMp`$#v&)&mTn$$xFhsKjmNk^qh(&kA&o2Z z5;~})({nahuwWzAH1lLtrZ#ZKqK)=LBNv_8g+q(ftWh9EYnaKDpCu&E`|r#9B+v7{ zN49S9F6+6c2LP504)hH*>zZb)>}qS~N&WSI0NP;d=577Wv8AP@wY9aat*yPiy`!U} zv$GS!u&%DI?(S}z)9EBhH^b08&x)d7mZeA}l1QYo*<7J8XPWg!gLDJ!0gko!{nlX6 z5emDbF;61NWwL^vmrF*hQcW`i=JQx2)~5Izs_06|WEP_}Grd?Zc4o?u1FFELV-i>8EBPRbcd z!HgTVOl2{T(_rPn763;WTq;JTY~HNPpQk0m7putWx>`W99AOnHd&o<~e4dQR=rV6a z#BxHeYLR+Av1n+hTEMN8i|~h(GTy9BNTMrLqE zxAP?;P+_7~f4UaZ>*`!1TU#nGA`5}zl+EUKIC;V?dOR}AMTO?Fa5fe%X0m3%XjEtr zSWM<|MR2G=A{nN&D6c02MNKK^leKc8(YT6e03U!1paN(BMSv;>s0ofiVHs&@WR^J> zNF>B*$a%r!0P%n%8;X%A&7oWnm7>T@!)@a!U>WdnSWvVnAtJ7NGig!RBZi^XY6fa@ z*#kg^EwpOm(hec#l1z_U_iK%izL+R2ud1P4-FC`qCmjSRMV{M1^@pSOQt-_RBwo?MvU-R!#u`!;TSXzI18;F}Zo-!*X- z{kUz1aq8t&(-%8e7f&8N{=7Ef5C%faH$62qZjatLwD-aXyS|>{Pi**(?_E5GPoJ)j z-du%-PYi7zee}rqTgMh=FKi!KeeUqez4VLM+QsPyE{Df{Iz4~uqx&|3Hdws5{j>ew zx82=;{g)>`K00)H*K#>|_}$0PtUIMV#yq!f#WNk(SM2M zSo)P;(54@bzcljfCq4DUdnzxCbq~yMUV3MF%gEVp*Q1kvf4=62eQV*sdk4NW&RFo; z2r2$?Wq9W4{pa4M-ar5Q?pHG_$JXN)TeWXC{QDa*`Jr^)GIQhSgRk^n**S6V7sJ{c ce~tdv(G!nO-s<)1O@&~ve@oxYrX2_W2N?nF3IG5A literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_3.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_3.png new file mode 100644 index 0000000000000000000000000000000000000000..aab7785f7fa114c167a0d5c1fd0e1f8cdc4dd272 GIT binary patch literal 1294 zcmXAoeQXnT7{`Bm?Z%iz3Y1Xc28A5jU>T<#=75{DP-@K%cVO8%EO6PX7JDQomT)0O zN+`3z1F96#Yz-Ezp+JQ(>ehu4J2pwtQwJ$>N`V56kWgna1E%~eA^ARU|2*G6KF`y! zve8gGZrV5iK&^3wzNuI>#XzdcirM(yfDwQ)u=1@{%Zg)3Nl9sGX<1oWd3kw7MMY(0 zrA#KPs;a84u2!nmY7EorbRqDC~B` z$!k4c!XKc*QENQGr9^Kg8`5cHW}=2QDP3knV9+3kb-Q&5zd03Ur6EsF3XSHI1{JVs zfRh9QEeo@LP z!bC!aDb%D=OCf|6HLx193u6R=3+UVtlP^w(Qr4JcLvWSWpeAUIiNP(bj`dKUpfwm{ zW1=f5`NUi}Gn$Z-KtThg4In%~1sNVx8ltErL9(LRo8dxvAql%Fje@~dPJ_m4Cc=y^ z&e5WqN&C5M#GOz0N5u%tCglno)tE8dM(Uh2?PZvN(;4-86TzSui)Ds~^Z7gkDi)xA z85Wl7;wn0&v1N3gtR<9l#`D5(A(|UYkHQ*_T#hT121HG3vQ9ZuGBBM-6#z$M2CdveB6b?% zZ6?8G5BXg2h)+yLa#9i&GPubEV*pA3!XgV#(e9a4Za$FB;sO6NajBHfVxjGJhUZyK z>&CTy5{u}tgh@M0X>w*Yv?9=j!T<(iBos}>fczk zaL*oJ?J22l{LXDKa@n;mH~Y2H@(q29=3Z(1^_@c<=nbZ4|5xiD&KO((Z$F%f?rS^L zK43mRb!2L8HOqUoEtB*gj@|p`Dt`Qn7Uh89^80UF22Z!#`IB>;dc?Or=<3}(!`nGw z$(ADrcOjeT)TJj&)^y!kf4#nKQ|G3x$0Zjmsk!{`tDiqIiBR1vTif6`zDm(Izt>a! zz>xp%Y;Tp~Jiqya>Ee~1#=GS1HOG4H55_O;pMI<9oWxz@+Yg+(ajnlgWnlIv3)?jE_*cd)#w_fw4?ngM-@fo=?nUvy!fd~K{8Fy@^$Sw{#M(<&mk&1G zKdF6rXweqp>$B5lp1JkSj}6;q?npN0UTtYde(t*4b+LZY%?I%(huRhr{ix;q#YeOE zwH|(VtAD^N159;9xc~qF literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_4.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_4.png new file mode 100644 index 0000000000000000000000000000000000000000..7e1768e6fb1c363ae39fbaac7c7dff44d561b950 GIT binary patch literal 1262 zcmXAoe{2(F7{}jjW!G(tCe~0~qbF9^NP#AtazF_;xXlhucF+S$tWZp49Tsw$YFg}) z1IjE=<#3fiCrw672NjBLR3}#Q(IeGS68P}sbe-EFyGizP7`IpkX?oP{&T`z{ zSPaUt9@82KotZ{0PNS7I**VO`Tf9*+C{mFW6VEuMoEydUW~;%%m?#(SU`aMahhol{ z#7YX6&P9}BB43d;1kf@-=LTp178wekLnc_o9?pB?B|Z%YX_MB4>wQ*J*ltO< z$ds2+g08IKEr`LAEL0Q`7Sb9mZZz33+)a=^h6%e|QJ*gv4$HBaB1!qNu~Ml7fu03M z0l^X)GNorSCU>3;6&&%RFID2l%E{t%wgQ_>8V#<~Sy2OHGP^7mFGYu()n$QXI5L_@ z=F&0Y`*a7eYzylxxFbY5c0kA5X zgaI!U<1m+{jex~KgaDEiy8KW`GB^0M7f;2HFDi|aqscgf44kp zUS8g{fBlm7-v(!F=9>#&_=#HZ)#$#LM?7<_FP-jLQezuBysmb5=hu_MQSr0aYo^A7 zHq}0rbnuF*_0B%zROp=N^1*Lbs#(ALbmwblu1uLU_{zO+r7u1Zj@};MpY~ro*>K3S z`om2ce|pQ#Kk8RxZtQLYJ-UfAhvuc~d)G96F=4Z`44>HS&$sMZp!@RS+_Q7Oe|&9t z%RntNcIsAf;8}SIcE0tr{{BS&?Vn}o4OG3ca*5~O-mnJ;>bCBoS9kR{Dg*r4-u|T> z@hd%@S3m6(zr9~c;r`9*o7CGjUKpC$dmz9KOK19eT3*3te|$tD%B_Lt>4x4eV!1H2 zBG`TX1B6K)U3#_QMy#%_d-D9Rs>jd$?LT+?{^aGU)zT*yZf<`t^XHEO{#W17f7Z!m zW^(JI&Px%WfA_q5Kg{{Xa(7_Wd#Bzx`A^^Cns;ZOdBnR9)2n9h_%3Tj``;heu3U&J Y@*G=7pU{eItwIB9JG$D>uGzl-f5VV1SpWb4 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_1.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_1.png new file mode 100644 index 0000000000000000000000000000000000000000..337d7c8969191cb91d4f6bacdabff051972ef1d0 GIT binary patch literal 1132 zcmX9-e{2(V6n|ScZexy;R8q2Hs`ihYT=XJ`9$3i@ZllbT9qtwyET$$GDWS@NCst{~ z5sGO{(F>GVk|HM@QcRVa5WPqfD{I0+YP`V`3%ig4B{q@3X$sab;@1+A&-?Yy`y`*w zd!KF?3-r$)m=6H`qw9vp+jXcNi+UXGeE#0z(*O?G@cP6^d+g}w=JFUEST? z^XARNFs!Gir?aFg`onlYB7zDfs(v}kCh}amDCm{2VMV;OhYa}q0>O!NNMfZVpVY#dAsMDp zw$f%JS8J7=47dbvN5C5gT*YY39Vpg?@`g0;%lm#;( zRx@%vpRh}rmYGNOveQN5M3AB*3>y=KlqhCnu|g_U(lpaBYBMvoZ6okVfM+l&=VXf> zp+ZDzY_cBG8?mCT&NK^+xoQjb5l$!Vb_cvZfgnY{U*`B^xVc}YYc=r zOctC<*sDf~Y@Ep_g<>``l~<~zY@=FkHg6*aAP67>r~r9@DS$c#s12S)aT(=xWL0?_ zBnr|D7y+<&Kms7ijZzfSd1ORUC5bE@9vM#q$3l?DqM}=g5otA$)5T&jVVe0y!$fT^ zPXwrVAEUZ?-5WM=$?~gqDBp|~Tbat7QA1T5cLD9i0;Dsn<)n z((#S);)SEr)L(D1%MQJ#tP-wG&rWV-&z<~e!QhYAS1x?^-{;nj9i}2@ItLH_eCz1? z9og+ysDp!tPyTr%t~hS}Ffopw-u?1P$87(T3wv{+?yckBnH~E-Tzh|F_`g-l|JgKq zf=dpJZ!9i&>#2Y}dTLA8%DVo}?u`ewNJQatSv)Yc^ILRg^N>_}X3;tEh2S1>=`HR0 pvagQY>GEFb>IwAyh_<9P#!Npvy%XED!rhh(Mn}em&#ZZS-~Y7t^0@#2 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_2.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..b1a3d038ec0157c9a1ca10a555035973d9c481dd GIT binary patch literal 1150 zcmX9-Z)_8F7=HJM-NrJjRH<4+)kaTp;t`KwV_REWdwY9FM@MI8=b}Z6 zy1KeB4D0Uh?&;}qdA(kWB3YIZ1Wpu#vMj~p@l+~f7Pw~hoDnJ%<&vdVs#%u60=`~}b14CjCgK^Hnu@cl3%~<}Fidhd6t`Q$@vP4`#q+b_a9L3nG8t4X zx+$lZagn^o7sCA#5l|>m^T}y8u5-zPkS&GscGyF^Nx#=85S&N{C00uCiA*Sym-3ck z+DWUHt2B!a2Al%8!r+Mku3>b>`Uv~*N89Zni20u&u)*r*_=qL_|G4OJ~>GFCocnVYNE>j>Nu;3NP%{7eLt#T9f5)KFLa``=8fgnYnPv-bUsI@F+sL9!!VVhQ?!a#__ zWWk|?JX(ZE#~3{!6w={YT`3pSwX)f0EFcCT03ZWs06M@dKotYj0?(qDjPxwB%RCMe z1xW_-ez18!0wBqSR0?Hzl#ifN0@+!(Z9EMe3jrRBh%O~cBsG67D;5fI%hGE#3$?i1 zVW48YjOOCAo=_f_Y@b#S>WyfjnJV4NS5Uc*JAw9Ke$o+SJQ0D4g*i=$WRprkPgV;IfNVghC_#_r4kzq3XzByi%Aq2r^ysU=`2;`$T^;< z1-vNaK?;u26v{Km;#$W~uju{l_7ChE9u(lY`5*SQ`X{&aZ`k(48)GM4xDa32-9LpU zKN@{S9f9I9_RQEFenq`xfr|B69is%dS;w=9}o`chXCRo)gB=bsNuqzy5hp zFHS$(*?iNKC$X4!;<3)?ju-dsJ^a?1*V28?#lTJevUJz}!HW05>2u@NY8x;;AHIY&&F5m{`bah~ HornJiq%-<# literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_3.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_3.png new file mode 100644 index 0000000000000000000000000000000000000000..5892859de0b5af6b4c88383ba8fee72a12d5acba GIT binary patch literal 5435 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_4.png b/resources/g2/track/corkscrew/gentle_up_left_bank_to_left_bank_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..f8cf03e89d9e1c171c4f5bd76f1155a2a817e84b GIT binary patch literal 1195 zcmX9-e{2(F82+|0Zl#QdG;p#Kiz%ii2cB|^hj!s~$LN+bJJ?|kXw0bx7A*4!hc;4O z14SAr<`NoPppZ%$Y32nQ#CVbl4cwNQ)p*Jzg&f$B8fqBQj7EnN{461P-e3Q`Px3tP zdtmK=uVYT<8~{K^f8XlCW?k5fu69c^pP#p~3jhmP`}+Fc=GfBG(%RZ;u~=r!n$_0U zHhcDL1VP%{+pShB>UO&c0;g$;;}}u&%d!-WMpLOwKCkKeq-oY04FU(07qE=Y?{@@) zu22|{#l5LCo68G@qFgfKm1>s85Z-H(7&OAW6w#BBiE~l9nBq%$$sCW>%WvC9F39_)^OMm;6nvM-3fPf&9-5zl|6^|$D^`2wd@j##)iA-fO zuvl~w4mXA3tjjBSd=kb-2vPCMX*#Mhi2|1`37Q#jkxty__Hq~_l75MnVr(oUWHd=L zBD$F{YPrfx(M|ye2had;g@H#w$PDVsd;CR8GWd8!&ejzjo?|hGNIFA4EY5p#B3+O< zBPy0ta#fAii>Vnyg;m||AUzmQkO7Jgaa>#!)1gp49xrAxhNe{}C+qb(1WpNfQV5Z= z(*-A2!U7dKR`q9Vp+a4mY~*VX%QMi1+3h5X`dn@f!$q%GX4sg}To%s96XUtOsT++7 z1q23>IeSEKDM2h9rqmc$NC(E%NV%A@0LTC+0H^?r15iZ(Y=Wg>ScYmA znq}4lBmyKTp!tBw0>}Xz431JDvm&=NULewzS zTFrn>E@uD`VH>5OY}O@c9?A47b-&sO6=qVUhgt=e>mCOnU5F32`zcqDBf_@J*r<>U12q6m0AbUMSd;DvoY8Q)S|!t|Cy+}e+VAIrK`|Vb2s}#SDT+{O zqR8NrELP*)P;kMB2c`+AQP5zT$4@S|O+WsDU4sK0c=h(Rcbomj{?)IoU-{Vw3IDg3 zm(1-w3V;2k^T?c~`+m!$ktNqA(0iXByL?~Z8Mt9%(xAM=# z0(5le*ryk_4ehly2DY?cs&v_gt@A2J`gY*^A8dG0TjN}FCAn|c{k`)qe0k{R2Hz(u z|GKlat>r?eC%JINp<9PscMl&NGPdU*Tcj^NPHy1$34f$_0rFSkyQ+<*VT%@sYp@8tp`)BUUVbI(6l>ghu^4qrc8 zLi%uY>PUCb$WL#Now07avvrhPbvikJqT|#n7bo__HyxWe_{;A`ap2L_u9FMW-GeFN zt4WR={JQ&+13kMqf2v#0B;BP=Th2R_WtQoK&-_S7|Fhg)NaOUT;-aSFpucxu^_iZx G_Wlp^p$stq literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_1.png new file mode 100644 index 0000000000000000000000000000000000000000..f8f4d3df6b0d8db0cd446f267580f74bf1e08d61 GIT binary patch literal 1256 zcmX9-acmQH6#i`kZev2H(-dh~g(h}V;Wo~A#xopnV7DCE;f_$TiHDw0LZheNT(>mg zfEo)c<{$-%DN;#I8Z2^=g;ee2Bn9VE;6fHC?$nMop^=3gTOkeG*v}G@@4fH6f8O`U z_q_v~I-CpUFP;woSkT_KzO%wDm1?c6sr2NYkp=*2z^09xH&oWDs;cVh>YAFGIdkUB zojZ5lym<(M)YjJ4)zz78HXDYa6h*Qu>+i6as-jBob4UR3qe=Bp@1X+L)W|A zjb5+S=SPDfA`)d13YS*JtQN`_;*2qKtFlEot1?Qw$WXP7~cCnrhc zu^3cU3)W~O%_w6fIJ;ADxFn312{B3ql5{xD#a-E8gXVF!KnX!67~^6o zA*D$fJ**WI`Lb#vK_d&y9$@tYyNuv5vs1CVRZ`Ggp}ZJ3qahopQg8{+w>&!>b!YAmLuQu*Ow!!RJQ2*4ge zu!M<9TiC3_lc$0Ocf9CJ8}e{TDNg6gu-;)Z;bybbYGWNJPY@!_1i8vFzY+=$CKNrR zmGUIuXhdX95@(gYj;NnZ2HAAfGnkZeYP6WkluF}}1i%G=2!LEk0sw;m6c7L_U?}Jp zVKNT&9AgIp2ErsrIf2dq$O0&sVF-h92By3)8-#isJTV>zGzDA?;^obf&k>fLi8!B5 z2Q)2NENZZ#W$^&aUr)+rCT`_Yc0ng(!<{Vo(&b2YI+cex!`=vRE8;{=Zqn*yF~5hF zC2u?|rITSTlPu~PSjyux4O0N>0K$qF!HV2dSOWfNp@2stPa$Trl-tdEy}aKqU}ykG zBP5ojFqKA!8As7&gPavgb{NHAii8?n2|vD~e&Wdwbai&HV9lLdJ1X+ddtd;fN19j|_C?mNj|z96xn& zx_5u~>DlMhrR#>ra*NhXnjWpL`s}*ATzS6tau6E3@yDYB`cJdWJGWMhE0?HiTY9bM znmcAsat)`iWoIv~EUV2e!lKq_aM?-m!q2Vd$8V0fCp)o-migox_kgnXwy^Y-_a0xJ zS$kmL$jstXiyh7F3g_f67!#TWrke8U1={)cpO&U#Z8--PBCaYv*=6+MADC?@xaD;O!I4!irs> NeM86kv+K6)`yV4KL@xjU literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_2.png b/resources/g2/track/corkscrew/gentle_up_right_bank_2.png new file mode 100644 index 0000000000000000000000000000000000000000..d3ec2f34cb849538e6aa8d5a5d62793b6d4c55dc GIT binary patch literal 1146 zcmX9-Z;aD)82)WL=)rmH!<3;Vlw=8$luJKUDA<@D^vF0WSD<$eGqq~L=}oNI#bFjL zVPb_zDh@Jn!5J5sNfRcVvFZ%{P~_B^R5-~zs@WwAjtDw&Bo_qyIYRQh|GvCW@;vXm zfAdJBfBpmW0Ra8O8-})aE8Y#X*VoPGZ@eV}-~*c<9bMlYJsywO>-G73Jv}{h=FFKp zcP@e;y}iBj=FJO+LLrhQSe6k4PLg7ZB4;w0e7;zzn6^FTy6sMfBmhGLp6iRn0*M5c zN)uX^&KLM{MXXv%&B->JB^F1bbf3%x)hMP*;i5uLWLPU7tyN@qQfs-T*|r@)frx_? z19Sl?%ZQcr*UN!U4TUWNc0_nnhtLiIzyly6i0t>PD5{6UC7Pb#`N?>^uBumxMQB+l z83-{!g2!kv9Fg&;N=iDd6xfWx<*GudCYo*>qfjCeq6M6jsF=*k8m|?_qA8n>YP&h7 zRc_2$eg*^t5R3yX4Z=D?6@!sVIA$@j6U{c1Qd_s-1dj(K3Qa}uY?LlbY*i7Qj8xAn zO(WB`^0STso3=kdh4Cm!#Thmw2w6!gq*9e^)+!bq(`-ylwcBk7P#J{t2wC>CRaB_q z@dm3kW2IKA+SaE!mDbJrEbPPmekvG@U?Bk~B$`$@UK6{^(v@s(vRrX(r_*47$RUd0 zS4B)u;Dt0}XhO9RpET6ERcO`iPUi|_0Ehyh0H6b405Aza69KRbo`q=z8YSq~`7n@4 zkYj)u0WJ@q0H7R%SrV3bXeMAygKi1jF`fb(3!*%dkb-Io&*_nJNvc*ej$^c14(xKF zaX_Z~7(K|BFwqRlF0Hp?MkiIB&DU<44Onl71AxMi2;q-0SVADvaZXngrJPzda*l1Z zTpM;86vsgmKo>yR^+M~?-36LS7n)6~kiQG1R%2r^A(4>MX_+K46p?30gC#AFnBwtP zGz3Kqs$p0lp~*mp>mENf(0A?54 zyVo2zwC&ALJ!sE@55K=2)xJrtJn;VUr_MfB{&v&M@h#=%q911OJ^E61@r_|;_$)Sg zl9;~u$n?(BR}byfPKej{jGg;>to+5;)zg1TJ91y(F|HFTrV=j3$ z_2bLSzkAm@dH<1teWNRm;NuJBgl||Y+_ydX^U1G}rH8R)#wUy4vG=|D0r<^3vUcIh z@jsd5uKGp8G&lR{)zz2yZkrn~bOi*%>qmx8tb2Oz E{{V#cRsaA1 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_3.png b/resources/g2/track/corkscrew/gentle_up_right_bank_3.png new file mode 100644 index 0000000000000000000000000000000000000000..fae56c9883d13272724a7ed57fb7864c8c0fc3e0 GIT binary patch literal 1080 zcmX9-Z)h8J7=HWr(sf&?0V4~Vv24B7(?+-thXy_CwWRg7UhNGIjd04X%P``7I3+@a zvz{erWJen{ZV>|BG)U@#?Y3j4dW;(@8st9oLzKhDnbL@33o~Gm4u570p7(uuzPt|) z&-;EbGacQx=fEBS*f%vfKHHg3bZW@c)9K5P)rSFkVCL9~i4N`R>gw+9?&<02?d|RB z>+A3D$1u#}@eB+M_(P!(NroAQ=6P0u?BH~e*5L8mqBTAmpN^G{m8&%PC<3TDAj)o#U!Aew2X5=)NE{FwFHXYS= zvre;E-?6+j_;~QgA(#SO$EbooTE=4*EjvP{t{5%dMynj*lc+#4N@RpcQDQ0z?`Tpj zr!-1h%gXIICDgFJJ_;uUl8VzzlIJs$lusthnT%B^IHp#j*LK=<8blUT zc&{o3^#qYm(WNwB$;a1AYR$?wYj(SR6VU(yfC8WclmONN8W^AsI0mH@R5FlT<8Y8k z$kJd&!Q}w)fMh?)kjUVWnLyPvat*i_JOwNR0*56eznUbndbDUrm5Sy#rDoGX9j!nd z$kZUM`#B>hnz-yn^j56YPF8ku)m^iWYAxIcR1k}Xy)inN;K@{+)zyTNRV$^eW0#t) zjoNjJWswQU1%x_Tq&sr=5ztckMuW=d?n9|onOKZZB&1YICc_#P&e3FvAuTq%!4XX% zgv20Hag-;KNh62t96$B=;GKIv@aF6^56^D@a;ihNr^d%l99>*kOsr@J_b&W~HkU8X z;oDtZr``bVvi5zwO#b-ffu*^#^UT%dw{P5d^xD6_zVA-X3TH;XzPo>Ib92|vkN$Ay z@G~FRUjIa#zr-vF*^#qbE8lGR|J-`{`qt9%*Z#R~9sKh2=w+B$8-StPpB|2#dH%Cq zE<615`HAl?#n>bEI>@P-}31E%C(1%{%2n~H-p`l?_QnD-I`7Hd0uV(J`xC; hPs<+TTh6N5?TtO-zqpcYL)_YhbgvYC_PR!642Q8h?qbyskXDrNNHm_IWHpYQj}=jHq1 z!{__GvJ#KYP92#7fZ63!ORL@_y?SNB=k*sms|f%ftejpu>CusqkbYSSrpx;jT<31(X1@mzw?mAsQ7p=GC6lQai&nMjm}aNd>i7EyLJCC67*z{!jgZ(R zQys3*P3pZ&qp!6F_1;iN#Kpq4RWmRP8$ZZP|P$(#| zV8*}|0EvJU92F^~3&>2PW&yc6JPn=(o`ZydrDZ&qAxm1Urpt{+-f@gx&q1D6CVYCnPhXxQy0M8iPz@SZ*Gg9n|hefDPGH^^-`{3lpNdWxi%Vf zXr4zVAQuqwvM6|R&k)LIE8Q+#DL;eSY;wt@m`=;ttU^WebhOM;21i+Zv?Y+eL>Nf~ z%0*CxLMDqG-aCH!*z~_of8fGuT!a$`zifD9Z+U5P?fBI@`~2MZug#3DbkI5fHG9W; zu6xaIY+PQua_+YuN(+xqESFZ_d1MXzxU(9XaC*&eDhN5_4)2%e9r!EZ}sj}=gVK; zyjW5GaK5P0_a4c{E&Uk!mc94(PkYb5Te&lHDOf%kU;5^a^~?VQMXAf| literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_diag_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_diag_1.png new file mode 100644 index 0000000000000000000000000000000000000000..f5f7812f6735b6fa6ddb3cd92f6e40f6499ae452 GIT binary patch literal 1130 zcmX9-Z)h8J7=F`#*FSDSBWCW#GR^Ql+-izfJV#{Ld7Wu@HdlMa;G)aqwq%mA6HgW- z!i{B`)!9lQ8YLf2n-682HDCr&!btUC-H3WhhLOfmT$Bjaw(v7!@Vx)NybnCj z`_4>yJ=^+s_5;AS@v+gVb{%O4(c9V17oPoQJ3uE)J~w@+Jz6Z5j*gDb&d#o`uI}#c zo}L~I!+Lvr`}+FqPN$QiTrA570w;=oS(ak4SSppt=k-!)#Wb6(7UcrQ4LmpC_uIl@ zM}LludPOfAOPV#-&^OJ+IVFth8;k_U$X z2@wWV0n15PF=4IdY^@588ZOidpiLE_k`sUj2w<3GwJJES5=7SRUgY_5C{$IHwM+&T zi#TO-GIkg5a0dvFMEVp;RNZo#jcHu6AY>~6-3&Qs+~sk)1(FkKzr;#$KAs6=bV)aq zl9@Cbx!QWs%79G(dk7p+AXJRb*gbi|Ut}c1m#E3vrdmRaJZTeYJmMh}K6g%J3$kFu z#A-^eYq4fAwQgvrUb5O~g7i^zh+!jwkPyXmB$7`gikXa|>$R1YX0wR^mw-rNRL;s4 zaG^qmYHYmj&o&~3rn=I~H#V#5Xn?d@X}jIya0;YLbh~Aaj|bYzqWMI!oXeXfqg7)d zz+tjrRRRt*Os1oZ78eTXP+3!|#dM=uYPHr71K4xQKI;hRgk-wareAAC3hSxLrd~tUCSe2Gfq7h3KjR1sR5Zk?N;sQT3R==A zX$`Z4S~Z&EkPgTMgxX%j+jRGU$D-+aold9jL9SF-zh4N4#b{KbTrt{}VknKJikxeO zCmTK|3OJBLpfrVa1{qxY`02rczwiFQ8&h5ZMpl0ew)-99qX(zQW#JJUM?uIWqcqA~YmzJT+<=X`GpLjc-*}KYdZsu71(I zdTIaM74f~n+4}Ll$8Vm#{K3hee>w3^^Xx}&Dxc{8ES=v@&29AV|LSPZ#uYqxwR(N) zp}~JAhWB;`H~WXiE}naAcH;hHZ|$7AK1}_({L|szWAA_el4-edVd(~0SQy^j`kJX-G(KMb;r4Id zOvszGe>*)>-nINn^K2xtTVD86{Vw?E>OPA+_@s;v8K*jA+4$UvJMWgB9$uW4 juFYnkPk!Wp{H5c_^sBG)Vas1_!C?H5cXZ*IW9R+{L_O}t literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_diag_2.png b/resources/g2/track/corkscrew/gentle_up_right_bank_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..46162c4a8d5b6a8cc86f7c124d28b3ba618eab62 GIT binary patch literal 1046 zcmX9-Ply|J6n^`6_75e8)D7D?M9d-Tumn1|BaU>evo&3&?$l0cpi?@PSvH4c9qVW# zgfiL`)0)E&BSZ)q=soG&DRs zJTfveIy#DB*x12);AB};RV9)DQL^t$yZ z4iW(=26O?dD43n|H7kCvful|Yc@o;w5vqp(cmN5*6rWGSaXlP1XnK|B*W>Y~radZ` zk!|CoKg0wge2|vHQH6+Uq^#3wiOrZ?p(Yp&$#UaC3XeoXv_Nn&B`U0v<+Ej}Y$=wb z)!l;AskC~wj{&~`fj9)y5Y{oO9EeuKqRl8yEZ0(vu3ks0JmHrqJQXE!F}fnNHC1pj zapnjfCSoKNXV{b=y_?yIgiGtF^Jw?RF913WSRoS@E$o zTxbyS7MpF0MkiJ4>Kk6Qv)AmQNy6u&0)c2SBoGmqrd5v5O8sT&YOb(esk(K?YcU{k zm@4=*DX1riQkpTdLah{EH?^i+>NM+~_XsfnF#r`n2QUHF0ooX#K6nLh)-mK34u(&Ra$~Syxp^J z-~43lAoFlbzZB;Di{JqrW^L;-se{5my>(?(_`5(}L B(>VYD literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_diag_3.png b/resources/g2/track/corkscrew/gentle_up_right_bank_diag_3.png new file mode 100644 index 0000000000000000000000000000000000000000..a5f26c76694d1e1c99763100cd3476026ef4c53d GIT binary patch literal 1054 zcmX9-QHa}g82|2ice&fSbyB3V%DS!N0>&97$FdP-PII%KahJPgP_PeC0;|x64059n zeTZA;x?A+J(T9#z=p;L;1XtW4ao2}B`cOs(VHT_sv|!yjIHX9`Iu87sG5CGo$M5C) z@$vh8t4oXVojdmI0Dzqf@64a{=bT@ACj)-BsmE!604%+C>bOrwMn*n+dg4+azoECT{RolJ(( z>1ZZP<_xA#6v`E;T2q^@(dk+ofhCw}g%4|qs43$mmDXN9*=-T zK!ycV#L5a*GlK1MXwZzH9*G7L+BOlY#{dKX3B#0NP>V!N9Jd%|Ll7FNR9n-wN+ndQ zMW|4W4Uo}cOtKaVnWrk6CAt(9EvK1rWC|A6?JLs?=@t7(G zH7RPQiDH(ub7HlaYS>!4R_wLwgTWSJ0TKWzfaxazpaIau0QnF&lvR;!A+Igqpiq!! z!HI(>01^QyVPsIq5|EQd%^dP9cxpTiJO>E@OUq#`L*&hP*^;YO-F59=&qcmgBn4D< znl;0M6_p%Z@ffq8vpLqJEdI2lZ`(X>cqQ@p9At-MyX^KRYld37}C z&^(VEKpr6Edy(_yo*|-Vi`_0=EIfnSY;wt@m`=;ttU{4GO%_x9lhi5khJ#@a5+ui%Tb7ej8-LXd(j@ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_diag_4.png b/resources/g2/track/corkscrew/gentle_up_right_bank_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..dc2e6452e702d5c3b8cbc797171d30f5a79e0bb7 GIT binary patch literal 1048 zcmX9-VQ3q56n|~nUfM7NhAp@QGmY%f+sNdETRr8h*O8U0z1iEAK{l`Kra_`y>p4=% zhjZq`q0yZz#T3&LFw7ta3)&BdgcpXk$pfq}unL665XG&D3k zJUlWof?=4~>m3~(4Ti&Eii&U?D~h}<$5mCyWHR}Du~M;Yd&6}*-7XaYmH~nH#p8iw zGL%Y3^emGv2<3`Yt*Lb<+iaCM5{ofDg%4`6kRcOAm0HViwS25zQQURC?Us5SJBouu zLW%`L#L5a*%laGTK(~&gb_8`Lv}Yh>hXDit3Bwe>U&C>OAW96gCJ5_^L_^bdi$zqc z;Zz{Z1|vdi?OLfU|6CoOpM8k|o@-iJ)I7JuqqExgL%h7B% z=d{bsUd_)!K!jidLTMljj4lSF6(U|^6(^Q$s-=!$qcwpH$TXgclGzwjmbt1bIvKf< zS6gPLQ_J@p6SZuAfF{ToMJHG;C5l;DE~HYGY_?V`I+oSk*ywaR2yg|6JVurMToo7V zWTMIGt$3-Os&bcs1@1`yW8DGEI`&W4gAl}_-6mMrD8s+n_av+dfb z+oX9OS%6$XsGo)2mwNy_lPurz(-Y5k!ff&Fskk8i&o|6=*)A@Y-* z?ex{(eth)fG;#jbzpp(%{_883x3{L;?S;RN|D)&jPZJZHZ~cDm2(iDpva&dT`%Znz ze)g->?PD+BU0uPi-Oc1?AHQ{U{>tvcLQg(BAG+|3e)G+nOF#7;!PJSF$r~@uz4t!` CLBv!5 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c85c1c63318daa73520394aa422d0e1947742c13 GIT binary patch literal 1360 zcmX9-e{2$W6#vp+SBj1)T~Uc;iVNA!g>GlOI!sPWD^_N&_UhPVN)?q^rnii3SaFib z9CO5;4joRW*bs+`7MnKG4HYwLniey3ouXxmw%XHHi|tLjtxN*ROPYsOmbs)$<~3)0C>2b=VbrK4&I z(4)XY0ER;RG!k(N6MhjFlR#DhIXxU_AdJcYAOX-L2rU%aBoan0_bHXFB-v>+CTzAL zuNOul5=;a7{O!;E^P|_&HB?`4nNue48uA^17gLHWH z-Vhy%+oDNVob{*1B0>U)C?GZhsTIf>1ow*7LAfqM&~dFZW%i|+C~PHBkpY)j)TmRd z^cz%RGZnWR5^i&Uz@Cn{$KnCl9~FvlIjY5QBcZZTl+$4FSS&%OGvf8eL!nepPdc53 zKtcn#8^QcSRaipBP-9Bv=-2sJOE}H+a6xuFF$M*wP>74gYN?Du6$Yi!tRWrx%rR@w z>FV?clhHVrB7k0lm?@!6FJ(-q$4UeoRM=ze4A>G851WW`+z=!H&;novfB_%?KqmnG z2!I)oDrhysfDa}Uq#V!~a1kJ+21yb?3P4&6of!0yFl2%;2Tc0FbK`NKQ2{N9m<(c@ z1$8lMzt0d3+vD*7%f?|wOJW3=RX{Le(kIo2RS)WwkP>mqMEydN3FwU|f?4KmMj*xRVCHb|h)-%91{I&k+ z(ld>MtSxN=&4;yLwEaTUeJ4-*rVjs(ZgX#1QRq{?)EE4Ky&zmaXZoQo&0&-`a#)=V z4r(VCJYILnxX^!M`FNOL`Bi=M6an+6d=(M6j?S9J=WVXrbm_o5qxP01cP@#>U##DZ$IdRfe{Y3<X;`cVY${PE+ zzPk6iarMl>!tSP(x3(7UjeI_oziaN1{S95b(#Mb1yxi70xntQ>uKs9kqigiL_R+lI z-Kktr^uK8N(W1!gvX18a53dm-dTB_0u2$6asAGR`9ggE;b^fZ+qI0#b*vy|t?|xK_ z;DX?^>xEak&&=La_fzx`!#+MX|Dx@U?yDCYy7nBa5*&jM+K-Pfd!=V^UBR5y+>}-0 z^Srs9<<)<`eSBTx%`5Tl`W>aVqVroTC*8f%_Hgop`)Alk6(ubUf4Jk;+~Oytqx#_u zKP=zAW~k-FF!r0V*r1+Q-Ek0_C8?ocU^jdItsVQc#O9Cni@#B{@2NT6boQ3y!L|9F zpWc|UI<<17Vp3ndwBg9ce+TYb8y~iOcy>xKCuk3xENfRRczSb0%n{rTPJMge^1u`Q fuUnq2#yhn1b-!x~Smu9z8`a7rU3p0P-ybhmHO{=_?lL~sQTv2Eo^OEf%V-0)lvfxZf#Mua)OLz;aXiP+_hB8yjdu+ht z5Tronu(XKfV&+oXQZLw0)rIOjnw1gCI{;V!9>YYlIc&4ZPNzbWXIXZ_?=OYJQ>hfn z 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 Uo_|i+2tC96>BYHAFRgy@Kdkt*00000 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_4.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_4.png new file mode 100644 index 0000000000000000000000000000000000000000..26ea4a7debc4a2a4b64de4fdcd4fa38b593b8b39 GIT binary patch literal 1179 zcmX9-e~i;)82*mqu6Nv>X1d6FwP+(EMd_lHnJQiX|PI7O1Qu<1qbY)e@t0&3u0K#5l%$&IYRQhzy5ijYeKTgy008s_SNPYq>Od0c`*w)rIZQ8W<_V(%1r+0L8 zbar+k2-4Nn)!p6g@_0Nr?xSgn;}}5*OOlvKBr=&?v8b75*|r0^ID3_0Qle{+|Vj&q96jI9436)9fT)xC>cEnAfzJQ11Fh(H4A}uD_WRA~iqGrja zown+Q>XhN2fRh8R2yn-NS3!uJD^T=?4N9~^sj8H3C?*_bF{ePFu>h6|kp+R)CC*9+ zm5fwV6AdFXWvQ@cI-GoL8dl$*u+{mK;V!5j|4dc|xuZ$S!x5C9SY3IHkqV*u0;09#;b7?+@$hjxYa z0ucvk3TOdfvjB1ciY}PKVV;Fr6qb_E&VvWW6M&&Xh()4;OO9b_B~Zu#C-|Em!WW##tp_- zX0dw619>-;y)cVIje-`_I(}kq&*Xz2*s*pM2Nq9^Z*KL$pnu8Wf-i;-hKD|Vs`ry? z@aoVbnUh_o{=OW%_*U4@9{u-D>`?E=Gj~_WMa3g!X~D#iT-kTg{d(}{;a5hUQBGDX zXA$>2`@;GqcOsh}@BeYAZ^Ny?WB2yOmidpJzdPio_np~&ZpO+}@7n&)`saUh=!ZGO zSNA^`xPE!II`PYY*M3`^J^V&6qeT9x-X7QzoY^*1dv?qGqc@H7!}@zC{u5li%Mvy<^YZrSq~+{Hf1Lo?8>W zTDWxjqw?h8(+%v1aAAR&DWRXWZ&e0ZQJ(# zar(Pgcb)A$c(Y^8hpTsV?5}Rv*onTAHEt~4dtvJN@h9KkqjsXq0^{p*TU9;0{bu(* p-l-82zqT9Z-4p$CFS2l4960c;IkK=Yuca^uE?eb4zI4N${{e2J4GaJP literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_1.png new file mode 100644 index 0000000000000000000000000000000000000000..3764b5c21a8b300f0c3b6a5269447eeb74305f23 GIT binary patch literal 1228 zcmXAoZ)_8F7{{M&tk*F~BUKwM*pW&K9<$D4JD`T!xQ$v0JH|~46exO1m4+PTh>bMZ zxB>-=9I?a_8YoFky3jz?i4}^}*e#7Ia^MI>j!>j*RTpSR(WwM~mXLg(e{Y`ei_i1y zUEXb;GWmtc05HY!M(2uZZLh|3WnDEl$BqmE)WPzlyxa=B6=j6j)yu{PT6YL`pr z_89#EQz*>D5{^__$Vq`hF-qf@&D6+SHC~%eb|vlbjU zxG4}>EXHH$fGQtTS8`fZGNOtDJrohj=m8i22Zr$~l~=134Th-6G{7)fr!(*MjzuCU zoz@a+J*6=+I+Md-=5d>s;6#%UrhRd1FvUi5j->3=ky@i!Z(?yPN7{Ls_cQ*8Ba-Bk zk~bp!A0D<-fiuR|xg@UVx9``J|3nT>n%>2N8ZsZ_=g1z-aZ07QT|Ko+2g0ji3jkw-xB zD3bGx0eAv}6eP_cGk{n?yaojb6lGA-g>rr*N8vGe609`X7|g|Kyly-wnqyHemGVha zyi}4<)l2IH!qZ5J8YZf9Bn`Z563g~@#hsc670+IotDhq$r?uoQMPq(?C72M$ZIfIop%>Lcx~mbpRU`kHXni8GY)@VJb9WJ+4JGa{smk2ZFGP1>-;5Sb6Vo3*1i4Q zjisgQ>)PsH>S*1(SKB($H0t|c?KdNByPxTL-F0v0{TF@R|14U5plhhbmG!Q;s@OJl z+l6I&raUjK`S|dy!CmdjmfqT$NY59&(~chM->p2j-lAT8Y_NUy%hcrieLJU3;EQg~ zIe35i&#U|Tf7$ElTP1xZ{P^DJJFr7qXxUV}JeSeg4>J$E~lQ+N{Id+7=hioSU;y zx&P^@hk4)dZ1c=5LpRUdeOLL1rJ-E=og+8!Y16rum19?5y|DhAiuiv!CQCw*PN;%0ZUhR=cz>-`u+zG)gSo) literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_2.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..f8a481aa300e39265f6898b326a9add27a5bce91 GIT binary patch literal 1197 zcmX9-e~i;)82*kO*E^0&HH(h0GbIeD*j#EXq?mld(E@5S-YF@e7miguPxg28~`@3;*I_#&9SAWWy+K(Hk+-rwRP&$ zscmg-2!gb?w|8`OI9x6lMUgDa2m&WbqN2!=NF*LlX0t{&;|4s}DT?-B z5DSILsOF9*_;l89=9FSdt5j1gf%x2=GUrfzm@eT-g*qEyb8%lWD_ezV%}Pzw^Ij+L z6ClI@T|m+@lGD&~+TJKSVU2_hKb+Jd%)0>K0q`S;jH0U3spELc?LN!%g+QRJs&|t~ zn9DgSyNhvf2;WY+cZMz%Ito`9VMiqZ~;7jp>&DY@MW$4C9mW#OzAE2OhlzSO8N zz|SFyfU15>4-$zmlZgsuB2dVvMoOhj ztyY3fE@uEx;Z8<(@F~o1;Iie`>td!6GAH82NuvVGb=(eU4Dphv$Y4Q%3I{k{4W?qM znTeJ1nVOY{jS9_i&;ZZ^5H`JtHtC+g83`wbbYNRd+@7B` z-SZthGq-Jh&+UD=(@)P^Cj5+c5AWMBXIHm2Yt8YCLtoxoyKSNML+_kh&K*my^z3fk z{Ehj=?d!zs(_$NW@zkB+h5Lse3>;n4MRs2Eq*^||Gc>RA*{CV*xnjhB-*nLW_m`yS z^yTW`AF#jf^_|;zGV-SFo&M3Cp&pDCP9o2G1`Z62%|CyWJxJ|Y^;JuKX!QJvZglY< z3kt_aM&~Z+|17by`wn*KOkiwPhqFiLU$C#+vj5QFCIYRt ztY1C&=>4rXkOkYPV>j0A!~fd6XY9~_y=PwE5>nq@KdW!?k$1n|wfp9SPuoU3bFS`v zYkJR%JAd+>nEBpq!g zS~z)X2L18sWji`BZKG}YsUK&X^3dgn1#TG}e1u;g86Y3nH1?l+LVW3^rskk;$#Tzd I@7j<42SQK~B>(^b literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_3_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..509523128ee0ce6e99729fddb5b8b373da1cadc0 GIT binary patch literal 997 zcmX9-VTjvw6n}TUyWF)KQLBbs1{oBLBS;uQ;>d?gb4Pb(T*fl3P$Wv!>N?4X3_Ix{ zV#O*&;#M(^3KjC9lgJ7lGt8>x$fO_oAxOar`B1pZikwhp85K_Wn=$yk_xOEzzsLK% z_vzW~?BV2k5&#Zwo!&SX*HdxetBE-4w@42HZ8UZz2FnR4Lnf>oW$Sd)lti#q ztYu)`8a`~LXMGY)STxhnfsIg*0Z;%m3^Q=tB1xO3T|wAUlwP4Qw5MIk3Zi;AX^rMx zT!gd=L;km>7#!3^@UsvpfK)&R zfodFb733FDzltIk9vIJqEJ04eiaKGHn7W;9xq7El2}5r(2~n&?7Jw_KM4M1tO7m$W z66|T-o0U3qr+?s&&~Qqpfv2!6i|0kEsB-0kY+FUQZgsqR7H zpMNHG@4*jTI=8LDsk?u?6_fhb#`EW&zWVdkSCe;+9r`HV$*;d%b}szxzq^nBa4i4k zUq3DFUb+6p={qMsxG&YNJyqCE!OC~$XM4nn$Dg=ybUMFv>9KE4{v#GV z`3Z6G$hDitFRnjVem{9TvG?A~mE`UX?$74&M>+EA>qm!Y_Ns$Jr7vH+^6lM!ql>M~ rKgq8y{QWHd{o9v6ckbiV$G;r;&$;)?=Ig0=JlNXY-njX~Yajj(A#$jfq2Rh4)=o=#`;`9it8Wm&CuoAv_h1A%u0gU)c+ z9f^7qNnbi6NbAvsqLs zxoD?{CA@;$Cy{=I3dCqx^QjpwZt$t1s8^+e6>>8!uixVnDPCrR3a2E5L{`ccl!6&6 zTPd@dt9ME`3r-P;5V)g2Y8aCx{CP51VihxxtgCuUE29m8a>|S=;-``UUry$Vs%XaL zT3T%w@m49_F%8rx<4%U80yGn1xritxWjPaxBXvsP}mZz2{T0H6YB00uw>pn(DELf}wTMTU;7nm~d= zLyCohA1nco2uLANl193K3Sm@DAWMfk!85>f5D>7iOvEBoO7rJ*xmb*wrqOJgsH^1) z0UdR)8X@RzsX!{0PiqB@cBI%zS9c0^RBMq=VBDDBiw9YESfryNUWAO&?RW2A5!(llZRcLRV@upeY;OG+X-4du~ zz=I?=ijgQoqXLUezI*)40mrR7Kk&xFoCuRQem>PDH)f}vUK~6B!G)v4@rUo3-azZ0 zpZWT}tCOYodoGvP9{lT;P5u6=v+phQv(@)DXUB(#CqZ7Fc z+dXT@7ruM`+ohGoqkocDR@X9Ib@YYWMBkUo^Pac&t{i%C?DrFAS1z91R$hH~jo5QK zckJ-Q3O`l(<>FlX*P-fv2ep0g9C~Q{?C?x}dpm1CLTrwnZ{FVj%DI=9-wge`er+VT ntzUcXw*S+Oe-2z8KHdAxFZI~Fj$w9sZt9a~j-UA-_*c;< literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_4.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_flat_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..23bae9e6bd415ddfa68204049cd1a18d591771fd GIT binary patch literal 1311 zcmXAoe{2(F7{}jIw%gchnI$P&ut;4B)}?W`t+;9qJeH0Xb_+LGLzTmvuEr)Dp-MwK zJfwpT8azy4MVr`>0u{-l0HXGw~I=xN#ej?iatly8fSN;eez_s6Hpeg~X>w<5fjq~MKIWZDhG3SL%5-Xt3DsFJ+)k2in)cc4VYfTx_a`HfOe&Sn=OIuq zK3XN2%lgkZC6{*qEdcDm^xTxYXN7(I& z2g3rNEMzc184(*PWho_R)%YA($VEndmUxIw$9%aoUnty#7yu>!YyfZogaC*GkVOD2 ziol`6215ZTqzN@(P~gEp!~g^WKoUSk4&5jW5HMne2^SOs;0bsgFyg>OAXZw=+BF`| z5Dd`Ks56-i<#I__^io&=>ZrgtIT27&5j7*|xx6`4ut%r7iJ3?Srt@kU&?ymvR%*tS zRuXksj2vqXc-UyjljK7=fro{R&S-=Y00jVHk%g;h_f!g}!4)P`!>v7ckHTX=)L&rT^)<={nOC&$+YazH;sGiM*lqW=5Y5H!VaHf z`-%Qn4?O$%ywTsq4Va?8x+S50N zTaI@h8AJb_*R-=-knj_-+n&m0LYLn#ZCQGIW0zxSVXEP^<9Ao=p*FQ0lRc{5Ydu># zc&F;XSX|TEe0tKlr}|s|mo1OFPHyTM6OUrPAK$NzTU}d6&v*K6)(=!w<|XWcU025I z?O(3r%CjlBykb|={6A_~mWu8mFHe?GFZ888{A}B`Pp>cf`UBIUO#Qa*{K(7O(T9KC zlAP|iH*qqpQ_Q{pR_)05hqeOd!a3D?{+eR!l{=R^9~f)y-+tWQ-E}xmNE2e7n15pA ddi)G`5t{;>Xz}>XmLg@as;PD5z?&O({10s*RpbBw literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_1.png new file mode 100644 index 0000000000000000000000000000000000000000..31197aa875d46ad5f9ef63d9be40af1b9a23dd4f GIT binary patch literal 1362 zcmXAoacmQH6vuyCH*TX~(IQ1VEUbfWR#xK)Csw^dw-i$B!EVq<30*v0!3L{2NpYPt ztgs3tJ7yh~bfIVy3h7wEi6!f#N|8>EagfP6>}HjQ6=AV%MK+k>X9>yYy_fgT`~LC$ zzJ2So>e(}&p9uh%y=HZFZEn7ttCxy+xjwg#-2ea&tXo@GlUwuh^78ZZc|2Z0K|x_* z;fxtG5CkbIDk?567D=U26ji8HI7w9^fyWQ?~dxODHG&+z-WU^UQ0dOTCG<>~Y zXfjDGR)xcSpD1u_P~ydrf_rjOuePUlS0z6=wE-Gp37VPcC~ z?$jy$lqyV_$4h&>6 z83@E?Aaf(AU!V$$Nmg!5svIf3FKr2Dn1O6CJsqEfe7Qh?i9~9Nl$0wdrIOYV4nyvk zHRyE3{J}(&%O-JP&>%D^uo)zbN$#=Y0S6iO7-IojJmN{mquK0Thy$PlfChj8AOJuN zfD{5?4nhU3Gz|D)B2LJF83isJgw!BG07wF87C|QpeFO}dAnSk$A9!p$1~e+5BM=iM zvRULVM(y`e;jo?K0_ijdb6R2}K&^b75fMI#AtW;=luSk+$XddaZgx79gz=0_2rvnv zRtWUC#6+T2qlU4Wd@fr!;NqfzbRr6~Nlc@GApjEq!kib5oZJ({cB?0q!aVLL&@8Lc z>q(P|vRcik!j382I2ur)5shMikf(K0Xplgg40=!)!Xc;0g&$kWAAkG9{!Tg0hL(O^+6JWCd->rwid|#i7pR{^1i% zlJZ~6%9}3j#Wz-5$97QFd(Nw`a2GBv(0wi0jA?#)rmRVO?d+ci4Lexw4K;f9%>!*? zjo$OZ#m9c{iM3A7$3|*j*moRln=C$R$h!XNn6vQS;5sc5Td=fJ`0gJic}JIBDQFlP z@A6Omy{)3HL{$I9s-fle!{6yy-Z!5fV&>D8BZJM2D=r-ojjYt3n79R22)B;*{M;gG zxK+xUVzrIqp5}*lzUSVl*;vm1YRR&}hOvbg>fOup*6TMH)Tl!AaM_tH7ZS=fQhTbBa9CANyV@?>JIyIMUey zULR%0PPJA(#3J5PHC63V{-b*@bWI%oxaR_~so%eKzk8?TPQS2fZDWn#=q3NQ{2d1m z+<%}fJy+4Y#C00};(j)B!`nCO0d>+84a>&ky63 d@u>%ukQaS#>(0FcykIUEU`>s-x@%Q^^Z!OZaF+l8 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_2.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_2.png new file mode 100644 index 0000000000000000000000000000000000000000..0b47fad82ab19eb3175fa280027e6c8709d74492 GIT binary patch literal 1173 zcmX9-e~i;)82;ey=#EJyPT1vUEHJ!EicG2A&;=?K7*M!guIM6D3Kp2$kS10$afSx! zIZ1&EOB}L0M{H!#B`%6k%?t}pIl~A|Si;U!m}c>c+#fqx;vgsa93gq$U;n&M@;vW* zsJ|~TYi9RM0KlyE>sAl6>f%;(+uB-rYG0oWKpW`axOq)$oHlLR^y$;v+S=ON+dDcs zX3Us@Ac)Oo>+I}wc|0D1@KO}XvNX?!L{X4sIhjo7a(b~?HqCmYL3jb_2Mlcwg`ANH z8jX45ia(iRGC3|^5KD$qt!WgF1pRh_c1b~0<*~F#oRO(QGFZw9=4jk9wPw8-a03np zQ4**uk`a)C;;3YtjglK$UfAH^lnPjs|cg=+E#}UStiK zuO!7|GhOa?#}K*0qS0%{D@Bd`>QrUvdC?*lXif(#PjT~ZWJsDX^e=ku~*WG%~p zEiQK$5HUNcx)=@RbWAY)YCV)~MDxvLX-cocN*!|oABqILju44PSRxjtRVkt+qJ&;48guxU6brKqM>-c?7+5fr!18)!XvEaq=v0bg6TEBYb=4D5Y9DnoV&^+7F zb$IR4;?&5KC%EPEmcdQUUMu;F9qG9E-tLJp^5?tD9?sYQ92rsOE($*XIwu!^ z!SBy2f8T!m532m_JihnbjloiIiQ0eZ_Rf1}pIz8Buwne6@n^;^?_F`n9RKXqt+p2! z=k}fpD?aXCHo5dAw*NrSj;TFEOWx(S?z=Vj(_54Chn`!D^nA1M((nA2!<*JzT{i;C z9}F<_yR| jl>UNy?vH1bqLnLWlp=8pGaDJikzwX?M|Wf_W4W_pk;p}^&VI;ACjC&3 z+!?Xl$_!GqxNel04@II@IWb_7eu!{F(R}D!2Z41^SU>DTkWNmx$nbmjE;_ujg5_uk55cY zOioT>7&bLEH9b8YPbQNLLkj{g%c81gbX_w|vr?%w8m{Mcf*>3Y85(#FByl#AiRE%c zzCagCT%{`28%ndKxBXJDZwnNb=4Lf9ZlnoIC2KmfYYMGOy4}!%z2YFS_d_q00EL1) z50;G8HLO*_yY<+xoj?N`4Ha}?A><_iBmf1&G#ob)35z6cj@y-_y==B?824*6)M_P| zSdx#^62U2CN~6*SqgtF^6--AgH)Xr6xIva+6Lc!c$&{$F8BNfNQn9AgT+Q_jFDUzi zdT+ml^AM9Eo&}-+q=m7yc&b5WTD<0`OFi8VEf4KVR7_auUD-HP6K z%&=A2_Z`&t@EA){X@<@6LSB|js#?wG8>LdKR`XrA*Xe{|h#;W>S;3e(E;JKzo67ct zVn1UK^3Bld3>$-k?mn8OaGZ_DQ$$jxXqDr1Q7S6YvO=R&-m5nP&mZ=9P()0ZaYG@j z991pwPEl@FvwM!wZB++dZ#cYk-5u!0%yg(p7QMCst<;^yZsUAtsu@5;yj zc@ta5*B;({ljtnZzi~(R>R;VCR13FPW;V^^OaETJ{?s>XKRvin6)tXE$!$G5UtYU> zcVU`-@APlCt{#16Y3J~A=I*L%hawlSymW5y`_u1y^grKnyY>J8 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_3_2.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..2016027e44c3bd4f902fa977e26596113c262ab3 GIT binary patch literal 1007 zcmX9-QHa}g82|2ice&enRxH}Fz%nc&lb}I@M94IAxuZKGmt#5XLmx5-tYFn3aaUa* zg7%@=ZEUIc=*R@Ke(rC0g9mn^3VHl0a3=KR7lDL@9r;0_Q zRHmynuF;g*9mVzZZcrNxErG&v+@dC?jT~XBWJ_muDuUO@bvs(PTOEbgB=WO3C=`@< zFlDT*VO}lSZ>Ppx9F1r+R?wk|ke>mN02B<+;@30hUEwv?8mIf3Da^BU7}>ak?l~m3UdXQ>*W`JE0$p2RtYurprk~A^O3QIS5#ugY)q_F4DJ z($+cqQvH4E($9&d+y9>0IR4igy7}~fXf*Zp^)qMA zoHc6}f*=hI4ULVBdXve7<7SE?S(fHFyCCpBpDz@O#N%=*l~vVJxs00uX#ot~WVh>F zE~DFH_6IDXFcXVA5=kMg1oDL_g&{Ue6Hn{CHlxU)5dk0YQOS@k9p}{%e^HHAN-3)W zI56NQfyg2;9!UnYxtOk;Ho&48mL0GvLYOiEzyRPt5MHbG8Vn+eMlF^Bh8b}>b6)T5 zNCYO623%(%^=8IsaiCTnvw3k&v4RBo8?T!Zm$w)+z<$N|$+2==& zZ0_+r_ek4bC_T0R!!NcjnVvtm_L;9|s~^P=4P8DxexrAq>^(-dkr{qW6+SpV^h%5v zQ@S$b@Y7?175k6hZo2dD#o&owR=kLgV`rxh?%a23|M=9>MZSgl7_t3KLtx^QeTUzu z>mJ-R+4J#{cTV@VoEn{8x9hCaJ$KKu6J7uHUAtFZ`Hl4ovUjw)Y3j@0>a6XQ#U4 zH-BqcFi<5EgWFqyf61@p=rw6w_W19{Rj#hbna!6obB7Kt7@app74&+mMSSo0txip|!u5r^`xd_2WqfSk zh2e=sOJ9HDr-h{dZ_CY>e|Yp~#N8^~opJleCnQK4O(LXI#zeK^|x+4@IS}nCb$3q literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7df31fec806a1e23b7fed7fc14ffb97fe84583fb GIT binary patch literal 1257 zcmXAoe{2(F7{}kO8|~;wfjY}*qzjEXLpLsZ%v(~DW86qL&+P^`sHDMD8djyoOFUSE zWhqi)oi!d>Lxl!vY@~rY8tk$P1uGV9po=#s&}BEQTA-039Tc1}^|glN`~3Rn`Tp^F zo}u0z(}MX+=K}y1bai%YsMIx;Sgw#&@`M*X1Aq+lzSy^}GFDYpRaaNbWU`u?n%dgh zdGqGU<#L5WQCC-|(d+dXhLR+~FqGA5;d##OcKiLoXf&QmWhJRpE@LPljDV(;7K_?$ z*EyW1$7}Ql=x~%xB>9Z!%@;zXL2foGIZER)>jWzj9oz3bGfF2 zL6}TxF}0r1ptR1&A|}pYc41b*$OlMwgz_brP=<|5HXW`-O?o3^pscusBRLQ439`XB z7Z+VA$tM=W`Prn30BQzkY(VD(h#<#<8dDUpBneJ5d-Hs#B&1-BHmI$*)?qSu&Bm~m zOz@28w&whNA>uA2{j*{O7E&rTju^}sZX-ws!+5RMfWr~>dXvGR7?0<(*;1(lftCY^ zUyg-UWJ1ei47NP!DOf^9N1`NT%hBRoZWbyHDiyBLm~?u^fLe`4o}xW$WtlVT^`*m6 zDJ7Qk1YjvS&!}9iPOuvSP9oxA5&>H};>slh#ayafo`wVfW&n5q1OOrcqyZ?%0j!87 zp_7M^5R`H>0yqr#2oN^`i3X4Xkkddf217KA+hN87r4aZZJPs%lm}$A)s&P3CKEV_Y zSrZAjC`O7!5mvmkHh?*mgrK2AIyR1Ql2IsGB4tNn)}NV+=V7jdr~$5%n^2X7(AgQx zX`=*}J>+vGB0ez{DM~3=&f^pX;{Zwk!U_vd#qP1RZfBrSzytor;xif2VqxrdtJBG0 zs2fN91QsE&B!y;aL(!~^TS9*U}M|)rA z(4oGrC%N4T{z(`(8!oJ$ts{%D}Nx`Xw#yg%=c;pU7<2k2K9} zK5?%0(DUn8bNwq1ytH}WSnr9wf1WHZUT-^caqZ~T_|evqLRml3w0~?*_h@X{!`07r z^KG{G7A>{R{BnJ|Zt#s|&3iUIeQW&i!Zks|Hf8n3iFfz^Iyw2VC7?L`c}HjCwP9rB zubZEFPkpnp`L{E#kKMW<>lLSmw}0Jt@r&*YZ{>cz-PXP0hk>8&{$4xYta;{z^oG8p zQ&-))=w9d6mAwaUPwm8O9*ml+$M#b{Ub_}Ka!2!B{kQMOR!r64k5+WE0;m7-L1A8FOQyHl4cdRcJ1Wu$Ta%vm*2VHoVOjLM*u5~>f$Jf5H_diVtFc$y- literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_2.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..82cedc55a0d2ddd460faed383951978aec27ea23 GIT binary patch literal 1123 zcmX9-Z-~=&7=FFGUhb^Y&2Fn+^}11AoMD75Xc)oeG`f0=T+|$^t{WW&*AL|g7)PB| zJMD*VD;j180n1jQNQJ;vcW&kAG#lACS-E9eWNUWBd44XI!*sQBO}#Z*Om3U!Tk6 z>hJHzFl=C8U~q8I7Yqg|isU#}6nROCD2kj;r!}omE>}#mZrh!1mm+~>K;Yexh&LV& zB$8w%%V>F_RE|~+rDkQDts+NYVa6@UB}6eRN%=&goXr}Af>o(B>-A2jgTOBXu3=Qk!&Uua zjfge5Oe<1sC#oH_-YvHm8uQ3acs#Vv7YYPLf|M9W;e|}pS(Yqkb2Fu~ZCc$X3sD|Z zL{BOjP~${C$?6%gnvc!ssfLknH_UGLK4JmF01AK#paaYRv@k#p1P&z?q!*Fh5O9zw z$gxlffh_rD`>8S$ex|A&1K! z11jleRi97{L@T&#GioQIcN5ilt+r5UqDBYz0v*6Yq$k1#;v$ud@oFkw%%!S&&NB73 zZK7_I=6O^BWCKEu7a51{3H<3~zSW}h+7l?X8W)L(@wk*s$`qNVNsXm+jxu<%E)eZ- z5Jdwhg`+%$DlD>i=lJQD-47oBz=2(3B8=R*@xIePJ-TJn_}b5ooZ5NHe0~Y%XtI9r zGJj#;!>^aEwtrjkvGMlr+n!r&Z&)!kcbDwj>*9Ovx(}Xy?fgfK_SS9hJEOBFcfYvz z*5TtyF)z|2qHQy?@=;pW6P?G5r=@ zKXK%0_l%aD`;uEe^vjOF$0D<1d-mVHdF~ZEbMg4x#mVZ1J3GJgp1V0d;97n5{JxQ6 zZ)`sF!}9(AOb0$adTGt)rzS_5AO5*+{dnl$sy)*?mrZGhH|}07WQafTLlSvpV)&V% z4@6IFc;e@4?AmgAw)4fwO8PCc04G;?-kZsOtfxbfyUbM@(;-o1R~=v9|J fd|(wq3%#w4ryre|UUSJ&3P!h%ZJFHs-tqqdQxfgV literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_3_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..deb68081d0609eaf9d9329ad18c596a0cb1a9d48 GIT binary patch literal 1013 zcmX9-QHa}g82|2icj@ii`p}1hne?Pe#&WJgz)Yj&cDd0Vk;{1*gtK6T;1%gZ#3+3z zm~n-b(TyNIDWlFF##u3AW!^&=WeX!{CshMG&JOZWu+D%3t5z)I9{y$we&6@;d-;Ap z_5xuLOiWHrMk0}^sj2Dd z>6w`s48x+)=r8I_cDN--F%&Xp{_+7`{OZ2P$+ji)myMkINK&Z?YR7Rn8|VXL;MyMEOR zn*Fg8V<9d=A_vJL5C%p!5}6i}by(GtDt*ly8ZO!u$hbn|g$!Adn5M$DHPI_6y_z<# zN<*hM_AE4TV{w`wC5q0mTtO5oic&8WT9t~^Xn3~W-`g7whX`;Lh#E#UV_X{-yJW7< zl?PcfD71&h-l!EE^u}n8jK%0gB9lysWLjYujTg#txUAT!R6EU$#4l_ndmrb4R0xhy{=UGyns@0_Xq?FhC&$4izX|DKqMx6?eC)_)Zyx>O`}tq*{$_l%m3eph+b_?pX*(02aLTn`ZUoQ0Jayx( z_tqC%-0>^e_U)zI#o%jt{K4&K`hP@Au(`DI{>PWsJAW-Ke0SmGPXF!ASKzD7XOByR zwdn`fPMrApi=AWh&%fr}d$jTTRpaROe_y)u-@%W!cJxml=?nk-IWhg>_Wis3ol~J* OSUJ7Ae0}Mit^WZ!RJNl4 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_3_2.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..38a274e595674b294f0ee30ee0459d959b33e4ed GIT binary patch literal 1132 zcmX9-Z;aD)7=G^`y?;2vqC=|b$qe-FhliRU@A=t6cf5#xkuF63fzc25TJkR?c z-aO))-@B+60OoI4KRnv1t6Jgi?r3Gt`MJvg9k6-hmbI<1t*x!Sy}hHOqqDQKtE+3? zym=Ugb$567^z?YVUN6JYg22nNs3-wVQ{(Y?I-Skutx{>qaT?7gLj%u&B=!XY?r@lh zMCnA5OJ}59K3FJfWjk4|83Kj*xjt3&#QcP=kXenn6c>tVe>tx@lZm=x%r;6s9D)=? zc+h1mr((sVtCDj!%Q&jjs2N0aIzlBcfCLc4FxBOX;kZtc2FG2Jq{&dI5{uo*W>K+- zGj1>Mp(TO~l0KF4#~4NDw2Tlp#Z*By%0bHs5iCyoyqrvl3L8)bH6bOk!K|fPcC6&2 z?0T*`TXgZ@mcbJOA_}CAv00BVPX>y-YWtH_&1mQ)bV;Jz3X4a4RMOAo6rrHWc3i2X zwVD}k6w|Y|iE1U6nY5}7jDKzw{X1+dGnMHk+%f)&;KEf+gw8C+kC?$feWzl>xHJQshCA(SWAt+*+ z?1}{mJxpbyyqS;-nb4#es}wW!N~zhrgLnWxfCiugm;jRiH4IP-l7ONbG7aQZBob5x zQao5ba3nx7Ak~AC3^F8Sg;6JJ(58LEmCzjy%8{*k-}`cJZDu=r9rxZB`_cD3h+c&W}+cckA;m?tYD_>l3903 zs99x25m|s7K&a(KqDA)*cs!b^)!0n>A+&N?2n6JCScyhehK{pznrBRbDT?%zMAiLX z6eLiLL>UHIJhH{s@w3bO?mqZ|@zD_(R^7V(Myp@6VR-eHp?A)twk;?P^a~Sc`uHa^ zOXpv|WnMgeVkdX|De7mKVpslF}Q!Bk==M>>g-cp{|rsTj_DEy!T@rryUVDGZM-%ST zSI$-a)klXm?P}iqxARG#d3pTM^RM0f>E5}o7A_m#yK?gP;g_MG{_f57@Ymqjfmg`; zA7IlLj~;#T{>c|!dSdrm=Le3g+r8{=|L7O5E*Yg36KGv}P+xmx=I3jBdUt)pjPHFc pbPWG3yl>~XO?>R)J?=x{!l@Q?{& literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_4.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_gentle_up_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..6616a8594ac43050fbb736af4a6a0c6a331c5a4e GIT binary patch literal 1346 zcmX9-acmNI6#li9UMngpQ!=Tc8;KZ+!+7dxP_LCb>~KBoIniRI^<2qHnzK3QP0`Va zlQ}dvaiXCeDzTU$rL#_SIGLUiH>T*Cc~zolh$T)_RN`s8OQ?0zr9s zIf5V+6&010l@hsJj-o1!1}8}!MHv}}w%hF(#qAOQb%D%T0=VshtK4T z(2=B#OSzNTK)MhU;Xq6Ri5bYOK;c3#pF|s07-Kk{G&s|YKj-3LKcN&;n3UBjod$J) z(nJ|DX{UG(lL^{$F;5{Ggc(jG#uQ2eikWc@OOj5C^0I8$>5Tb&$w(wUFp$gTAdu2P z;X%-VNE4Nk38gu$ab%4CEE~~zNi z;S`t5r*UA?Aq*+9nPe`D(rd+o4l?RB$AdOL=FRe4KK~fv02lyZ0B`{i1RxGT1_7`L zLIbS~4EkY;Clr82fg1-AEl3dnk^s^Y=tQBPfDsE!IAF>T-WZPoody^P#6n4ItkUh$ z2K-bsYELGE*=!OPwWMZ%T7|evLilB-h=NY3T{&Yg&qfQL#7HC!`J6%wFd3p%iHx|+ zLZVi)&SkUs-L`1Zo#cYq6bJKZOs9hp08;?Mq8E;$+*?TPR&OSQc|C8zBoZ2mg>N&4|WL7V}a5w(y`OOQj zM{}`iYEjGnwm!6%J#==hesS}(rueCMhSuvX=eWy_hsW%y{<~_$i<^9taMh%P2R^G= zpW5=xfs&37gtsb}-THmEZ~TL{&$rDsJ>7%MXsrodu3Mm}@(u`AOw}(42@fAdyQD)e zt|nC*#<$%U{^rcpItgV2Y)vgU} zU|-&Nc%qHGr!Nc!7S&9e)>5-=__t%59mkzZxlZ@F!qpa9yzwNbJ=62W#akau;kW-g zA8WliIdrYHuqCuy?EKKeT#VF?nKkmV^hx_-%6sVaKRYL+t4?-IR~$scT!8tB%AsUz}^P*OmShI(c-?n!d!;Zon@*AG~*eQ}xO=7~Pb+vUy2ed!dGGGi;U2*-Jm@Gp(cSSVd*n(7+xJUmUyuGWhVahvx!>ZjGqui@eRtoP z^if?v6l%vs)X$au J^)6}N@juH*W1s*4 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_1.png new file mode 100644 index 0000000000000000000000000000000000000000..958ca3bab27e249b002e75039d694ccf46c6eac1 GIT binary patch literal 1344 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_1.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_1.png new file mode 100644 index 0000000000000000000000000000000000000000..b51a07b3253c47ab61db9c401b9b050365e8cba6 GIT binary patch literal 5395 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_2.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..e57c81eaa03b47ddfe94c05c5fa279ab8a528127 GIT binary patch literal 1137 zcmX9-Z)g*D7=GK-UTdq_$YzQGkCBZN54p*0+~CyHT{Xrlp7WH*0=v$GW?OXk;pQ^P z;Mjs>HONuJ%p}f;u|#%g#4#gWhC<{tdM3eFGND>gb*jmhlV5II0UyXD z#5gb{te|3*l)GN=bZS1-qEJUhD+WTAA3y|Ah+;Josq6Y;E{7@= zAMNpTUP{DSnFy$4NT(Hp)v|oT6w+lWUz1Bt1ZR9yz|TsgpfF*TSCe8gC+A9P$<{3= zZMO=I<%*jFj|AQb;Bg=fjLCTeMIv0`R6CSvX!*8bp&60%D2y)_AX6c>pzvi)vJ*-@ zqczP$yOLS9P1Lm99)=)8G!xjWWXO~Kig@tyzjlib@k-_MKn=kvM z8X0Nu$!0j;ij~{OLZ{eTsV}1;((Puv-T>~GNJ?Q@O%RiEcUiocN>>X-$Fe&O4rBq- zB)2Z(MwHCPIWsAhvyrN)*DKjp-Rg7}5eE)!T#z7#s^w?l6Z(B|07v3_Y4p>t!=-TV~6# zP^ZBN0xAJ=0HLlI$u8Y9_!9AKv&m#L&!E+6d^jvcqe?uk(o}+>G8}F4bVZ;RM6wm~ zBN<0JfwD9zamW_B$IomYT6+2eA05~y!Hx%iPIP-bIJ)!T#;IecgJ%-24v!v3=FTtP zNKIe=`cU-Z;B)GuN5{UI!!9oVJvd!GJaVgvO}BJRO^GwX!5f#yPHqWoJO9^o?B2+Z`#Z;vPo0rYeUK5} zNjLw~PtDaH@823fua2j`Kezos>&NKTTjM`PuYJ(SUsTe(`qS+IjPz pjfc*CnZ3JoZ*IfyzwTaM!rot*ne?*jC%d{qaM!-kt8b2f{y%G%@YDbR literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_3.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_3.png new file mode 100644 index 0000000000000000000000000000000000000000..8b905d236a2fea50d622e8d37b1eafed1b86e00b GIT binary patch literal 1144 zcmX9-e{2(V6o0H6w;y1))TPtY6sdCHp~pP+21jzk8wL6`Rn6su!I}mt00os?<11l?qG1ashXPMW58o|7a&mc6Q~L?V$yB9+bNip3ezY&4rR1sn^a(Bt*m z0s%)bL`7q4A}MCFzI;I~8?kCF&6Aji?NJ1K*yGS-BBj#P5x$V{l(ULiiq_5aLZj%y z!AC-n15Ls*3RZ|&D;Zm}jH5b*nm%+-L#XHk5CMD`rdX|E9M=dU&9c*?Sn~TT;qZJa zg$f0nwmCUFB|2Ci;ZjIXn3gqGP4W?4i07qr*_Si@4hE-OPF5lXnei&T5*4E)pSEEqG^$|$qXKJkueXOk@>tT z84&{*$^}q4ip(_JH=Y532akvaWP3PB#x++aE$8zQ!_ez> z1GThpKhU8bPP2^Gwe__kUn~+o%M?H)h{#%`4m^8@3O9dh%!Q(T|q( zc5J;Ym5%{^xMB{n^lt^5Cg&hF)=NONQ^R zX$$sW-FIc?;`@F0ign8`L2qAWmiYDb@%};f{C6*3nq0N|p^I%plLxnLYVXjxiLuw; za=%NJKH1p!{*1<$qu1mNB{I&$Hq Hoge-WMOf)} literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_4.png b/resources/g2/track/corkscrew/gentle_up_right_bank_to_right_bank_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..77b24c5f5bbc63b5cfdb2696c3e7758ac64fabe9 GIT binary patch literal 1208 zcmX9-e{2(F82;FR+Zf{vMJhC;XfX|*@y`Q)W*A05o?jTe_-NXV#*%p}v;SOk30nKs{Koe06(moG@WRU0q#$ef`9V6DLiY zGuO>Vcz z>$Um=cqmLoV{9VHr_w&%2p3BVgCQ=eNpzYemsJ+*aUXFa$fTn#Jt-Elp>jbPuVfq+ zz+=Eq1DQh-B9acH`Gl#eTVNT7RUST&A364HcF$sEM>=E`s#XjGyDef)Mljli_eW9yc_tn9Efv6$mUMutyOh zfifuzr(>QX6DqltvOiUkbJb+|L4F)IVJJ$P%?_)L!*GG3d`>pR*Omp6;Yc=-EM$yo zkp{dI@o}icTV*d63(#taOT|1{Rm!Jh<$R`E9f33eE&zN0$N;DSWC1840M@`VFyMo# z0t?49CxMdzE*9|$X3395WJf{~QmLR} zsO7Q&Yg`r&AOcOaY-SZJui3={C0E>P)t?%V>JPLc%vbCtKw1$8j=E{9mm>lmr!0Au zh?G(zMn)|cGO$`Cold9$SO5^#ya?6k9>Wq0#7ZSH7JUq#t}|{o=k*GKfJop$5|7e^ z$`ENMo@24H%LaKXljj?gSl}2`u%H*GyQ?Vjcpr{_okxAGk2aC-Z*>Dy7=pD|8CCp z_FMm0&^xyO$d`AyzEA7!*^XB~ep6f6y{Gp|<$nKvKOSr^#gfD3lW$$vKFI1lmX^|V zGvrO=p4H_>t6rh@NZXtAcuDJ z48L__?m1=5q-9QS0_?*zVtFd@-23xXr9B zU)en{wQ+%d*Y7@hVf56kZtVkM%<;)+&p!5ztvja;Jx%WH+&VvZ<=sl(%UVm%F6x(2 zE_>;4{q)nkwj2MedE>m>dq*w~pxFgHJ}0}l?&|lq=Pv)|bLsu>mYnK7I4Ax!+ut#R zx^BsDT65^EKF|D0%i3gLXdS&dwdmosR{h0eTjWc3Mt2?Q8oO~@{2N>zO`Jr}(PxnM VCvCIO{aKSAbhLLa{kCmw&;N_;9!>xN literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_1.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_1.png new file mode 100644 index 0000000000000000000000000000000000000000..9e840387c4ddc1ae394eeda5b2bf41793928e9f1 GIT binary patch literal 1271 zcmXAoeQXnT7{`BQFSi%4!2%^TSfR$M2NrUZgPeNE4LdlpLk=iXpvol_Q<76|(n5s; zPgh4X4pT`3=d4(_2AizFFh#5Bk^%*aG-H|~6-sDa!={$e$rwX^mXLg(w|}1RAD`!G zTiI-$R5zmz05EA;Q{$>~HI?I~nu>Cs(r|Y!02N^6iq%WYqe`WkFkwPPMMY(0WmQ#G zb#*m@AT>2LwY9ZcgTa7dCW<0imgYFCAn=kT`Tc=NB$`O{XS2mp2{Qqb01RDkwQ3v= zz0+;-cnQD4gd(EEXZq@xbUu zu#lRH>DUx%&rzPdHCS-QigJG`QW(#S!g^G##GJX8bL)p6|3J&CW)>_SxVoj>cP?vuWA(!J zLx+YA3_UyXlhUKe+NZajS1K=cF1qqm!|i)bsm@1-mg~3Nnb`7nmv^9Vf9cUo{$JC)J%$f>W#_9w19f4lKD zR-4;P9{0?ed;z}c>YKe#WgWheRBciZE}c^B-0d28x%;pe&Ym~zG_&!c>bn^&TREv| z`J#KLj=wVa;M$9u4{qF`bVQhwUp}~h^!znq&b1?|e;Vc=v-(d|Je;~W{Ke(5-_O$1 zzmM;6&8)ueHKVP6cM#L$&ZAz(0$1hD_vXG}7~xy*?;|Xo`pfVBa&9g6+s*|K;I7q! z9n#hF56|)P#kZ=IHuYWnuc?Rs%kSLhn!_CX6j}G(LP~TZRGLrkuJbnJIo&$aB iS7P|R*qPLsUq#SZ_|tl_UH2FwShlpev3tooAO8<1p+sc> literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_2_1.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..861f53a4eb866e70c5823754834ad733d940488b GIT binary patch literal 891 zcmX9-F^HsQ6n?w2yUyO^Fk}jsv#^*#f(aHD78YLO-kHT?J5HiIU1`JqOOfe9PEhb=K2m>+X2oi)$v4lS!2j6>-uX!JQ-+SLY zy_WCadvFf`?q7X!`K+DqwRPI%#C3${ZmUYu`EQkWAN^dyqkH^%+VW++j z&ei40NHcp=_`7{1F_55N=d;JsNFY_w{0dvW(>V1Cd}=N-${I zVsw`?1Hqn4UaZVgE!r4KIih%yl?Q^xC?-F&Bx|Zp7sev7lETf)Sy3%_hYS~?uK_Uv z$^kmS_yr-a=wT*Wh3@a{s19;;qcVMyCnqxF>%!8MQd=uLa~s8vo+i`s9?;@9WkD2>3p<~-EB6n zwt3UMMk0U?U;_jIF~AyNj{$0-O31NM9HDZn(qM5g6CshIQ~_y#ECTr)id2-0(PoOu z2;KzGgCc>hVq=qVC(JC6mywyKUQxtVRiIXj90BL_#DGvE%1CId6oPsfH|-(LN2@%0y literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_2_2.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..48c96820b0a7c69252dbed5306a53fbde07e4e4c GIT binary patch literal 1100 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 C(z4qC literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_1_2.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..d3e98d71e88ec471371054b3c5d3ecb2567f4a3d GIT binary patch literal 1113 zcmX9-acCQL6nqFQ7~IK<#Bz4A%UC9>izUM_3;UTd_}=^8`{#Xs zeBV2{XEL~c-OxG!SU)iynCkM*ZfzRq?e^i~=a&I`Vb4o@cX!vGo}M*p*7WxFIvkF^ zzP|qcehk9~1_suyUF-4rd^AmQ94m^vB!v}4PNh=0T%lAdo94W2x7ux*0@e=#?+l0C zv6wfWpwbzCE-w^I5u>71txUb4aU>S~bY>TqOw2@1GTfxoEVOOx`XO zP^E&?ZXfHR1g}3r1Z6Umq$Sm_fr-gJOQYg!1 zD{0zUt68jfDlQh>B6ysF*2WE^|WZ@qjP$)R>?POX1jeGu>c_e1waMR0py!rc^-5Hw*jP2bv{Y{o1G&esI_yPU4 z|M~bc_rD|0XCMFie9vfR{N&y3=A{$=sGFPYtyBAqBO{}Wowr_ld*q#~LudM~KfP&8 zqqEcdhga_WIQII?yhyI+7jt4&57Z8ukT;F`@nDLh<@aW}Y|FIj6 z!xyx}H>{IA?=J2q4*m4W>iM3zFPwi&e!1)5R%yqIGH`$6LH3ubfJrJA?8QcFtVzX!154;}MW-%WVk3*rP%jl17}&@# zQeC4{w?tnP!HOfLV0Givja>gyi#n{qsJ_=kwlM zV_Tw&hi@MSfW@0Ot{?B!WxWV_2739)x$p?U0E}(kwxKun_4W1l_YVvV3=R$s4Gk?? zvOj2UpyX2Cc~*T znaweUqEN0#)tXv&a?O^(5m=1zDSS|ig>@M(snm3as}*APisH^>+pe+Dv7;f72uQJ@ zi&$B~YB_(S9O%|Vs7<1-gs$oc*%1H%K*BJ^@7F>h9mfrZnHGeZM53W-mr5m6tA(gQ zgbk8Hn33?PLc}ym))}?PWlTO_6^*)Nxrs0xBBK#TBzT#QE1Z%QvL&fxDVC$zZr*8^ zn+r8R3jq;=2?(bF*D<;jj8^b?ja8gjuBjRw-A2;_5s>LnDoW&HOj+its_10oMnP?v znNF>+;Fzdo`vWvi#3(w!aw$>F$#OB3s^oIDQpvHb=Im^z(?JkY054!v+0Ru&Vx34d zxoj(Lv{TiNKHIIduQnEtkMR5HU@#hvhy*D!jLHjHskba$$>nFt71wsUO%@~`Q$@cf zh4my+OtWTItQHe9rq-wx+YP(hy@XhR7=Q|(1DF6a04)qq4+4kMDl!e^HUu0L3i2#i zQE&x7A|NG*auhNIWF=8Oi(CV)8&3nzK}^7sa!^YVc|BS-OsK>OBSxUjNXZx-Bfjk!7KZJ?i21A#>NM3-=5i z=$`aU&YgetP-XMTE&ckzRjuhCw2^z+srk46z2<){c67xT_VU5GcRf4*n+Qx?94jkd zK6Ufb;JE{bPI=Znz9v=QbM4LBUcB=m{Mfk@ORxNT-wVu#%e<>rKGW!1X{{zsZ@(}( zb@=1C-(UWIiV{bQyO(@$fVe#W$4%|*iuZ zpHCN#tbJqO{;y6v`0V)DXP=b2XX+;_((%(r|9M^-^F8tYTu`l&u>)%Xzt_;d3XQo VOFq&9{XK&95htWaDBW$WMw&C8ZB^+s@2qS z!x9PJeOM&7#>~M~vg;Xe8g-NPboiOER3CZ`~_ufD6`{VoG z-qp?OqUj~m0RTmf4Rvd>yfRx0^K-KuFWKq?AQ!A|YOT+%)22GkWlpfM7)C6XRoF3_k78A8lzq;?u{8_|9X9&~CVekLBarsAH-bVw}$ zIyo?5z)lIgj38(e#=N3TL;_O^n9;#0JA@$_03-l9fq)STS&77sARd*fpCrS2eT-!% z+-?{QN>Gsu6DvrmN{6T!xrRk)yUOUoEk44*QJ#n{5Z6nU5`|i(qT~dv)G|0@C9Q6q zJHP~@Y$)!Cro4&Cpb!Hh3W)VUY6gg1pmdAXencC@n5f2E(&;n= z5(Xen0qPavoP>(V^$FaX)Ou1TE^Qyl_)}A{NmwWs3YB89S}LRD3RYQoBL!GGjg~#kurh9~%q0Qn64bGXXIGGyoU@umg~dK^TCf z0KhCr9GZ>L=YjDUi2w!#4h#g;AWi~E0mz7<4TT;O1`IG_g>esfY`hW>IM9#+11)Av za)({*_0Sw=iAH^?R1{{lBzl0F3o*Nx^hk99go&%{X{|3~;wGJusXzk8(ufEsr2@4= zsKulP3N`BqJ8SSbSkC8&hJ2}b2xbyWf`9=4;{d{}7uKxY6G$v(S2C$|IiJ87iQrl- zWiZfYGlMEDN`(_ceK;B<6eFZOrIA6M6tW0(p)i2KD3J}nva;~^$3O7anq~^D9KXIf zJ7*f}YFiuj9zNL8W0^mr{wBP3G-n%sXN6Am)as!V-tG{2*n4CAo0{8y_C7ju>Wcr5 zk1}Z2WZ9O1E5&!qHf?wwKUF#0pZRJwG9&n}rTFW8ZPHK3UFGA?%Enr;-m;;~JeK$C ze=S7?EbshSYUuQr^)BhR)g48*!ylfTS^J96KdWUnc_xrig5sX`S%%{WixUC@jyOwkvn!V(oO@Le2*}I-N+g8)mKKlKfpL$yAmhY@Q92O7w z{f)*sqxQk!#lJ1%)Ajy^_4kh~o2QQ4vQ}MhEq!L=_E#19k?t$+-FY`J^@?AZbj(4p)J9p4Gb*5ahVAuACS10Dwuk3&I+Kv+)7yjOJ zXjR9=09b*3zLm>cy8c)RRbyDOsIBSZf#RZ#`(pRILHQA?RQ}7_dz}yXRklb^!E)i# zm(CBIS9Ep$P;qYl>+9Yf{_8=@3*8^z+k2JAcX4y+rjwCAJy=)K(X|*EzWJkj4Qse? zVPBtV&)O^Rh^np)wne*s{;Y%zWtbKS8QH-7LxZP-z8 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_4.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_left_bank_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8b168aaa86f67b316debea5d9ef02ee1e8f7d8 GIT binary patch literal 1342 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 Yd*gBHw-fuMjz+L;>)7apEqjjt52`}xFaQ7m literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_4.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_4.png new file mode 100644 index 0000000000000000000000000000000000000000..efa5f88c3322d1c40c53ddc55be3ea952c354872 GIT binary patch literal 1225 zcmXAoZ)_8F7{`C5TW_O*F4R$_V-;&W@q(uwcw&>Ca3dWSdW;*nzzHRsQeriy98gJ3 z+Ux=yspcXLDN?Y6z9^<*gA*%M>7d4jG;qkkPA*ubgoZGzSY*nCpCu&U=ii&>`{MIF zyH>cJ)27av3ILe4w6Aw%v*OLb+Vss_*)(Se06kc-Y+y-q)ai6nrcBZ6^(`$et*xyF zg8@O1wzjtR_I8WiZYKzwrYV+n2?8%kqAbg?SR#|j77C-9R&O*298eCxxQsk+_W5l7 z03MDwVsR#w@#OMSNsUyhNg6{qhf#D{f}Bke(1b(`%XB`*l`^7M4A->eM7`j&0uKiK z6i`?sB_jEVshl!5N>*6IVZ#F_6$lG<02lx~2qKzHL910k(WJvM%rHf-w;T-KOeA1F zZzarj%7QaChX-|v7#Ac2#UaIMIqiz(*ks9*)x0*+iaYHN7IO(CFVbR|2`4;>te91U z1ud%9Qk99ki2`O8SiHa%0H}hH35zp>@_9;BxkyDy)|CPrW-zlrTK!He!Z}g`os(Eq z7RoWHnwIPN*o2yf)q=@Pq8LYzUW)d!Y(x;^et#ws$tMzOHd`4Tt=H=iSVe%w5F%xw zb5^#5c`J0d$|r07TwNJ$WNMS;324MjCemVY+UzWb3l4|mV#1#0vOp#hEv7PBL2Xnh z;Bg@mYYKX7iVuqisC1ak#l6LJu$+(A%7sSbCZqu10FVGs07wH+1fYrl*c3ymy=aB zU8||E>1Fi-B4DHx3zM{YvZ$yzlscbo_;VAn(qy&*%XQQYNE_nBO+01uu|&Y@Qi8r@ zG?+_A)k3P;?*h{k3Eu9D$zX8`g}qlAQHGt;xURy z(?s5dk1|+|vqO&!22mI%V3vZat9kt7Jmc+$Kd@z`n+303AKTdM{Y!fn4fO3gu!`UP z!;@`y9&quePp_WQ`QPQ8?{u@r`iC!m_|eQGSLW~S=;&J4dfPFw49AB=9bDh5%O5>F z>(F0|dq?|DY`S!47W&k>dp8zZ<{s}*&o5u=p34vIzO?BX`ET99f&1eoaMTE9uiAEZ zdx(9h{ahQjN9P88{V!~oOYdK%fA-X|H%mRK*&*3qytm&ya&lbS9D1Yo#Qv@hy!*$` zx9PTgJox_G>wb4fHZS~H4<0X0AA31f{_MMJyFdNOy|457@>{0|l?C10s#9-$)5-7H zs=FGxHO8;mv6g=Bt5E+QN$hzS5(mv)cMSi0jdX&0hP^{O{c&w4_uJ()UzDw&?;t*M z@v)=(T8``Py0cT6p z?wa?+4RtlC>p8IIT4|_O{W$x5pAeddp82K6IQ@Lj$fP;+$_It+!^f9zJtO}+#}KSL lU*FPl&erq5^4@)@J88Inf}ekKxXA-7UE=Qja`F1X{{dZk6ZQZA literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_1.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e564cbce9886322ab6e7565c691d0cd559a175fe GIT binary patch literal 1285 zcmX9-e{2(V6#sTVxNgfDVO98lZ=MNe|*frTCP7`IThvI-aNq>&4`Wfco6 ztdIr^o~FTq#T95+4HxKSuuE2;YG)=?t)znz>!@tWnt@oci!&MWwS?sJ-sio4-sg|c z=j~r_Hq}-)R09BN*Q{Q-p~NdnHCI_)>QuuA5&-33{o2-5rB$I&l$Dj0mzP&mR8&@0 z&YCp~K@g=1?)8EaC=05`dv=tX8$d zp>w(nULO$%GLfh)78jB!Uv4~1VTgsO;c1QAq7ykZB;frXDju*TqkMMQo6m-)3kj1J z*f8KEfyg2e9*O%@nTWcW)WW<07Hx1wgfO88fC0dUAiPTD)@nr*4HHB^!wlQ)8MpgR zC8&S-H8|@_JWLY1_1)a{Q&leAcQnH*&rwfGw1X>=T z0R)ezsF;>bV)h*69k+(_&R9WA7o+)^%rvaQR4SuJW76qa%)k+ZKr>!j>6k0(^AAU& z*+ibdi#mjRoz)k~h2!JIp z6m$tt3d3xMK>?2gKM7!(o_#vI8c)FdGIBjW+_C0u}~wa2mH0^NXfP zn2W_csg#t@r(j7-YX`Wih7>hSSZ9+_K1+xNt5kHxrUS_tIR`TZR1J(e#AHxeNu7hm zU3OY@JHmc5Fl}h!sE0d&0u+p9@=!!jlv)fWfG?7QuvJvYVJM!fsPGk7Oa@K@m^`}U$gSn z*46t@9&()ZEK=?ph1W-3a5aikxt~1qj&+VCJ9@ty&^=>Tn$vJgm-qSe@{-=Eg$jGy z^^vi6yX%JgE*zKsYK}&?s$RadCt$YR8v0i`XJStKtskc5@8PwF3+aJ@p}Q5HPs~kt zMxQAYOdcC}9 zo%*Ay+6ULK^_d$xv%gg$TtjVo@9AfSx`7i7&BXi@uk?QVRIIsWHZeLB=ulogJNovy z>0?tn7aeRj;ix<`S|70QdvU?M%jdVX{4sI!=fS3fhsJIT?)$sys?OCv-t*+;mrnb- zI%fA6wzPM&wqw4dar3=fxBq#p$^K?fqS4)aDZil8pIj!@RDURJmrorxZ|%hPE^HpG z4^L>msfb%1w5{G&-*b1EP|SW};o7dA$<6l_D*EqhlcRtBTJjRCS!G^%=Cyaa{|6;$ BJwE^d literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_2.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_2.png new file mode 100644 index 0000000000000000000000000000000000000000..60b54a7c6c39be6c8556e5dd770ca2a3c89780a8 GIT binary patch literal 1114 zcmX9-f5;Pc7=PZMx7QaNF>BUEM=hIl*%hZ9xZr%f_hr3ay{GS~6DMA9;G`)Ro;hjQ zk;_J1FNg1lSt|#gv})wU*ScWP-dZth=@A2`ov>iqus51Ha+u|}iST)T{qua_^Ld`P z*G~l(FM4nh04$z-etf!DAL<3}8tCOM=ZS{_24MXQ8z*{WUteE;fB(S1z~JEE(9qEE z@Gyp9E|+U$WW?+9`DmKrI93#SSq`hJl1L=d>1?53mCH59X?Hp_1#AEWel#5RM59D3 zP9^m~IwRx?Qn92~ZN1SnIT8y6Mit(xg$P6TXH|MG!IjdXYC&--$(Cbw+vOk*5(zOD z3=zvISV?!+bDmBWM=c62!b8fDPi&Zkx z;F8U-*@_k0My*q5-KuxdDCu@HUT=`_i6kWl0xB;grQWi5K~Gh31*dFx8Z1aWriyM& zB8(`RiL?2nSjRg^c8Qy2W8(2!!m z3W6g55&|;q2O$BA%3du-ri@_Dl#9iLZRcAp8}+#G2+;9S z*6<1@Az6OK2^j5gz7s2U)74v61J&Dp4=@B4q}*Yah>CPP!W&xDOlie@$}Z&yDxI$A2hDx(^o})`VRTIco$cH2X zX?~QUk;NjL?;St0V)U;&Kd^UtN`y7PUD(m-G~9Q%Pd{Kw^i`MLKu>2C~nm#lg3k#lqNmqvd%r0?2%Bl_nFVOjZb{1T^)aC|FzXGzI$_fN?i3L^~7`6_uYHp)SJJ4 zP*}OsI=gh1Irk}Z;LIz>pWW}N4PBRB8%v~T>m$qQ)w@bX6k?>WA3>hz77*H74UaNz3gzSE*H V^VYxXq@F-9IWaYUV(m)@{|B|l>g@mk literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_3_1.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..d7ec2f4173289a086086478dbf3acc1e65eeba21 GIT binary patch literal 1028 zcmX9-VTjvw6n}TUyY#MZRq8A*a2-_0AWA>PGlSxCGk12kjLWzjR46Qyfc;P;jNGWB zVAQI0t0Nye>9lHx`A{Ta)!U3vHDiI@ph%{L^;p2Vb=nU@!-!JkV1F|PzxN)$FYot* z-+O0{t!8%3?VSUFT`Px|)`Gbh6dn!*edodHZGaFQJG#Cc(20qO$;ru3C^R)SH9b8& zGc$u>SU4P>ot=#*lSzt7u`DA9oFwHGMJ|`i^?I}2Hf_7-x}NV-DPYpTbCFywRwyKj zrBtPwt~dBrTkKd$*QpMMI!j{NbVTOjYBr%sL{p(Q%dAz;cH6SMRT;VZ*t0V@h$Ivl z&;+a{V^%fVZ^isBjz%fui)cqf$W8+A03wFT(Wr{!8bRpk^d`@5<@0@2z1M6a%fhKx zl8LAIL|P;=GMQB=NlPmYwrp^Oj#w%|@F%8Ix$dm?5j#bW378ir|!`eq9+F zWzVXQ9Rm&RXpAPvEJf!TwkQZyNoo{}?P}F(HXYL(^m?A>A;4uI>KN6EvK?ILlKBB! z8Rqm+vEykyzdhRNk5Pn-M(KDwlSm3=N=l~{j<1NpvQoQR+iJC4+wlhsh#aN}QB_Q6 z1+r0MjEc}{Q<1e!^7Zd;8@7=SV4-bMY5)4TDsKflpV(yjT{tc;d!7+5k`yi zdO|b_*-dL+&hU$!alN}^4p84CVn8RbOe&gV5(R-OW`pwyKF8e6be$QBvYv}ovJgG!BQ5N>ha_#n?zy)sRU|J z$YhYi1;{lK}O&mY=t?|W?OKh(c+!hdStGp)V1 zE?!z&zH<1l&ktPuW&7HG{qEb-AMTkyIWa7L^Rnq%8ym}uV{hZmnNRoJWbgh+Tsr-e zdHu@^S3mAeK;@i$;n&Yz55FqS-FoX3fAo(V|K9(HZT;}z#!2&uH$J+VJ9uj5*(bl7 ze}BDbo?n>!{mAjL^vUrz#f3WuUwE%LRe1MBC-nW}^IwFIE&T0x-0t6=zs;PD9J$@! eANu-QNPGJ1D<53GdOdItE6b}(U%hnVo&N#NeZaf` literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_3_2.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..268d2441d768f30dc975777c2dd83576a7f50840 GIT binary patch literal 1164 zcmX9-e{2(V6o3204Z6{}jx=~kDGfH}AQdlqXo&~hpe%>Gxf@pL%n>e9wVKnMQbH3> zsZd72L(42uvB@elp$Q!f|E(=<@DL`*7a$P7fjmXLhjuYcYr`F!3R z8yfU<&v|qX0CW$m?;mc~Rn2&;v#ptzrH_0E&;~;rM%FgRmX?;**4DPRw)Xb+j*gC5 zvu0r!*4f!Pd-iOr!{H!F7sJpz&x)c?mZfkw9FHfnS*=hg8AiR)AYDMafn!ZRpCu5m z1w*b#)E!T7>8y~;%SAm}siqhL^SVtEYgN29Rdgn0aw^Q^lZoz5Bsy-}e- zU@@6DD}qf85Qz|-iSW6Ee>$U-^NCuy&}iI3G=LXC22cSq0Mh_f3{VpsgF-UOq>xeO zoFI`9qe1h4!2#j{NmdjkQHn!a02L$1NWlZ+DPS4!a#%pLDnTNqdeSK|mkaB9rdHEY zlMD9)88XqTl}p(K%_$jfweHI_g1MP^@t#&e<+{@XlnwK^%s$!{;K`7mRh2+0rsOg) zy^yIH1=OfeEQ>Ti1|Zb*BGROL2s|80RI5}X{t$Ap$oPDGARvZ966p$4t~gC*7&6bg zN*q!1I*?#PiW4PBq|r!co5xQrGu?jh1MdwF^04a9U$-{<=LY&$kE}RwY<%^OJ&U^f z&!Q`vcE2;Pd*J5r0SI{M*SB4ombdmkd86yv#$)XVOZbJEll!}F&vP6<^zzMaF}n1h z_3QTBFy=m@o$i|KvDcO^w%;vmnK-xnOy`Mrzj^I%(+4M(j80CBOZzr|_U-23Ij4Rs z|8Usm_w>BlWAC_n{rP9{wk=(|xAPZ&|MxI+e}Ct--s_+DZF^z^^L^KZX|?&z!ZG`s zN5#>eb8CmMjQ{+~{2;Zg_x%fRy}gl`+N+$mC&;IkvwQKcT7LU@;hC>XJI<`1^ejGb zYI|UG&AP|;9en!Y&}I9`q0>8K=!LN_zgTnn$hydA-*|6w(UHF7w(!dTj^5n;)A-8v d1^)Q1{N)9v4fYrBq??k$z}mt7lWR8b`X3mS^)Ubd literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_4.png b/resources/g2/track/corkscrew/gentle_up_to_gentle_up_right_bank_diag_4.png new file mode 100644 index 0000000000000000000000000000000000000000..e1a0c91380ecb2976f855cb7d020fa064bb458eb GIT binary patch literal 1361 zcmX9-e{51`6#ZICUt3n0!;UGgY$X#F6_Z!@oUD7b&j!2K^wmBcTBfKNnIrXSUsqg+ zVI5Yiv?GpARCK7!pt6ZeV`#+=Cy8Bx9crC)vPvymnLj#as8(&}H;l=-_uTu>J%5~Y z+iGi+g#|MT004zm%a_$1J=fPq+ygqEhe}QfN|%ZCa^|MZ3&I(4h+Zm{^}B8FNphLP`

Mx)q8pit5wpq9)UQ zmkS1iB2*y3g>p))&`6bxOl3l~HU;Y>%wEzSpxt4OKc*97BDqqcpk<^MQ!@l(p)4+q z%g^{DrclftNqXWFK|T%yG!W{5*a)OH1ak?MKB+p0GZB?F&bm{!5bUC40xc#oC}mca z!lNYuEFCdxqYgIVHK&4(iHH{_LVN)xm8nonhZ6>xwraIbgTZID23@X*-ya_sNTpH` zh!`MsAgG5=1VnULri&AngxZ}n1X8wvv@basoq#+UpN|QJO0k5N$+ZdvOHvk1=9tlE zwfA{^u}~x($AN}KSekFrh;4eA(};U5bik?W^O~YTXEGW}r|&}?02Kf%05$-;0Q3Qn zKmg2uBA}6lUN?+IDJfu3V8?-931Sq0G=Pi{T2bhxpkEKe78rAb7sg|NB!G%S^je|G zAhX+)9=A3SFh?TZWHJIXS|S}ljXc~Yq}*bSU&_Q3wv^hNHUuUd;YoiSMpIG&z{H4B z&R64NJ&hW5q|Kyv+f4zlJreRJV880juxt9=`jm|^@b2?sv4TlM} zn%3*JMk9mD&6wPQqh10HlJWscmQ+cgMhs0-=tQ9(hY>Oper!JP;fo(=s;i+v`RL&0 z%nYlREnT^|<47mDKk?QpmA}KAbyHmR1{MHdDh_mQ|LJ2i(0-uUOMhRQYdJ35Z^ep&y`ipOG z#P4iqIeE!=ciS`dyzdG>TQo;nYAq@M==1AOz8~9FoIcukqI$9Os@=WrFwZ^}+eo-D3+!&tGh6 znOfAoCUEgu?fB4}XTPnz5zk+>@9MR&dH*fx9-ezayXsD7Nym!Oou2-lrqzMo!`uCP zHqSXlhKp`Z{uV5E3yT*f&c9Z3`Nu7t4~F#B^nxo}uTE;+ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_1_1.png b/resources/g2/track/corkscrew/large_corkscrew_left_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b350782b15833bd7c9a25a2323342b0fd8de7fc GIT binary patch literal 1271 zcmXAoZ)_8F7{`D6!){wwORVvf2Jc1Dq8BOVgo4E$avOyla$`5GvA{`A=|*t}DY0RF zQL+-dt>S?NDikPEwUNTg7_&$rm0fU}MlVY>1uxiyGO8dc&}hK{KTAly&%Za%_r>RV z2HICz)y*@S0RZad%UV0C)mV*Ljdj&L#}ZrvKpkjb(b-lVYieq0YisN3>gwz3r%jvI z(9nP&NMmDTQ&SVF*Xs$wNKquq(mZc>xdflj7YaoZiKHZD6{S=z6GlLq0Yj_ocCFKi zxjjaIz#IxQu>_Y&yE1YhUx-pTVl%4*8ui*RkvBwK#E6edhisXIpp5&AO0-gvtUAEq zz)b>?MPdSy4rp>QZ8@WZMI$V8a7u(w(gVN%z#)jB(Rg(_(O`(0%_9sm?r`M1-W!n! zOs92(R!^cv1~YR8tAN|Q1TUIhVagY$gDEze;gX62GwF<0y_v;n-eeaj!O!?3TqG$Z zWv`?JH=c>y*i9m2XmQW%F3`0F#~6S>fFKEyR-iBdvH%Jw3=lBNz@!sq{7{L4N8n9>rhtt>oIL7v<3Z6Hi}I6s@so#U`xkJ7A(GYaecM_YI*A$oeOr1 z?pF5p&24GB2RXK@ck0Rgbl{i$r{=Wb{pGn^`-U!Gy}EO53$poR{SoQ>eSMGbL7koD>>VVP~|CZ?YM-m);*b7^L2VnfTt72OvmwU*cZ z+10=A`kq0@k8A(kRN&{WA3EGXuiaKYDaH403Vo_Zho3&ZTm6h23_Lvh+;qpf_M5XN z*O1NI?=GsHwQxjzXrMc~ZSyNDW)3aw9oxR!^YF``F5enNPgF*JHB=^atBWta#UJpz zdAon&LL)`o+S|DAyLT|t3p3&a6FcU0kM7)bC|qtI`@z!j_V4+r1B!Z77@i-xF=d;v z=Ly;A@1;&IKwG$8_ULCrT}Ll9b)GrAFzcWqy12=dsbro@)nJg+F-x81?Py zbG_y-nx#8`EM9W(#kJvc^_9;DPc7Ut_?LQPd09sgd+^bzS5>V2?CSe9m(OfmaC-XP z|6HGB)V37ZdhdQ>)q@SYmfp;E>9@K^OV>x)IbFxU(d2K8 zX2q)KtlDVjI_l&d$lnnK^T2 zZf-7uAOe9PFE39llgThlp;8ePrC}JI$z-%ztxl)g=ktd`!?9Q@oyHV^Py$kuuhWSP z2C3Piu-TPP7wPrUfuJcIvBwi06^dw;`9_VH)k--=?lxiFR#nic4f~9-L0dBBnM#G! z59JbXWqD3YezhGzVcw1^@{FjUYy$kd;U{x!j{vc9Z0wULR%I z3AY;tgAz<6Bg6_)s-)#=BdTRFhEtkcDl4yX1Sn6K_Q&*6T%u6RloYCAaGg-wN02;;6jzJFz{RSAe!I%fUG#&>U70{B1ff2K2 z)WNB}9wrd5Mk0JN8G#usi5_52sFdfG=8t4Zw1|ZCMVav$9g2ZZZB@(#H`3k0RSf$fZ z1_NWU7%_zvS2zibS7AYoVwgmeS{bCJkd;Fh2K@w#Xfol)-^_pb@&|S`)>B~h*vLnj zd9tp$YC~=NKWD-xttACD&mm3yo%=|>#(M7h@}kNIqT1Fo#UN7r)~J*JY@N|Z7X!0zvN%2 zXjwPVRn&C;?LhA}_E2$uOSEj$M1T7q13k~SYRV=Wq9@EQekk2}<*egm!=L3}$<`WL zyZ$R(F^IPwE9Fnsp)3DQ_Ql&5RPLy_bMEHO!X%efwG_X&u;gkoJ#b)F#dh6c&R%kY z-9J7$fw~3?(d*y9)$=c>JJu~;Bp5vMyx?N`mSEHAijMxoTdTHQ=BDq?>nPK#+O|7z zqr9{HboOM6UK%cPI)9P+y4%uuRD@^wYmUv=Zh8(-^Q->itNbd}tGdhqJK z;{|=qKN7zchwgvSd$cgG$341dt>gaoT|;BbwC^qayy5qz2YXf!StGwb^isQB5IohISyAN(Jt1zMH> literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_1_3.png b/resources/g2/track/corkscrew/large_corkscrew_left_1_3.png new file mode 100644 index 0000000000000000000000000000000000000000..9556fbf2fd6cfd35c2899184b2b3da9345f8809c GIT binary patch literal 1219 zcmXAoe{2(F7{}kOY_~C%f;ASXa=5A&D5Q{64sGPX8+1!`x9lKQ3pvOE1!{5`$E;HH zh9xOWT`tmW6`N3!BNjPW6A+3i?4}h5Y2qQ36+M#%s+2fq#l~!~h1U|2@AK=Q=ljR! zdHOm#oXxWr&ISN9x3{%+RjaWYZ4HKMUbKll4S)f3zPWLIb*!nWsjaOw7!0#!&8n-b ztFNy|5Tv1@p|P>iY_(c(+)hy>!?-xkBM5vj7>q{a$z&>%$?1BzQo-$jbO74b{$=bXHDpd5yC4agsN0o?o&YWixM{@4nMJ=XA~_Q>mre&Y zO(~T$SoN}a0Ul@~B{MCfYzpIbhg9|`6@Pj%nw?G+V7`o*0D&S-yU|0UJ_ZkXU6SaN zBVt;KXc?uXXJDm3xLhy=pbj9cvIte}p2!jm#EL~C7JVWio25J+#^>V#0Uoyp344^p z6$)2f_8e_1xvh{zp@_j44pSu5T-DynB6~ta=v@EV%}J|9Q6B@9fW`r&_wo!-tP5L*2Pt z`@?l7zIOJ``|;M$lIt(US1y`=_~LKezXuo0?Q45z?S1h5jN9_-mSYD`EPuJ~;lh!b zQp?if^5cf*)!{-HY?(~Y-5h1&~iKD~Wyl$**lp4m1s_c^L1^xwU;=Bq=I@Q&To zBMoz*mma)wbk%rI|K-4*jp;?mM>l>rvp07>MGgKr)wAX7yq3t*__2#U z)8vb)<27YAg*@Yl_?aG5S18Qv!helZZ+y*SqDAHUMg g4?j}o49yrXT%GtfzvAr2RT7|meMjri8(Tm5A0Xuu8F9jE3CZ{Q_0RMD~K%=?Fqk(-g-sJZ}+2!R2!K{lRE7mP`(1v&B-0&;!ZB)Z6V^ zhg0wN82kY?9JR(1Vp{g(@*x^W%m$Ufs3o)3%VR;2IO(Djesel1WK-@!HZ)#L8a2R* z0|y1X91<3gga^%p>q}`3Ea+j$3Mae}CUpR?09X-3Kv7Af@nTrWU^vOLDVr@LNjHK) zm`G@ddL5>16n7*ya*Xo8>5&dK?$CDm%9R>$Fb-e3?J)@>~>b4ESBR5+SV z%B36ytPCP@sASc8?RdaRMciCGU`s`$Od?RoBuk|mkOIIAfCzvWfCvC70P+ZcWwA7L ziZBv_*$j&TfdD=V#Ec-z0>}X`#xNmk@D?qRk|RFuPfx^hFjK_p0jWiddelN`?Hu8> zF`hMnA;j1+xxXwNS!ffPgUy%1rtA$=RxZ?)^ab@-_}EyneZ}+#fNuyx2Z> z&o?X5`(1M$C_(sI_4=*Unn6wHI$y8z?BL8x;R}cNJw0y<$Ss+d>^qG%h97?y>sUJP zE-|NYc+1A#8Hesx3@1BVwkS-`MUK|auiUw~UFrGi?Y>_R)y;UXL0L0QjGi%7RBHSF zyY@vxQ=8KHdaAO0sc$WzJIXbV_t_SbQq{CCU*3HFT=U5BXJ75O+BkMVQtWEFe(a4I z-6PB+%&nTP{z}DY-L+%0G#$?j?Q{>l((~~6felBNe7AOP*UvH2#NNo}HQJujBke!! z?l;HT2S=N~y;(E++^R*-kF~CAT<`>*p;h|^R=sm^O^QfY0=kzE4{63NDKRErju{EbYxjcBA jdTG0KJG=hxTpm3y-r3gh`(K_iIbdpSYdOB?&29e!;3h5@ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_1_5.png b/resources/g2/track/corkscrew/large_corkscrew_left_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..5c5749479b65d5aecee866a93f2198c1df3fc33b GIT binary patch literal 1146 zcmX9-UyRdq9RD82(c=!BX2_DOrjikh7Oc`-ifN=mkBqY?#Vclpih~r{!yq*&xj}}R zamE4T(uXB3ICT#t4pU&lVfHZ0B1JB^V2OJeq`!YyLDAJi2mMg9+^1%3_vez9^0~^JNESS%$ql_x3_ox{P}%- zeG3*Wz%Z=8zklJvg@Ir&$S|}Z@Ukqbs-o*!DwWFR3Z+unw(G9j?sOO$cn&0SP*MD` z7!gm<=?s_4OT|*8Qq^ltrr9zD3JY_Cnixoi2}30dIy03Ls=08jq`A{+&oyV;b_j87pd7HREd({hb<)JQ{T(XwE>$4gyF35e(COz9fztBx!Qolq5|@qm5+pZlQpx zRh;n$`2Z~uT!aj1R5;0~2B+tRlqF^>vRR9i-6+B0bSTKll&G?bCTM9XU5FIQTG>h3 zZr1UN&DpAt2fqw~C=dxC4U8=WLM2kE@|qLQG&55SQhQs^;VIQYKR^6r6IoS+BR-Z3MUmWDaABKB0ok zH7eQ^(k;dG;+3{h@07f`#w;47d_Fc12oXVl7JFAvP|SQBoZ_R zvOJVS;7WjGKw1E07-UMQ97DAsK=oCxmc*YW#sz}!*$_ock zgg{9WZo?p7?=SP7j^Sm;>O8OP8M&SP7%BRIpK{B9W$bHN`B3S z?RR#}{Eok@Nvl3Qz4yIk7uRj22yyn(xtX_E>$ji?(w@q#)~+jk&6%morze&)y)7Jm{UUv4W@_^BHv4c_Kp5SyY2?)U?VtY-u7&`R literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_2_1.png b/resources/g2/track/corkscrew/large_corkscrew_left_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..64e3878fc4df56e575df58954f67faab1a3d2952 GIT binary patch literal 1090 zcmX9-acCQL6n<^iUfNjWj2JMpDdvwbj*;rA=ZJXSt|ithxzgK=GuYFe7}#|j?l$vB zz{nz=U37;=8!>JH?~ll?8l<>$gc;>V17_}^)kQopgTR6mOiREh1%GA?zV{yAKkwt? zdvAF@8W|gXXcPd(W}ls2=+7tn^?=jS?>p$34FCts&mEcR(}973!NEa?!?9=2o}r)pZvSFH=w%zG=i4ag>U>R3D?h!?Q zG8Iy?;e3HDmHA3lu3On=OQUft7IsODHy!hps*Dp)QYhRfNm{01LolnB;b+eLgi9)WYF4maQccjdXgeSVYyT zkMIO2Z;17W`CvrCV`)NA!*YSn=uED{X?5PP6MoVciUh(O&In{&q9uh@ihR+K3@dHg zIjdc2_Ns0QJREov;7>tN#mJ&JQVzzelw`%SOZb5=%Z zINUls8}iqaLXQb^SFbfa2mH_UE#3sC?u02x39&;e=yEeuc}ER9k!(lul^*dRy* zC4@PFOw>?T4W)A7jnH$$K#wR3aOMtgfe6(PZ2szRGH8wi??F| z#QRY?hzbNUC}c7H<0lWecJBPZ>4hiirA3mp;5U;e7iF`sKZ| ziRFn;@<&_In?K%AO=k7`gmH3YGOtMI-n|@}WXE1THcUHyS~;kU-BaK9?e@K=5n5T_ z``x*Z|C)c^(Y*TkZwD@ppJ{rhjz;*OSFMYSy8Y*K?@&*t4#pjDG2 z{_*{ycxK^+(su8@+WPeC(d8NI!Q(@1oH^xO8s8Z|bpP!sbwjCr^v%B7$^VS{@24h~ zqF2rML#lCl#orz9=b@=78{{wDB-A@1j literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_2_2.png b/resources/g2/track/corkscrew/large_corkscrew_left_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..22a9f5552427925a8fa0e3d4a3cba7d64266ff1f GIT binary patch literal 1141 zcmX9;e~i;~6o1G4=)rMWbZ2Imall9l7AdBLVkQ*rT?SUKNJ;ib2{qI>j$wLIaVEnw zVVK1XEHE!Kndgj^OjBWh9NOGXTy%*CE>M#*4kC+Se!rihNS0*;fs-AAEk-rsHF&$ievfrAOaI z6W!wY6Wx*j9v%Pbv##FG6${v%`Ez?N-nh2;bmrPh{@+vhKhbZa>#onn@3w{p^@R;J z@yQhje)WaNPHemzyfL-+(_>TX{96Y0-Gk9%#%X!C=g;*cqaQspdQbc0=Z~k(pI<=^ zjWcWD-109jeE80@iMdDq?z-waKX5SEU!NR5-lHtt|4NKG8Xi3v6yGSncME_UG22{`(z2M6RB@x%!Xx9|71tG(33rg;$UK525?` AZU6uP literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_2_3.png b/resources/g2/track/corkscrew/large_corkscrew_left_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..948a25b94d58ed09e515946933bd95bed0c4fa76 GIT binary patch literal 1387 zcmXAoaZr+X7{`B#iiRF_G%3kZ$2Kaqzwcr_?(;m)J^wu4Kfd4R z@a7t6-lBp<0D!#es*2jwT%W29*|b!@Jk&7=01a&3R9Bf=)6&w?)6;1*T1G}jW@ctq zRu-L3&(6-y$;n~!csv9VVi-ygGL=f9(`ij6lf`0lx!gWqC=y8|lZX(Y5`fDX3I$7} z;pz=S(k!u9afeIk@#+FWb2Mhh1a!HCp_Q?XaxSIf+jPjV3G-Uy0hc!7C*u+Oe8MN? z0HpxvQ9u!NhnDU&Gs6y6GQfdxAxtXa0tKOu2LKL$l1|q$nMMwW;`8ki$uN%l)#|X( zIBT;(ua|?ccqm(lb0tc?R4b4h5fvrTSuvAS*6kte0i`>l=88E&DNjNOWGb;ji)l%m zv?*DExMS~l<->SgH9OpFs@BE*Jca4-O*4e zkw`$m(E`4OjyRZ@heHGe>L^CW6!y5@lb}LLS9~En4;ca`Q_N;dxjaH3R7oT{8BQuw z#|$oWx8LE4_=3qO3Y0Rsj$j&1_ny8aXVM(=4&GoDxq*D^`3c4V8I=Q;RK%r z#9X>m$W)+Q4S^WcGRmm2cN;yZkN99RDwfHh8^8#FFy#fAl6wxvWU$6!Vyopj zxRuo9bPk z{PE=Sws^4twq8AV-u5DUZssW?_Qbd5)sanmvn#O0MebEAmoUrUv;d&k!A{WjEd@p!d-y7%NO>ySOo zsM~&jal_E)m9#CwYtbgr$wQmI_$l%FSM}Hu(p&WO`>m^MA5T}UIjW(sQ=|JY6=mtf zB=J#4Nmd=IY7ciFOWZ@Sp}eAKQ~l8~-{03eYZN|g=jU@}lb6=*qa(BWb30m^H=n($ z*)=jU(J08#I( z-YVLoXrC=uU2kKR_A|yu z4=!{Kl{HRId8Y1s^H1r;y}u5)I@b7F%V+$3@~bEMA{Qn^xw{Tc^nMUI;#fF%-Jjl5 zS@3(myKlf%CN+i3)dJU~F?U*Biv=s(j?31V+EutfC3U-lI*aK{ zhb306Qnk8*b#~gs0!^$Aw1ducqehrzb`ulSvQ$^4F(}Qbjv?FL)tLOwIXPd>^Wizq zVOfP_URHh<0AOBOskkyZ*Ck7kk(%s#iaT@wqypKts*>b7XU?3Il$6xe)VXu#rlqB& zr>7$bl97>-nVHGta5xyo7m0)(F97Mv>np4|?eEpeYu1PR9ch z7EtkkP6#X{;-V41869;o5@nJ#*XDtv0H~kdYd-X`^mq+;5u>xnVSbG6Y>%@}kN(5rz#6AU}SYvTn#Dgtr> z(NIi-j%T$_(lQWCdAw#%rE7S5WJY2166Ej;6ghFy+Rn0zD~rN>_1;;U{7TQ z2{w)2s|O%uMVWYWRq5f=UuU-kmgk83;Qd7(?6p*0Uh#Y@-cIaFZK&z0;hn>Z{3OW}W@!0yOPv7a29s4TBke)Mnjk@sm*zJO2xnqY8dk+ki zZC=xJ@Td3h)Gd?M?BxvQPMoW1FKw*ttUL9*NKYzjy7!Iu7uP?NG+Afzet{3}N|u}- z0ylFyzB`#U_1jwwbD;|aZ>W&h&&r}Byz zOC^?7eZMz09C?{C@Mz|WWD867@8CA^k7JEjmVb6M&%QO)-u=%R+0>5mf~!7E{9tHX z`K4>KtDBl|tayOMK~DGE&fhD)cXr3Y-tDgVg0iN+56$n{jxZi=XxjY8NJF!6e$}n= zrMi;V+&fpDb10e}VR{4n$9YuCe6j OfU=Sb@ud%T9{3+3vTL6J literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_2_5.png b/resources/g2/track/corkscrew/large_corkscrew_left_2_5.png new file mode 100644 index 0000000000000000000000000000000000000000..28f65b73e10f768f043b34959ff78f27eeecf1c9 GIT binary patch literal 1203 zcmX9-e{2(F82+}dyNxjpQ)AJJhZZ>X0*yKJh=;ks4ZG%aH@L+jMGicqkrEF*v`B+R z8f{327pYi6(Iy;H@C*fp9$J^81)5OdqEkxNkS=MYD8_~q9m^6wOGuvg*FW!*JkR^? z9_V*>PkU$@0HE8`*SoS=@n+2Fur%|LZ6D_Vuz-OV2A4O-mX?;*)>ezf($>~ywOZTT z+Ytom=;-L|?6f5CYjzl7fL@JXp^7+wnx!!1yF2K-$=em48TOfc1 zL#}9yP9*tsM$G1vq8Y1HHI_iUbeGK8!(L34@RULhN7!7#Tg=GiLbO)aChB>&1Be6& zGC&oOw2b6pXen)L6dkbUf(;Q)sSxI!0Pp~a2qL3s*x^udT%+k>o-g?QrEvIWDg|>n z2WfLMb{CJ)BJP$6Zkv3(fF}?#jj~yX zP$c{nHd^&*wP3ccjy5v2snP`OB2bjF+ufK`AY2knD;ysco6AC(SiF$Vl=Ehz!T^y& z6afv3m>M9GAx4i1*`&XqhfBF+t(0#xZbAkCF8~SvDgZhF1pulDfKBi$3@K38V7bKO zKqf()0frltc>o0fWjlP~A?HXAWby;d_} zlgr@;WT=Z#?YxGG1}>LrweHg!!R$n$IAv5|sgBzKg&}Si>SM5gK!*IB8V+dja8{3- zdA(N7!$yVTIA{P^1`syAh&Ji&!4U~1t5qtQxCf7v`8VoeK=J8Vtx^CV5fvqe11<-T->c(cj-qX8uaPgi!@xZ5%InzJ5 z27kGL+*!SQX6sS^-Z`^RNBbw87fZzv&)A~W1LKtY!sH3>iSC(?!XFFOCB#8%^v2m$ zb5Ayw5W5ch7l0ogd#6pTg1*c1PTtU$_PoBwvl)Hl@8~lj*|zW8nr&aMSQK1w;Gp%* z>yKZwoNk@bdyMG0{l@T>=X$>RXlrWkp_BV(J;g8Qp4L_m^lu1c&-5XmpE~;Piy3C~ zkUqcj)%%pHTzvK-SGX{@d*0$h2E{MDJo4AoaAL}{%JcOnSmv`U7Bsq!{%~O3$n$+` zQs;)|j?=HSoWf$Im%cbVWR<7CU%GVd%)%YRul+GJJM?G#{OyOYzrCpooiBa6>DYJM zU;bw#u%)nJe8)JA5$k`SzT(a;&(CA(w*0Sylj-vV|L)v4^U22A`;GY8Qu}|_8KZ{} zTpB!a)zx&xVps<$-5; LfA8^S>vsJQx?2+7 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_3_1.png b/resources/g2/track/corkscrew/large_corkscrew_left_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..379eace14a4eaa8820fb66955d36ef8c35be3dda GIT binary patch literal 1196 zcmX9;VQdq16#sACb{%CDQl!o%+@zWVF0;W)c9TX9xQ#LoxWN$`>4%b?Smj(U@y4n) za)gG|*^t9ETgeJE;dBKm7DOppv6>RAmUzN|Di`R70wpe5v4)!L!`~8;-+RCJzP#Uu z-+OOtaEq&B-ZS$6038Dx`?fWBc_TWFhDIJ~JL(3&00uX0?{BnCO-;?s%?5*^rKP2{ zwY9CS4M7m2(b(SJZnfL(1mU1*isKlb_ehc$3bf zAfWz$BNTQ&VhTq4c~>1@I*OIWDGh0XucN3(KqWv5f=J}Z4p9+Vw@wk>wmu6692Y_rs;j|He?h|9!$`J`OT#wx{Jtu_lO02=N~04M+?0muVTMgVMprC~sV zNfqiv76T#yA{0owfX)KQ0VrBwn1Ct^(*i7npss?)#*=`dfty7H-YWa?h~i49d?pjr zv}C2C!G@O22Z(@)Qmm|sdefMwJC&*@S@UP=(ZXE11dCP70!S2bIm{jk6*wZ`V-#6X zBXTAg(Q?U(o`ba#$uKYtpbj8xcoAyIJ%KG4h?UD^Ecygep+I{)oFMRlfJiukq$5fZ zNt(zqju{rOxb4u3LK%ZG0;VabF^%OXyG;)t-@wSWEgV>T|F_p0_0EC5b=!Ln9UR{} znd>t4--b7Dt=#kZ_=dIWONO4v>SI0ku%%zES-OzFlkdKQzNmG5^L4NG&=y)a{qBNC zrqSB^{)@+rozl5iHYbLx&FI8GzuYtbcw;p>{X*-bp(S@WRlhssTKq84GmZ!f7}D^6S*x_#j%iXI!4D@+E^6L|ANgX%okJZ>VEc~BYs!J^Z_n?#wEyz8 z9qZbs=RTS|HswA%dHmbLtq1XQ&koA_OZKww*ZHH@#&-GlP2DLYy?Z7m-yh%l_zQu7 M{w;l1Ove`Q?=R{#J2 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/large_corkscrew_left_3_2.png b/resources/g2/track/corkscrew/large_corkscrew_left_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..47656c362f7ebf4b5cf1bdc41773c49232da759e GIT binary patch literal 1142 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 RZ^O)i%=GNEee+km_FpPbapulsAn7V7 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_1_2.png b/resources/g2/track/corkscrew/zero_g_roll_left_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..9c6f4b96bdc4c347fae0083d4e54277f5d3d1997 GIT binary patch literal 1064 zcmX9-afsV=6n?$lUG7%S4hvUVm3kDZ8fV17qDGgw+$}pYFUPXkL6sattgMGQ$#Hd5 z%&=;8o8zFit8Wyqezv?PWjm}_}+Vb|GbZn z@4fdI7r3cidv*c9)coPuqr>^ouwoPbVc-8i^BjO57LOd88&aRoH!?Ef_xndjN5{s- z#>dAo44askn4Fvp$6_&(Bv_UaMP8PZs;cC2xl*Z8t67fI^t@ibPZGe;An<`?GL%k7 zGg%^Epi5<;T9fLw+Hec)j=|zsf(|HrSW858IbKo8%^Yi&5{;VTZRNY3G3Ys51SA|X z4Co?ORWQ2{Y*j=3Mg(;U)R)kXj*t@r5C9|$Q-VP)64B#vgQhnHVJnqtY1++71=)6l z48@o*Aw+2@&MA08BW0ad%WTf%i*?axNS2q1QW1iS(IU>vR8nD;ypXR*6-%*P&GCwE zx7r@qK?Xu1gi{dBLR`nFN|>v~lQyHci9%a7db)!)1w15Ekqn0y5_DB&>#FGHz-)tOnV7L~P)x zHk?yDg{Rzlj)t1b_;l1DF6?038g_5CV&`Dl!e^wS+h*BorC2 zIPe5OA|NG<3M4WFWTjCfk30iz2TuXdLPEgOa#+jYMV+e}a=o5&U9;PD(NHUr0x}z5 z^srz=B`dCYwBAda{Y-sOYV25T)au1UKt(Z*2qu|mS|qb6Uf0q_QLCFp*D<@EgZgcX z=aB`-1B8ZILJ~QOC^4kTk~U8?1-zSxAt{Qq zI4YCKVvx%ZkDuBb`1AG;tR7tu;lPdSFAvGJ`PpZWJ+Z#tq^JEe6Jv`5+nQb78>>8e zdf~$})b#U%({C)FfBLhp#|NjLd1w95K9y?kM_eLP|?9~oDl>Yv@m zZ7-2`U-JF7``W+3s|#yS?tbaj)#;H(Hk?mquH5^Wxv}<|^T8D5tQ>NPxyNVT+;O zH=Q~EE3?afzwi6r=lkC0z4slKeeIj{E6cAd2LP;WYi;g;&!YTYRsz4*PAC%aF}A03 zv#$g93p`%hPW6xi-);{nAp0mg0DXUTwOf9i5|n+DySlNsc-@WTijOwZf1c)*e01s= z&Gf%EJ6g7%KW;r&_4G}Gm+z(yKi%}C;^TvB)nC80oOJB}c(0j%U-6bdTzlFe*~xxr z-QN+vWqAMRKRGF{FrKs`>(Bmdyjf&T9r^jHfr^_~yb`Q1Oz!#i@kL3fIrjqH z`XFK*?AX_!;ZZQRx=Iw=wsGq%={1ksw-U9yo@~6~ek9YoW!0Lu&zyyU zJxJ+v?QJ^Ugu{Cwu^{-hihYxqE-)TCvdVBAS;fK`+*IheyJ0*VUoH{+$_IAsLZ>$|VR!xuX)Sh`S@a~C{<43PE z@Bh8(=_AiR)wbrrd+?_Vo|C+_;pmup?kuw6n!h}8ONM$>ureE4x$|pq_DJj>)$hOmqbkJwc2TgnHXApp3EEYQ+vskxw$J5(RR=(Ww$FnTPSPjnCLNT!Q8<%G3I&v{QP@>y zlo~xcatGDA$4i>`Z0aQTIEi|jPd=%{#aTS z0?ik3FVVgbdqEj$8I9^@n&{2D*Vf!9%s2a=f*^5;itLt3WJ(fO zbYl>nv@d}$c_~gA{sB??eB zLcN~$x^S3I%7r^f#N&1p7V?Cvo7&qNh4NbIMM--P?z2M!*aMW?M*EqIOP!R9H2d&8 zpE3+aB9&t(hDp(SU)ZzzOD|dBkjt324%3GNR^~pCAUlJ6e=aEz-8T79admr5uKs!K0odyn;eiw z$Q3Nm0#|~y3#q#KQhompGM@)XnM9Va(?!aJ$U?A4{=~QtZ3FThJ{k%NOO6<5H!p)n z7d#1(#iMY6FX-zJ`B})r54nXvaAlLr;`a(&SLnJd1};naN_AbK>#`WQEafZJ^?#$Q z{Nl?L>4v|6{P0!jF30dW07^jn#?BV_x>ZzER9swKQc`l&RacdkmM&YijKkrSm6a`D zzMLl#iBJ^L>9l6EfgmglLx)14!NK9t(ReB~na$43&Y}p=YJka5VX;&?oqT@)=?`lL zhfE`*)1ygs2&2&|@K8a_j!2L)cj>dp^RlDG>lB0IVDi&E*EGt0OfvQH|!9$u#b8WP-s@ zhKJc?vKp-vX?ci=ud&wXX>nH&B_bMTNEeD31`_7zgf*UZ@Udz{FVdLB1_HCtI=bJ~ zKWrV2)A4jLl^sauMyBSHTrH?H1D*r$1E40t!G?MI(HcuqOQ*ZSQ%rOwl46gU#FYeA z?bnOLU78U>mtf545Rn;VremR*bF9$z-V}2d}K76O3zMdfz`la%-o=rA90F@0@_%=IWgoIj|DTyprsn5w-~PaV0oPtF AP5=M^ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_1_4.png b/resources/g2/track/corkscrew/zero_g_roll_left_1_4.png new file mode 100644 index 0000000000000000000000000000000000000000..34837ce7df13a9284c0a473ddf22c58a8ad5e8ab GIT binary patch literal 5794 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 F{{lYwo7w;X literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_1_5.png b/resources/g2/track/corkscrew/zero_g_roll_left_1_5.png new file mode 100644 index 0000000000000000000000000000000000000000..1b0a8d9eae0fd1f3c82be5a1d56478c01f17ed8a GIT binary patch literal 4975 zcmeHLac~-C7XQ+ik|uW0i%LdR2vpH>WPv5w1d?JxB1w@FLo{~M99@=$t^}5{q@=~l zjd-S&8>!}OW-dLW6K(3CMy(o^=4g*-J>$ta84ne0oQo%VJ%@VSHEPwp50a+ooHI9_ zIsYrO%YNVc-uu1xe(!zXuh&juY9gzRyqH| zEAN#3`GFON=ph5DL*`b?H8eux}+>iQFrGvV9r zdSn04Lnn0a+aKTf^~u+73^ZpC<@A;B$(wgn{i-SV{3~6(NpYVh`S?ADLZ5$h+BEgy z>FdJZhYtAHJy-SE3GnUZ%_r}z(tU|HD;_Mac;nE^`+|Y1n*^!dn=d~-y;=wJx{uQ7 zI@)!*v$??{56|Q*qHA@Q2FRpMLXF*(1GgAM3yS<3u7At4w;e3z^D&;nl?rtF|AY zUTZ(n)Nq)(>%hWZ@zbKWrZdwO>fU`{KXmfp1btwpHn7v)k|aOdE1qtCb@0jS>{s?y zJ$l1~Z#}T_n-fP8%8cxtjn5oYFMNtzdgXhM{5(ZHDBOGf6Z`H5Yu0w%7TR0+%=(*F zD_{2f86!1Sa@XZmM#7oiu=k(MfX3dx{c@hqkgt$eNoo& zFJsBpQ&*KfTR+u*di%HF(?ij}@jvTZZ4tQ|FN&19V(m}Z!McG(fB&2MOqV5`_-00Df z+o-l(Uedg4Qx~zzNz~g!+6`q518NB1B7L}Uz}4qw)B}y808uO{nlIy? zr+qf}f-=-H8r3Z{(Vq{my`@o<_pi3m1Z7hfhH}Ctx7A^oOs-H`Wh$i{lhw;HyUcD= zSZlF5wAPB-S3tG986WN@$UGDTucjc5oxtnrRM3#9wPO&%ZkJi>M7HbQ+1 z?RDX>oRkZ9kch|aC@ka&S2uOEH;R!p>TW}u$()RYP43ZsFBJQYWWI%+D6%T{x9wP z_7OHL7QKyPp#Pl((c+#mliL?(i_<=;u$hFy!nRQ3#9|5zzJs(C;)Ga>OT;$Z?I7X# zvDC0<<9o;`bt57wNhn1};eXVs~An>w*}#AmxkQ^?#$Q z?A*%~>4v|6{P0ytm%M2TfMU>bYga3L-6|?7TD59badGh_mt0a(QnGsWY7U1}T3Whh z%^IFqEJjg8r_-9v27>5e7&;UR4G)h_OiU&cv*~m;mqQVt)c}*Byr-wa=@j?_$Y5AA zJYpK3u*BlbOfoz-Kc?*S&9%E z4P!73S|C_pB0O|_d?KAl=H|4(V&E`lZqOo#IHe;2ZFJBa8*v+iNyi2lHaf(RU|=T!n+7Zk zYcUAjEnfUkU}SzC8yQ}_n3)+}PmkH@Bmw~%MM4-dtVN?bG;Tm{k7@{3P+&5byLf;&0FvN53EKq AfdBvi literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_1_6.png b/resources/g2/track/corkscrew/zero_g_roll_left_1_6.png new file mode 100644 index 0000000000000000000000000000000000000000..803eb413b18aa77d3d1d9bf122cc9f4b469ff6ff GIT binary patch literal 5545 zcmeHLeNa9C#3=kwJXjb9z@)FXJJj@FOK^qk* zDr!`8=oAz+T5M6+)wa=w8r$fiqNT1=S&fPnTC{#d2dx&=w=coZ+0N`Zv;EJ^`?~j@ z^E>DK&N+AT-kOZ`q>%yd2LJ#@rX));$$KPuviy9>Yg3%x4)S)aEGx&D37e=z227nZ(L)_Zv7AUs(qU`e@g%TXnpbUymCiL zsc}@mi74%t3#!Gb>pr0`7;-yrn&Ga`#Z0F*tU$J+_1JiR^Mbx7d%HWS34Mivu{WT~ zpQnDj+wt_hIYaM+Jy@C+A&vNS6no@?b#p(zv2;8<);h9a-1UiNx`C30W#u<}2=>{3 zo;Wf^b-rNvz`Iw^59|GI)*SuQ6ZMsxGfO8BzeR!Y;v@5y4$S?527phcMl8-q5sRP4 zLq<`*Y*T!)bH=#ix$->=rmid*wfIEFwp;m$$3DyYhu@glik)*QHB!fp6!GS3*Crnt zGwyNDKEa{bo4;P2>bEkS`u#iUYa=tS5t|dLbAmPu+`Dt7`%V}&YHDh9`L5-k&!07Q zeDJ};bI(2u5cP9b@g);gzplBTKYU?ZXS{IfH-UZo?({w#=R5m~a(U9k4cyCrU(H*s zj$v-=o4$DC)`^vm>P!E%Bk(UG!@`o^*W+j573$&ZQ$N@qn>=kyT+W@mdEBgPnrj<( zeXxb4TsSWlTRe{ueg12@8K$=E-+ee8AF+7agcTDdC-&}K7cgy==Er2trd>~RLWsTH zvdz*-*<;s@3*4Jf+4JaI;;PA}n!x>e(y;s)?rNQRo$rx_JLcPNyAhXuJGi30I$Jx? zG&1kEn)_vnz%ZW**U{s}ikgSZ+r#pDQffz>+|(LXnc!0@vSO!voVMlWGq?ADX*oxs ziWf4w0Hx}vWYd98d#ksA9~3QllcHBH7HuQcVe$ zHa&nUG$>VqOv$Wg5acMHR$w$130N$X$rNdVA~A!S#o_b$EH;(giD!v zJi-Gph#^67#GolMYA`+3g9+zj#m0CVja;Wb_fJ=pmi7W(k3VC9EwMepGlQe2nFUfk%H_wVUoL3zo)nDMgCjC5iuP`Zg)sRl9+w#v1M`@%kP2n;W1>{iP%IDSaH3yF$1#=B1RKzqYLZ8iE3!bn zTu~=KOVyOu%~_1j4#io^C$kE<>61XKtjJY@<#l=rRyzSZ^XbG3BRqbw{*P`18*e!wz~drbOpS8 znL_pCKOhtNs?@vY!TzJx%4EAk!^+$OB`M&u4t0h*yYytT$@WB&I@HFMa0P&QiP|# z#8{QAsv)<*hS@sIPFGDwZ)4X(N00~v%Rz`5gqH)lg~DqHNot`h93reEySfXvx-CxP zpo|fW@Ip;VjOy&TMnr7KpFMN?RFC&6a(~H3e*@Rwuj2w8R{-^Rky<0YqGm7=lWWD2Ra`TfsCLa zUPwq%c!Zq6LgM0ZsjMoO1S@Z;u4!v*aXCBsx(p&c z=1xalZ>O`b?_S;KQ}bj%fJaVwhoO!kMh?E|(hqSH+e2E1@e5-Ug{3fIb^a<$ZA)>>=K_NJN+ zXH&1sN%VE`q*B5L2p1p-G8a{(xxpi}qP(uVn^#vmc;M~rVueDk)gtBP7{sdJv1&z7 zlNfSHS?6So-s}h>H=Hoji8_d|iHHs1CO>ZhpL}VO1gstw zmP`)(i<0M)WCaF$P9N||{d?pj#h8+oNVy*1A55P*9v$)&fFYt3$;_N9e zHfK@$cM-R?`&K%((=QIfCz{6g)6}bN0cxxsUD~j_G;7HT2f9w8?=oI7vHp zZCLxhj~eH%oBNZdPJx7PJAM57}M{q>A?4%41x5r)Bj4*~Rk`-$x&v4;nb-NS@zwMR^zf z@E!5Z)eV=M4?XHR{FTEtYyFwi31tf-Hh*|{{nJVU4w%zX!Mx!u}XKA`xuUQ5J9u&FUXjEG*vfW|2 z4&V2b;Yb@t<}`5@OJAh1I$t(q+^UnVP7O@<)E1+DeL6DINjFRV%_^1%&}e82;Hucr zz#^wIA6C~>0%Z(ZYv|lXD6Ro002+oFm5N0WE=Bn~f2t^xW^-;?PX_}OMFd-|2{@yW zyhcd|UAI`>3fP<@OYR>U!(PU+@C>@FLA)*i3i z*?N?n&o`({S1KHiOJq%@8J*`%S?Ox|v(CurO@^a1PSy(nG#NA1ilvcmi}pG~&{fA? za}rqd$jj#Odi@j$0CfNpzy$~ZCICweP!2^z9TNpUO6Lj%1`9m_LJ3j@kP67ak;5Wi zL17C`yD0VH!gvm35$X!o(s8Rz_grb{>*KMVBte!XDAyvIz;?=liz_~2 z+v81tdLAy&d_`4(BQc4oGz7AxvYn>vS}nh4je}ki2U!}U^@5XS6aq>Cq1=mZF83US z-SL)7&g(yiIh~4)hT3ZBosPjWHplb@HW1lJW@ZYV)oVy2kwqboMWKKaIS)VgYWdkk z2kxF6t8nn-&-Zeo9v!}ZyZH5IpC6UZUU>ojL+PVm!$-ed!QXVgc<{;ZmtU*iy#D@4 zi9h@8;Rg@yx%bcRIR9?lzjx*BgMZ%jzJ2SPgO9%Z>aV|N&vyR!@bQzEuD*Ef;pMwO Y{cx3d{NtAweS@PL$A{lvf9K=>0m_n&(f|Me literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_2_2.png b/resources/g2/track/corkscrew/zero_g_roll_left_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..d918e483f70d10ea2d4de17bcedb912fe1cb9cff GIT binary patch literal 1052 zcmXAoacCQL6vtndwwJcffEk=LU{)gB@RSpdd5oLh+_k3lq*r>AAO}0;V3|ZX=s6+_ z5-}aI1U$BY(FF|}HQ-qz6g)MSQ%A^`wm7DoBY#vV<7dX;``+XG&-?!I zd2e}sF0p@XVhjNG&(2IO4CdsZ?h6G6eP=sy5+Dfk&zzVZ*gzn#Z{NOPFgP?cG(0>! zGBSc;SSS=49UaBv@iT&^}6mg8)Bp5O1&6mTqv!niC)(&<tD$-8g`QX2^_@f%6cREV z7!p?3FuNFT*CYK_6!j?7SJ0k;kP`YZIX%t1r~JO!~V5C+Cn@kE1=ZBBEO#g1O{4F|1?WJG16nFLu(vUQbj>XMsR+hx6L z=6$=o>zb(Rgd+?=CTS+c@fk@fs%j;ZX%vfgwdz_{XKTy%eFRYrh%!dk!+bL;wa8S5 zFLdQvFVpmmt$w4o*WN|rWH`*=cp?^;NJ?c{T@VY(U|F_NEUniYp5yjA94G>&OW~Xn zGty)w%b5kKSxK#%xwc*DwVi(dCgK2+06KsHU;?ZIbTL2!i9E{c$gCl+EfS#7P~yN! zfF}Zy0BJZX(x@gPD~(zOk|LH?@mz*18HsvLZ8r0+Yxa6B8e~ONKxfA} z0~c#C#UeD1HGJ9ZXPUd^)}GZtZJ&q$6T=czSmt7BiO!}3BbTm~a!s@3I%dyvP`|?n z0_~NZa{33ou zoqW-p{pT^^=mGZ4z@Op2uwU3u{rLBHWTa7e=hc~$>EBK@i1^wQuf25jqklhKI{h46{QahhSeeB$qXOabRp1Lqn{ULSagQdksUwPn- zTc2!PJGk+<_`TCTp3eSUpAPw)|Ml(9zg-J_6L{$T`;Ukl69diwv(s}^pB;bx_5T5H Cp2_Y2 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_2_3.png b/resources/g2/track/corkscrew/zero_g_roll_left_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..5a36b66b411809c6fc6ae424f2fc12825cd0b418 GIT binary patch literal 4975 zcmeHLe{d6Z7XOx7(jP#$>1jF^O-SwtnoBpyrp>R`Sksc0SW=pLg$Yd9Y&Ky{lMUIF z6e1Tjjumo8(4KVW3REXRRae8O{z4uL8pv*br zFmwLb%x?Dk$EGnm(pE$e5q+ES^VY~x7o+M-@W|OMCa{G7B^)7M0I_3 z*%eMC8#KaIdi!sRUOWlXtCaj0dqvdXuuZSzki&TP@X|6btTk-}5QZa4ki9gwF|cFBVTGh zRbP9Yd~o0NPQg+BD`&H3%henAeDUPvr;^mZ(VDpFa48fOl%~h7JB|lKtYl1&<$)ujRP@rXMrkT`=kRcT3Tx zE4LLtuNvw4e9KqhqvvA(sQloAr4@+j^Or{Bg(D;11`dynv#-47ef!JqdJ5LuRub0M zx|aLZIOVFsY?PI#>UMcx(E(7a?e<`}lkoAZgoAX~@h9U6K9983@jI$pBrP5tv6*bz z?j=my*ReS@Trv|lId2H$c!`Eces0@bhK-XMK7 z_Pj8ZYH3k7P%EWd_wOuT?DKN28VpWMz+%Azy zRdT6ZuABqa?52H~8z*v55WI?nI1)l8RVrn^i1@w#D*lYqi*Fv)jcrw(6Q1m83?FqV_zL4Og$C zyeiX8^I=-w*a($(>6Z6@j0_*|OZKM43^{sZ&MVNe8j!&sV zrj$$MXpOQ)CRNDg*M)vbcxhORIaH~n3Z0=Oml!n+2U3gWDis3cHDEMqotMCTl((It zI_vm3r+7KdYuhcbp=_8BYruR21eM6-YNjk zKD^qQq&JZ?w7)ICG}BWiV#~~IX4*;Sn~BHEw}l$RXF{N{t%NP_C&ZfB!Z%}X2LaEI z*@C^gPJT}@sA_B&p(JX=s7eWoL28qTm6(+fS6gMMM1iVMdo^|=I!)Pqe#}eMJ0Opc zD_Ed;u6QeFQ+3yk^8U?4E)S40u~Z_SLm3~L4Hn6r7+0gMMgE76+PuJ=BL?cttihuT zo`lG?qi~k5+@bR$erEIVBU*sa^G0rp-+8*`>AEQfZc2E*y5{M+DF$vzc)q&+Z*-Mj zf0-iO@E4FDzA7zw=8>-eCQGqt%8Dr1q&7w78c%e%PmDkMGF@$WU*Mq#l z5HYa^DOMuPP7jt(jaD*QgqgB1Uq=`wDFDC-fQ7}P*z90sWke{9YBa}<#`6wGIvBh> zFu)`dm1wy@%R!7>jYX)ZL>)mCk7($AT_|SgjhmvQmf?(ptEfcu0*y&zz!hdnNA(zc z1}p=^)Nm@8%=D(RgX7Z)wic9|0LKBi0U(U96ayUnkkFjaQmKycI31mgB$?wzQ8})t z^y@|84$UC0i_@l52v7IX6S2@_qHj7CVzOb|v;O#GWNd0E`*nJnDHE~T3Jyol6_`W_ zuF=p2V~+)b1%|@C=Ld%}$<)-i7FY}{+Qbf8xDltQKcJ2EnBx78^RZw$(VtBxr=~75 zS^zo#paF;g5Ch;m023_0z{{v(0yGngGMThd2q+ZvYQeA`WQ>3@0fyo*VU&p)nPDe0 z+QVd`AeVRrFz7&sk>$iWLBFUsq92Un@pveeie(dxP;tfW|GX*xWZsyh5?fS z31Z|0&$M|Ebi$?3!c0SZMz3Zzeq#&l@HfQ%VM*$x3?;W9xX z(~mO4S|(+H#jg;TeU|G1U)vfJxcB3W@SiPEU^VC)z!ODxG{H%Ur)fPTtE@bC7l7aG ztAL9vUvo<%>r!d)((+}0XOA3(OQp>X_3g!Jd=nfm00kc|KZU{(Xl`87@cez79{n%8 CLM}M~ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_2_4.png b/resources/g2/track/corkscrew/zero_g_roll_left_2_4.png new file mode 100644 index 0000000000000000000000000000000000000000..5d93e9d9461cfd72c4308b9ac6540ca005e4fe3e GIT binary patch literal 5321 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 GU-w^(ui)SS literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_2_5.png b/resources/g2/track/corkscrew/zero_g_roll_left_2_5.png new file mode 100644 index 0000000000000000000000000000000000000000..12b6450ef0d9a14060ee011abba3feec892a1633 GIT binary patch literal 4975 zcmeHLe{d6Z7XP-Tq(9)|Ss^{Emyp~MB&M5Rbn~M%*0iQIgp{UUVFDL6n{8OrWJ5M3 zg{ZkPV5wmU+SATl(K-{co&h=>-sLnv=mihXsyU}~S2aqVs~QoV;`OwraPEDRmQqG% zZkRd$BeU84{&?^6-ut}wzLQOF%R2qivRlgl085*j8d~AAAondPg7;OUiUfR|+S#_j z*NXXh9xv5Fb`m__4iCX2y2%azy5DuRSZ+@7N-k$_sVgj8U%QX|Y%TTINlwxE)6Z!p z|GB}@_-ybT(!HeR=KTk^9#KW>Uu=8esa5KC-z+5@dq3S{=004w@z2ZOF}$&j`NX=n z^;oCsC+Fq6x|YAVEBVX4XNw}e_nzFneyLz3r?pbSEdTh$k1p^2{p6A_i$V?Aqg2vA_rpJoI>7Q|j*9UbR{d9&A&;U4MGTmagB0A5%ZIdilsbr0Atjw|LKU6l7ED zrrV0g9|>{8_p>;T&9`qVuD@7x`kj&Hw;J!eY;E28y*-aAor{P3;jy(g8= zzVQ4r%`103h~0lN$=?J1RQc+mvrEKJZhn2F>%sR^sqsW*+N+((R_+fkE~+iuc7S}P z`FMTpG4g=}GrfXC{MSxrPgkfn@BjDX7oJE_2S#fGJ31QD#K*mY)AzjGbMU7f%Qmlg zX63%u9=q@BbH`J%toY6Q4v(m3K17x*``eRuj+6U%y+40$|D&LEY1{fxZ{^|DcPy5@ zH0b$)o%vSr^3S~YkDNXFEA=gV{=mJ=e%SB)_46yAey*kPli<-q5$UO9`AY*&efd!5 z#?LEG%`DmU+s(lf#jii~#JSHNcuT-LzI4+j{~D70$M*^zeMYgK8|5XC6as|X|LnAuQ5uD9v!ij zY})B1%sbb$;X9qU%Ffr`RaV=rh5#Is`OT>-cYxZp?#7t0jobg)G#deT~~8$ecspt3kKH7DZYKn(Ff6MB{eC?Gr47u;cUko-S`^ zJ{&ua5S@eziqg=k^cs`;W@F2|Mvejp>GI^YAlcVQ`pAx}WL@K1ZYLkkLPwzbJnl8p zS7Of#Ln)(C-9X`8Iro|y>i9YPYCDCKc6ENZMp`4qWHyPIKry>mp_D1bN|g;2OKNPG z9h0F-rNXuVs@YBZFgH%*pdffP32{19*ct_4Bg6`OjZF+kDzU0Yfx??oM!;0ppmOB` z2$PqDRf%;j^eP8shfpd>hr*`9Ffne2J}BgHq>`d*#5R>wiD6O&Dv_XhC_Apcm-4zW zm`>7#IS9n#cH}p5gsbaYn(O$oYRT1=mQKvq0To~mkZwEWr>}0ckuJjQ!*YB|QJGR9 zQ7CFuQi%+e%zB+i`~~5qVJ+rRrIPBocyftR!*C$ASgukbKpqxGqt zzo!`NHl$kJ`Mzf+Gg%&91?t3!a3? z{82c^7xeXq{LJOyhcv@ZU45A% z-0&BWAHFJyjgm6}6oHntZH@4CtDvBuu&}VGsA$omMa9L%ix)3uu~;P~C8edM9DzU} zmm@lz)@(N5xP_*vP$<;jKR7%bPo>5(nW^b%IRdmAU^0|jEEP^C*B?N7!kYd8)6lRr zk)%h{;fcwpPQ+^0lv4&yu$>#hg@d&GSV))bZyz0|GG}_Sndr<^N?!%6BH-78h?zA+ zv65l-_)x|4Xcd!1m}x6>DZ(%*0RScdtSlDAW(TXPB0^zQqd8_WopCtEgTV`fgG@46 zC9e=@If#j?u?qE+s68mhBN}=@7m6AB66WZrHJ)*B(JDkQ(3nLA9JNq7s>jqbXdR4G z@pLei=}TvaCT5asEvPU9jstK5Kp0`6gB<;^(2~?r>Gtph9i57#m}4eU1&&tv^`daQ zW(e0MXmdJ*kN4A)vCveqe6cF~a&)QpkKcy>Y=HusLEixO6yM$iC#9aIjgYMJirlvV{N_L_1*;2$fF%i#z#H?C_qa?h4W{tL+7EolG% literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_2_6.png b/resources/g2/track/corkscrew/zero_g_roll_left_2_6.png new file mode 100644 index 0000000000000000000000000000000000000000..d88b3a48f0f033c898f294fe8a059dc0e7c7b21f GIT binary patch literal 5530 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_3_1.png b/resources/g2/track/corkscrew/zero_g_roll_left_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e45c141e38bbb32cedae5ccc3cfbdde447ed2419 GIT binary patch literal 1200 zcmX9-e{2(F82-wB+_tjRSft?1R8nJsW8U!`-AA#ofY18`Fe?9Hg2C z3KY`0W*pMYYU-@XVJaz5bzsE`HI}fLq8Bo=f=8&NhDJflC{l2S&k~a7{q@iLB+v7{ z@2&5(x3)aq0sv_3S=-%LtL?Q|*i=``hj6D6fI6_=(Z9Mj>U6p}bLQ05)z#P6H#9Uf zHZ~#%($v({+}v!kSS$pA(=^3#j3BrqNel!6kw`3=Ol7lEnpUn<2pmv0z%qK5%jof# zy*@k`vPGh7JjtgsQcevOiVBS(PMcn2On#?X7OXLemx{x9R)lF zycCc*BrYPEkRcy8R&ppT;jqHPSsB8t1ppQR9zjHd!H=S{)vDNR6D&LFcIW;6>#-Qj zWKhCrp-ebyw((ZGh&la)AlsxU9Y`?YG^gbFl;$>*C~mjdIE)cUmq?32HW=e$DKVw` zvszd!#S7JpfdWPjnB2hZ16CO!VdH`}>I@Ymr7UOR1dAC367|}#kkb|y=(NPC z0U;leiitou6RD~RSj-xXq!n`#q?@9>92XLVsMnheg)*_2no1R>rpo0q1gHqC5rl{v z=rqdZFn56t7F|lon=Z>!m1Jo)Uxj+iU?5E)NY%Y4aDcru>UvTCJ3 z0iHo5&fw?GvImR$s6>!UN8OVNe?Ai}<+GK_bw~l=1V92n1|R{zBmhMOz#3Q@`Xrc8 zpq6K?KqNqz0x3JtSO7TyMH37WP+?)p19L&BDd2(eBw%RZWD$>G@_VtcY>z8KIvr5e zM5(008W-vYgilY&CRQ=?DXXa2b=8(fsx!x26=Bl|r{ z*q=^>)oh}qWnra2G7L-sr~wFTUIc4&4}k`J(PEK|Mjk@S|B4sqlpU=zqb%&*!pNCO%ub^;YkfL%qnT=j7p5 z{Wrr^XIpTr^X&bb)5nGvp1EMgR-L=r{3f^Q?UwAw_X{>YdRvdhAKx#QNwP?qR zebJ@+FIG?gK5yXa`w(UByW7(RXC1ca;mMpWqE4SU)rY&WR$a7Vb2LW&lw+Jy?2tU#Fs z>*!3yx*XbJg<>1ivCcH1EEURV@Iq>=Si_lYr0D4i7FTpH8Yof*AwNqIVyT2hU|FUO$mNuCdNr=PeBToiz$N| zn03HG0-i-893prX*@&`~QNscTOJ?|(hcKl9fC0daAe=(sQmc8bHcSw4hDlqkS(j@r z6oP`F#+4dUg)t~$)*3jS(S=)h!XBX9QQDVe!x?izvZ8u5X3!9bv=zP2( z61F6hZc&UD3L>m{sjUEa%1BX8YTdg0E875o{HTwsol;%KCch>pUIxdP$m;=vss)@ z4#(Vj%unJ`3KwW>iqRE}8fZqLOA7-yOps8dE61;YNp|4Ck`yWzA|@d{PaZW-kqZ( z7pM2MebCw=9^KtLChPnq9&cQ=X*@YSc_Ngbz6h?4b&d3o4S~T3UjOQC&J~$pe(vxK{fMf&YvS1K{m(j4*{kyAYoqf^&g?rloGeWAb+_K`f9Rk2 zxAgv@Msd%JKkqy@pLjD!+orc`etqs`Ro@%y|68P3fmuhsq1#WSg!EtK@x_OB|I>bU z^_A;lW-{2+vM)dS-MUR5?%ul>z0@uI3FX^9dFS`KZ|mYaPZDXz!sD8IbxZfoJvh_! z$Kaxze)s{t8dfy|Jh3Z0D|{{{tZt BKv)0( literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_3_3.png b/resources/g2/track/corkscrew/zero_g_roll_left_3_3.png new file mode 100644 index 0000000000000000000000000000000000000000..6e1f524c21b2662f58dcdc4dbf02064ec1fc9865 GIT binary patch literal 983 zcmX9-UuffW9RKcbw)M^`JqVbG2t^_nk06nSk%u_5EsmVau^g7shfD(Yp-3L0SEQT~ zi&iNZMwL7iu0oIwB9>#E5ew!Z$iOXdcN$8ot#tyk8`b&)SER8VpE6|J%8|BCHBI)QA_h*b+cx6E>M(XEqfjD1qoE{# ztzs<$3u@_JD>LpAXvms;OtjjB>@YE9qpBP)#S(XiE@ z1Ze>>D&Pem%Rt!}*TkhZl@A0X%GLU&JF-J`pwJneBT5oo%keE;?3ij)(R+?L@G7Ig znM58Mgy{@N(K(hY2x3W9Yr5VjmD;sh&}>G&-#T`Qv?ESX%-ZSSmCjYfx`&PMrp>gfr^B*nf zm7k90Z#>*zTRyt~{S0J(b=6>)dzv%@^PKe&xsAPhR+N_pr-ic>zluC|7u_FUHbg%W#@@kM+c|(e>o{SpRKN@VDRp(J8$m% e^X1|Rc?uV$oeks9ht^QUi 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 a&f!tNbwl+D_F2=+F literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_4_1.png b/resources/g2/track/corkscrew/zero_g_roll_left_4_1.png new file mode 100644 index 0000000000000000000000000000000000000000..4531feba3f082f07e7b345958d16d4bbc3cd564a GIT binary patch literal 1384 zcmXAoe^8Tk9LK+aFn)wX=Cz}xGZ(EGIO4&ca@HeG8Mxv>9$>ktOCOGLEq#<}tDClB z=A@lXTRLlU(;K;J!V1GjUDwPha4sA$ZN@|GavjU#bk)3e9^ton-n~Ab&wc*+y#IK= zKi!QDvcmi)@&N#a^>u5S(z7gG%X72R9rSby0muT4uQsnuZy6aGnVFecSy}Vu&CAZt z&dJGPu~@mexp{ecT!BD-GRHkYM);h3|XQvmsG@3ND3%9*QnrINug7RoH0rLc16%jF~jCK<4Pq0 zG9FNifF1)@g5{=IehWL|<|KnW7#G8&8qQiF3JZH3&1qE6dH8UL1z$b7thO-*xM_raD8XJ?i?MnaWVI>M~Gn3anE(q1<)w(yk|i&_qsGB4_1K3+0) zJ!9+iOV2L2^`wW*teE|;=)q`4M&-V3nf18`sKb?4y02AiF~I%BrSGbZ>x$a0weG!n zDKwmPo)>q{A;paycPz$Fz@dp6PiM@&C%a@*m6Djv=dEubd%qvz+$lbG{k)|5XXCEH zvLD$e-V-Nk9S2{yHTLb8sad&n?)`J~SIeI&?+h)LI`T}-$>ZAFg1kApqvz09dklr83pF6r^VgD^d~eTK2i|hec6n!G+td*{ zoPT9lS=3#%_fYj<+s)dUL2B7H+eNzg)7I(Vo3n@5lXtr&G8L0wO8&^)y)*G~NyV|j z^~$a1xRaTc%G<%Z^5>lY+~09Jtdw-D4b*6{Q~7;l zfxSzL$Iq5Eeppp)+nl<(^u$QvKv5s(oV)k4P4uPt_1o@^mvR1`D>_=@Z7lhqNm=q+ ze=9S6A$8*&#jWQjrv!5Yb)z|sfdS5C$@uaeHO}^mo9#`TslG8; zXZeZE>IZFiV+#zY{hICn3{I`L?p`F@-c#Q@vDgW-rnmO3TA5mPBpnw}zqVmb|LQlo F{s$iiXx9J$ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_4_2.png b/resources/g2/track/corkscrew/zero_g_roll_left_4_2.png new file mode 100644 index 0000000000000000000000000000000000000000..86eeffe0a184793867e3a8fa10ef7c3a06313831 GIT binary patch literal 1325 zcmXAoeQXnT7{`BO8@Cro$x0|vSb>g|QK7&wFIct%ucM43yKPriT|)}qq$YJ9S&$q$)6lk=DfekEJp^!;t_OpcK`@H@0eE;}7 zPghf;ac0@PG62BLhE0Z+e67w$O-W%skN2&v0-z8yZ86p7$AW@_Y15_^78Vv26%`j3 zPoF*=L6DM?lG4&rg<7pfQ5`|xG)*#$#o=JxZg(IMibSHKIGRdjb2(H8a6O>Na*IW7 zx2v2koyV&W1gUVu8jCv;k~clZ6I#TqFK0;wXIA+bO~`=`xQTecoQSZgK~E;dPh>@- z5?Hmsi31;vgjpo+l_kUSTtW#mI+(M8co?$m{Mm{>uD{?U>25OJ(MS8 z4Mo|g#EB`tlnJLN;xZh_X`rwHl?!Nm2o_QpBN|H_XC<>Y?clRM5e`sVIfE&kMy=PZ z4>Lr}K}&8X8E}jV?rc0TAqj9yl*uuT){J5{oN&^#mtlfVXT`njRg^X0s3| zS)d6ZXjn$XlypLCOB0?k3!ibuvcAz=Br}zPQ2^2avI^)$Ay2`m9VR?5#ehQhRLi(4losB)X6Nk z%1)y$8|mZhyq}8+en}KEDG}z<7)in?fGGfBo`olG_ex5)D>ycW1p}|-NF)f0g|^!n zmy1PpZcG=zQGr0?q;8bbX3T16RY6VzgD8yRP$Kikk1a2M^703Ew=~jV{a?3t=KEBG zVS{N?*OAXHd&Gq^40qs2o6>NxLR~cV@R0FQ)pm=jc8~P<#PH9*%{|-xVe4jRbHj_u zUsj#0if%f(xclCc_rI#Yv9GIQ!|IJE6bsH6=KJ5+^}t>u$e)@_RC9dxwx^B5>yQO6 zZn-BaKDoKS=GfLR44pf#9QmQ(shQSaBJBcDt`<3JJao-;{hvzl!c_h9y))`6TkoB{wW4kEbqtt{r}&XMSCHeTyZ*}iBG%P=;7Ij5 zwPcHaJbS(8=7lEVbT3!8m|HaOZt_mO=D{cJSY3`?kaOCjED=g;T`3{$F=jOuD@L mI@eu#{70EHS39dumF3!ol*5-UoN?!wgNFJ>L;qXbKm8vrnnj!d literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_4_3.png b/resources/g2/track/corkscrew/zero_g_roll_left_4_3.png new file mode 100644 index 0000000000000000000000000000000000000000..5d42f9e44be8bbaa284242980662748be240cb8b GIT binary patch literal 969 zcmX9-Pl()f6n?w2+w7mNQ=NsNIixsUA{)CS28;71{~}hA`F<~AZv*@hX@gtGDw6)rWolQMw~+rV~Mbb1%IX#zV{yA<$WJ~ z?_IyNC$6nLw*mlbyKik@$>;gJ)|U!--}-+0SAYUsdi&~5PUq(4=I7@Ng~GzZ!s6oM zsZ*yg3|m@ST3%kp%jGh|R0M%n6iL%+hM_x-({6YB{VWLV zX;qpo*Y3!@zB-7EVd9P_zCdGDZdI3XyGnW*)isy{M~K?hVP8)Vo72=kp2Z>oDh(zN zo`UssEOLvZUMU+AXj(y;icUO);xd2?pkkO_EZPL&QIyYd2eN!vua9i|VYiE-h+s-( z9{0hvCJv7q_H(!(3^6zt9C;@Ozb#qCDY#c zI4bf`QUI?5X#wS7Y!?^%R4wB5r0R|hf9A#LK&DF?OPC_Xhn;{@{pxPMID+&Wb8PfH!(45r# zsX3T=M_GS*GCD@9bg{_dxJZ^2x}tHMA<0cOUuN~))?u%o#z{8jL6tB=DcUOOHRz7T z2Tf(rsUHURDC$f{ah5$qJU|t|0Pp|;fJ1-@1}KLtAj?33kJ6D$fzCjShfsu62BZMe zapW?{mr>Y2!zN07cpN+nk^og1YiPJ_(k)Ny`PyLMBuOxxCMee;>cCj5yobv^sfLuE za^9>KWai+wJv<4=Xf&frz>=6)Db{$hp)gim^6ZA+vIjvciGyhxqioDd5()vOfKZ-A zGnab;!m&D&3EOEufiWBkwVKjsXqKfj6^E^~c_t8;NU9vk^t4(=Dv4|gbr=-#D3S8x zXV0%bdi(>QT-j6Ljlb`IkP~xv`{LCXZr=U!;>yowPcLMs|Bm*V`_Uf{Hg|;A)<*)q zP&l~v%*M;NK0WjGgCD-pet+rmpJz9Jdj7{3cej4|_}!Z)gmL++^7V6fGHdee>o94E^*j5IF5G|WKl0iulYcgDZ=n6sg)h#%`q$dMYv1M; OV0UM4`@1*a|NMV!pPMTH literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_left_4_4.png b/resources/g2/track/corkscrew/zero_g_roll_left_4_4.png new file mode 100644 index 0000000000000000000000000000000000000000..280511fb9194fe7d9af3f9cad0016e22d953ed2d GIT binary patch literal 5328 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 MIg7Io&40E2KPmj!ivR!s literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_1_1.png b/resources/g2/track/corkscrew/zero_g_roll_right_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..60c1431798edd3df059343558cc7426488e36ffb GIT binary patch literal 1423 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_1_3.png b/resources/g2/track/corkscrew/zero_g_roll_right_1_3.png new file mode 100644 index 0000000000000000000000000000000000000000..edd1bc0dfb78f587bfdf4159c7c487110617220a GIT binary patch literal 971 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 YpI`oF{h8Mvh1mf4x$|;bW-ndyA3RRq-2eap literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_2_1.png b/resources/g2/track/corkscrew/zero_g_roll_right_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..2c0e9eff7423ec14b1f61623d2a5f42b2536d565 GIT binary patch literal 1137 zcmX9-e~i;~6o1DZ*W<>y=t2g}P-K5ptuUczCDl~y!8of|yrMJAIAV#5S+I~IGY%}F z#6<=+GQ%Q+Os!-gRfZf|VI)(h+=WRRGRTMx4xBiY#3>Ula)z%XB%k-|pZ7^VpZDHf zIUF45pWP1t14AnYM>=(WCua3^ck=E)$OF&~E1y}ltTT3XbxoNvrMtVkr>AG?)TzC_ zy%>h|_4Q4gHqGnz`zb2GajYovk`z`HS<|#kCRZp}<#N?=TJ1I!0G0uPcZI{ASPYLR z0?8DU$qM;Gq*ziacBsGFRypW{2nlf( zbP>zTSSjVMbd*9YK>iLS;XI01&}2+3i++KAj*8h8Y!vv1qiWs#kM4R4Vx> zkDv7h1e}QwL75Dxl%z9CmeWi=T@;N<#B!oI?F$6`j7ahl9hNycDI{}|oF!YfT6WTQ zGhd%5xmoat;Ee*F07A#;oHtk?!X;L=L#euAwDd9>6-bXn`{F?|6=L!dS5!n>lWG~I zVQQ^XX2Ld6qwMz31R0{}D9gn~F(paac)XBGm2x@Tvg*}ptJOl_lYz)!RNl=MePV@- z*12ROY&7G=mR@Zanv=B&-jIq#&9=>E(?%UGUlgc> zi`Bh?fk!Mtb{M@CHrw&yM5Z!n)lscQc!0*SV89(_@t8;@qP(ugjI>%b({|ZxI%U+Z z(>#wXKn@_(@gmuwy91w=$Tk{uHgg9`rNV{7Vk{;l5;7Ig=stPVG*AE?fk2q9v>Q9y6UlAyV9ZE+aI1jxCNO5U!6$I z_-xZJ(&fR~FJAfN{_hm?@<(Tx4Xd86@-u(0?fCiIz5SD?jvF5|#I5I_n{WTyb!hFf z1E>GOpP1z=KJ{sFt{5DW-y6Sm&$&&mi<|RH9`Y`}ezUrMr+@s~04?skd9O9sd-M!` z%pU*v#IZ-d{I#@y-51kOA3igxUFp4X@Vfl~ao?=3lLs~{8yEdB$2=r%Kk??mwfoM# z?Ro9GmKb?7J>nj@`fAr$?yIy*JWZQ++d+rvl_N~3NFWWrw=b|;= x>{v2y%d_p*+2iZ_AH22x?KwWAvhEgK#@^wgSd{{!`C_R|0W literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_2_2.png b/resources/g2/track/corkscrew/zero_g_roll_right_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..8b851546e7cbd32199a979fbf402a7179d998281 GIT binary patch literal 1230 zcmXAoZ)_8F7{`C?Ukhaxs8XRZoz~>kb2-czJGqc^+-4mG4!B823On$0jg;gviz!gd z;VRZq$IaAGuxMk>t+FzT%yCK`_oB*TsvJ0yLe5xBk)jKft(rwP^RtBH`}}+Jd|!N? zr+348NBx533jhH1ZLhR!s#K&B4f^Uz9^CVh0zfs`u(rLmGR~Vfud1r5y1Kfirlz*G zwyv&Dr_<^6`uX$cn{755j$;%>GK`bs+&&*43RqpbvsIC#`0;G9VKVpK5cjHDSU%gUO^YPVnx8^NGX&hF+ZK17G&Y+UAL zRmf-&wV24yC`J;P7-04QYXBgk&K@^AQixk2dDRup`=pYXfg?0(;_Mc`0}Z=~1V^QP zj2h%}QC}e$EGf|$H3^KKQU1%l_0S20Ez1G zgpo>Hm@MkaQ=x)eD*DqUaiW|m&gN#I0W})!X0yX;V^EAE2%nPlmXNLgcTN{iroWQf`M3}V2?!~$d}DhZa3rga)AJkV?jF> zCGjMMD^6^JMvE>RWUWv@U<`*c2~}t1`0b5`srx^$d((Obyma$wSEb+I*3#VG)OWCb z%bD*R^gsQVI?~;CYDsJD$$kA_Zt2>)%F4ZFsDI(uAb<7zonQNp3U?eW7v7}0E>7$J zHT3Nqe!lsS_f95m;fs&dxMyM7d#DI>PM;e>VzFtPOhDC5g7iN3?ghty#0`_%VO) zr_rIhg^O!8A9}{ti4I^pe*lj?boWQEdggN5#^6$6vSG#9R^(5*dvbTp*uBQij-LIu zJJHDA{=-epU$^g@e(U^KJu6piADcywfBvNHM&}b--`Vr{?V$rNpS^@R4sSh;T!~r! zGAZSALmwd6lCjI1ZVlvi6r#%e%*KKEmDq%Gtz%TX{?Fzqebr?1wae4~jliS~vQJ s-}Bj`?BcP3dj}p3T^CLt{F|FGHqGI$`gUFOR-k~k*7Yr?R&Ve5A6053Pyhe` literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_2_3.png b/resources/g2/track/corkscrew/zero_g_roll_right_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..26b59ed2d735469a9a99bfdbf7b1ecb150a665b2 GIT binary patch literal 976 zcmX9-QHa}g82|3Bcj;Z76*>*rhYZVzE}KCD2FWyP?&yw;%eWj?7a>Am75fl0O2L3} z7om)TQHoYAN7aB80~Wo92-QU?ShPZzRVoDRLuGl`LzN;05AJWq;P-tWznAa#gWvaE zyR=h0v2p(f0G!yqu(_K|GO3g4m83t`_$>vn0+%lCZ6$PRX=!vMg$vVi>w@+s$UX+x7eXQ54PQbA|?<14+y%O0H5NswQ2l zbIq32>8icJ7>4!9)DUmXG3yuepi)rf!I80! zjs^AXxRaX?^C+g#Tt!C?Lj3}O1fXJ=p3PeMyhD;M#~n)2pj;kX)~$9M1wo$46?mMM z2u>x7I#se5&EbreV0&VtC%Z${kIDp_r;7znrbLZZbV094wYJ*!bw9NFQ6r2ylSPo_ zAtwV~2Eqi=!Pqul?2<~r>tU%rG2EHcM~4!X)7X5qNYzVRM-zI69NOBrX-qwP7Bm;3 zho=2(jwPuQ!DQ^k#| zy_qwbcjKe+0%fRdmc{WRQIIKG<2XZ2fzau08BAJ2_ylT2J&1KjU^Iv1{ys0MTjIoG9VpC zbq2W-@+)XqLy-%&gJ(e$pd?`x4Y#UP!zp%Lt=F@|(2L^`C0hA1FlL5#aLFZ9pVTAH znJM19+FLY-NB#tjXJigo0xQy4g(oU9W0pn7s<;iS=QYB<7e{?GpRl5cd_WN(lw?s$ zw!kKE8VMc=wANm+wiPRF2Od#AhBodvwP9{qjetAO9Zx zb@tjz=RSDtqD?%!xPIke@2BXi$A39K`1P}A<0sA!|GoNp`nzX@Z@zXvU-#bsKJ)4I X=eG7gyzfTh1h%(!HotuOh5i2lHu9o1 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_2_4.png b/resources/g2/track/corkscrew/zero_g_roll_right_2_4.png new file mode 100644 index 0000000000000000000000000000000000000000..84c2021046042b3b2bb9af8b7a45d995c04cbd32 GIT binary patch literal 5257 zcmeHLeN+=y7Jq;c5H;OW4K3Qlq+8T9Op-|mB+!Tf14axbD06Il1;1z48&P=ktu9(@E5z)a zDl2KSloK3VZ56>GYAhxIYQCr_2u}2ICfqV_+I*q7^99wb*_UIcd1Dj{OIJT^?mIlG z?}%5gUTu45-j+S3`_t>Q-Y#0PeMZ_B%f~&MF+))A-z;hFX`%dzQJ_X zD*DVEd*!L3IL9v{F7sUS+%l53a2MM69!@R0Vk| z)tzu)5IfhroSEyJJ@rF<$(}t$@-tbdrZ2BP)VN8$eb$tdb1eKLmzP_=VM#2xg-fSK z_pGgFH!ftb%*&=Njn29jb?WTNywf@JZs`k4|Il}GrSkljb>~h*9pCqu?uGZ$UVrP& zU3pKgdlp-G&CA^YK1lrVosT96wk`YQWc9OO`g}c}#DG;f)SviLV@y;=E$b1eB@4lYF(`>z9;?kvdsfBs$T*Ufal4n>Ie^Ymt%!(K=f1e+{{MwY* z{plyFe_Z)9xcHXqKS>uZJd}v&etggGi8^uOm%2B*dzsfhwVu6ElSRU^TV;XewK#vi z949MMFe7OoQfexyVBG2F%V`;WhQsPyB}Wju-JW7cQ%I{B5v8Z6BSJAE z77L(+fU2#uVKstEiWhgfp+-j+^S;$IG2op1q)wWD77w&WJ_*YStpFav;NsX`o z`9Ny0DnyhbL@Fwfu^N;uXB7k)ap*TSs3O>rUED%SEiU=VplnBy9GE5*b8ifMPXpjkH>84bP(O{H` zB-j`TtK}NS7L=Moeswno`rlP)1xn zm$X)3FrAhP%uFCvmFDn9h;VsUL0%?ToFcrtQc#ZBOi%&#fThw%+Nrx+MV1OeXTw5# zie%z6iBKX;l}OV>s5tem&?3T0!CDNVii9a>T6iav7�FQj3Ku6#|6UVKj1;mB4JI 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_3_2.png b/resources/g2/track/corkscrew/zero_g_roll_right_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..654d93c1a49ff6628b112c495a5ee5c9779d75fc GIT binary patch literal 1065 zcmXAoQD_@=9LIlc+FskNM4N|DBV-!cDTkcnRt~)4Ij=RAlU~_%1{c{)Z!Qm!-rRM~ zL!iful8(5YHH?4(1G|Sj94s3ZPR%3_5!w;-gxbb=x@-#?v@4lpn2oA`GX~$^@5lG$ z_kH;MerIQALL~Y) zUw?o9z`y{8VS|H%LqkKpU@%BgB*(F$$jfp>Rh48ina$>lMXOTTaGX}VO_9JdAn@); z#2bqR;t4X9X0kbIhYW00Mx7VT#A2`TaVM8w|552y4-3P1CmX zc~ma@DQ}SVkwSox@Q^};HA>bQHOD1QK2s8ns$@CQ0PQD3K}IBanT{x&k`hvRDQ_v3 ztyP?i-7M5QWe*Ep5qwbyBmmbjI`0b=@kp6f>~OlS8ZEtoRt3T<)BbpfNQaq%%#~Ep zPRg~c+Ax!?a<*fes8R8FX`BdCbd=@dqL`NDTs&S(r_1@gZCUk=jaI9Lz^?$F#i)XZ zEBVDL5v_BnM#N~wOD%n)U2N{wI>=3UJhaaj3Is)hlo>|lg_P7?mMEq(YlWgyvDmk0u557?De`W=bsOqHCsBE9aWEO1r&{Sb#8q3ZMg+0BZmZ3{Y1BhY~6>4dm1W z925#NELb6M1VADn#fQ=qG6ZDBP&I`d10I5>f#)DBU@_UJ#fgj_Dj0I9l(cQL*|bqN z%O3?Q;bwK8U<4!!R~$xfMa*`*)X7$Ntvaf;a4*mSEJS)DY#=65i72mYF(adu%#2+z zn@$C_>om_J3y=c{by=jkagXFrCUT7ioy$IwTCH-Ch!~5>iG)ItNt(>El*v(Lp4xsc-|gg{~N!%^N!kDIQpw}X8Yy~6Zfy4oV)(g(!~7-ztFBf?C;?4 z$PZWd^=KEln0tBo-CFPHm3isb)W_E!d~xH}*?VJwRq?G;qsHdm-t))yT;}&*J9vEG z^1YeeZ*=GJo!hUXiKp@L>8u WZfy2R;>#|5fa$53$xE*s``~|uMALTw literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_3_3.png b/resources/g2/track/corkscrew/zero_g_roll_right_3_3.png new file mode 100644 index 0000000000000000000000000000000000000000..c520c0aaa980e42f0c1b5043255785aadb74bb35 GIT binary patch literal 4976 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 Sdjo|<2FZ!D6ZXznwDLb#>Kw-a literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_4_1.png b/resources/g2/track/corkscrew/zero_g_roll_right_4_1.png new file mode 100644 index 0000000000000000000000000000000000000000..d66f1f132ab8c9ec8af886aa7483f162161ba100 GIT binary patch literal 1127 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 y@x;NlFk?(vU9gksf_{d7-ZaUdl^K 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 F{{!%-Fq8lQ literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/zero_g_roll_right_4_4.png b/resources/g2/track/corkscrew/zero_g_roll_right_4_4.png new file mode 100644 index 0000000000000000000000000000000000000000..be44720ec7e1ecd12fd4c97682a02b44475a59cc GIT binary patch literal 5473 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 literal 0 HcmV?d00001 diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 8dc1032cee..2e67630a3d 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -49,7 +49,7 @@ using namespace OpenRCT2; // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -constexpr uint8_t kNetworkStreamVersion = 8; +constexpr uint8_t kNetworkStreamVersion = 9; const std::string kNetworkStreamID = std::string(OPENRCT2_VERSION) + "-" + std::to_string(kNetworkStreamVersion); diff --git a/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp b/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp index f61f868de0..50cc3e3672 100644 --- a/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp +++ b/src/openrct2/paint/track/coaster/CorkscrewRollerCoaster.cpp @@ -11046,6 +11046,8353 @@ static void LayDownRCTrackHalfLoopUninvertedDown( return; } +static void CorkscrewRCTrackFlatTo60DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 0), + { 0, 0, height }, { { 0, 2, height }, { 32, 27, 4 } }); + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 2), + { 0, 0, height }, { { 0, 29, height }, { 32, 1, 43 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 1), + { 0, 0, height }, { { 0, 4, height }, { 32, 2, 43 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 4, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 4), + { 0, 0, height }, { { 0, 29, height }, { 32, 1, 43 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 3), + { 0, 0, height }, { { 0, 4, height }, { 32, 2, 43 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 4, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 5), + { 0, 0, height }, { { 0, 2, height }, { 32, 27, 4 } }); + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 24, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); +} + +static void CorkscrewRCTrack60DegUpToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 6), + { 0, 0, height }, { { 0, 2, height }, { 32, 27, 4 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 7), + { 0, 0, height }, { { 0, 4, height }, { 32, 2, 43 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 8), + { 0, 0, height }, { { 29, 4, height + 2 }, { 1, 24, 43 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 10), + { 0, 0, height }, { { 29, 4, height + 2 }, { 1, 24, 43 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 9), + { 0, 0, height }, { { 0, 4, height }, { 32, 2, 43 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 11), + { 0, 0, height }, { { 0, 2, height }, { 32, 27, 4 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 16, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 24, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); +} + +static void CorkscrewRCTrackFlatTo60DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrack60DegUpToFlat(session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack60DegDownToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackFlatTo60DegUp(session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagFlatTo60DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 15), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 12), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 14), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 7, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 13), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 7, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 7, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 7, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + } +} + +static void CorkscrewRCTrackDiag60DegUpToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 19), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 16), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 18), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 20, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 17), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 20, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 20, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 20, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackDiagFlatTo60DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 17), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 18), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 16), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 16, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 19), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 16, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 16, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 16, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackDiag60DegDownToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 13), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 14), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 12), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 5, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 15), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 4 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 5, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 5, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 5, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + } +} + +static void CorkscrewRCTrack90DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(26607), { 0, 0, height + 8 }, + { { 4, 6, height }, { 2, 20, 31 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(26608), { 0, 0, height + 8 }, + { { 24, 6, height }, { 2, 20, 31 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(26605), { 0, 0, height + 8 }, + { { 24, 6, height }, { 2, 20, 31 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(26606), { 0, 0, height + 8 }, + { { 4, 6, height }, { 2, 20, 31 } }); + break; + } + PaintUtilSetVerticalTunnel(session, height + 32); + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); + break; + case 1: + break; + } +} + +static void CorkscrewRCTrack90DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrack90DegUp(session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack60DegUpTo90DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 0), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 1), + { 0, 0, height }, { { 24, 6, height }, { 2, 20, 55 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 2), + { 0, 0, height }, { { 24, 6, height }, { 2, 20, 55 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 3), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetVerticalTunnel(session, height + 56); + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + break; + } +} + +static void CorkscrewRCTrack90DegDownTo60DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrack60DegUpTo90DegUp(session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack90DegUpTo60DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 4), { 0, 0, height }, + { { 0, 6, height + 2 }, { 6, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 5), { 0, 0, height }, + { { 39, 6, height + 8 }, { 2, 20, 31 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 6), { 0, 0, height }, + { { 39, 6, height + 8 }, { 2, 20, 31 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 7), { 0, 0, height }, + { { 0, 6, height + 2 }, { 6, 20, 3 } }); + break; + } + switch (direction) + { + case 1: + PaintUtilPushTunnelRight(session, height + 48, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + case 2: + PaintUtilPushTunnelLeft(session, height + 48, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 80); +} + +static void CorkscrewRCTrack60DegDownTo90DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 6), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 80 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 7), + { 0, 0, height }, { { 0, 6, height + 2 }, { 6, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 4), + { 0, 0, height }, { { 0, 6, height + 2 }, { 6, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL + 5), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 80 } }); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height + 48, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 80); + break; + case 1: + break; + } +} + +static void CorkscrewRCTrackLeftQuarterTurn190DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 0), + { 0, 0, height }, { { 4, 6, height + 8 }, { 2, 20, 63 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 1), + { 0, 0, height }, { { 4, 6, height + 8 }, { 2, 20, 63 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 2), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 63 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 3), + { 0, 0, height }, { { 24, 24, height + 8 }, { 2, 2, 63 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 4), + { 0, 0, height }, { { 4, 6, height + 8 }, { 2, 20, 63 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 5), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 63 } }); + break; + } + PaintUtilSetVerticalTunnel(session, height + 96); + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 96); + break; + case 1: + break; + } +} + +static void CorkscrewRCTrackRightQuarterTurn190DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 6), + { 0, 0, height }, { { 4, 6, height + 8 }, { 2, 20, 63 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 7), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 63 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 8), + { 0, 0, height }, { { 24, 24, height + 8 }, { 2, 2, 63 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 9), + { 0, 0, height }, { { 6, 4, height + 8 }, { 20, 2, 63 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 10), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 63 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 11), + { 0, 0, height }, { { 4, 6, height + 8 }, { 2, 20, 63 } }); + break; + } + PaintUtilSetVerticalTunnel(session, height + 96); + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 96); + break; + case 1: + break; + } +} + +static void CorkscrewRCTrackLeftQuarterTurn190DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightQuarterTurn190DegUp( + session, ride, trackSequence, (direction + 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightQuarterTurn190DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftQuarterTurn190DegUp( + session, ride, trackSequence, (direction - 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack25DegUpToLeftBanked25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 0)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 1)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 2)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 3)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 4)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); +} + +static void CorkscrewRCTrack25DegUpToRightBanked25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 5)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 6)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 7)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 8)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 9)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); +} + +static void CorkscrewRCTrackLeftBanked25DegUpTo25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 10)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 11)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 12)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 13)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 14)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); +} + +static void CorkscrewRCTrackRightBanked25DegUpTo25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 15)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 16)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 17)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 18)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 19)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); +} + +static void CorkscrewRCTrackLeftBanked25DegDownTo25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrack25DegUpToRightBanked25DegUp( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightBanked25DegDownTo25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrack25DegUpToLeftBanked25DegUp( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack25DegDownToLeftBanked25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightBanked25DegUpTo25DegUp( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack25DegDownToRightBanked25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftBanked25DegUpTo25DegUp( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftBankedFlatToLeftBanked25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 20)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 21)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 22)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 23)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); +} + +static void CorkscrewRCTrackRightBankedFlatToRightBanked25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 24)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 25)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 26)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 27)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); +} + +static void CorkscrewRCTrackLeftBanked25DegUpToLeftBankedFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 28)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 29)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 30)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 31)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::FlatTo25Deg); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); +} + +static void CorkscrewRCTrackRightBanked25DegUpToRightBankedFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 32)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 33)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 34)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 35)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::FlatTo25Deg); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); +} + +static void CorkscrewRCTrackLeftBankedFlatToLeftBanked25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightBanked25DegUpToRightBankedFlat( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightBankedFlatToRightBanked25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftBanked25DegUpToLeftBankedFlat( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftBanked25DegDownToLeftBankedFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightBankedFlatToRightBanked25DegUp( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightBanked25DegDownToRightBankedFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftBankedFlatToLeftBanked25DegUp( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack25DegUpLeftBanked( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 36)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 37)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 38)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 39)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); +} + +static void CorkscrewRCTrack25DegUpRightBanked( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 40)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 41)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 42)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 43)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); +} + +static void CorkscrewRCTrack25DegDownLeftBanked( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrack25DegUpRightBanked(session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack25DegDownRightBanked( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrack25DegUpLeftBanked(session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackFlatToLeftBanked25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 44)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 45)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 46)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 47)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 48)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); +} + +static void CorkscrewRCTrackFlatToRightBanked25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 49)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 50)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 51)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 52)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 53)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); +} + +static void CorkscrewRCTrackLeftBanked25DegUpToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 54)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 55)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 56)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 57)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 58)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::FlatTo25Deg); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); +} + +static void CorkscrewRCTrackRightBanked25DegUpToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 59)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 60)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 61)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 62)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 63)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::Flat); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::FlatTo25Deg); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); +} + +static void CorkscrewRCTrackFlatToLeftBanked25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightBanked25DegUpToFlat( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackFlatToRightBanked25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftBanked25DegUpToFlat( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftBanked25DegDownToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackFlatToRightBanked25DegUp( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightBanked25DegDownToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackFlatToLeftBanked25DegUp( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftBankedQuarterTurn3Tile25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 0)), + { 0, 6, height }, { 32, 20, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 2)), + { 0, 6, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 4)), + { 0, 6, height }, { 32, 20, 3 }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 6)), + { 0, 6, height }, { 32, 20, 3 }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 16)), + { 16, 16, height }, { 16, 16, 3 }); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 1)), + { 6, 0, height }, { 20, 32, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 3)), + { 6, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 5)), + { 6, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 7)), + { 6, 0, height }, { 20, 32, 3 }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + switch (direction) + { + case 2: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + case 3: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackRightBankedQuarterTurn3Tile25DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 8)), + { 0, 6, height }, { 32, 20, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 10)), + { 0, 6, height }, { 32, 20, 3 }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 12)), + { 0, 6, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 14)), + { 0, 6, height }, { 32, 20, 3 }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 17)), + { 16, 16, height }, { 16, 16, 3 }); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 9)), + { 6, 0, height }, { 20, 32, 3 }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 11)), + { 6, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 13)), + { 6, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 10, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 15)), + { 6, 0, height }, { 20, 32, 3 }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + break; + } + switch (direction) + { + case 0: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + case 1: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackLeftBankedQuarterTurn3Tile25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + trackSequence = kMapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence]; + CorkscrewRCTrackRightBankedQuarterTurn3Tile25DegUp( + session, ride, trackSequence, (direction + 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightBankedQuarterTurn3Tile25DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + trackSequence = kMapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence]; + CorkscrewRCTrackLeftBankedQuarterTurn3Tile25DegUp( + session, ride, trackSequence, (direction - 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftBankedQuarterTurn525DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 0)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 5)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 10)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 15)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 1)), + { 0, 0, height }, { 32, 16, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 6)), + { 0, 0, height }, { { 30, 30, height }, { 1, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 11)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 16)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 2)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 7)), + { 0, 0, height }, { { 30, 30, height }, { 1, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 12)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 17)), + { 0, 0, height }, { 16, 16, 3 }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 4: + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 5: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 3)), + { 0, 0, height }, { { 16, 0, height }, { 16, 32, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 8)), + { 0, 0, height }, { { 30, 30, height }, { 1, 1, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 13)), + { 0, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 18)), + { 0, 0, height }, { { 16, 0, height }, { 16, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 6: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 4)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 9)), + { 0, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 14)), + { 0, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 19)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + switch (direction) + { + case 2: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + case 3: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackRightBankedQuarterTurn525DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 20)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 25)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 30)), + { 0, 0, height }, { { 0, 27, height }, { 32, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 35)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 21)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 26)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 31)), + { 0, 0, height }, { { 30, 30, height }, { 1, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 36)), + { 0, 0, height }, { 32, 16, 3 }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 22)), + { 0, 0, height }, { 16, 16, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 27)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 32)), + { 0, 0, height }, { { 30, 30, height }, { 1, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 37)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 4: + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 5: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 23)), + { 0, 0, height }, { { 16, 0, height }, { 16, 32, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 28)), + { 0, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 33)), + { 0, 0, height }, { { 30, 30, height }, { 1, 1, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 38)), + { 0, 0, height }, { { 16, 0, height }, { 16, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 6: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 24)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 29)), + { 0, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 34)), + { 0, 0, height }, { { 27, 0, height }, { 1, 32, 34 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 39)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + switch (direction) + { + case 0: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + case 1: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackLeftBankedQuarterTurn525DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + trackSequence = kMapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence]; + CorkscrewRCTrackRightBankedQuarterTurn525DegUp( + session, ride, trackSequence, (direction + 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightBankedQuarterTurn525DegDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + trackSequence = kMapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence]; + CorkscrewRCTrackLeftBankedQuarterTurn525DegUp( + session, ride, trackSequence, (direction - 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftEighthToDiagUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 0)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 4)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 8)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 12)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 1)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 5)), + { 0, 0, height }, { { 0, 0, height }, { 34, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 9)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 13)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 2)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 6)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 10)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 14)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 3)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 12, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 7)), + { 0, 0, height }, { { 0, 16, height }, { 16, 18, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 5, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 11)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 3, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 15)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 3, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackRightEighthToDiagUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 16)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 20)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 24)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 28)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 17)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 21)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 25)), + { 0, 0, height }, { { 0, 0, height }, { 34, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 29)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 18)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 22)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 26)), + { 0, 0, height }, { { 4, 4, height }, { 28, 28, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 30)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 19)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 3, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 23)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 3, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 27)), + { 0, 0, height }, { { 0, 16, height }, { 16, 18, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 5, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 31)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 10, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackLeftEighthToOrthogonalUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 32)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 7, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 36)), + { 0, 0, height }, { { 16, 16, height }, { 16, 18, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 5, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 40)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 5, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 44)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 4, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 33)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 37)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 41)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 45)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 34)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 38)), + { 0, 0, height }, { { 0, 0, height }, { 34, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 42)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 46)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 35)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 39)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 43)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 10 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 47)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 5, height, session.SupportColours); + + if (direction == 1 || direction == 2) + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackRightEighthToOrthogonalUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 48)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 5, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 52)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 5, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 56)), + { 0, 0, height }, { { 16, 0, height }, { 16, 18, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 7, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 60)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 4, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 49)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 53)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 57)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 61)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 50)), + { 0, 0, height }, { { 16, 0, height }, { 16, 32, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 54)), + { 0, 0, height }, { { 0, 0, height }, { 16, 32, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 58)), + { 0, 0, height }, { { 0, 0, height }, { 16, 32, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 62)), + { 0, 0, height }, { { 16, 0, height }, { 16, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 51)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 10 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 55)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 59)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 63)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 5, height, session.SupportColours); + if (direction == 0 || direction == 1) + { + PaintUtilPushTunnelRotated(session, direction + 1, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags(PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::bottomRightSide), direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackLeftEighthToDiagDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + uint8_t map[5] = { 4, 3, 1, 2, 0 }; + trackSequence = map[trackSequence]; + CorkscrewRCTrackRightEighthToOrthogonalUp25( + session, ride, trackSequence, (direction + 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightEighthToDiagDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + uint8_t map[5] = { 4, 3, 1, 2, 0 }; + trackSequence = map[trackSequence]; + CorkscrewRCTrackLeftEighthToOrthogonalUp25( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftEighthToOrthogonalDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence]; + CorkscrewRCTrackRightEighthToDiagUp25(session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightEighthToOrthogonalDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence]; + CorkscrewRCTrackLeftEighthToDiagUp25(session, ride, trackSequence, (direction + 3) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagUp25ToLeftBankedUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 4)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 0)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 1)), + { -16, -16, height }, { { -16, -16, height + 48 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 3)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 5, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 2)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 10, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 10, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 10, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackDiagUp25ToRightBankedUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 9)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 5)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 7)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 8)), + { -16, -16, height }, { { -16, -16, height + 48 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 10, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 6)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 10, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 5, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 10, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackDiagLeftBankedUp25ToUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 14)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 10)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 11)), + { -16, -16, height }, { { -16, -16, height + 48 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 13)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 5, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 12)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 9, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 9, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 9, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + } +} + +static void CorkscrewRCTrackDiagRightBankedUp25ToUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 19)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 15)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 17)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 18)), + { -16, -16, height }, { { -16, -16, height + 48 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 9, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 16)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 9, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 5, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 9, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + } +} + +static void CorkscrewRCTrackDiagDown25ToLeftBankedDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagRightBankedUp25ToUp25( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagDown25ToRightBankedDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagLeftBankedUp25ToUp25( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagLeftBankedDown25ToDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagUp25ToRightBankedUp25( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagRightBankedDown25ToDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagUp25ToLeftBankedUp25( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagLeftBankedFlatToLeftBankedUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 23)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 20)), + { -16, -16, height }, { { -16, -16, height + 34 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 22)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 0, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 21)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 4, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 4, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 4, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackDiagRightBankedFlatToRightBankedUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 27)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 24)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 26)), + { -16, -16, height }, { { -16, -16, height + 34 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 4, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 25)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 4, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 0, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 4, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackDiagLeftBankedUp25ToLeftBankedFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 31)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 28)), + { -16, -16, height }, { { -16, -16, height + 32 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 30)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 4, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 29)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 8, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 8, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 8, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + } +} + +static void CorkscrewRCTrackDiagRightBankedUp25ToRightBankedFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 35)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 32)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 34)), + { -16, -16, height }, { { -16, -16, height + 32 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 8, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 33)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 8, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 4, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 8, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + } +} + +static void CorkscrewRCTrackDiagLeftBankedFlatToLeftBankedDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagRightBankedUp25ToRightBankedFlat( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagRightBankedFlatToRightBankedDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagLeftBankedUp25ToLeftBankedFlat( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagLeftBankedDown25ToLeftBankedFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagRightBankedFlatToRightBankedUp25( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagRightBankedDown25ToRightBankedFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagLeftBankedFlatToLeftBankedUp25( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagUp25LeftBanked( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 39)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 36)), + { -16, -16, height }, { { -16, -16, height + 42 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 38)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 6, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 37)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 11, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 11, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 11, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + } +} + +static void CorkscrewRCTrackDiagUp25RightBanked( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 43)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 40)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 42)), + { -16, -16, height }, { { -16, -16, height + 42 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 11, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 41)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 11, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 6, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 11, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + } +} + +static void CorkscrewRCTrackDiagDown25LeftBanked( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagUp25RightBanked( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagDown25RightBanked( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagUp25LeftBanked( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagFlatToLeftBankedUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 48)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 44)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 45)), + { -16, -16, height }, { { -16, -16, height + 34 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 47)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 0, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 46)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 4, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 4, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 4, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackDiagFlatToRightBankedUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 53)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 49)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 51)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 52)), + { -16, -16, height }, { { -16, -16, height + 34 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 4, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 50)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 4, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 0, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 4, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackDiagLeftBankedUp25ToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 58)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 54)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 55)), + { -16, -16, height }, { { -16, -16, height + 27 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 57)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 4, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 56)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 6, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 6, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 6, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + } +} + +static void CorkscrewRCTrackDiagRightBankedUp25ToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 63)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 59)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 61)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 62)), + { -16, -16, height }, { { -16, -16, height + 27 }, { 32, 32, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 3: + switch (direction) + { + case 0: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 6, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 60)), + { -16, -16, height }, { { -16, -16, height }, { 32, 32, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 6, height, session.SupportColours); + break; + case 2: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 4, height, session.SupportColours); + break; + case 3: + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 6, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + } +} + +static void CorkscrewRCTrackDiagFlatToLeftBankedDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagRightBankedUp25ToFlat( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagFlatToRightBankedDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagLeftBankedUp25ToFlat( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagLeftBankedDown25ToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagFlatToRightBankedUp25( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackDiagRightBankedDown25ToFlat( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackDiagFlatToLeftBankedUp25( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftEighthBankToDiagUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 64)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 9, height - 4, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 68)), + { 0, 0, height }, { { 0, 31, height }, { 32, 1, 32 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 7, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 72)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 9, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 76)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 12, height, session.SupportColours); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 65)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 69)), + { 0, 0, height }, { { 0, 31, height }, { 32, 1, 32 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 73)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 77)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 66)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 70)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 40, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 74)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 78)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 67)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 7, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 71)), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 6, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 75)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 7, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 79)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 8, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackRightEighthBankToDiagUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 80)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 12, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 84)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 9, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 88)), + { 0, 0, height }, { { 0, 31, height }, { 32, 1, 32 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 7, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 92)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 9, height - 4, session.SupportColours); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 81)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 85)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 89)), + { 0, 0, height }, { { 0, 31, height }, { 32, 1, 32 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 93)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 82)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 86)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 90)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 40, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 94)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 83)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 8, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 87)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 7, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 91)), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 6, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 95)), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 7, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackLeftEighthBankToOrthogonalUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 96)), + { 0, 0, height }, { { 0, 0, height + 40 }, { 32, 32, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 7, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 100)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 32, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 8, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 104)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 9, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 108)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 4, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 97)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 32, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 101)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 32, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 105)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 109)), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 98)), + { 0, 0, height }, { { 0, 31, height + 32 }, { 32, 1, 32 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 102)), + { 0, 0, height }, { { 0, 31, height }, { 32, 1, 32 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 106)), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 10 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 110)), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 99)), + { 0, 0, height }, { { 0, 31, height }, { 32, 1, 32 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 103)), + { 0, 0, height }, { { 0, 31, height }, { 32, 1, 32 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 107)), + { 0, 0, height }, { { 0, 0, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 111)), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 11, height, session.SupportColours); + break; + } + if (direction == 1 || direction == 2) + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackRightEighthBankToOrthogonalUp25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 112)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 9, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 116)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 32, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 7, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 120)), + { 0, 0, height }, { { 0, 0, height + 40 }, { 32, 32, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 7, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 124)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 3, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 113)), + { 0, 0, height }, { { 0, 0, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 117)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 32, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 121)), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 32, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 125)), + { 0, 0, height }, { { 0, 16, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 114)), + { 0, 0, height }, { { 0, 0, height }, { 16, 32, 10 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 118)), + { 0, 0, height }, { { 31, 0, height }, { 1, 32, 32 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 122)), + { 0, 0, height }, { { 31, 0, height }, { 1, 32, 32 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 126)), + { 0, 0, height }, { { 16, 0, height }, { 16, 32, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 115)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 119)), + { 0, 0, height }, { { 31, 0, height }, { 1, 32, 32 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 123)), + { 0, 0, height }, { { 31, 0, height }, { 1, 32, 32 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, + session.TrackColours.WithIndex((SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 127)), + { 0, 0, height }, { { 6, 0, height }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 11, height, session.SupportColours); + break; + } + if (direction == 0 || direction == 1) + { + PaintUtilPushTunnelRotated(session, direction + 1, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags(PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::bottomRightSide), direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + } +} + +static void CorkscrewRCTrackLeftEighthBankToDiagDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + uint8_t map[5] = { 4, 3, 1, 2, 0 }; + trackSequence = map[trackSequence]; + CorkscrewRCTrackRightEighthBankToOrthogonalUp25( + session, ride, trackSequence, (direction + 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightEighthBankToDiagDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + uint8_t map[5] = { 4, 3, 1, 2, 0 }; + trackSequence = map[trackSequence]; + CorkscrewRCTrackLeftEighthBankToOrthogonalUp25( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftEighthBankToOrthogonalDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence]; + CorkscrewRCTrackRightEighthBankToDiagUp25( + session, ride, trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightEighthBankToOrthogonalDown25( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence]; + CorkscrewRCTrackLeftEighthBankToDiagUp25( + session, ride, trackSequence, (direction + 3) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftBankToLeftQuarterTurn325DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 0), + { 0, 6, height }, { 32, 20, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 2), + { 0, 6, height }, { 32, 20, 3 }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 3), + { 0, 6, height }, { { 0, 27, height }, { 32, 1, 26 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 5), + { 0, 6, height }, { 32, 20, 3 }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 7), + { 0, 6, height }, { 32, 20, 3 }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 1: + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 18), + { 16, 16, height }, { 16, 16, 3 }); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 1), + { 6, 0, height }, { { 0, 6, height - 6 }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 2, height - 6, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 4), + { 6, 0, height }, { { 0, 6, height - 6 }, { 20, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 20), + { 6, 0, height }, { { 0, 6, height + 32 }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height - 6, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 6), + { 6, 0, height }, { { 0, 6, height - 6 }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height - 6, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 8), + { 6, 0, height }, { { 0, 6, height - 6 }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 5, height - 6, session.SupportColours); + break; + } + switch (direction) + { + case 2: + PaintUtilPushTunnelRight(session, height, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + case 3: + PaintUtilPushTunnelLeft(session, height, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + } +} + +static void CorkscrewRCTrackRightBankToRightQuarterTurn325DegUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 9), + { 0, 6, height }, { 32, 20, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 11), + { 0, 6, height }, { 32, 20, 3 }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 13), + { 0, 6, height }, { 32, 20, 3 }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 14), + { 0, 6, height }, { { 0, 27, height }, { 32, 1, 26 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 16), + { 0, 6, height }, { 32, 20, 3 }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 1: + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 19), + { 16, 16, height }, { 16, 16, 3 }); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 10), + { 6, 0, height }, { { 0, 6, height - 6 }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 6, height - 6, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 12), + { 6, 0, height }, { { 0, 6, height - 6 }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 6, height - 6, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 15), + { 6, 0, height }, { { 0, 6, height - 6 }, { 20, 32, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 21), + { 6, 0, height }, { { 0, 6, height + 32 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height - 6, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 17), + { 6, 0, height }, { { 0, 6, height - 6 }, { 20, 32, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 3, height - 6, session.SupportColours); + break; + } + switch (direction) + { + case 0: + PaintUtilPushTunnelRight(session, height, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + case 1: + PaintUtilPushTunnelLeft(session, height, kTunnelGroup, TunnelSubType::SlopeEnd); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + } +} + +static void CorkscrewRCTrackLeftQuarterTurn325DegDownToLeftBank( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 12), + { 0, 6, height }, { { 0, 6, height - 6 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height - 6, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 15), + { 0, 6, height }, { { 0, 6, height - 6 }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 21), + { 0, 6, height }, { { 0, 6, height + 32 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height - 6, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 17), + { 0, 6, height }, { { 0, 6, height - 6 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 3, height - 6, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 10), + { 0, 6, height }, { { 0, 6, height - 6 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 6, height - 6, session.SupportColours); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 1: + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 19), + { 16, 16, height }, { 16, 16, 3 }); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 11), + { 6, 0, height }, { 20, 32, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 13), + { 6, 0, height }, { 20, 32, 3 }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 14), + { 6, 0, height }, { { 27, 0, height }, { 1, 32, 26 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 16), + { 6, 0, height }, { 20, 32, 3 }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 9), + { 6, 0, height }, { 20, 32, 3 }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + switch (direction) + { + case 2: + PaintUtilPushTunnelRight(session, height, kTunnelGroup, TunnelSubType::Flat); + break; + case 3: + PaintUtilPushTunnelLeft(session, height, kTunnelGroup, TunnelSubType::Flat); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + } +} + +static void CorkscrewRCTrackRightQuarterTurn325DegDownToRightBank( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 8), + { 0, 6, height }, { { 0, 6, height - 6 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 5, height - 6, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 1), + { 0, 6, height }, { { 0, 6, height - 6 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 3, height - 6, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 4), + { 0, 6, height }, { { 0, 6, height - 6 }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 20), + { 0, 6, height }, { { 0, 6, height + 32 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height - 6, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 6), + { 0, 6, height }, { { 0, 6, height - 6 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 8, height - 6, session.SupportColours); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 1: + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 18), + { 16, 16, height }, { 16, 16, 3 }); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 7), + { 6, 0, height }, { 20, 32, 3 }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 0), + { 6, 0, height }, { 20, 32, 3 }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 2), + { 6, 0, height }, { 20, 32, 3 }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 3), + { 6, 0, height }, { { 27, 0, height }, { 1, 32, 26 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 5), + { 6, 0, height }, { 20, 32, 3 }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + switch (direction) + { + case 0: + PaintUtilPushTunnelRight(session, height, kTunnelGroup, TunnelSubType::Flat); + break; + case 1: + PaintUtilPushTunnelLeft(session, height, kTunnelGroup, TunnelSubType::Flat); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + } +} + +static void CorkscrewRCTrackLeftLargeCorkscrewUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 0), + { 0, 0, height }, { { 0, 6, height + 4 }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 5), + { 0, 0, height }, { { 0, 6, height + 4 }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 10), + { 0, 0, height }, { { 0, 6, height + 4 }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 15), + { 0, 0, height }, { { 0, 6, height + 4 }, { 32, 20, 3 } }); + break; + } + + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 2, height, session.SupportColours); + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 1), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 34, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 6), + { 0, 0, height }, { { 2, 2, height + 40 }, { 28, 28, 1 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 22, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 11), + { 0, 0, height }, { { 0, 6, height }, { 20, 20, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 24, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 16), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 17, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 2), + { 0, 0, height }, { { 0, 31, height }, { 48, 1, 64 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 7), + { 0, 0, height }, { { 2, 2, height + 40 }, { 28, 28, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 17), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 4: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::bottomLeftSide, PaintSegment::bottomCorner, + PaintSegment::topLeftSide, PaintSegment::centre, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 3), + { 0, 0, height }, { { 2, 2, height + 50 }, { 28, 28, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 0, height + 56, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 8), + { 0, 0, height }, { { 2, 2, height + 50 }, { 28, 28, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 0, height + 56, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 13), + { 0, 0, height }, { { 0, 0, height + 50 }, { 26, 32, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 0, height + 56, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 18), + { 0, 0, height }, { { 0, 0, height }, { 32, 32, 1 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 40), + { 0, 0, height }, { { 0, 0, height + 64 }, { 32, 32, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 0, height + 56, session.SupportColours); + break; + } + + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 5: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 4), + { 0, 0, height }, { { 2, 2, height + 40 }, { 28, 28, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 9), + { 0, 0, height }, { { 2, 2, height + 40 }, { 28, 28, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 14), + { 0, 0, height }, { { 2, 2, height + 40 }, { 26, 28, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 19), + { 0, 0, height }, { { 2, 2, height + 44 }, { 26, 28, 1 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::bottomLeftSide, PaintSegment::bottomCorner, + PaintSegment::topLeftSide, PaintSegment::centre, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + switch (direction) + { + case 2: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + case 3: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackRightLargeCorkscrewUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 20), + { 0, 0, height }, { { 0, 6, height + 4 }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 25), + { 0, 0, height }, { { 0, 6, height + 4 }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 30), + { 0, 0, height }, { { 0, 6, height + 4 }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 35), + { 0, 0, height }, { { 0, 6, height + 4 }, { 32, 20, 3 } }); + break; + } + + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 2, height, session.SupportColours); + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomRightSide, PaintSegment::centre, PaintSegment::rightCorner, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 21), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 16, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 26), + { 0, 0, height }, { { 0, 6, height }, { 20, 20, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 24, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 31), + { 0, 0, height }, { { 0, 29, height }, { 26, 1, 32 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 22, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 36), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 34, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, + PaintSegment::bottomRightSide, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 22), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 32), + { 0, 0, height }, { { 2, 2, height + 48 }, { 28, 28, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 37), + { 0, 0, height }, { { 0, 31, height }, { 48, 1, 64 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 3: + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 4: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::bottomLeftSide, PaintSegment::bottomCorner, + PaintSegment::topLeftSide, PaintSegment::centre, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 23), + { 0, 0, height }, { { 0, 0, height }, { 32, 32, 1 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 41), + { 0, 0, height }, { { 0, 0, height + 64 }, { 32, 32, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 0, height + 56, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 28), + { 0, 0, height }, { { 2, 2, height + 50 }, { 24, 28, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 0, height + 58, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 33), + { 0, 0, height }, { { 2, 2, height + 50 }, { 28, 28, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 0, height + 56, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 38), + { 0, 0, height }, { { 2, 2, height + 50 }, { 28, 28, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 0, height + 56, session.SupportColours); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 5: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 24), + { 0, 0, height }, { { 2, 2, height + 44 }, { 26, 28, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 29), + { 0, 0, height }, { { 2, 2, height + 40 }, { 26, 28, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 34), + { 0, 0, height }, { { 2, 2, height + 40 }, { 28, 28, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 39), + { 0, 0, height }, { { 2, 2, height + 40 }, { 28, 28, 1 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::bottomLeftSide, PaintSegment::bottomCorner, + PaintSegment::topLeftSide, PaintSegment::centre, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + switch (direction) + { + case 0: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + case 1: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackLeftLargeCorkscrewDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightLargeCorkscrewUp( + session, ride, 5 - trackSequence, (direction + 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightLargeCorkscrewDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftLargeCorkscrewUp( + session, ride, 5 - trackSequence, (direction - 1) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrack90DegToInvertedFlatQuarterLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 0), + { 0, 0, height }, { { 4, 6, height + 8 }, { 2, 20, 31 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 3), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 31 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 6), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 31 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 9), + { 0, 0, height }, { { 4, 6, height + 8 }, { 2, 20, 31 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags(PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::bottomRightSide), direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 88); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 1), + { 0, 0, height }, { { -8, 6, height }, { 2, 20, 31 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 12), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 20, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 4), + { 0, 0, height }, { { 24, 6, height + 8 }, { 3, 20, 63 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 7), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 63 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 10), + { 0, 0, height }, { { -8, 6, height }, { 2, 20, 31 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 13), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 20, 1 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags(PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::bottomRightSide), direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 2), + { 0, 0, height }, { { 0, 6, height + 24 }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 5), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 31 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 8), + { 0, 0, height }, { { 24, 6, height + 8 }, { 2, 20, 31 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 11), + { 0, 0, height }, { { 0, 6, height + 24 }, { 32, 20, 3 } }); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height + 16, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags(PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::bottomRightSide), direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackInvertedFlatTo90DegQuarterLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrack90DegToInvertedFlatQuarterLoopUp( + session, ride, 2 - trackSequence, direction, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftMediumHalfLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 0), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 5), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 41), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 10), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 15), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 7, height, session.SupportColours); + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 1), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 6), + { 0, 0, height }, { { 0, 31, height }, { 0, 32, 64 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 42), + { 0, 0, height }, { { 0, 0, height + 64 }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 11), + { 0, 0, height }, { { 32, 32, height + 60 }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 16), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::topCorner), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 2), + { 0, 0, height }, { { 0, 0, height + 2 }, { 32, 32, 0 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 14, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 7), + { 0, 0, height }, { { 29, 0, height }, { 1, 32, 96 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 16, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 12), + { 0, 0, height }, { { 31, 0, height }, { 1, 32, 96 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 18, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 17), + { 0, 0, height }, { { 0, 0, height }, { 32, 32, 0 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 14, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::centre, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 144); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 3), + { 0, 0, height }, { { 0, 2, height }, { 32, 1, 160 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 40), + { 0, 0, height }, { { 0, 29, height }, { 32, 1, 160 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 8), + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 32, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 13), + { 0, 0, height }, { { 29, 0, height }, { 1, 32, 160 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 18), + { 0, 0, height }, { { 0, 0, height }, { 1, 32, 160 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 43), + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 20, 1 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::centre, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 144); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 4), + { 0, 0, height }, { { 0, 2, height + 48 }, { 32, 32, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 9), + { 0, 0, height }, { { 0, 2, height + 48 }, { 32, 32, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 14), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 19), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topRightSide, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::rightCorner), + direction), + 0xFFFF, 0); + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height + 16, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackRightMediumHalfLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 20), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 25), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 30), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 45), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 35), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 7, height, session.SupportColours); + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 21), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 26), + { 0, 0, height }, { { 0, 32, height }, { 40, 0, 64 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 31), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 46), + { 0, 0, height }, { { 0, 0, height + 64 }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 36), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topRightSide, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::rightCorner), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 22), + { 0, 0, height }, { { 0, 0, height }, { 32, 32, 0 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 14, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 27), + { 0, 0, height }, { { 31, 0, height }, { 1, 32, 96 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 18, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 32), + { 0, 0, height }, { { 0, 0, height }, { 32, 32, 96 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 16, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 37), + { 0, 0, height }, { { 0, 0, height + 2 }, { 32, 32, 0 } }); + MetalBSupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 14, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::centre, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 144); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 23), + { 0, 0, height }, { { 0, 0, height }, { 1, 32, 160 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 44), + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 20, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 28), + { 0, 0, height }, { { 29, 0, height }, { 0, 32, 160 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 33), + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 32, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 38), + { 0, 0, height }, { { 2, 0, height }, { 1, 32, 160 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 47), + { 0, 0, height }, { { 0, 0, height + 140 }, { 32, 20, 1 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 144); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 24), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 29), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 34), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 39), + { 0, 0, height }, { { 0, 0, height + 48 }, { 32, 32, 1 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::topCorner), + direction), + 0xFFFF, 0); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height + 16, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackLeftMediumHalfLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightMediumHalfLoopUp(session, ride, 4 - trackSequence, direction, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightMediumHalfLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftMediumHalfLoopUp(session, ride, 4 - trackSequence, direction, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftLargeHalfLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 0), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 7), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 14), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 21), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 1), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 13, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 8), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 57), + { 0, 0, height }, { { 0, 6, height + 48 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 7, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 15), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 7, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 22), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 1, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 2), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 9), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 58), + { 0, 0, height }, { { 0, 0, height + 70 }, { 32, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 16), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 59), + { 0, 0, height }, { { 0, 16, height + 76 }, { 32, 16, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 23), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 88); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 3), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 28, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 10), + { 0, 0, height }, { { 0, 0, height + 200 }, { 32, 16, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 26, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 17), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 26, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 24), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 22, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 224); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 4), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 11), + { 0, 0, height }, { { 0, 16, height + 110 }, { 16, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 18), + { 0, 0, height }, { { 0, 0, height + 100 }, { 16, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 25), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide, + PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 128); + break; + case 5: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 5), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 56), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 12), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 19), + { 0, 0, height }, { { 0, 0, height + 200 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 26), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 224); + break; + case 6: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 6), + { 0, 0, height }, { { 0, 16, height + 32 }, { 32, 16, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 13), + { 0, 0, height }, { { 0, 16, height + 32 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 20), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 27), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 16, 0 } }); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + } +} + +static void CorkscrewRCTrackRightLargeHalfLoopUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 28), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 35), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 42), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 49), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 6, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 29), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 1, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 36), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 7, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 43), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 9 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 61), + { 0, 0, height }, { { 0, 6, height + 64 }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 7, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 50), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 13, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 30), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 37), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 0 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 60), + { 0, 0, height }, { { 0, 16, height + 76 }, { 32, 16, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 44), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 0 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 62), + { 0, 0, height }, { { 0, 0, height + 70 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 51), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 88); + break; + case 3: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 31), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 22, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 38), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 0, height + 28, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 45), + { 0, 0, height }, { { 0, 0, height + 200 }, { 32, 16, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 28, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 52), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 28, height, session.SupportColours); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 224); + break; + case 4: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 32), + { 0, 0, height }, { { 16, 0, height }, { 16, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 39), + { 0, 0, height }, { { 0, 0, height + 100 }, { 16, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 46), + { 0, 0, height }, { { 0, 16, height + 110 }, { 16, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 53), + { 0, 0, height }, { { 16, 16, height }, { 16, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 128); + break; + case 5: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 33), + { 0, 0, height }, { { 0, 0, height }, { 32, 16, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 40), + { 0, 0, height }, { { 0, 0, height + 200 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 47), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 54), + { 0, 0, height }, { { 0, 16, height }, { 32, 16, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 63), + { 0, 0, height }, { { 0, 16, height + 200 }, { 32, 16, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 224); + break; + case 6: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 34), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 16, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 41), + { 0, 0, height }, { { 0, 0, height + 32 }, { 32, 16, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 48), + { 0, 0, height }, { { 0, 16, height + 32 }, { 32, 16, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 55), + { 0, 0, height }, { { 0, 16, height + 32 }, { 32, 16, 0 } }); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + } +} + +static void CorkscrewRCTrackLeftLargeHalfLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightLargeHalfLoopUp(session, ride, 6 - trackSequence, direction, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightLargeHalfLoopDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftLargeHalfLoopUp(session, ride, 6 - trackSequence, direction, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftBarrelRollUpToDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 0), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 1), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 4, height + 1, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 6), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 7), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 4, height + 1, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 12), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 13), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 1, height + 1, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 18), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 19), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 1, height, session.SupportColours); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 2), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 3), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 8), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 9), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 14), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 15), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 20), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 21), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 4), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 5), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 10), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 11), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 16), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 17), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 22), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 23), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 0 } }); + break; + } + switch (direction) + { + case 1: + PaintUtilPushTunnelRight(session, height, kTunnelGroup, TunnelSubType::Tall); + break; + case 2: + PaintUtilPushTunnelLeft(session, height, kTunnelGroup, TunnelSubType::Tall); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackRightBarrelRollUpToDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 24), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 25), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopCorner, 1, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 30), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 31), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::RightCorner, 1, height + 1, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 36), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 37), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomCorner, 4, height + 1, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 42), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 43), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::LeftCorner, 4, height + 1, session.SupportColours); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 26), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 27), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 32), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 33), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 38), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 39), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 44), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 45), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 0 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, + PaintSegment::topRightSide, PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 28), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 29), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 0 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 34), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 35), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 0 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 40), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 41), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 0 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 46), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 47), + { 0, 0, height }, { { 0, 6, height + 44 }, { 32, 20, 0 } }); + break; + } + switch (direction) + { + case 1: + PaintUtilPushTunnelRight(session, height, kTunnelGroup, TunnelSubType::Tall); + break; + case 2: + PaintUtilPushTunnelLeft(session, height, kTunnelGroup, TunnelSubType::Tall); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + } +} + +static void CorkscrewRCTrackLeftBarrelRollDownToUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftBarrelRollUpToDown( + session, ride, 2 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightBarrelRollDownToUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightBarrelRollUpToDown( + session, ride, 2 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftZeroGRollUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 0), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 1), + { 0, 0, height }, { { 0, 6, height + 40 }, { 32, 20, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 6), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 7), + { 0, 0, height }, { { 0, 31, height }, { 32, 1, 32 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 12), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 5, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 16), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 11, height, session.SupportColours); + break; + } + + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 3), + { 0, 0, height }, { { 0, 6, height + 40 }, { 32, 20, 1 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 9), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 1 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 13), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 17), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::topCorner, + PaintSegment::bottomLeftSide, PaintSegment::centre, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::topCorner, + PaintSegment::bottomLeftSide, PaintSegment::centre, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 5), + { 0, 0, height }, { { 0, 6, height + 22 }, { 32, 20, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 30, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 11), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 36, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 14), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 15), + { 0, 0, height }, { { 0, 6, height + 48 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 36, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 18), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 19), + { 0, 0, height }, { { 0, 6, height + 48 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 36, session.SupportColours); + break; + } + switch (direction) + { + case 1: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + case 2: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + } +} + +static void CorkscrewRCTrackRightZeroGRollUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 20), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 11, height, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 24), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 5, height, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 28), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 29), + { 0, 0, height }, { { 0, 31, height + 40 }, { 32, 1, 32 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 3, height, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 34), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 35), + { 0, 0, height }, { { 0, 6, height + 40 }, { 32, 20, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height, session.SupportColours); + break; + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 21), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 25), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 31), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 1 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 37), + { 0, 0, height }, { { 0, 6, height + 40 }, { 32, 20, 1 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::rightCorner, + PaintSegment::bottomLeftSide, PaintSegment::centre, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48); + break; + case 2: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::bottomCorner, PaintSegment::bottomRightSide, PaintSegment::rightCorner, + PaintSegment::bottomLeftSide, PaintSegment::centre, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 22), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 23), + { 0, 0, height }, { { 0, 6, height + 48 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 36, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 26), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 27), + { 0, 0, height }, { { 0, 6, height + 48 }, { 32, 20, 0 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 36, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 33), + { 0, 0, height }, { { 0, 6, height + 28 }, { 32, 20, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 36, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 39), + { 0, 0, height }, { { 0, 6, height + 22 }, { 32, 20, 1 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::Centre, 0, height + 30, session.SupportColours); + break; + } + switch (direction) + { + case 1: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + case 2: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + } +} + +static void CorkscrewRCTrackLeftZeroGRollDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftZeroGRollUp(session, ride, 2 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightZeroGRollDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightZeroGRollUp(session, ride, 2 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackLeftLargeZeroGRollUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 0), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 8), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 96 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 15), + { 0, 0, height }, { { 1, 6, height }, { 30, 20, 16 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 16), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 40 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 23), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 24, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 88); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 1), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 2), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 96 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 10), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 64 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 17), + { 0, 0, height }, { { -3, 0, height }, { 40, 8, 64 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 18), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 64 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 24), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 3), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 4), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 64 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 12), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 48 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 19), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 20), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 56 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 25), + { 0, 0, height }, { { 0, 2, height }, { 32, 0, 32 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 26), + { 0, 0, height }, { { 0, 29, height + 32 }, { 32, 1, 32 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::topCorner, + PaintSegment::bottomLeftSide, PaintSegment::centre, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 3: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::leftCorner, PaintSegment::topLeftSide, PaintSegment::topCorner, + PaintSegment::bottomLeftSide, PaintSegment::centre, PaintSegment::topRightSide), + direction), + 0xFFFF, 0); + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 6), + { 0, 0, height }, { { 0, 26, height }, { 32, 0, 20 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 0, height + 28, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 14), + { 0, 0, height }, { { 0, 26, height }, { 32, 0, 20 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 0, height + 28, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 21), + { 0, 0, height }, { { 0, 10, height }, { 32, 0, 28 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 22), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 28 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 0, height + 30, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 27), + { 0, 0, height }, { { 0, 2, height }, { 32, 0, 32 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 28), + { 0, 0, height }, { { 0, 29, height }, { 32, 1, 40 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 0, height + 32, session.SupportColours); + break; + } + switch (direction) + { + case 1: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + case 2: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + } +} + +static void CorkscrewRCTrackRightLargeZeroGRollUp( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (trackSequence) + { + case 0: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 29), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 35), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 36), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 96 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 44), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 96 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 51), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 23, height, session.SupportColours); + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 88); + break; + case 1: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 30), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 37), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 38), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 64 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 46), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 64 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 52), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 53), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 96 } }); + break; + } + PaintUtilSetSegmentSupportHeight( + session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 72); + break; + case 2: + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 31), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 32), + { 0, 0, height }, { { 0, 29, height + 32 }, { 32, 1, 32 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 39), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 40), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 56 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 48), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 48 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 54), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 55), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 64 } }); + break; + } + + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 64); + break; + case 3: + PaintUtilSetSegmentSupportHeight( + session, + PaintUtilRotateSegments( + EnumsToFlags( + PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide, + PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide), + direction), + 0xFFFF, 0); + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 33), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 34), + { 0, 0, height }, { { 0, 29, height }, { 32, 1, 40 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomLeftSide, 0, height + 34, session.SupportColours); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 41), + { 0, 0, height }, { { 0, 10, height }, { 32, 0, 28 } }); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 42), + { 0, 0, height }, { { 0, 30, height }, { 32, 0, 28 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopLeftSide, 0, height + 30, session.SupportColours); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 50), + { 0, 0, height }, { { 0, 26, height }, { 32, 0, 20 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::TopRightSide, 0, height + 28, session.SupportColours); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 57), + { 0, 0, height }, { { 0, 26, height }, { 32, 0, 20 } }); + MetalASupportsPaintSetup( + session, supportType.metal, MetalSupportPlace::BottomRightSide, 0, height + 28, session.SupportColours); + break; + } + switch (direction) + { + case 1: + PaintUtilPushTunnelRight(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + case 2: + PaintUtilPushTunnelLeft(session, height + 8, kTunnelGroup, TunnelSubType::Flat); + break; + } + PaintUtilSetGeneralSupportHeight(session, height + 40); + break; + } +} + +static void CorkscrewRCTrackLeftLargeZeroGRollDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackLeftLargeZeroGRollUp( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + +static void CorkscrewRCTrackRightLargeZeroGRollDown( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + CorkscrewRCTrackRightLargeZeroGRollUp( + session, ride, 3 - trackSequence, (direction + 2) & 3, height, trackElement, supportType); +} + TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(OpenRCT2::TrackElemType trackType) { switch (trackType) @@ -11297,6 +19644,299 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(OpenRCT2::TrackElemType tr return LayDownRCTrackRightFlyerCorkscrewUp; case TrackElemType::FlyerHalfLoopUninvertedDown: return LayDownRCTrackHalfLoopUninvertedDown; + + // Added by OpenRCT2 + + // Small flat to steep + case TrackElemType::FlatToUp60: + return CorkscrewRCTrackFlatTo60DegUp; + case TrackElemType::Up60ToFlat: + return CorkscrewRCTrack60DegUpToFlat; + case TrackElemType::FlatToDown60: + return CorkscrewRCTrackFlatTo60DegDown; + case TrackElemType::Down60ToFlat: + return CorkscrewRCTrack60DegDownToFlat; + case TrackElemType::DiagFlatToUp60: + return CorkscrewRCTrackDiagFlatTo60DegUp; + case TrackElemType::DiagUp60ToFlat: + return CorkscrewRCTrackDiag60DegUpToFlat; + case TrackElemType::DiagFlatToDown60: + return CorkscrewRCTrackDiagFlatTo60DegDown; + case TrackElemType::DiagDown60ToFlat: + return CorkscrewRCTrackDiag60DegDownToFlat; + + // Vertical slopes + case TrackElemType::Up90: + return CorkscrewRCTrack90DegUp; + case TrackElemType::Down90: + return CorkscrewRCTrack90DegDown; + case TrackElemType::Up60ToUp90: + return CorkscrewRCTrack60DegUpTo90DegUp; + case TrackElemType::Down90ToDown60: + return CorkscrewRCTrack90DegDownTo60DegDown; + case TrackElemType::Up90ToUp60: + return CorkscrewRCTrack90DegUpTo60DegUp; + case TrackElemType::Down60ToDown90: + return CorkscrewRCTrack60DegDownTo90DegDown; + + // Vertical turns + case TrackElemType::LeftQuarterTurn1TileUp90: + return CorkscrewRCTrackLeftQuarterTurn190DegUp; + case TrackElemType::RightQuarterTurn1TileUp90: + return CorkscrewRCTrackRightQuarterTurn190DegUp; + case TrackElemType::LeftQuarterTurn1TileDown90: + return CorkscrewRCTrackLeftQuarterTurn190DegDown; + case TrackElemType::RightQuarterTurn1TileDown90: + return CorkscrewRCTrackRightQuarterTurn190DegDown; + + // Banked slope transitions + case TrackElemType::Up25ToLeftBankedUp25: + return CorkscrewRCTrack25DegUpToLeftBanked25DegUp; + case TrackElemType::Up25ToRightBankedUp25: + return CorkscrewRCTrack25DegUpToRightBanked25DegUp; + case TrackElemType::LeftBankedUp25ToUp25: + return CorkscrewRCTrackLeftBanked25DegUpTo25DegUp; + case TrackElemType::RightBankedUp25ToUp25: + return CorkscrewRCTrackRightBanked25DegUpTo25DegUp; + case TrackElemType::Down25ToLeftBankedDown25: + return CorkscrewRCTrack25DegDownToLeftBanked25DegDown; + case TrackElemType::Down25ToRightBankedDown25: + return CorkscrewRCTrack25DegDownToRightBanked25DegDown; + case TrackElemType::LeftBankedDown25ToDown25: + return CorkscrewRCTrackLeftBanked25DegDownTo25DegDown; + case TrackElemType::RightBankedDown25ToDown25: + return CorkscrewRCTrackRightBanked25DegDownTo25DegDown; + case TrackElemType::LeftBankedFlatToLeftBankedUp25: + return CorkscrewRCTrackLeftBankedFlatToLeftBanked25DegUp; + case TrackElemType::RightBankedFlatToRightBankedUp25: + return CorkscrewRCTrackRightBankedFlatToRightBanked25DegUp; + case TrackElemType::LeftBankedUp25ToLeftBankedFlat: + return CorkscrewRCTrackLeftBanked25DegUpToLeftBankedFlat; + case TrackElemType::RightBankedUp25ToRightBankedFlat: + return CorkscrewRCTrackRightBanked25DegUpToRightBankedFlat; + case TrackElemType::LeftBankedFlatToLeftBankedDown25: + return CorkscrewRCTrackLeftBankedFlatToLeftBanked25DegDown; + case TrackElemType::RightBankedFlatToRightBankedDown25: + return CorkscrewRCTrackRightBankedFlatToRightBanked25DegDown; + case TrackElemType::LeftBankedDown25ToLeftBankedFlat: + return CorkscrewRCTrackLeftBanked25DegDownToLeftBankedFlat; + case TrackElemType::RightBankedDown25ToRightBankedFlat: + return CorkscrewRCTrackRightBanked25DegDownToRightBankedFlat; + case TrackElemType::Down25LeftBanked: + return CorkscrewRCTrack25DegDownLeftBanked; + case TrackElemType::Down25RightBanked: + return CorkscrewRCTrack25DegDownRightBanked; + case TrackElemType::FlatToLeftBankedUp25: + return CorkscrewRCTrackFlatToLeftBanked25DegUp; + case TrackElemType::FlatToRightBankedUp25: + return CorkscrewRCTrackFlatToRightBanked25DegUp; + case TrackElemType::LeftBankedUp25ToFlat: + return CorkscrewRCTrackLeftBanked25DegUpToFlat; + case TrackElemType::RightBankedUp25ToFlat: + return CorkscrewRCTrackRightBanked25DegUpToFlat; + case TrackElemType::FlatToLeftBankedDown25: + return CorkscrewRCTrackFlatToLeftBanked25DegDown; + case TrackElemType::FlatToRightBankedDown25: + return CorkscrewRCTrackFlatToRightBanked25DegDown; + case TrackElemType::LeftBankedDown25ToFlat: + return CorkscrewRCTrackLeftBanked25DegDownToFlat; + case TrackElemType::RightBankedDown25ToFlat: + return CorkscrewRCTrackRightBanked25DegDownToFlat; + case TrackElemType::Up25LeftBanked: + return CorkscrewRCTrack25DegUpLeftBanked; + case TrackElemType::Up25RightBanked: + return CorkscrewRCTrack25DegUpRightBanked; + + // Small banked sloped curves + case TrackElemType::LeftBankedQuarterTurn3TileUp25: + return CorkscrewRCTrackLeftBankedQuarterTurn3Tile25DegUp; + case TrackElemType::RightBankedQuarterTurn3TileUp25: + return CorkscrewRCTrackRightBankedQuarterTurn3Tile25DegUp; + case TrackElemType::LeftBankedQuarterTurn3TileDown25: + return CorkscrewRCTrackLeftBankedQuarterTurn3Tile25DegDown; + case TrackElemType::RightBankedQuarterTurn3TileDown25: + return CorkscrewRCTrackRightBankedQuarterTurn3Tile25DegDown; + + // Medium banked sloped curves + case TrackElemType::LeftBankedQuarterTurn5TileUp25: + return CorkscrewRCTrackLeftBankedQuarterTurn525DegUp; + case TrackElemType::RightBankedQuarterTurn5TileUp25: + return CorkscrewRCTrackRightBankedQuarterTurn525DegUp; + case TrackElemType::LeftBankedQuarterTurn5TileDown25: + return CorkscrewRCTrackLeftBankedQuarterTurn525DegDown; + case TrackElemType::RightBankedQuarterTurn5TileDown25: + return CorkscrewRCTrackRightBankedQuarterTurn525DegDown; + + // Large sloped curves + case TrackElemType::LeftEighthToDiagUp25: + return CorkscrewRCTrackLeftEighthToDiagUp25; + case TrackElemType::RightEighthToDiagUp25: + return CorkscrewRCTrackRightEighthToDiagUp25; + case TrackElemType::LeftEighthToDiagDown25: + return CorkscrewRCTrackLeftEighthToDiagDown25; + case TrackElemType::RightEighthToDiagDown25: + return CorkscrewRCTrackRightEighthToDiagDown25; + case TrackElemType::LeftEighthToOrthogonalUp25: + return CorkscrewRCTrackLeftEighthToOrthogonalUp25; + case TrackElemType::RightEighthToOrthogonalUp25: + return CorkscrewRCTrackRightEighthToOrthogonalUp25; + case TrackElemType::LeftEighthToOrthogonalDown25: + return CorkscrewRCTrackLeftEighthToOrthogonalDown25; + case TrackElemType::RightEighthToOrthogonalDown25: + return CorkscrewRCTrackRightEighthToOrthogonalDown25; + + // Large banked sloped curves + case TrackElemType::DiagUp25ToLeftBankedUp25: + return CorkscrewRCTrackDiagUp25ToLeftBankedUp25; + case TrackElemType::DiagUp25ToRightBankedUp25: + return CorkscrewRCTrackDiagUp25ToRightBankedUp25; + case TrackElemType::DiagLeftBankedUp25ToUp25: + return CorkscrewRCTrackDiagLeftBankedUp25ToUp25; + case TrackElemType::DiagRightBankedUp25ToUp25: + return CorkscrewRCTrackDiagRightBankedUp25ToUp25; + case TrackElemType::DiagDown25ToLeftBankedDown25: + return CorkscrewRCTrackDiagDown25ToLeftBankedDown25; + case TrackElemType::DiagDown25ToRightBankedDown25: + return CorkscrewRCTrackDiagDown25ToRightBankedDown25; + case TrackElemType::DiagLeftBankedDown25ToDown25: + return CorkscrewRCTrackDiagLeftBankedDown25ToDown25; + case TrackElemType::DiagRightBankedDown25ToDown25: + return CorkscrewRCTrackDiagRightBankedDown25ToDown25; + case TrackElemType::DiagLeftBankedFlatToLeftBankedUp25: + return CorkscrewRCTrackDiagLeftBankedFlatToLeftBankedUp25; + case TrackElemType::DiagRightBankedFlatToRightBankedUp25: + return CorkscrewRCTrackDiagRightBankedFlatToRightBankedUp25; + case TrackElemType::DiagLeftBankedUp25ToLeftBankedFlat: + return CorkscrewRCTrackDiagLeftBankedUp25ToLeftBankedFlat; + case TrackElemType::DiagRightBankedUp25ToRightBankedFlat: + return CorkscrewRCTrackDiagRightBankedUp25ToRightBankedFlat; + case TrackElemType::DiagLeftBankedFlatToLeftBankedDown25: + return CorkscrewRCTrackDiagLeftBankedFlatToLeftBankedDown25; + case TrackElemType::DiagRightBankedFlatToRightBankedDown25: + return CorkscrewRCTrackDiagRightBankedFlatToRightBankedDown25; + case TrackElemType::DiagLeftBankedDown25ToLeftBankedFlat: + return CorkscrewRCTrackDiagLeftBankedDown25ToLeftBankedFlat; + case TrackElemType::DiagRightBankedDown25ToRightBankedFlat: + return CorkscrewRCTrackDiagRightBankedDown25ToRightBankedFlat; + case TrackElemType::DiagUp25LeftBanked: + return CorkscrewRCTrackDiagUp25LeftBanked; + case TrackElemType::DiagUp25RightBanked: + return CorkscrewRCTrackDiagUp25RightBanked; + case TrackElemType::DiagDown25LeftBanked: + return CorkscrewRCTrackDiagDown25LeftBanked; + case TrackElemType::DiagDown25RightBanked: + return CorkscrewRCTrackDiagDown25RightBanked; + case TrackElemType::DiagFlatToLeftBankedUp25: + return CorkscrewRCTrackDiagFlatToLeftBankedUp25; + case TrackElemType::DiagFlatToRightBankedUp25: + return CorkscrewRCTrackDiagFlatToRightBankedUp25; + case TrackElemType::DiagLeftBankedUp25ToFlat: + return CorkscrewRCTrackDiagLeftBankedUp25ToFlat; + case TrackElemType::DiagRightBankedUp25ToFlat: + return CorkscrewRCTrackDiagRightBankedUp25ToFlat; + case TrackElemType::DiagFlatToLeftBankedDown25: + return CorkscrewRCTrackDiagFlatToLeftBankedDown25; + case TrackElemType::DiagFlatToRightBankedDown25: + return CorkscrewRCTrackDiagFlatToRightBankedDown25; + case TrackElemType::DiagLeftBankedDown25ToFlat: + return CorkscrewRCTrackDiagLeftBankedDown25ToFlat; + case TrackElemType::DiagRightBankedDown25ToFlat: + return CorkscrewRCTrackDiagRightBankedDown25ToFlat; + + case TrackElemType::LeftEighthBankToDiagUp25: + return CorkscrewRCTrackLeftEighthBankToDiagUp25; + case TrackElemType::RightEighthBankToDiagUp25: + return CorkscrewRCTrackRightEighthBankToDiagUp25; + case TrackElemType::LeftEighthBankToDiagDown25: + return CorkscrewRCTrackLeftEighthBankToDiagDown25; + case TrackElemType::RightEighthBankToDiagDown25: + return CorkscrewRCTrackRightEighthBankToDiagDown25; + + case TrackElemType::LeftEighthBankToOrthogonalUp25: + return CorkscrewRCTrackLeftEighthBankToOrthogonalUp25; + case TrackElemType::RightEighthBankToOrthogonalUp25: + return CorkscrewRCTrackRightEighthBankToOrthogonalUp25; + case TrackElemType::LeftEighthBankToOrthogonalDown25: + return CorkscrewRCTrackLeftEighthBankToOrthogonalDown25; + case TrackElemType::RightEighthBankToOrthogonalDown25: + return CorkscrewRCTrackRightEighthBankToOrthogonalDown25; + + // Small banked to unbanked curves + case TrackElemType::LeftBankToLeftQuarterTurn3TilesUp25: + return CorkscrewRCTrackLeftBankToLeftQuarterTurn325DegUp; + case TrackElemType::RightBankToRightQuarterTurn3TilesUp25: + return CorkscrewRCTrackRightBankToRightQuarterTurn325DegUp; + case TrackElemType::LeftQuarterTurn3TilesDown25ToLeftBank: + return CorkscrewRCTrackLeftQuarterTurn325DegDownToLeftBank; + case TrackElemType::RightQuarterTurn3TilesDown25ToRightBank: + return CorkscrewRCTrackRightQuarterTurn325DegDownToRightBank; + + // Large corkscrews + case TrackElemType::LeftLargeCorkscrewUp: + return CorkscrewRCTrackLeftLargeCorkscrewUp; + case TrackElemType::RightLargeCorkscrewUp: + return CorkscrewRCTrackRightLargeCorkscrewUp; + case TrackElemType::LeftLargeCorkscrewDown: + return CorkscrewRCTrackLeftLargeCorkscrewDown; + case TrackElemType::RightLargeCorkscrewDown: + return CorkscrewRCTrackRightLargeCorkscrewDown; + + // Quarter loops + case TrackElemType::Up90ToInvertedFlatQuarterLoop: + return CorkscrewRCTrack90DegToInvertedFlatQuarterLoopUp; + case TrackElemType::InvertedFlatToDown90QuarterLoop: + return CorkscrewRCTrackInvertedFlatTo90DegQuarterLoopDown; + + // Medium half loops + case TrackElemType::LeftMediumHalfLoopUp: + return CorkscrewRCTrackLeftMediumHalfLoopUp; + case TrackElemType::RightMediumHalfLoopUp: + return CorkscrewRCTrackRightMediumHalfLoopUp; + case TrackElemType::LeftMediumHalfLoopDown: + return CorkscrewRCTrackLeftMediumHalfLoopDown; + case TrackElemType::RightMediumHalfLoopDown: + return CorkscrewRCTrackRightMediumHalfLoopDown; + + // Large half loops + case TrackElemType::LeftLargeHalfLoopUp: + return CorkscrewRCTrackLeftLargeHalfLoopUp; + case TrackElemType::RightLargeHalfLoopUp: + return CorkscrewRCTrackRightLargeHalfLoopUp; + case TrackElemType::LeftLargeHalfLoopDown: + return CorkscrewRCTrackLeftLargeHalfLoopDown; + case TrackElemType::RightLargeHalfLoopDown: + return CorkscrewRCTrackRightLargeHalfLoopDown; + + // Barrel rolls + case TrackElemType::LeftBarrelRollUpToDown: + return CorkscrewRCTrackLeftBarrelRollUpToDown; + case TrackElemType::RightBarrelRollUpToDown: + return CorkscrewRCTrackRightBarrelRollUpToDown; + case TrackElemType::LeftBarrelRollDownToUp: + return CorkscrewRCTrackLeftBarrelRollDownToUp; + case TrackElemType::RightBarrelRollDownToUp: + return CorkscrewRCTrackRightBarrelRollDownToUp; + + // Zero g rolls + case TrackElemType::LeftZeroGRollUp: + return CorkscrewRCTrackLeftZeroGRollUp; + case TrackElemType::RightZeroGRollUp: + return CorkscrewRCTrackRightZeroGRollUp; + case TrackElemType::LeftZeroGRollDown: + return CorkscrewRCTrackLeftZeroGRollDown; + case TrackElemType::RightZeroGRollDown: + return CorkscrewRCTrackRightZeroGRollDown; + + // Large zero g rolls + case TrackElemType::LeftLargeZeroGRollUp: + return CorkscrewRCTrackLeftLargeZeroGRollUp; + case TrackElemType::RightLargeZeroGRollUp: + return CorkscrewRCTrackRightLargeZeroGRollUp; + case TrackElemType::LeftLargeZeroGRollDown: + return CorkscrewRCTrackLeftLargeZeroGRollDown; + case TrackElemType::RightLargeZeroGRollDown: + return CorkscrewRCTrackRightLargeZeroGRollDown; + default: return nullptr; } diff --git a/src/openrct2/park/Legacy.cpp b/src/openrct2/park/Legacy.cpp index 3b99aa1d06..fa05855f0f 100644 --- a/src/openrct2/park/Legacy.cpp +++ b/src/openrct2/park/Legacy.cpp @@ -2423,6 +2423,146 @@ bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, OpenRCT2::TrackElemType break; } } + else if ( + (rideType == RIDE_TYPE_CORKSCREW_ROLLER_COASTER || rideType == RIDE_TYPE_HYPERCOASTER + || rideType == RIDE_TYPE_LAY_DOWN_ROLLER_COASTER) + && parkFileVersion < kExtendedCorkscrewCoasterVersion) + { + switch (trackType) + { + case TrackElemType::FlatToUp60: + case TrackElemType::Up60ToFlat: + case TrackElemType::FlatToDown60: + case TrackElemType::Down60ToFlat: + case TrackElemType::DiagFlatToUp60: + case TrackElemType::DiagUp60ToFlat: + case TrackElemType::DiagFlatToDown60: + case TrackElemType::DiagDown60ToFlat: + case TrackElemType::Up90: + case TrackElemType::Down90: + case TrackElemType::Up60ToUp90: + case TrackElemType::Down90ToDown60: + case TrackElemType::Up90ToUp60: + case TrackElemType::Down60ToDown90: + case TrackElemType::LeftQuarterTurn1TileUp90: + case TrackElemType::RightQuarterTurn1TileUp90: + case TrackElemType::LeftQuarterTurn1TileDown90: + case TrackElemType::RightQuarterTurn1TileDown90: + case TrackElemType::Up25ToLeftBankedUp25: + case TrackElemType::Up25ToRightBankedUp25: + case TrackElemType::LeftBankedUp25ToUp25: + case TrackElemType::RightBankedUp25ToUp25: + case TrackElemType::Down25ToLeftBankedDown25: + case TrackElemType::Down25ToRightBankedDown25: + case TrackElemType::LeftBankedDown25ToDown25: + case TrackElemType::RightBankedDown25ToDown25: + case TrackElemType::LeftBankedFlatToLeftBankedUp25: + case TrackElemType::RightBankedFlatToRightBankedUp25: + case TrackElemType::LeftBankedUp25ToLeftBankedFlat: + case TrackElemType::RightBankedUp25ToRightBankedFlat: + case TrackElemType::LeftBankedFlatToLeftBankedDown25: + case TrackElemType::RightBankedFlatToRightBankedDown25: + case TrackElemType::LeftBankedDown25ToLeftBankedFlat: + case TrackElemType::RightBankedDown25ToRightBankedFlat: + case TrackElemType::Down25LeftBanked: + case TrackElemType::Down25RightBanked: + case TrackElemType::FlatToLeftBankedUp25: + case TrackElemType::FlatToRightBankedUp25: + case TrackElemType::LeftBankedUp25ToFlat: + case TrackElemType::RightBankedUp25ToFlat: + case TrackElemType::FlatToLeftBankedDown25: + case TrackElemType::FlatToRightBankedDown25: + case TrackElemType::LeftBankedDown25ToFlat: + case TrackElemType::RightBankedDown25ToFlat: + case TrackElemType::Up25LeftBanked: + case TrackElemType::Up25RightBanked: + case TrackElemType::LeftBankedQuarterTurn3TileUp25: + case TrackElemType::RightBankedQuarterTurn3TileUp25: + case TrackElemType::LeftBankedQuarterTurn3TileDown25: + case TrackElemType::RightBankedQuarterTurn3TileDown25: + case TrackElemType::LeftBankedQuarterTurn5TileUp25: + case TrackElemType::RightBankedQuarterTurn5TileUp25: + case TrackElemType::LeftBankedQuarterTurn5TileDown25: + case TrackElemType::RightBankedQuarterTurn5TileDown25: + case TrackElemType::LeftEighthToDiagUp25: + case TrackElemType::RightEighthToDiagUp25: + case TrackElemType::LeftEighthToDiagDown25: + case TrackElemType::RightEighthToDiagDown25: + case TrackElemType::LeftEighthToOrthogonalUp25: + case TrackElemType::RightEighthToOrthogonalUp25: + case TrackElemType::LeftEighthToOrthogonalDown25: + case TrackElemType::RightEighthToOrthogonalDown25: + case TrackElemType::DiagUp25ToLeftBankedUp25: + case TrackElemType::DiagUp25ToRightBankedUp25: + case TrackElemType::DiagLeftBankedUp25ToUp25: + case TrackElemType::DiagRightBankedUp25ToUp25: + case TrackElemType::DiagDown25ToLeftBankedDown25: + case TrackElemType::DiagDown25ToRightBankedDown25: + case TrackElemType::DiagLeftBankedDown25ToDown25: + case TrackElemType::DiagRightBankedDown25ToDown25: + case TrackElemType::DiagLeftBankedFlatToLeftBankedUp25: + case TrackElemType::DiagRightBankedFlatToRightBankedUp25: + case TrackElemType::DiagLeftBankedUp25ToLeftBankedFlat: + case TrackElemType::DiagRightBankedUp25ToRightBankedFlat: + case TrackElemType::DiagLeftBankedFlatToLeftBankedDown25: + case TrackElemType::DiagRightBankedFlatToRightBankedDown25: + case TrackElemType::DiagLeftBankedDown25ToLeftBankedFlat: + case TrackElemType::DiagRightBankedDown25ToRightBankedFlat: + case TrackElemType::DiagUp25LeftBanked: + case TrackElemType::DiagUp25RightBanked: + case TrackElemType::DiagDown25LeftBanked: + case TrackElemType::DiagDown25RightBanked: + case TrackElemType::DiagFlatToLeftBankedUp25: + case TrackElemType::DiagFlatToRightBankedUp25: + case TrackElemType::DiagLeftBankedUp25ToFlat: + case TrackElemType::DiagRightBankedUp25ToFlat: + case TrackElemType::DiagFlatToLeftBankedDown25: + case TrackElemType::DiagFlatToRightBankedDown25: + case TrackElemType::DiagLeftBankedDown25ToFlat: + case TrackElemType::DiagRightBankedDown25ToFlat: + case TrackElemType::LeftEighthBankToDiagUp25: + case TrackElemType::RightEighthBankToDiagUp25: + case TrackElemType::LeftEighthBankToDiagDown25: + case TrackElemType::RightEighthBankToDiagDown25: + case TrackElemType::LeftEighthBankToOrthogonalUp25: + case TrackElemType::RightEighthBankToOrthogonalUp25: + case TrackElemType::LeftEighthBankToOrthogonalDown25: + case TrackElemType::RightEighthBankToOrthogonalDown25: + case TrackElemType::LeftBankToLeftQuarterTurn3TilesUp25: + case TrackElemType::RightBankToRightQuarterTurn3TilesUp25: + case TrackElemType::LeftQuarterTurn3TilesDown25ToLeftBank: + case TrackElemType::RightQuarterTurn3TilesDown25ToRightBank: + case TrackElemType::LeftLargeCorkscrewUp: + case TrackElemType::RightLargeCorkscrewUp: + case TrackElemType::LeftLargeCorkscrewDown: + case TrackElemType::RightLargeCorkscrewDown: + case TrackElemType::Up90ToInvertedFlatQuarterLoop: + case TrackElemType::InvertedFlatToDown90QuarterLoop: + case TrackElemType::LeftMediumHalfLoopUp: + case TrackElemType::RightMediumHalfLoopUp: + case TrackElemType::LeftMediumHalfLoopDown: + case TrackElemType::RightMediumHalfLoopDown: + case TrackElemType::LeftLargeHalfLoopUp: + case TrackElemType::RightLargeHalfLoopUp: + case TrackElemType::LeftLargeHalfLoopDown: + case TrackElemType::RightLargeHalfLoopDown: + case TrackElemType::LeftBarrelRollUpToDown: + case TrackElemType::RightBarrelRollUpToDown: + case TrackElemType::LeftBarrelRollDownToUp: + case TrackElemType::RightBarrelRollDownToUp: + case TrackElemType::LeftZeroGRollUp: + case TrackElemType::RightZeroGRollUp: + case TrackElemType::LeftZeroGRollDown: + case TrackElemType::RightZeroGRollDown: + case TrackElemType::LeftLargeZeroGRollUp: + case TrackElemType::RightLargeZeroGRollUp: + case TrackElemType::LeftLargeZeroGRollDown: + case TrackElemType::RightLargeZeroGRollDown: + return true; + default: + break; + } + } return false; } diff --git a/src/openrct2/park/ParkFile.h b/src/openrct2/park/ParkFile.h index d6be3f4944..0dc6c046d0 100644 --- a/src/openrct2/park/ParkFile.h +++ b/src/openrct2/park/ParkFile.h @@ -11,7 +11,7 @@ namespace OpenRCT2 struct GameState_t; // Current version that is saved. - constexpr uint32_t PARK_FILE_CURRENT_VERSION = 41; + constexpr uint32_t PARK_FILE_CURRENT_VERSION = 42; // The minimum version that is forwards compatible with the current version. constexpr uint32_t PARK_FILE_MIN_VERSION = 40; @@ -32,6 +32,7 @@ namespace OpenRCT2 constexpr uint16_t k16BitParkHistoryVersion = 38; constexpr uint16_t kPeepNamesObjectsVersion = 39; constexpr uint16_t kWoodenRollerCoasterMediumLargeHalfLoopsVersion = 41; + constexpr uint16_t kExtendedCorkscrewCoasterVersion = 42; } // namespace OpenRCT2 class ParkFileExporter diff --git a/src/openrct2/ride/rtd/coaster/CorkscrewRollerCoaster.h b/src/openrct2/ride/rtd/coaster/CorkscrewRollerCoaster.h index eef28026ff..dfc385ca61 100644 --- a/src/openrct2/ride/rtd/coaster/CorkscrewRollerCoaster.h +++ b/src/openrct2/ride/rtd/coaster/CorkscrewRollerCoaster.h @@ -22,8 +22,8 @@ constexpr RideTypeDescriptor CorkscrewRollerCoasterRTD = .TrackPaintFunctions = TrackDrawerDescriptor({ .Drawer = GetTrackPaintFunctionCorkscrewRC, .supportType = MetalSupportType::Tubes, - .enabledTrackGroups = {TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::verticalLoop, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::halfLoop, TrackGroup::corkscrew, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes,TrackGroup::booster, TrackGroup::slopeSteepLong, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes}, - .extraTrackGroups = {TrackGroup::twist}, + .enabledTrackGroups = {TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::verticalLoop, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::halfLoop, TrackGroup::corkscrew, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes,TrackGroup::booster, TrackGroup::slopeSteepLong, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeRollBanking, TrackGroup::slopeCurveBanked, TrackGroup::slopeCurveLarge, TrackGroup::corkscrewLarge, TrackGroup::halfLoopMedium, TrackGroup::halfLoopLarge}, + .extraTrackGroups = {TrackGroup::twist, TrackGroup::slopeVertical, TrackGroup::curveVertical, TrackGroup::quarterLoop, TrackGroup::barrelRoll, TrackGroup::zeroGRoll, TrackGroup::zeroGRollLarge}, }), .InvertedTrackPaintFunctions = {}, .Flags = kRtdFlagsHasThreeColours | kRtdFlagsCommonCoaster | kRtdFlagsCommonCoasterNonAlt | diff --git a/src/openrct2/ride/rtd/coaster/Hypercoaster.h b/src/openrct2/ride/rtd/coaster/Hypercoaster.h index 05ddd730fd..6e900c5df1 100644 --- a/src/openrct2/ride/rtd/coaster/Hypercoaster.h +++ b/src/openrct2/ride/rtd/coaster/Hypercoaster.h @@ -22,7 +22,7 @@ constexpr RideTypeDescriptor HypercoasterRTD = .TrackPaintFunctions = TrackDrawerDescriptor({ .Drawer = GetTrackPaintFunctionCorkscrewRC, .supportType = MetalSupportType::Tubes, - .enabledTrackGroups = {TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes, TrackGroup::slopeSteepLong, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes}, + .enabledTrackGroups = {TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes, TrackGroup::slopeSteepLong, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeRollBanking, TrackGroup::slopeCurveBanked, TrackGroup::slopeCurveLarge}, .extraTrackGroups = {TrackGroup::verticalLoop, TrackGroup::halfLoop, TrackGroup::corkscrew, TrackGroup::booster}, }), .InvertedTrackPaintFunctions = {}, diff --git a/src/openrct2/ride/rtd/coaster/LayDownRollerCoaster.h b/src/openrct2/ride/rtd/coaster/LayDownRollerCoaster.h index 0a6bc07583..69ad588bcd 100644 --- a/src/openrct2/ride/rtd/coaster/LayDownRollerCoaster.h +++ b/src/openrct2/ride/rtd/coaster/LayDownRollerCoaster.h @@ -23,7 +23,7 @@ constexpr RideTypeDescriptor LayDownRollerCoasterRTD = { .Drawer = GetTrackPaintFunctionCorkscrewRC, .supportType = MetalSupportType::TubesInverted, - .enabledTrackGroups = { TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::verticalLoop, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes, TrackGroup::inlineTwistUninverted, TrackGroup::flyingHalfLoopUninvertedUp, TrackGroup::corkscrewUninverted, TrackGroup::slopeSteepLong, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes }, + .enabledTrackGroups = { TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::verticalLoop, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes, TrackGroup::inlineTwistUninverted, TrackGroup::flyingHalfLoopUninvertedUp, TrackGroup::corkscrewUninverted, TrackGroup::slopeSteepLong, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeRollBanking, TrackGroup::slopeCurveBanked, TrackGroup::slopeCurveLarge }, .extraTrackGroups = { TrackGroup::flyingHalfLoopUninvertedDown, TrackGroup::booster }, } ), diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index 16c4b0b237..e827e024d1 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -1344,7 +1344,23 @@ enum : ImageIndex SPR_G2_CORKSCREW_RC_BEGIN = SPR_G2_SLC_RC_END, SPR_G2_CORKSCREW_DIAG_BRAKES = SPR_G2_CORKSCREW_RC_BEGIN, - SPR_G2_CORKSCREW_RC_END = SPR_G2_CORKSCREW_DIAG_BRAKES + 6, + SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP = SPR_G2_CORKSCREW_DIAG_BRAKES + 6, + SPR_G2_CORKSCREW_TRACK_VERTICAL = SPR_G2_CORKSCREW_TRACK_SMALL_FLAT_TO_STEEP + 20, + SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST = SPR_G2_CORKSCREW_TRACK_VERTICAL + 8, + SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION = SPR_G2_CORKSCREW_TRACK_VERTICAL_TWIST + 12, + SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED = SPR_G2_CORKSCREW_TRACK_SLOPE_BANK_TRANSITION + 64, + SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED = SPR_G2_CORKSCREW_TRACK_GENTLE_SMALL_CURVE_BANKED + 18, + SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE = SPR_G2_CORKSCREW_TRACK_GENTLE_MEDIUM_CURVE_BANKED + 40, + SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED = SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE + 64, + SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION = SPR_G2_CORKSCREW_TRACK_GENTLE_LARGE_CURVE_BANKED + 128, + SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW = SPR_G2_CORKSCREW_TRACK_TURN_BANK_TRANSITION + 22, + SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP = SPR_G2_CORKSCREW_TRACK_LARGE_CORKSCREW + 42, + SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP = SPR_G2_CORKSCREW_TRACK_QUARTER_LOOP + 14, + SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP = SPR_G2_CORKSCREW_TRACK_MEDIUM_HALF_LOOP + 48, + SPR_G2_CORKSCREW_TRACK_BARREL_ROLL = SPR_G2_CORKSCREW_TRACK_LARGE_HALF_LOOP + 64, + SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL = SPR_G2_CORKSCREW_TRACK_BARREL_ROLL + 48, + SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL = SPR_G2_CORKSCREW_TRACK_ZERO_G_ROLL + 40, + SPR_G2_CORKSCREW_RC_END = SPR_G2_CORKSCREW_TRACK_LARGE_ZERO_G_ROLL + 58, SPR_G2_LIM_LAUNCHED_TRACK_BEGIN = SPR_G2_CORKSCREW_RC_END, SPR_G2_LIM_LAUNCHED_TRACK_BARREL_ROLL = SPR_G2_LIM_LAUNCHED_TRACK_BEGIN + 0, From 3eb9a03708f3908d2ecd3e68466d91b64274f917 Mon Sep 17 00:00:00 2001 From: hnsdeveloper <176238983+hnsdeveloper@users.noreply.github.com> Date: Sat, 2 Nov 2024 09:54:54 -0300 Subject: [PATCH 93/97] Replace #define with constexpr in Colour.h Co-authored-by: Gymnasiast --- src/openrct2-ui/interface/InGameConsole.cpp | 2 +- src/openrct2/drawing/Drawing.String.cpp | 6 +++--- src/openrct2/drawing/Text.cpp | 2 +- src/openrct2/interface/Chat.cpp | 4 ++-- src/openrct2/interface/Colour.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/openrct2-ui/interface/InGameConsole.cpp b/src/openrct2-ui/interface/InGameConsole.cpp index c1eb790659..9934c24f26 100644 --- a/src/openrct2-ui/interface/InGameConsole.cpp +++ b/src/openrct2-ui/interface/InGameConsole.cpp @@ -333,7 +333,7 @@ void InGameConsole::Draw(DrawPixelInfo& dpi) const // Draw current line lineBuffer = _colourFormatStr + _consoleCurrentLine; - DrawText(dpi, screenCoords, { TEXT_COLOUR_255, InGameConsoleGetFontStyle() }, lineBuffer.c_str(), true); + DrawText(dpi, screenCoords, { kTextColour255, InGameConsoleGetFontStyle() }, lineBuffer.c_str(), true); // Draw caret if (_consoleCaretTicks < CONSOLE_CARET_FLASH_THRESHOLD) diff --git a/src/openrct2/drawing/Drawing.String.cpp b/src/openrct2/drawing/Drawing.String.cpp index 4ad0215b06..74db073471 100644 --- a/src/openrct2/drawing/Drawing.String.cpp +++ b/src/openrct2/drawing/Drawing.String.cpp @@ -332,7 +332,7 @@ void DrawStringCentredRaw( for (int32_t i = 0; i <= numLines; i++) { int32_t width = GfxGetStringWidth(text, fontStyle); - DrawText(dpi, screenCoords - ScreenCoordsXY{ width / 2, 0 }, { TEXT_COLOUR_254, fontStyle }, text); + DrawText(dpi, screenCoords - ScreenCoordsXY{ width / 2, 0 }, { kTextColour254, fontStyle }, text); const utf8* ch = text; const utf8* nextCh = nullptr; @@ -463,7 +463,7 @@ void DrawNewsTicker( } screenCoords = { coords.x - halfWidth, lineY }; - DrawText(dpi, screenCoords, { TEXT_COLOUR_254, FontStyle::Small }, buffer); + DrawText(dpi, screenCoords, { kTextColour254, FontStyle::Small }, buffer); if (numCharactersDrawn > numCharactersToDraw) { @@ -749,7 +749,7 @@ static void TTFProcessString(DrawPixelInfo& dpi, std::string_view text, TextDraw static void TTFProcessInitialColour(ColourWithFlags colour, TextDrawInfo* info) { - if (colour.colour != TEXT_COLOUR_254 && colour.colour != TEXT_COLOUR_255) + if (colour.colour != kTextColour254 && colour.colour != kTextColour255) { info->flags &= ~(TEXT_DRAW_FLAG_INSET | TEXT_DRAW_FLAG_OUTLINE); if (colour.hasFlag(ColourFlag::withOutline)) diff --git a/src/openrct2/drawing/Text.cpp b/src/openrct2/drawing/Text.cpp index a83ed35025..1242b6fb30 100644 --- a/src/openrct2/drawing/Text.cpp +++ b/src/openrct2/drawing/Text.cpp @@ -52,7 +52,7 @@ public: for (int32_t line = 0; line < LineCount; ++line) { DrawText(dpi, lineCoords, tempPaint, buffer); - tempPaint.Colour = TEXT_COLOUR_254; + tempPaint.Colour = kTextColour254; buffer = GetStringEnd(buffer) + 1; lineCoords.y += LineHeight; } diff --git a/src/openrct2/interface/Chat.cpp b/src/openrct2/interface/Chat.cpp index 2b7c8bb4ac..4761888887 100644 --- a/src/openrct2/interface/Chat.cpp +++ b/src/openrct2/interface/Chat.cpp @@ -192,7 +192,7 @@ void ChatDraw(DrawPixelInfo& dpi, ColourWithFlags chatBackgroundColor) auto ft = Formatter(); ft.Add(lineCh); inputLineHeight = DrawTextWrapped( - dpi, screenCoords + ScreenCoordsXY{ 0, 3 }, _chatWidth - 10, STR_STRING, ft, { TEXT_COLOUR_255 }); + dpi, screenCoords + ScreenCoordsXY{ 0, 3 }, _chatWidth - 10, STR_STRING, ft, { kTextColour255 }); GfxSetDirtyBlocks({ screenCoords, { screenCoords + ScreenCoordsXY{ _chatWidth, inputLineHeight + 15 } } }); // TODO: Show caret if the input text has multiple lines @@ -288,7 +288,7 @@ static int32_t ChatHistoryDrawString(DrawPixelInfo& dpi, const char* text, const int32_t lineY = screenCoords.y; for (int32_t line = 0; line <= numLines; ++line) { - DrawText(dpi, { screenCoords.x, lineY - (numLines * lineHeight) }, { TEXT_COLOUR_254 }, bufferPtr); + DrawText(dpi, { screenCoords.x, lineY - (numLines * lineHeight) }, { kTextColour254 }, bufferPtr); bufferPtr = GetStringEnd(bufferPtr) + 1; lineY += lineHeight; } diff --git a/src/openrct2/interface/Colour.h b/src/openrct2/interface/Colour.h index edf055eef3..8cc545fb69 100644 --- a/src/openrct2/interface/Colour.h +++ b/src/openrct2/interface/Colour.h @@ -213,8 +213,8 @@ constexpr uint8_t kColourNumNormal = 54; static constexpr uint8_t kLegacyColourFlagTranslucent = (1 << 7); -#define TEXT_COLOUR_254 (254) -#define TEXT_COLOUR_255 (255) +constexpr colour_t kTextColour254 = 254; +constexpr colour_t kTextColour255 = 255; enum class ColourFlag : uint8_t { From 80f61fca5e7384e35f752b99e2cee07aaaa3e4ce Mon Sep 17 00:00:00 2001 From: X123M3-256 Date: Thu, 19 Sep 2024 23:51:32 +0200 Subject: [PATCH 94/97] Add LSM Launched Roller Coaster Co-authored-by: karst --- data/language/en-GB.txt | 4 +- distribution/changelog.txt | 2 + resources/g2/sprites.json | 152 +++++++++++- .../block_brake_alt_closed_1.png | Bin 0 -> 1245 bytes .../block_brake_alt_closed_2.png | Bin 0 -> 1233 bytes .../block_brake_alt_closed_3.png | Bin 0 -> 1243 bytes .../block_brake_alt_closed_4.png | Bin 0 -> 1234 bytes .../block_brake_alt_open_1.png | Bin 0 -> 1231 bytes .../block_brake_alt_open_2.png | Bin 0 -> 1243 bytes .../block_brake_alt_open_3.png | Bin 0 -> 1238 bytes .../block_brake_alt_open_4.png | Bin 0 -> 1242 bytes .../track/lattice_triangle/booster_alt_1.png | Bin 0 -> 1237 bytes .../track/lattice_triangle/booster_alt_2.png | Bin 0 -> 1215 bytes .../track/lattice_triangle/booster_alt_3.png | Bin 0 -> 1233 bytes .../track/lattice_triangle/booster_alt_4.png | Bin 0 -> 1215 bytes .../lattice_triangle/brake_alt_closed_1.png | Bin 0 -> 1237 bytes .../lattice_triangle/brake_alt_closed_2.png | Bin 0 -> 1211 bytes .../lattice_triangle/brake_alt_closed_3.png | Bin 0 -> 1232 bytes .../lattice_triangle/brake_alt_closed_4.png | Bin 0 -> 1209 bytes .../lattice_triangle/brake_alt_open_1.png | Bin 0 -> 1218 bytes .../lattice_triangle/brake_alt_open_2.png | Bin 0 -> 1222 bytes .../lattice_triangle/brake_alt_open_3.png | Bin 0 -> 1215 bytes .../lattice_triangle/brake_alt_open_4.png | Bin 0 -> 1213 bytes .../track/lattice_triangle/drive_tyre_1.png | Bin 0 -> 1227 bytes .../track/lattice_triangle/drive_tyre_2.png | Bin 0 -> 1232 bytes .../track/lattice_triangle/drive_tyre_3.png | Bin 0 -> 1242 bytes .../track/lattice_triangle/drive_tyre_4.png | Bin 0 -> 1241 bytes .../track/lattice_triangle/liftbooster_1.png | Bin 1140 -> 1262 bytes .../track/lattice_triangle/liftbooster_2.png | Bin 1149 -> 1140 bytes .../track/lattice_triangle/liftbooster_3.png | Bin 1274 -> 1149 bytes .../track/lattice_triangle/liftbooster_4.png | Bin 0 -> 1274 bytes ...iftbooster_0.png => liftbooster_alt_1.png} | Bin 1262 -> 1252 bytes .../lattice_triangle/liftbooster_alt_2.png | Bin 0 -> 1168 bytes .../lattice_triangle/liftbooster_alt_3.png | Bin 0 -> 1164 bytes .../lattice_triangle/liftbooster_alt_4.png | Bin 0 -> 1260 bytes src/openrct2-ui/windows/NewRide.cpp | 1 + src/openrct2/libopenrct2.vcxproj | 2 + .../track/coaster/LatticeTriangleTrack.cpp | 2 +- .../track/coaster/LatticeTriangleTrackAlt.cpp | 217 ++++++++++++++++++ src/openrct2/park/ParkFile.h | 2 +- src/openrct2/ride/Ride.h | 1 + src/openrct2/ride/RideData.cpp | 2 + src/openrct2/ride/RideData.h | 1 + src/openrct2/ride/RideStringIds.h | 2 + src/openrct2/ride/TrackPaint.h | 1 + src/openrct2/ride/rtd/coaster/GigaCoaster.h | 4 +- .../rtd/coaster/LSMLaunchedRollerCoaster.h | 90 ++++++++ src/openrct2/sprites.h | 30 ++- 48 files changed, 503 insertions(+), 10 deletions(-) create mode 100644 resources/g2/track/lattice_triangle/block_brake_alt_closed_1.png create mode 100644 resources/g2/track/lattice_triangle/block_brake_alt_closed_2.png create mode 100644 resources/g2/track/lattice_triangle/block_brake_alt_closed_3.png create mode 100644 resources/g2/track/lattice_triangle/block_brake_alt_closed_4.png create mode 100644 resources/g2/track/lattice_triangle/block_brake_alt_open_1.png create mode 100644 resources/g2/track/lattice_triangle/block_brake_alt_open_2.png create mode 100644 resources/g2/track/lattice_triangle/block_brake_alt_open_3.png create mode 100644 resources/g2/track/lattice_triangle/block_brake_alt_open_4.png create mode 100644 resources/g2/track/lattice_triangle/booster_alt_1.png create mode 100644 resources/g2/track/lattice_triangle/booster_alt_2.png create mode 100644 resources/g2/track/lattice_triangle/booster_alt_3.png create mode 100644 resources/g2/track/lattice_triangle/booster_alt_4.png create mode 100644 resources/g2/track/lattice_triangle/brake_alt_closed_1.png create mode 100644 resources/g2/track/lattice_triangle/brake_alt_closed_2.png create mode 100644 resources/g2/track/lattice_triangle/brake_alt_closed_3.png create mode 100644 resources/g2/track/lattice_triangle/brake_alt_closed_4.png create mode 100644 resources/g2/track/lattice_triangle/brake_alt_open_1.png create mode 100644 resources/g2/track/lattice_triangle/brake_alt_open_2.png create mode 100644 resources/g2/track/lattice_triangle/brake_alt_open_3.png create mode 100644 resources/g2/track/lattice_triangle/brake_alt_open_4.png create mode 100644 resources/g2/track/lattice_triangle/drive_tyre_1.png create mode 100644 resources/g2/track/lattice_triangle/drive_tyre_2.png create mode 100644 resources/g2/track/lattice_triangle/drive_tyre_3.png create mode 100644 resources/g2/track/lattice_triangle/drive_tyre_4.png create mode 100644 resources/g2/track/lattice_triangle/liftbooster_4.png rename resources/g2/track/lattice_triangle/{liftbooster_0.png => liftbooster_alt_1.png} (66%) create mode 100644 resources/g2/track/lattice_triangle/liftbooster_alt_2.png create mode 100644 resources/g2/track/lattice_triangle/liftbooster_alt_3.png create mode 100644 resources/g2/track/lattice_triangle/liftbooster_alt_4.png create mode 100644 src/openrct2/paint/track/coaster/LatticeTriangleTrackAlt.cpp create mode 100644 src/openrct2/ride/rtd/coaster/LSMLaunchedRollerCoaster.h diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 15cf329813..0e69146f78 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -99,6 +99,7 @@ STR_0094 :Single Rail Roller Coaster STR_0095 :Alpine Coaster STR_0096 :Classic Wooden Roller Coaster STR_0097 :Classic Stand-up Roller Coaster +STR_0098 :LSM Launched Roller Coaster STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops. STR_0513 :A looping roller coaster where the riders ride in a standing position STR_0514 :Trains suspended beneath the roller coaster track swing out to the side around corners @@ -183,6 +184,7 @@ STR_0604 :Riders ride single file on a narrow monorail track, as they race th STR_0605 :Riders toboggan down a meandering steel track, braking to control their speed STR_0606 :An older-style wooden roller coaster with a fast and rough ride, with plenty of air-time, some lateral G’s, and designed to feel ‘out-of-control’ STR_0607 :An intense, older-style steel looping roller coaster where the riders ride in a standing position +STR_0608 :Roller coaster trains are accelerated by linear synchronous motors, speeding through tight twists and turns STR_0767 :Guest {INT32} STR_0768 :Handyman {INT32} STR_0769 :Mechanic {INT32} @@ -3610,7 +3612,7 @@ STR_6537 :Allow using regular paths as queue STR_6538 :Shows regular paths in the queues dropdown of the Footpaths window. STR_6539 :Brake Closed STR_6540 :{WINDOW_COLOUR_2}Special thanks to the following companies for allowing their likeness: -STR_6541 :{WINDOW_COLOUR_2}Rocky Mountain Construction Group, Josef Wiegand GmbH & Co. KG +STR_6541 :{WINDOW_COLOUR_2}Rocky Mountain Construction Group, Josef Wiegand GmbH & Co. KG, Intamin Amusement Rides Int. Corp. Est. STR_6542 :Contributors STR_6543 :Contributors… STR_6544 :Loan cannot be negative! diff --git a/distribution/changelog.txt b/distribution/changelog.txt index cc81bb8a0c..b149ee2a7b 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,8 +1,10 @@ 0.4.16 (in development) ------------------------------------------------------------------------ +- Feature: [#20810] New ride type: LSM Launched Roller Coaster. - Improved: [#22937] Add banked sloped turns and many other pieces to the Corkscrew, Hypercoaster and Lay-down Roller Coaster. - Improved: [#22967] Add medium and large half loops to the Wooden and Classic Wooden Roller Coasters. - Improved: [#23010] Make AppImage compatible with Ubuntu 22.04 and Debian Bookworm again. +- Change: [#20810] Giga Coaster boosters and launched lift hill track pieces are now locked behind cheats. - Fix: [#21221] Trains use unbanked sprites on flat to gentle diagonal banked track pieces. - Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. - Fix: [#22633] Crash when drawing loading screen with an outdated g2.dat. diff --git a/resources/g2/sprites.json b/resources/g2/sprites.json index 4282107096..7105f9b22a 100644 --- a/resources/g2/sprites.json +++ b/resources/g2/sprites.json @@ -2711,6 +2711,106 @@ "x": -22, "y": -5 }, + { + "path": "track/lattice_triangle/booster_alt_1.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/booster_alt_2.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/booster_alt_3.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/booster_alt_4.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/block_brake_alt_closed_1.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/block_brake_alt_closed_2.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/block_brake_alt_closed_3.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/block_brake_alt_closed_4.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/block_brake_alt_open_1.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/block_brake_alt_open_2.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/block_brake_alt_open_3.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/block_brake_alt_open_4.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/brake_alt_closed_1.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/brake_alt_closed_2.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/brake_alt_closed_3.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/brake_alt_closed_4.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/brake_alt_open_1.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/brake_alt_open_2.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/brake_alt_open_3.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/brake_alt_open_4.png", + "x": -22, + "y": -4 + }, { "path": "track/lattice_triangle/brake_horizontal_background_open.png", "x": -32, @@ -2748,25 +2848,69 @@ "palette": "keep" }, { - "path": "track/lattice_triangle/liftbooster_0.png", + "path": "track/lattice_triangle/drive_tyre_1.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/drive_tyre_2.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/drive_tyre_3.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/drive_tyre_4.png", + "x": -22, + "y": -4 + }, + { + "path": "track/lattice_triangle/liftbooster_1.png", "x": -21, "y": -20, "palette": "keep" }, { - "path": "track/lattice_triangle/liftbooster_1.png", + "path": "track/lattice_triangle/liftbooster_2.png", "x": -21, "y": -4, "palette": "keep" }, { - "path": "track/lattice_triangle/liftbooster_2.png", + "path": "track/lattice_triangle/liftbooster_3.png", "x": -22, "y": -4, "palette": "keep" }, { - "path": "track/lattice_triangle/liftbooster_3.png", + "path": "track/lattice_triangle/liftbooster_4.png", + "x": -22, + "y": -20, + "palette": "keep" + }, + { + "path": "track/lattice_triangle/liftbooster_alt_1.png", + "x": -21, + "y": -20, + "palette": "keep" + }, + { + "path": "track/lattice_triangle/liftbooster_alt_2.png", + "x": -21, + "y": -4, + "palette": "keep" + }, + { + "path": "track/lattice_triangle/liftbooster_alt_3.png", + "x": -22, + "y": -4, + "palette": "keep" + }, + { + "path": "track/lattice_triangle/liftbooster_alt_4.png", "x": -22, "y": -20, "palette": "keep" diff --git a/resources/g2/track/lattice_triangle/block_brake_alt_closed_1.png b/resources/g2/track/lattice_triangle/block_brake_alt_closed_1.png new file mode 100644 index 0000000000000000000000000000000000000000..b0a15201b8f186adbd371466f2e32e566b3ad54c GIT binary patch literal 1245 zcmWlYe{2(F7{_1MZ8sRB(*_D2T1ZU}J)oKkIkIAI>{!Y?-N6o5SX~MpU4aYU;Fc6D zrb2~EI=q--iWI5w)c#SoMuuEM)gomUZ18{?yLgyJtJE+^6B@0KnAeg#&+~cyc=CLc z=g09)y^gkdPs{@VwDoM<&{yZmx?5Td^_V*zX_-5BuGwm} z5`>MWDUM@!-X%$5Fc^$Rw~CB8;Izm*7MF;LAf1Ui^C?l!h03~8t7IK0aO1#70hvP*B9aLk3kg#- zkHWGIR^9NS3}My^01JQ{K}4f5fTA*nDR%n=%jUe^LLe{`kHbs`B}`VzY-25UH|7v= zXMo^kyA-2?NhXr!l)PKjy%rL+IjnXLXL!;j(qf1W#ocjLRJA}>k7(sYv6eAXz{CNw z7g+oNlMym*cBC*@h7vVrxF{(VISVIP+{BZp&w+=X_5@F-B~A%hn#~T2mBVek-7Ya~$X##dPlY47L`u(U)glGl3?gyHfZHMqc+5{F zLtHxM%_RecOsrhUR;x3R0>BA?1b|#W7XWeqln?;x#?sI)!K4E90*e8W01*nP4xqCD zasY~E7$%^?LREnI5Y!d$Xz?UqXy9ZKfj0+yctmz26h55}YFe^f)?i%=^#a1*O37wc zvA9)C)a`P`m8|;GwP^mKT7-oPW&)%IaoCJ5$|7)t-^<7WL5T#?$%vLsmh~*G7DljBSd= z%T6nFTVMc#F#@U-)EEfidy>if=m$pndO6T}XL_if5A|$VzvaNsCr{@4v&-5$x6wB~ z`3q(?zTEK7^0V{h<*S!Ayt!>xX{G=5h}}H!-PzGw_pbhZ;?|u5hxE|tw-@|J-T0BsF&kgkzWA48t2;|Wv*&K^b=p2{|M2&&7rQc}rw6{+_|~T7Ys>rn zdkin6Ce_VoM}O03$Nb4JOE!AZVsv~ecdQTGY<+()Iz8+;-(PE6edV`~%jYi54zKd& z2U^~}Uism6%bB0_}KRTfti2b7^9zQPoMAKH~G$@KbvOH+%FMduTmaAgmoWp zy3#yM9^L!Vgq-?g!L;e_CF`F1aOttO#ZQ`tFB-0`X$JEP4c@iC{`ktpdmUY`u4??s zvHSA(pXXL27-u88M?L&}Eqm(e+cRUhGQMbL#lai9AM6^l*aj1Kv?J@bj)2;r@YLa^ z%g@&FE#j^WEU^Ty50=ZY{oPS?P>?T-jjs`=PkfeE!?O#wgU)S7;RUYOQy)L*>F(Vy I-nIS6|F8}rkN^Mx literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/block_brake_alt_closed_2.png b/resources/g2/track/lattice_triangle/block_brake_alt_closed_2.png new file mode 100644 index 0000000000000000000000000000000000000000..5e58c90853d125847a5bdf36de18114f32c44733 GIT binary patch literal 1233 zcmWkte{2(V6#woAyN)>vHd=yl8{(U(Mg7WEy;WD^ZDcDeUi_6 z@7=ZC?)K>&(*XeOU8`61)bXi$+D%RMs+=t?s>AG|&J9B>KQJWrzvc%kxAI&3^STE6 z1O6U=|JFBlUGXmipb4yfXy9-@t>tznN{;?SgkjYO!N?8#?%V>DVZQj=B9Z38|h5J@1hNSa4-F>^6(spW03 z;(|3FoRT2a8~`u?_z;9Qo5MDngrX^e7-5*vK%f{7-%ciBE@#6m4$|sk?1T?>^G;6~ z<0L{zP!WZWXW3NVry2n}ZgaUE1nZD58S@Znj>-zG9^s0zP*x(-LKHKxST32=Rkc(oRI618Y&<|^1WTK#tc}e(10^b2_NFRgwkj2B znaWgg61F+bX54CZ+a0Xa#Sw%+Gf`iCSSS;VkESz*rq@a&@X?6Cn!`T36m%v+q!MMb ziNL55F6I)IqE@Tjh9m$U00aP}`ndow3P2eFupSHrLjqJ%&?qt};4u&N)RgarL~LdFvxCdy?YpT`p)QC=?_4053mkGUeaOC~Xe!g92$z&I-& z2lUxt7=;N8swC8D2;m{Y61e{ZLp|Lrcy8k7fjaN&TD5ZB>*MbqzJBo1ycsWiKCrns z89ugt$3^^))+L?8&o0=ttv_}8#H&dK4QBI6UMe52AGq-#_8xkkit5@5#wIkHupN!C-bxia# z?+pLBAoT5l_cq>~esbc-)w>(cxCVCGPD~tG?w3vv=u3LBf6<+T^Dhj*hT+ju+rs%R^8o-0+n(FfS;IB8G-)-p8oN?lSA%8!tvmZ!VSm4;=a36*?iKdAR<<4J z;a#1sp5E8`zH@B?Km$6qb+y)->+0(2>+3ZdO+!ONV`JmIdGini(Q36#O-%-~*^FUU ziXvH-<~WBa3Vy#o9FD}}iF7(wC{(Id%nC>XFm$uSp?AAY976HvPk z<0L|qDSwO(C0QlwOcZz%ZnWCW1dGxf?hq&;zyu=BNJ2=czH}j^mZQa)l#T>?78rP7 z@&b#5;1Po@ZgHeYLA3{qqEeC4aD+ki9B%a3(4d`&a#T`eRX>*xi=~*qk_ykLF<46L z^tc7JV>nMz9+nMqob2($gTYiJq9zi>T&_~7KwuPrC5&KE9hEe)S(GnQfs#Whdy*9? zSB;nF@-wg*)#-49!DceEsFfoKk!AwU+AwcC7|KNBg|u2NlE6tLBCGQ`O_Cdxy<{xF zCS^Vo^W{@=IiIdpry&V|9RLvksdg>^WB@230M>$`pjU)31s3v*1qc`jksx6M1qMJC zK*0cm7*rUTaKmf>78LMc@i?F$rdKX*-9>dg z`X}^lXEWFTd;9zJ*n(Y47WAEOS)yKl_wdP|uAN>xE-xFHB$UCA|DC!&l-n>UPmN0N zPi_3LoLh9_@=!GA*syrd`qgJ?;e7q>i<-ZmQjYuE+85d{bmiN=8rp69hj{vnZr7o+ zvrp{!IeT&KhIPO1+`W3dZ}Z&f*kq|CyKm`~@$w=P+q?dgU(W5}FE!oX`Poo+xAz>c zb>yj24{yJ+YH8hDzv`m{(=E*}_pPdbWGnZ>U!$6X0~aoT`B12F!jvmP5? zeQjdX*VRk6+^*$b*}LKv+_tU-Kl>Y587JW Lw_JMmg*W~Om2)OO literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/block_brake_alt_closed_4.png b/resources/g2/track/lattice_triangle/block_brake_alt_closed_4.png new file mode 100644 index 0000000000000000000000000000000000000000..6613d0e06530a915da4c06ef74b9cb1a6555a01e GIT binary patch literal 1234 zcmWkte~i;~6#w22==~5EoibpNkxXb{K#^jK8CalP#@WkCuE3Om1gDF0Dwu|t5)_laBd?lZ7q!|e^p-4fT{kjSN*Ke=MQY&?g7iU2yb|1bZ_14 z_4Il+ZyD(S-m?UN7O=W!O;@A2si~>Cxw)mKrM0zn!h{JECr(5Vq^+&3y}jLJwOVl; zqbQPPX`XkBq7V*;aoIZs+7xnGBpywQcs5Mstq7CVPJ1e+^_ z^O9XmP+^&l<=9k-Q*^I|Fk=p@owdQV|q2RM2B;HC-Od8%SVefyoOj zL4ZmKku*6ns5?&zsw-L+Q#Gjovy9Ei6Xt-!7IoRvJe3n!HOy;qu_A|S`S_SB!%D$m zBv6|RC%hyTVA&|oCjx;?G@4H)RYfU}jMQp12+RUN;|QKMP&qSOvU$r?q~cCh1G$-RLnut(P$8j8LkJIvM(^Vv@b@}du^=~l@yxPEw_i99 zXYTlHav!pBx%p^x8@|W1b_PX%a2Bf!4lF$<51gER{MMDxOysS~{Aa=IJ4=g^joP_M_s7rtP}%xV z#y9uhE7<+7_Z+02-VZ$w7mU1T$Oca=D81AE-z8e$ko=axOZ zvGJCC>Da9Cqx0T<@hXzP>pa_g=#$;|^vTmbp9X%!M&<`abYI<@o!tlrWnZA zMw`1f1Zocoec%0kDmSPVFJ}GHu}w#uJAb|T9Jk^N?ar*}=iSnx$?Bbx_Tk-gUShs{ zV))>->vJyeo&SF1;PA9{2NK(do;?1b$_zGv&mC{hdl;6KhUcKW%enIOicNd|2UuS# A-v9sr literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/block_brake_alt_open_1.png b/resources/g2/track/lattice_triangle/block_brake_alt_open_1.png new file mode 100644 index 0000000000000000000000000000000000000000..4ff47adf7b80e790da06b798da46c138ed70a8c6 GIT binary patch literal 1231 zcmWktacmQH6#i{v+{QE|X;^_`ZdmjTh17WB5sDme%(5KoksW#q9jWywMNU2NCWSQE zu_}$$pKTGo7`@TP3-j{su zy$`n9ZI91eJP!cyc-!Vp9aUUWO|+q|T9X$F&sJekcWY-iEAHy{y54q!4Lilx+%0Wy zx;*X%nYHMrj>gwjqnNwe1KX>k21VI`a8X6lL4JMNb z$1M~^vMkN>4oMONfj}e@OQn=dW>nM4l?rYFq!lo9lf$7G1k~%Z1Vh$Hlu4wVX;sSR zLWN?SG9#R|Nu&*a4wZQMkXa-lB5FvNPv|RI zBP>~9#R+F+2s0)C7yz6IBI&o2DKW?dW6qc&Dmi~f3+GCS!i=gTfu02h z4?ukYlMy0ju%$4EN{TryRFL9jIRgh6vz{l6UYj|@Sra^!me^c?&qt(UGEi0{Gr1%z zW^{T2GjllMAt^7*hIl^e^`=50H5SV$N?~-gTrNXk6af}N@Pv*^8`-ScQ=o!HN4(@s zm*vq)sx+IQflX$ejxZQ(sEIXOc&k;SnV_>e%$Ev`y1dxlFR8WniU1 z&@@y4)BuE_s)YzUF*#@q_z=NOL?cA>c(hoQvRNW}f^s-mLEwEp5w`>gON7Le6t2>i zQN~>2Owfr!KL(>XR7jYkA%uOB-t*`Ox;yMFSU-MmSCx0RZQ8Kyz}V5FKXqJddF-XZ zBftJzc_`i=Yn}|OZr{A|%DvnBcW_tF4*qe{WnZ^$&&^YfBTG)rPfR?srk!2#@Noal zN_Oet^Pk^+V!ffS>-JNjt^eI=ZaDOD@2$_m-*=we{`>m-SEN(QEnjQl!6 z52ntnys)~tCT;H=dDt&_(Eb+=H?KK4-aGlrpCj-8@XoE3+>YdI&$WZzX;;7NOzE4{ zvAs^Z<;35s+F#DUXt7U5CcHd^ehE>5DU$7cLuq_tNHyUB{dlQQnBM)yZ`%isWOh&dymWHKw_s}U>-RdoG7VP^2W_qPP3Jbg+WS9N CCM?$g literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/block_brake_alt_open_2.png b/resources/g2/track/lattice_triangle/block_brake_alt_open_2.png new file mode 100644 index 0000000000000000000000000000000000000000..6022dff8b88c962d3432b71822d348850f5b2867 GIT binary patch literal 1243 zcmWktacmQH6#k8}-C$sel~gI&2~{t8Ldi}!wdjGzDD%h;cVLAEk9ivnspi02I81{j z)L7(z3luF_rLtlg(@0@p4sy{ND^x7lxSG`LR>~|`4MIaosL3EdOY+|PzCT{xmwfNN zk5~7)W=@|o9RM)1XXWy~CO+FtwB6LK$us3eO?Ygm`^_Ov+%zQjzc&b$4Tx_KKHl?g zzjv^2uz%qFtrrKE0AK>ESFP!8Hn+62OqnvpWHL>iI<>X6wXLlUL6G+L_G#0mS?zW^ zK{#ld;y6YSJdz{^gTY87mP%=vOu;Z}^*Z4IloPN_hsR^_`B2&K2r14;lue{~JuT(( zO1ToJam4NH5E*O0jj93`lZewnIvsK6QlgO!RgHL~mT}ntj{}(kDu*OQB(0c>2}?a^ zgH;Et^KepyFk=UR1%O8o(QFRbY$}GuozBxNoAr8&fxwMe45rgI!eXba4iPnP{k9k%6d&L z)Kk^TVgq*IW;1EEx==fZI|QdwV%QMh9Oh3c;cOyhWb*Yg1$YLLICFqURUaPpQ^^pg zN4?o(pqP$UiPo}~T@U8-$!awZn_4z6Ap9MaYGvan zuVJF$RBN7OUDg|s+@w~9#TsS-B#O8kW)Fq>IKuB`)POG@4(Q2nK9j5(8CWlq3ObywBe#AFOMk8eOaI{j9ayc@3g!XtipHJ}nMZysz9TAF1(nOkZ6j;3K zwnH9;0Srb7s8KM_KnM>=7Vm=}80zcgz|z0|*wo|$J=Skmtm%MYEPpmJTSB z{K3AHXHD)ekKK9xxpUn5y(>DehaTOZnK-^cs3mLbZeJHi9?4!kd2`Q}8QhKwOrev_ z?)%75^DmEH+(7!y_U-@s{C)F( zg&*dQY#xr?yWn|xAHg)Z&yN-_tsVb<;)(b-ql@Lhti9u=g!hYkJ-sjdhL$#8-fs3V zZw!4l|ATE>yMZtH6D=)cPipd&(s#RKvo{8k3rbsu(Za-2NA*IZb?kU{=vMEUnNKEq z4$WI18p(vV4AcLdS}|{jW8I4jbNw&v9=*x$Yyo?UhsS>T{oKP%^FdE{@A4C`Zrt@h DDu6IU literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/block_brake_alt_open_3.png b/resources/g2/track/lattice_triangle/block_brake_alt_open_3.png new file mode 100644 index 0000000000000000000000000000000000000000..a5d3af10a5cb25a761ade0cf69f9acb9da61b25f GIT binary patch literal 1238 zcmWkte{2(V6#woA+{OlV)}(_fMGG|Xz(P(vOw|K!vn;0^?vSo)q=Q>2?gFRWpkSjN z6l}0Arxa76LK9EYm}V5+NYSzsC~lZePTW{=7p&OCZcHtq!o(?GOY+|PeExWOpXBr2 zJGgGGdG@S%vj70Io7OZmmvBibbyXFm8tuz2E5Y2(#+FWo-_q&Yw8H^bwey=D3!1iV zayptFo7(rh^_}B+04l(`m)AFzn#;<{%FD|uDk>@~D`(7@F>~fj1VO5*s;aB2HF~`s z!;BY1s)Ucuyibc!_2os>G8ksx5zPut$6;fs`u%p050Fgl=Jd*UQG7)t# zt%Z3bEZX6;2w_SO01bd0L3owQqt%KAgJd%G()6Iynelig!(o_AYB9B*&=_f*$!;+7 zsKtY^qDcsm-Y6AFFjCqcSDZRrYc%Uk3`()MjVE~@?F-w(aXv14Qc6J1N3v5%6#>)? z&^Uq44GbcJhc)Jy!ImU=+2YR%QbA0?UK&-ixYlJx{T5S%B@+T8d)Z7-$VI({WN=E3 z!dyzF#toP$O$H2^8(Kmxj4x{=i@)rljOzmH>7N5g3)nt`j*l z< z2vI{zI(yu}D<-jEixyppsbG3Ko`so$K@D&nVm7L5gpOk{x04b*oD}dRq5(M-%_}Kb z%;FRU;{YlELQv8|xORi+(|X+q=fFcjJoHH@mlM)yJamM#*%*#v-EJN;dU0crz@j9U zq>RHfnz!hoT?ah|7{XwjfHDOk{76tcAN)XP^I8V1{O#J761O)stXjW&>~LV!j?{wM zMyq$C@A7~A$jI_D$VAJ-YdT*&b?nR=ZNGL*-1CO#>rNd1pm=k91@Vem8h-j-n)oa) zf$jdgk;s*cOAa;Pq{sH(K2hD)J<-y3oO)#IUkAQ8-*J0u&({q--(Qi3MmAqfU)vaJ z4>GnZ3x|%qyJxcJ*@o>0=j;UdLpA+J%e(r@Yr9W>6FbtiVf2>`qt*^E*?Q{Iq3)fR zURv&TmOfwsvVz?A-X-soXor>T{Q$;;dsW*821C&mZrxf2_P8 zwpwxPhrM;s}grrenpUORt*_|5Minw%v~|n#+uJmV5_I MjcXfDu5R1+KeO~L1ONa4 literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/block_brake_alt_open_4.png b/resources/g2/track/lattice_triangle/block_brake_alt_open_4.png new file mode 100644 index 0000000000000000000000000000000000000000..2791fb047497fea09ec57a475aafc3aa93c4aa1b GIT binary patch literal 1242 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 Z!0B_L?bTP8CF`ad7QB0K;9 literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/brake_alt_closed_3.png b/resources/g2/track/lattice_triangle/brake_alt_closed_3.png new file mode 100644 index 0000000000000000000000000000000000000000..1fa69a9ab65e563e13bfd43313419b6bdc26a40a GIT binary patch literal 1232 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/brake_alt_open_2.png b/resources/g2/track/lattice_triangle/brake_alt_open_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fccd9c9db3ef1238c36fbfb332d5c3d2345f4a3c GIT binary patch literal 1222 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/brake_alt_open_4.png b/resources/g2/track/lattice_triangle/brake_alt_open_4.png new file mode 100644 index 0000000000000000000000000000000000000000..a33b1018b2d606614efa176ed97bad154e72f054 GIT binary patch literal 1213 zcmWktacmQH6n<=s+Za%^#)>7Lq{N04sL7EOQ{n-~tnn-7jwHZQ{yi;_a=?nz>khwh2puU421T+!+k**z1E0{o)(Gr@MFU z@cVjwJNn<;^OJ8KKr3v1c}rKbdCr_UEiEmrt*vwC&TVUJn>TMBhGFgP?HwH*7MsmR z5Kf9BS(X+AuOx}lXf&BjWwTnLFlHFFdYy0r=>~@G^m@&K03HfEV{vyi3r-k*QP)mg^FhAM2=O9yk_`um(}U9xmgD-xV$1I#+X=&Pidm2M+!zlucph5yom%e3l=}% zVX(`XD`oLy?cO{o>Rh}msWrKPMi_@#a9KkhN1St~1u7@8dQ>PSrAj7R%O@Lp22~0s zv&-(_2$!FvLM$5>1SJ&8#^d=^O4qdV*jTMrLtqubp2Uc>iON~oqQhUNVim7i4drU` zSUp>vDK${1!(?(U870OJA^`~!G!GaIAQq5l zL2&}94AKIq7(<2%4;SwOngWi&0)izHawKF=S`~7+sIF(KRUI|8tbQQEouq7GRGioB zqT!Zn-b_7|Yb1*^S{apUb~Cte%;Pk9Nj$(3VLvTL0%{_X%OvzdrfL*Wz3ifCqyaJj zA!ur0fquIjvqr;Mz~@quF6D$$sYu15OF2n-y=)*Lgu^1?jJljjlE_d*o_3Bgjw)wE zJdPrEq!36WkxnCoj!I_#!ygFt_OP)2pWk*i`3v2fHf$OG{qS+)LiFjy(0K5KfKcMq zs~gF#ZGBshjSOeby!O}S6NjhzAA{?@1^wB(*S}ipxq0Tw_s=bQ@4s`(%;eG=(fWeH zc%Xjo*Vd(nf{oyTWj6KVirKT6tWo#R{d{loN(X*u|E<}f)k1!)d%Yf<*nOV6vyyFj z^p(A%gDZtcKK^K&-ovaJ9lW_a92@7}9hiRm_U={twrfND*Z9P@=Z~zrxwR4dGBw0i zApXJQjkC8NOzodN`N_`jE}t4Wx}r4QhfiET_RGxl>Y?n^t#o5p{lcbAK0ixz&wlo2 zc=*@`@oIK_j5J^44sJ!uE!%Ft)!1|YUhk@xe%KY#Ey}V9Wx8!qGVH(e)bUG;#eIKY zI~61Dc-o-v=_R&dNy6y`1-;B0rmhW^#A|> literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/drive_tyre_1.png b/resources/g2/track/lattice_triangle/drive_tyre_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ae2bb9065a535d54d8943cb1a4464d9d18bb06fd GIT binary patch literal 1227 zcmWktacmQH6#i{v+{PHy6m4c*4y>e-o9Xa`GgQ6dZIp3lhr3CQ)tzuF7t`nkZd&z> zMGGl<>ctdNW`!Cq(&#a6W{d(AiYZ}WF{hcXKqXb1P~(OrY2ru*{w&FR@B99Ed0+Cq z_deXz=V@K^z#;%ZYww2c{u*}F5^ZXzRsC48vj%O$JueKi;nE26k#aVBYS>5P;! zm10SwFvRO_5ouekacA>rd;DiibO46!g7DHpW4O4efs90r0UP+24?A{oV!Pg<)v zJ1o0km4ovtgjojw3;-O0h!#u8ZdaX7&Fvm%m`Op%he9)n1k7aYxYa@0Tny^woE{PL zhHzeWOK~c!)6q1m<+xNqKnc6c<8ZSW%@aP65+h6`!6i~+$_!--QL~&Z&Sfklu(H4= z08|D}6(JHfkKy!XNYV5vMMaJIK0gOrFpGt-**vI&#az7GEzwMbs|}M4B|4cj3R$ySBmqYw5^D)@s2afHGO0({ zbX=I!L-|a+oX=LPGmr$p3xEWGT00j2CIKiR0M>$`pe#XMgM~cf1R@TiBuIHcfdP;O zP_#h>hZ+M@0ho)xf(Gs`o&YojybKcHZJ{6*RXs_KPp8ACsh7(ptZCT=fXgkUYGX8% zOF6}YTdnx?YA`()%gv{XFkf+60f8bOm&He-0T!19S`7uXXeg~m&8%K7WMQ>P&@@Z| zSO5@$nidima;gz~SVjVVA|4~+`{SjOl*YDLg~FrWma3 zbwCbh7f)xS%telFx=nAg0AbAx7GMSZ}+-^x32DuUhCi0xp=+YdPJ+h zjY^jfJ-56!`upyc)7~j zTl4Zex7sdT!Os5t{-tjgFMH_`e8;D8ug5+EPAwZ-Dw_)B`|%UPsK0RLR`*|yV&dW5 zzv}yDKl&3hnybZubC3V_-86b|`x7g676<7EXD@GUG*&F>`{IYemgwH?)wNH(mm4~F ppYfIc?e&T7)}(e)PWC727X!4CPrAq2n`>r+-k!ehqtCqZ!T)J6Ah7@d literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/drive_tyre_2.png b/resources/g2/track/lattice_triangle/drive_tyre_2.png new file mode 100644 index 0000000000000000000000000000000000000000..69daa700dba148d113fb57f60d81024e9c471597 GIT binary patch literal 1232 zcmWkte{2(V6#v55Zex-nO(~6EDb5p@Iy~H<)TL@TIJBHovTZcMw&rfAtjl~vV1Mcd++o4mE@;ep}7p?7^h40i+20Q$FW-%@X0uwcQ$g$o-R8Wt^D)Y#bA)YOC^NON;@OG}Hz zX0zeAgQh8tV+6r1Nn$7zip3I{jH2uLVzFAQ;SNBNfMr_UZnM{m`U8$|gp9@6REAeI zDQ84V$|ZBWQuLsN)#0>}oShK}w@8a&Hk{xSil`Vty%;qrsnV=wqJWtL z77suJ0Fx0SVR2?Kw?>JED^ik@Rau7@Si4yutbV6G;v!Q5txB8`5(+V?oDNmB*sPI; zW!+>ZFuMyUJQVHcxQHOc{r*fOq9qcBqLlLaYPAZ1RRmZJ!BZw$wQ@PTr$mR#?qtQU zR^@yxQ<*Ew!dAP4PS7&3nIi&;(Rm=JWO4qHP3#5+vHV?_L9yj+%YIU+tryWO1ED+B@}?g$Z%7=@>4Tw@%0 z)?RVhAdkWz2IDwXC}=Pc!sC+J^XLag2l_bBb7x{#oxj?xBk+G@t(cWBV7CA)35wq z$afw`DlNB`5mS2Y=OZ17kz;*B`+s{lUjDBC`;*<%!ofp(viH@F$ey0|ne5a1uAwiS z`l90|x520Uac}F;s!bH#eEXP>zqWeAv#R#V>ZP9!bnjL|`XOK9*7)36^~;Ib`MX#C zy%IKkb@xAP#21?x*rlnTH|-c5^d)lNT%F1rqho)b4>YIMn`^F4otxCpEZLTs2_8An zwMRlu@1Ow-5so}yiL5^`h+QV zdgNol%~LylOa#xjo4z{w7|VSytl zShQe`r*u$e#l}?9Vdt7L@g$8o$r%O|y@UaUmC%La8Z)Jl25N%(wIuJo&->%$eUi`n zad^#Y$E+E1X8-_Zb-voMwt@>Qj@H#wV&c2pixqgfclr8WR@l<(?b_K5mTeX`bvJiz z@A7o7?e5yV=iQ6lO97|>YgVmWUMa4ss;aK8uBoY+Hf`GU>C^pbWD5lC;Rq8?x>Kr{ z)`PixjKUD7y+NQ&J|`-3)~JY&_$f8)OeclxXrPddm5Z9g4BQy-l0asWxPYiZLndx4 zrOmKlgC#e7BtxiK0AK)cBZy!y_{?V6YK__LBMdX@@nn3ysc00csu?$0NRy30?QW|> zz??pulkH-J@+as}ijAe+O4frCW}CxeXEB;1TmmHom_XDWRRl%%Y1xooi08_xfdobt zm^=WLfK^6_sL7GEx>Qoooxz+KE6N%iVK5^{n7s}x=(NWn`)Mahkg6^lg(%mT265j<|7Qf4-dd2&=B?}`>+)W>PX38jUBjnqJD0z)d3}Yw)>Ina3g$ znFz3{h-Wn6%czk;Mk|%3APImI01*JWvMvCO0+2@ltQbQ`D&^PpM4_O=3YXafaH)Zm zO-u}RD^?+Emy51M$(t&N(~p!K%oMFgK%j`jW^j=x&*GAYmVJCI#k~gZ63aB{fSE(uv1?QJfQmb4t{@OS>LrjmvsH|k{kI2 ze+;4`jRu6FJw(VbX_EOunmc93XZo4`> z1MA`HKkfhZC35(QJ%f!4dj?xT$S`k}{OqBp0)E^K={COjVs6YHhv#Ry>nhwer@*GrJZ)+`0XAt%tvNdr?NI{GL3#h8~)_|9eGy(7Akd K$IvSq-~S&|x+xF< literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/drive_tyre_4.png b/resources/g2/track/lattice_triangle/drive_tyre_4.png new file mode 100644 index 0000000000000000000000000000000000000000..b5fdfbe782f200cb18551cc37c669c1db5f3fdf3 GIT binary patch literal 1241 zcmWkte{2(V6#s66-F}Egnpm}9kw#BaLnXI(YBe`FpezSF*r6qyc#d0lY9j~Uq>iG8 zG_GL51Bxkfk`imyKqHOWMunnyOS;5O&iQR0 zbqdZ7XJ=RM*590O08j_ktXj9c+FVmpQ(IeGS64S<#*CRWXV%x(BM8#a(9qb}XfT`2 z7-l6&f?+70XC+DWdcDD5C>D#SQkh(?R4!vyK-d6HHM6YVva&oG3c+O3i0RFQ!AhHK9BLOW z4jJPWo1~K7C>2OB;WQV|2`1cVwVQ2>h2n8mBt;+X3vr>i7}w-fE}#`7`ASkp06hZ? z0x)?1svvmCV2`0}k`OhAKQDz#N(v6p7Cny}-FA!LVT_*fE&vPzP(T2z22Dbb1fyY?%hD(iF%Td?+zxUy zfDC}50s1i*reWL#(>|CBgGY1by_>y0bjRlcch*^+gij_p0P_MmtEV|~4S z?IpQ?w`BiZV66$9-FKtw{?_r{@z=L>j=Fx_w|M$0b$N5&Yx^%h{CpdC zTRnEZb?(r(I6D14+bA^$7Vq4Bg#B`G-bHWIsV-CP{uPH>_uP76s#MeeylwxIcg~7O z?mXN7!3M!ly72q$wGXG%ujNK++nvV`H?4-LE2sN?JMT{%9hkhc85=(~}9H~-h1`tN;D-TJV5&Pe=^ z&t4S1oA}24MP};K*put8jU`q+aO}9g@qA(OYHu(7_Sgs#xjS+6hnt1lv$gTl#3E|= z-nF9>hh3ZXjj5Ku&!l}@`=x(}E-qk->)xEY+4<}4k-O+Qu&8iqKsQ&}Rka?pEpK0T Ja_M`!{s)dSHuV4i literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/liftbooster_1.png b/resources/g2/track/lattice_triangle/liftbooster_1.png index 62aadbb3972d1bb3dac11d82531d24a404f75246..1ffc4de8c9863a960ba4bda5a59356aa93e2d626 100644 GIT binary patch delta 422 zcmV;X0a^a^2<{1x7YZu~0{{R3)`Nlau^~VMe*t$%L_t(|+LYDFa)U4o08rn9fwKJn z7bUHiL(hCcYAku-Qe$YE%+yP{0S}F&kp&_7i%C*@F)8`KXkSa;$v7|dbRN2DI`vMRn6tS(y&(^E!^dQNgGC>fIPdK%Hd)U^=Qc zG1ui1qrR`1$wGb7_@Uo;n%;1yieBQpfBMY4it}(E^D4rV3L58?$xL6pKPhA>xe5XL z`4}eWl@N4~sK=qyNlJ(|-MBBJV`bRYu*{Of&$qDN7IVz2$Wfw^_AR9!p;<;smS41B zE^TAnO&D9E0b5H@gTXQlDO&>CfT*BETcOV delta 299 zcmV+`0o4BP3G@h%7YYyv0{{R3xIT8Au^~VMe*pbSL_t(|+H8D}46>v3fBG*TFfUx%i27$3w`CUCQ8Pc6arr%~c%um4uO$a|gP#3HE;z{Nwd5p5V0F6W`vIbC3s^0UMxic+s@ xl#o7t!2GjRxo$0KrSm8D^3OL~jQtm26#yxBX0U@q>j3}&002ovPDHLkV1m1Ni6j63 diff --git a/resources/g2/track/lattice_triangle/liftbooster_2.png b/resources/g2/track/lattice_triangle/liftbooster_2.png index 01f342f00f097e7d994cb8d02d2bcf68aa135fac..62aadbb3972d1bb3dac11d82531d24a404f75246 100644 GIT binary patch delta 311 zcmV-70m%OS2=oY$P6Ge{0I^a10)LTn6K4Pb00DGTPE!Ct=GbNc008|-L_t(|+H8

D}46>v3fBG*TFfUx%i27$3w`CU4P2pWp;P< zrp;LH?E56*?sXett7EbuI}FHLA|XkLAOTtI4wY2XAE>c%um4uO$a|gP#3HE;z{Nwd5p5V0F6W`v zIbC3s^0UMxic+s@l#o7tz$pB)RJm>~X{GZg_VUj+T8#Y{U;rt1X0U@q>j3}&002ov JPDHLkV1n7`jfemM delta 320 zcmV-G0l)tA2>l3 za>OtQM7cpKp2__$#ZNM2}+1d!X*;*6Uqubr-9a za;R)|@8;pv*i|ieuUpkM_Fs@Vi7psJ<-7YZu~0{{R3)`Nlau^~YNe}hRxK~#9!jMYn$gCGzFU=E-o__+Ul zCKC{4Gh0s(6BG=jYIvxbO&VN(_1o3mwg{b%7*W>KAY*wRZo206G+DT5yRK1|rm=aI zwa3*Zh0QpcuZZs{O!+vX+Z6D8VM79oaV?9z3>Zu1U%X?aKrA2su{L1q9*f7@6fxEi zf4*w%urNE;7JtUqWnF!;^|)uKu9+^6&<*@f1~7AF3_@h#Q1cLy>kO=xSjJv62D>38J+PnP%s~83 zb`wOqea2yedWEo*5f^dmHv0tof6RQADUN-Hu+siR5@)iZ&^|ArN_*f7*o}et zn$`ZLpac#ps*4=V$B-<`cx2EI)H)t_19{xG0khB7NS?T9F>x3;T~dZ_m~tY76!59t zS5(Zm->OPoaEBL%`7{^lbARPZF~+v6KMv)qX4>Tao@lRZu0?d+Os;h+Y6Qy08~hx? bp8x{@zbuo-rt~PZ00000NkvXXu0mjfcD2jc diff --git a/resources/g2/track/lattice_triangle/liftbooster_4.png b/resources/g2/track/lattice_triangle/liftbooster_4.png new file mode 100644 index 0000000000000000000000000000000000000000..8a56a1bdc662ccb70fe58a6d20c8ef2fc070dec9 GIT binary patch literal 1274 zcmWkuacmQH6#i`;yN!)?+QkAT6m6g`hZb^#BNn;AZ7JjCZtO^ksnE?^sZik@H!QQv z6Dm}5=n<+EXry3~DkbY+LKmwxv1Sc+ri*ne;UL9KXv{PvRx-(upCx(k``%yg`{R4x z`>>70Dn$t=-3R|J(Sp8~t$hr)qtDsB*9O-2aIf2zwC?V< z+d6ICJ^j7cZEFEgfR45;EfB)8va<5>a)m-sQBg5x&Ya51N(4cws;a81tJON44#Ny2 zNiYn>vKF4_+-|qe7l=fni9|-03&kR40E7|HRE@==ayYb3m%$?%eSSI=vBu(jDlO)w zf+UKVjWryl7R*|S)dzTN*iFWL=2V1}lb*aBoGBzs8em0%lK>Kfgg7KFDzhO~F{Ocd z11wtMtOQ{~2LKI#6+t+qQqX85y*_9(4%2kfZqEwBbRYoZaSf)@5o!aiHCpv14mArH zD;aq|=?+ug7!yocqq1F#YYZlxkwGaIw{Rrqp*;a>Aj(D4LPGYY^P${KTuA^G1Jrh) zbpgGE-~qKMqPN5eE^QWbe6S!T;4qDYp`zIsV#yfKq}^=R$4`abg}84f9fng0 zr3%-hW(>Czq?2Jpmi0TG5mAf>0_kWpm&p_g1qd`8(EAW9q$Fb+CWYE_q-V+!%sXQR zDN~H(XR|Y~230C?wc4cBF{ptx8hMKLSWC-X5z(6rMdU=fm?MCdLU=|gShbP^^}C3$ zhl%;^$*_=(`}5gEu{aG00L%dJ07w9Y0Z0Ncg#cJ8nuIPMhJ#Sf(t5yQz)OIr3CJ{n z41k;(iWm&iFzSFQ50r!8iSam~NMNQB2dfsGs8=$Df^012PN&29d>WRtG7RA$1`vXh7UJm9OCF8eg*a@u--r88`lqJ&R0{W>A}toi;b2`Z4l}rMgO9+%Bo?O( z85+%-b`jFZm@qgmUwfh!M2b~_GLzvmjQF|V)QvbmVcQ>sZy>^MHyBpqd^Y{PG vyb*bGu%+*I+u%NQSH(}Gj~4w9DE+4Ra&Pj&KhJ+%@&>fFv^NiK=sNU2Q#Ce_ literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/liftbooster_0.png b/resources/g2/track/lattice_triangle/liftbooster_alt_1.png similarity index 66% rename from resources/g2/track/lattice_triangle/liftbooster_0.png rename to resources/g2/track/lattice_triangle/liftbooster_alt_1.png index 1ffc4de8c9863a960ba4bda5a59356aa93e2d626..53fcd60e5deb85091ec0b68f3a08b393e4e47130 100644 GIT binary patch delta 397 zcmV;80doHC3FHZ|Vgr9|Nkl)B^3`W_fizLncZ zXuaQM0`m{N=QoQ6)oBSj)s3tR?>Y@Lvsiw%DLpt ztM=v+GODX)vv}j6wpRXXB)~Xn`rZ@?23lP?+*5)8F+c6{a)j8JO1z* zsKi~b?-$qdnsfI`6s-~D?zQ(iFaZ2)hp?C^vj}e^K(f8&loGE7Zpls-XkJRMTIyn= z30Ud1Y8m8JG~9pEz51{#YdwZ6TC98ZaUZS6@4TXkx@!n{cmp2iRR_QB{gu}%?4r&! zQ}vlwN$ibFjHJ7Y9YzW%AKOpkdW70R{l^vkhc_Z_;D{0000%+7`HM+Xdod~bzi3}e-^n;H^>iM(YC82_g(9D5d$-vl!^_S2Nbgja zCqkao80G(gPFG~*?*l_>=002ovPDHLkV1jKk B$6EjZ diff --git a/resources/g2/track/lattice_triangle/liftbooster_alt_2.png b/resources/g2/track/lattice_triangle/liftbooster_alt_2.png new file mode 100644 index 0000000000000000000000000000000000000000..8a3dbf41cfe7c54e285282749a8f6af4e3602f23 GIT binary patch literal 1168 zcmWktacC2F6n<@5ueE9>aRv<|vM2{T-3^a<$jzPZT4Rapm7X-)@<-IOW?d$?dEGJz zEW_yH$mHsRi*m9IZkml_MhWg<(S?y==fXT#)Tp;DVAPCN4J=|6slP>d?|t7NkN3g% z-urBL$UA@T(zyUIe{fU(NE?ZEF6^gw+9o-=0-hG9KDJ-xlXPLIb! zQ6$H)g5VRyfGkV#cs!lX6y>s+ ztkpG+!2C>~D_JSCk*&=X?JPJ1aE8Dg z1zf@CjMJOL14ULc{mGiFHI)*|^MpgBT@f#l^fOtJE69Qw7prNxuE(3j^o*&addcpf zal%j0A(o2>LQ)jfNF7qR-e{Ppt>p><742gcC$G7K1}<5Q z(hTUWNMR;jer(iGwTU}`c4J=B9$?*Jfr^HFN-V6UVg)^Amh^^ILaiF@^C1I}1qeY~ z3k&bSm4quE#lmB>nx@qwYP~L(%d~ow3j~C4Sd2y`ij31_nx%A(D*DI@Pc-}<6m+8) zj#LU6EHZrvp+mAG^z;WNMur4ffBWjrHeWK>zhTQq*WaCdeRpZuy#3d*$u)Op$(xJb zyP9UUAUUh%@!;L-rPyHLd-1y)d@0CjaBrqKc;)YO4LmH%2C^v}w3||1d8e9QF=;G zJwpR-*Iw7a;E}^uU9SVwK;N7Dx~s$M)~#E=etk_%O>J#$U0q#$eLaR@4Gj$&Hf%7M z&1RCcFbvJ}tROffN%Z^u;czsWOl7lknpUnvM(OVKFGWQ?TVOdBkm$?C*y zB4L+FL9t2^#-CtAX+D;7rZl&SGFohAD^IWjM~z47@CPEwX9kx(BNb-iPy?5+TJFj|u6tUsV&Ol8UNcMmLbYCR#CY zF_SZei<(s_I}#OddL^7&O%+hSjO&3iVK$4-L7O~0>2tG+?1_csbRwi?6D2K+Dg}yV zQ3{X-2tm~g^9;ov)Kly>-y}dkiF8p?|syFs@?cDdtow3uir^mK5k4>qE zZtYlFrB9*%wzjwbar02kHxnbPoj)y;8~Jh9MReuBKW)!FzVYbOwP(5=^SSr7Pi||Q zzH(=IExvX5*2fPoOnJ~MAEUH!-Y2j!#&ga7~l literal 0 HcmV?d00001 diff --git a/resources/g2/track/lattice_triangle/liftbooster_alt_4.png b/resources/g2/track/lattice_triangle/liftbooster_alt_4.png new file mode 100644 index 0000000000000000000000000000000000000000..ddbf0414f86df8fedefd2fec99594b6d7b4602d3 GIT binary patch literal 1260 zcmWktacmQH82ycIyTRNF7U`hT4jXbImr>*rE~J=ayJ0swIM@+7QbV`hM%98hxseK0 z3pAlh#gkMlTCyqy3OQWW8mk=8&1O`sa*34{JVMbbC7>2*aD}c<gwv6nwr|$S_DDr>gs0BoT)V!3^;D2 zD3W0;ENkO=&g=CCgW*^#kxFG1rBp8CMnIYXZK=1}G)|}9~KreKJU#_Up(&&d9K zAwpq@)l|<}v>vNoV9_v-$GucCXwAepCG9IJk*QM3tOIroxJV!{NR&g8eswOYDQ9%B zXoO`uoE9KV833RGuprHml%wbj! z&I%?zM0rI^Kw=^pdqQ#O37yewFfo{gC2SnU`DkC*9!_ux*^^QNaxt2pN~%eqVSv^F z^lpF(2octrW2h}ja-cPVF{hfjQOpmC`(B^BYW9gkS~bdQZhIti?EPV zYX}sx;)H{wTnyu9*^tW>^ZS$Gu$)Nbv)NLq1c8nNXb{1pYD&^E8O)KVd<9#i=#ol8 zwj3)?=cZsirdAVLtyyniFe7U+@fO-=ub8=G{y;h!Q&Ms{PXfCI;Tg5Zt{0qG$W4kq zMhZF7q9>OO6?3U_`8Fg0umZpXAOIi&kOrWD09YBCf^Hs)5vb&76mU2QkRV|O3Jo9w zAg6_X97brEaKelaDiQFgcmh}`V5Jc!tM$0BfMAYBSV{8AvREw2u#%;70NhBLR;j2IQ1jR8p{4cZa0S;y@WAH;v$77EygU3 z6|Dwn*Fz5qLpV&3P_{q_5AqtvqaPUVUdw=0H!g3f=pCKyts7qZ^_@d&wx^mOd+v%! zhn|CbKC12dan0=J*&~a|1Nf#5V;4t=@I+v&?MUXY{_X20152MYA6)7?CFC|-TS%15H z{rCAR?(ga8Wwu>?_vU-$heOwLf4u(9==hb6BWKblC?k7s4|yrcOrIY zW4!m&-}9*ZSsckUoF{uP#)rSU($O$FqEU(67qU&KhwgQqK2tk2XUFn6u_b4fmKO(9 ztNv>k-MjDB$BU%Q{+%b6eErYP@e_^DBC4~Y$B+0|d_HpNCBqGGk6d-Tby>>_L;GZ$ z|MZ6!`gYGnyvJVt=@a*bQ*$OZUl@yDvn~5lW!wC4=+xx+eh1a_x=xaKr+1m literal 0 HcmV?d00001 diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index ef4043e3d9..b17e59929c 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -105,6 +105,7 @@ namespace OpenRCT2::Ui::Windows RIDE_TYPE_HYBRID_COASTER, RIDE_TYPE_SINGLE_RAIL_ROLLER_COASTER, RIDE_TYPE_ALPINE_COASTER, + RIDE_TYPE_LSM_LAUNCHED_ROLLER_COASTER, // Gentle rides RIDE_TYPE_MONORAIL_CYCLES, diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index b88e708d96..7323e94289 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -449,6 +449,7 @@ + @@ -920,6 +921,7 @@ + diff --git a/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp b/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp index 2e8ecaacc3..84f425a21f 100644 --- a/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp +++ b/src/openrct2/paint/track/coaster/LatticeTriangleTrack.cpp @@ -10341,7 +10341,7 @@ static void LatticeTriangleTrackPoweredLift( const TrackElement& trackElement, SupportType supportType) { PaintAddImageAsParentRotated( - session, direction, session.TrackColours.WithIndex(SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_0 + direction), + session, direction, session.TrackColours.WithIndex(SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_1 + direction), { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) diff --git a/src/openrct2/paint/track/coaster/LatticeTriangleTrackAlt.cpp b/src/openrct2/paint/track/coaster/LatticeTriangleTrackAlt.cpp new file mode 100644 index 0000000000..f2623d6649 --- /dev/null +++ b/src/openrct2/paint/track/coaster/LatticeTriangleTrackAlt.cpp @@ -0,0 +1,217 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "../../../drawing/Drawing.h" +#include "../../../interface/Viewport.h" +#include "../../../ride/RideData.h" +#include "../../../ride/TrackData.h" +#include "../../../ride/TrackPaint.h" +#include "../../../sprites.h" +#include "../../../world/Map.h" +#include "../../../world/tile_element/TrackElement.h" +#include "../../Paint.h" +#include "../../support/MetalSupports.h" +#include "../../tile_element/Paint.TileElement.h" +#include "../../tile_element/Segment.h" +#include "../../track/Segment.h" +#include "../../track/Support.h" + +using namespace OpenRCT2; + +static constexpr TunnelGroup kTunnelGroup = TunnelGroup::Square; + +static constexpr uint32_t _LatticeTriangleAltBrakeImages[kNumOrthogonalDirections][2] = { + { SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_OPEN_NE_SW, SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_CLOSED_NE_SW }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_OPEN_NW_SE, SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_CLOSED_NW_SE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_OPEN_SW_NE, SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_CLOSED_SW_NE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_OPEN_SE_NW, SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_CLOSED_SE_NW }, +}; + +static constexpr uint32_t _LatticeTriangleAltBlockBrakeImages[kNumOrthogonalDirections][2] = { + { SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_OPEN_NE_SW, SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_CLOSED_NE_SW }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_OPEN_NW_SE, SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_CLOSED_NW_SE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_OPEN_SW_NE, SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_CLOSED_SW_NE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_OPEN_SE_NW, SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_CLOSED_SE_NW }, +}; + +static void LatticeTriangleTrackAltStation( + PaintSession& session, const Ride& ride, [[maybe_unused]] uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + if (ride.mode == RideMode::PoweredLaunch || ride.mode == RideMode::PoweredLaunchBlockSectioned + || ride.mode == RideMode::PoweredLaunchPasstrough) + { + static constexpr uint32_t imageIds[4][2] = { + { SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_NE_SW, SPR_STATION_BASE_A_SW_NE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_NW_SE, SPR_STATION_BASE_A_NW_SE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_SW_NE, SPR_STATION_BASE_A_SW_NE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_SE_NW, SPR_STATION_BASE_A_NW_SE }, + }; + + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(imageIds[direction][0]), { 0, 0, height }, + { { 0, 6, height + 3 }, { 32, 20, 1 } }); + + PaintAddImageAsParentRotated( + session, direction, GetStationColourScheme(session, trackElement).WithIndex(imageIds[direction][1]), + { 0, 0, height }, { 32, 32, 1 }); + } + else + { + static constexpr uint32_t imageIds[4][2] = { + { SPR_G2_LATTICE_TRIANGLE_TRACK_DRIVE_TYRE_NE_SW, SPR_STATION_BASE_A_SW_NE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_DRIVE_TYRE_NW_SE, SPR_STATION_BASE_A_NW_SE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_DRIVE_TYRE_SW_NE, SPR_STATION_BASE_A_SW_NE }, + { SPR_G2_LATTICE_TRIANGLE_TRACK_DRIVE_TYRE_SE_NW, SPR_STATION_BASE_A_NW_SE }, + }; + if (trackElement.GetTrackType() == TrackElemType::EndStation) + { + bool isClosed = trackElement.IsBrakeClosed(); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(_LatticeTriangleAltBlockBrakeImages[direction][isClosed]), + { 0, 0, height }, { { 0, 6, height + 3 }, { 32, 20, 1 } }); + } + else + { + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(imageIds[direction][0]), { 0, 0, height }, + { { 0, 6, height + 3 }, { 32, 20, 1 } }); + } + + PaintAddImageAsParentRotated( + session, direction, GetStationColourScheme(session, trackElement).WithIndex(imageIds[direction][1]), + { 0, 0, height }, { 32, 32, 1 }); + } + DrawSupportsSideBySide(session, direction, height, session.SupportColours, supportType.metal); + TrackPaintUtilDrawStation2(session, ride, direction, height, trackElement, 9, 11); + TrackPaintUtilDrawStationTunnel(session, direction, height); + PaintUtilSetSegmentSupportHeight(session, kSegmentsAll, 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); +} + +static void LatticeTriangleTrackAltBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + bool isClosed = trackElement.IsBrakeClosed(); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(_LatticeTriangleAltBrakeImages[direction][isClosed]), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours); + } + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); +} + +static void LatticeTriangleTrackAltBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + bool isClosed = trackElement.IsBrakeClosed(); + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(_LatticeTriangleAltBlockBrakeImages[direction][isClosed]), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours); + } + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); +} + +static void LatticeTriangleTrackAltBooster( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + switch (direction) + { + case 0: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_NE_SW), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 1: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_NW_SE), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 2: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_SW_NE), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + case 3: + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_SE_NW), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + break; + } + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours); + } + PaintUtilPushTunnelRotated(session, direction, height, kTunnelGroup, TunnelSubType::Flat); + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + kDefaultGeneralSupportHeight); +} + +static void LatticeTriangleTrackAltPoweredLift( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement, SupportType supportType) +{ + PaintAddImageAsParentRotated( + session, direction, session.TrackColours.WithIndex(SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_ALT_1 + direction), + { 0, 0, height }, { { 0, 6, height }, { 32, 20, 3 } }); + + if (TrackPaintUtilShouldPaintSupports(session.MapPosition)) + { + MetalASupportsPaintSetup(session, supportType.metal, MetalSupportPlace::Centre, 8, height, session.SupportColours); + } + if (direction == 0 || direction == 3) + { + PaintUtilPushTunnelRotated(session, direction, height - 8, kTunnelGroup, TunnelSubType::SlopeStart); + } + else + { + PaintUtilPushTunnelRotated(session, direction, height + 8, kTunnelGroup, TunnelSubType::SlopeEnd); + } + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(BlockedSegments::kStraightFlat, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 56); +} + +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLatticeTriangleTrackAlt(TrackElemType trackType) +{ + switch (trackType) + { + case TrackElemType::EndStation: + case TrackElemType::BeginStation: + case TrackElemType::MiddleStation: + return LatticeTriangleTrackAltStation; + case TrackElemType::Brakes: + return LatticeTriangleTrackAltBrakes; + case TrackElemType::BlockBrakes: + return LatticeTriangleTrackAltBlockBrakes; + case TrackElemType::Booster: + return LatticeTriangleTrackAltBooster; + case TrackElemType::PoweredLift: + return LatticeTriangleTrackAltPoweredLift; + + default: + return GetTrackPaintFunctionLatticeTriangleTrack(trackType); + } +} diff --git a/src/openrct2/park/ParkFile.h b/src/openrct2/park/ParkFile.h index 0dc6c046d0..61c19360ed 100644 --- a/src/openrct2/park/ParkFile.h +++ b/src/openrct2/park/ParkFile.h @@ -14,7 +14,7 @@ namespace OpenRCT2 constexpr uint32_t PARK_FILE_CURRENT_VERSION = 42; // The minimum version that is forwards compatible with the current version. - constexpr uint32_t PARK_FILE_MIN_VERSION = 40; + constexpr uint32_t PARK_FILE_MIN_VERSION = 42; // The minimum version that is backwards compatible with the current version. // If this is increased beyond 0, uncomment the checks in ParkFile.cpp and Context.cpp! diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index 214cba38b6..882807edbb 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -619,6 +619,7 @@ enum RIDE_TYPE_ALPINE_COASTER, RIDE_TYPE_CLASSIC_WOODEN_ROLLER_COASTER, RIDE_TYPE_CLASSIC_STAND_UP_ROLLER_COASTER, + RIDE_TYPE_LSM_LAUNCHED_ROLLER_COASTER, RIDE_TYPE_COUNT }; diff --git a/src/openrct2/ride/RideData.cpp b/src/openrct2/ride/RideData.cpp index bf428be178..e503a233b4 100644 --- a/src/openrct2/ride/RideData.cpp +++ b/src/openrct2/ride/RideData.cpp @@ -49,6 +49,7 @@ #include "rtd/coaster/InvertedRollerCoaster.h" #include "rtd/coaster/JuniorRollerCoaster.h" #include "rtd/coaster/LIMLaunchedRollerCoaster.h" +#include "rtd/coaster/LSMLaunchedRollerCoaster.h" #include "rtd/coaster/LayDownRollerCoaster.h" #include "rtd/coaster/LoopingRollerCoaster.h" #include "rtd/coaster/MineRide.h" @@ -352,6 +353,7 @@ constexpr RideTypeDescriptor RideTypeDescriptors[RIDE_TYPE_COUNT] = { /* RIDE_TYPE_ALPINE_COASTER */ AlpineCoasterRTD, /* RIDE_TYPE_CLASSIC_WOODEN_ROLLER_COASTER */ ClassicWoodenRollerCoasterRTD, /* RIDE_TYPE_CLASSIC_STAND_UP_ROLLER_COASTER */ ClassicStandUpRollerCoasterRTD, + /* RIDE_TYPE_LSM_LAUNCHED_ROLLER_COASTER */ LSMLaunchedRollerCoasterRTD, }; bool RideTypeDescriptor::HasFlag(RtdFlag flag) const diff --git a/src/openrct2/ride/RideData.h b/src/openrct2/ride/RideData.h index 083ee615db..f82759026c 100644 --- a/src/openrct2/ride/RideData.h +++ b/src/openrct2/ride/RideData.h @@ -561,6 +561,7 @@ constexpr std::string_view MUSIC_OBJECT_SUMMER = "rct2.music.summer"; constexpr std::string_view MUSIC_OBJECT_TECHNO = "rct2.music.techno"; constexpr std::string_view MUSIC_OBJECT_WATER = "rct2.music.water"; constexpr std::string_view MUSIC_OBJECT_WILD_WEST = "rct2.music.wildwest"; +constexpr std::string_view MUSIC_OBJECT_MODERN = "rct2.music.modern"; constexpr const RideComponentName& GetRideComponentName(const RideComponentType type) { diff --git a/src/openrct2/ride/RideStringIds.h b/src/openrct2/ride/RideStringIds.h index 03855eba37..928ab36163 100644 --- a/src/openrct2/ride/RideStringIds.h +++ b/src/openrct2/ride/RideStringIds.h @@ -37,6 +37,7 @@ enum : StringId STR_RIDE_NAME_JUNIOR_ROLLER_COASTER = 6, STR_RIDE_NAME_LAY_DOWN_ROLLER_COASTER = 64, STR_RIDE_NAME_LIM_LAUNCHED_ROLLER_COASTER = 92, + STR_RIDE_NAME_LSM_LAUNCHED_ROLLER_COASTER = 98, STR_RIDE_NAME_LOOPING_ROLLER_COASTER = 17, STR_RIDE_NAME_MINE_RIDE = 90, STR_RIDE_NAME_MINE_TRAIN_COASTER = 19, @@ -79,6 +80,7 @@ enum : StringId STR_RIDE_DESCRIPTION_JUNIOR_ROLLER_COASTER = 516, STR_RIDE_DESCRIPTION_LAY_DOWN_ROLLER_COASTER = 574, STR_RIDE_DESCRIPTION_LIM_LAUNCHED_ROLLER_COASTER = 602, + STR_RIDE_DESCRIPTION_LSM_LAUNCHED_ROLLER_COASTER = 608, STR_RIDE_DESCRIPTION_LOOPING_ROLLER_COASTER = 527, STR_RIDE_DESCRIPTION_MINE_RIDE = 600, STR_RIDE_DESCRIPTION_MINE_TRAIN_COASTER = 529, diff --git a/src/openrct2/ride/TrackPaint.h b/src/openrct2/ride/TrackPaint.h index 9519baab66..9fdfbb9f85 100644 --- a/src/openrct2/ride/TrackPaint.h +++ b/src/openrct2/ride/TrackPaint.h @@ -607,6 +607,7 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionReverserRC(OpenRCT2::TrackElemType tra TRACK_PAINT_FUNCTION GetTrackPaintFunctionHeartlineTwisterRC(OpenRCT2::TrackElemType trackType); TRACK_PAINT_FUNCTION GetTrackPaintFunctionMiniGolf(OpenRCT2::TrackElemType trackType); TRACK_PAINT_FUNCTION GetTrackPaintFunctionLatticeTriangleTrack(OpenRCT2::TrackElemType trackType); +TRACK_PAINT_FUNCTION GetTrackPaintFunctionLatticeTriangleTrackAlt(OpenRCT2::TrackElemType trackType); TRACK_PAINT_FUNCTION GetTrackPaintFunctionRotoDrop(OpenRCT2::TrackElemType trackType); TRACK_PAINT_FUNCTION GetTrackPaintFunctionFlyingSaucers(OpenRCT2::TrackElemType trackType); TRACK_PAINT_FUNCTION GetTrackPaintFunctionCrookedHouse(OpenRCT2::TrackElemType trackType); diff --git a/src/openrct2/ride/rtd/coaster/GigaCoaster.h b/src/openrct2/ride/rtd/coaster/GigaCoaster.h index 135fde8d2e..fdb2ae56d1 100644 --- a/src/openrct2/ride/rtd/coaster/GigaCoaster.h +++ b/src/openrct2/ride/rtd/coaster/GigaCoaster.h @@ -22,8 +22,8 @@ constexpr RideTypeDescriptor GigaCoasterRTD = .TrackPaintFunctions = TrackDrawerDescriptor({ .Drawer = GetTrackPaintFunctionLatticeTriangleTrack, .supportType = MetalSupportType::Tubes, - .enabledTrackGroups = {TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes, TrackGroup::slopeRollBanking, TrackGroup::slopeSteepLong, TrackGroup::liftHillCable, TrackGroup::booster, TrackGroup::poweredLift, TrackGroup::slopeCurveBanked, TrackGroup::slopeCurveLarge, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeVertical, TrackGroup::curveVertical}, - .extraTrackGroups = {TrackGroup::barrelRoll, TrackGroup::quarterLoop, TrackGroup::halfLoop, TrackGroup::halfLoopMedium, TrackGroup::halfLoopLarge, TrackGroup::verticalLoop, TrackGroup::corkscrew, TrackGroup::corkscrewLarge, TrackGroup::zeroGRoll, TrackGroup::zeroGRollLarge}, + .enabledTrackGroups = {TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::liftHill, TrackGroup::flatRollBanking, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes, TrackGroup::slopeRollBanking, TrackGroup::slopeSteepLong, TrackGroup::liftHillCable, TrackGroup::slopeCurveBanked, TrackGroup::slopeCurveLarge, TrackGroup::diagBrakes, TrackGroup::diagBlockBrakes, TrackGroup::slopeVertical, TrackGroup::curveVertical}, + .extraTrackGroups = {TrackGroup::barrelRoll, TrackGroup::quarterLoop, TrackGroup::halfLoop, TrackGroup::halfLoopMedium, TrackGroup::halfLoopLarge, TrackGroup::verticalLoop, TrackGroup::corkscrew, TrackGroup::corkscrewLarge, TrackGroup::zeroGRoll, TrackGroup::zeroGRollLarge, TrackGroup::booster, TrackGroup::poweredLift}, }), .InvertedTrackPaintFunctions = {}, .Flags = kRtdFlagsHasThreeColours | kRtdFlagsCommonCoaster | kRtdFlagsCommonCoasterNonAlt | diff --git a/src/openrct2/ride/rtd/coaster/LSMLaunchedRollerCoaster.h b/src/openrct2/ride/rtd/coaster/LSMLaunchedRollerCoaster.h new file mode 100644 index 0000000000..75c8103dbe --- /dev/null +++ b/src/openrct2/ride/rtd/coaster/LSMLaunchedRollerCoaster.h @@ -0,0 +1,90 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../../sprites.h" +#include "../../RideData.h" +#include "../../ShopItem.h" +#include "../../Track.h" + +// clang-format off +constexpr RideTypeDescriptor LSMLaunchedRollerCoasterRTD = +{ + .Category = RIDE_CATEGORY_ROLLERCOASTER, + .StartTrackPiece = OpenRCT2::TrackElemType::EndStation, + .TrackPaintFunctions = TrackDrawerDescriptor({ + .Drawer = GetTrackPaintFunctionLatticeTriangleTrackAlt, + .supportType = MetalSupportType::Tubes, + .enabledTrackGroups = {TrackGroup::straight, TrackGroup::stationEnd, TrackGroup::flatRollBanking, TrackGroup::slope, TrackGroup::slopeSteepUp, TrackGroup::slopeSteepDown, TrackGroup::slopeCurve, TrackGroup::slopeCurveSteep, TrackGroup::sBend, TrackGroup::curveSmall, TrackGroup::curve, TrackGroup::curveLarge, TrackGroup::helixDownBankedHalf, TrackGroup::helixUpBankedHalf, TrackGroup::brakes, TrackGroup::onridePhoto, TrackGroup::blockBrakes, TrackGroup::slopeRollBanking, TrackGroup::slopeSteepLong, TrackGroup::slopeCurveBanked, TrackGroup::slopeCurveLarge, TrackGroup::slopeCurveLargeBanked, TrackGroup::booster, TrackGroup::poweredLift, TrackGroup::slopeVertical, TrackGroup::curveVertical, TrackGroup::barrelRoll, TrackGroup::quarterLoop, TrackGroup::halfLoop, TrackGroup::halfLoopMedium, TrackGroup::halfLoopLarge, TrackGroup::verticalLoop, TrackGroup::corkscrew, TrackGroup::corkscrewLarge, TrackGroup::zeroGRoll, TrackGroup::zeroGRollLarge }, + .extraTrackGroups = {TrackGroup::liftHill, TrackGroup::liftHillCable}, + }), + .InvertedTrackPaintFunctions = {}, + .Flags = kRtdFlagsHasThreeColours | kRtdFlagsCommonCoaster | kRtdFlagsCommonCoasterNonAlt | + EnumsToFlags(RtdFlag::hasLeaveWhenAnotherVehicleArrivesAtStation, RtdFlag::checkGForces, + RtdFlag::allowMultipleCircuits, RtdFlag::allowCableLiftHill, RtdFlag::allowReversedTrains), + .RideModes = EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::PoweredLaunch, RideMode::PoweredLaunchBlockSectioned), + .DefaultMode = RideMode::ContinuousCircuit, + .OperatingSettings = { 2, 10 }, + .TrackSpeedSettings = { 60, 60 }, + .BoosterSettings = { 17, 68 }, + .LegacyBoosterSettings = { 17, 68, 2 }, + .Naming = { STR_RIDE_NAME_LSM_LAUNCHED_ROLLER_COASTER, STR_RIDE_DESCRIPTION_LSM_LAUNCHED_ROLLER_COASTER }, + .NameConvention = { RideComponentType::Train, RideComponentType::Track, RideComponentType::Station }, + .EnumName = "RIDE_TYPE_LSM_LAUNCHED_ROLLER_COASTER", + .AvailableBreakdowns = (1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), + .Heights = { 33, 24, 9, 11, }, + .MaxMass = 31, + .LiftData = { OpenRCT2::Audio::SoundId::LiftClassic, 5, 5 }, + .RatingsMultipliers = { 51, 32, 10 }, + .UpkeepCosts = { 10, 20, 80, 12, 3, 40 }, + .BuildCosts = { 57.00_GBP, 2.50_GBP, 55, }, + .DefaultPrices = { 20, 20 }, + .DefaultMusic = MUSIC_OBJECT_MODERN, + .PhotoItem = ShopItem::Photo, + .BonusValue = 120, + .ColourPresets = TRACK_COLOUR_PRESETS( + { COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_BLACK}, // Taiga + { COLOUR_BRIGHT_GREEN, COLOUR_BRIGHT_GREEN, COLOUR_YELLOW}, // Cheetah Hunt + { COLOUR_BRIGHT_RED, COLOUR_BRIGHT_RED, COLOUR_DULL_BROWN_LIGHT}, // Maverick + { COLOUR_BLACK, COLOUR_BLACK, COLOUR_DULL_BROWN_DARK}, // Taron + ), + .ColourPreview = { SPR_RIDE_DESIGN_PREVIEW_GIGA_RC, SPR_RIDE_DESIGN_PREVIEW_GIGA_RC_SUPPORTS }, + .ColourKey = RideColourKey::Ride, + .Name = "lsm_rc", + .RatingsData = + { + RatingsCalculationType::Normal, + { RIDE_RATING(3, 85), RIDE_RATING(0, 40), RIDE_RATING(0, 35) }, + 14, + -1, + false, + { + { RatingsModifierType::BonusLength, 6000, 764, 0, 0 }, + { RatingsModifierType::BonusSynchronisation, 0, RIDE_RATING(0, 40), RIDE_RATING(0, 05), 0 }, + { RatingsModifierType::BonusTrainLength, 0, 187245, 0, 0 }, + { RatingsModifierType::BonusMaxSpeed, 0, 44281, 88562, 35424 }, + { RatingsModifierType::BonusAverageSpeed, 0, 291271, 436906, 0 }, + { RatingsModifierType::BonusDuration, 150, 26214, 0, 0 }, + { RatingsModifierType::BonusGForces, 0, 24576, 35746, 49648 }, + { RatingsModifierType::BonusTurns, 0, 26749, 34767, 45749 }, + { RatingsModifierType::BonusDrops, 0, 29127, 46811, 49152 }, + { RatingsModifierType::BonusSheltered, 0, 15420, 32768, 35108 }, + { RatingsModifierType::BonusReversedTrains, 0, 2, 15, 20 }, + { RatingsModifierType::BonusProximity, 0, 20130, 0, 0 }, + { RatingsModifierType::BonusScenery, 0, 6693, 0, 0 }, + { RatingsModifierType::RequirementDropHeight, 10, 2, 2, 2 }, + { RatingsModifierType::RequirementMaxSpeed, 0xA0000, 2, 2, 2 }, + { RatingsModifierType::RequirementNegativeGs, 10, 2, 2, 2 }, + { RatingsModifierType::RequirementNumDrops, 2, 2, 2, 2 }, + { RatingsModifierType::PenaltyLateralGs, 0, 24576, 35746, 49648 }, + }, + }, +}; +// clang-format on diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index e827e024d1..a51ea9ca72 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -1226,11 +1226,39 @@ enum : ImageIndex SPR_G2_LATTICE_TRIANGLE_TRACK_BEGIN = SPR_G2_JUNIOR_RC_END, SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_NE_SW = SPR_G2_LATTICE_TRIANGLE_TRACK_BEGIN, SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_NW_SE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_NE_SW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_NW_SE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_SW_NE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BOOSTER_ALT_SE_NW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_CLOSED_NE_SW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_CLOSED_NW_SE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_CLOSED_SW_NE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_CLOSED_SE_NW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_OPEN_NE_SW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_OPEN_NW_SE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_OPEN_SW_NE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BLOCK_BRAKE_ALT_OPEN_SE_NW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_CLOSED_NE_SW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_CLOSED_NW_SE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_CLOSED_SW_NE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_CLOSED_SE_NW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_OPEN_NE_SW, + SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_OPEN_NW_SE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_OPEN_SW_NE, + SPR_G2_LATTICE_TRIANGLE_TRACK_BRAKE_ALT_OPEN_SE_NW, SPR_G2_LATTICE_TRIANGLE_TRACK_DIAG_BRAKES, - SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_0 = SPR_G2_LATTICE_TRIANGLE_TRACK_DIAG_BRAKES + 6, + SPR_G2_LATTICE_TRIANGLE_TRACK_DRIVE_TYRE_NE_SW = SPR_G2_LATTICE_TRIANGLE_TRACK_DIAG_BRAKES + 6, + SPR_G2_LATTICE_TRIANGLE_TRACK_DRIVE_TYRE_NW_SE, + SPR_G2_LATTICE_TRIANGLE_TRACK_DRIVE_TYRE_SW_NE, + SPR_G2_LATTICE_TRIANGLE_TRACK_DRIVE_TYRE_SE_NW, SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_1, SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_2, SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_3, + SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_4, + SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_ALT_1, + SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_ALT_2, + SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_ALT_3, + SPR_G2_LATTICE_TRIANGLE_TRACK_POWERED_LIFT_ALT_4, SPR_G2_LATTICE_TRIANGLE_TRACK_VERTICAL, SPR_G2_LATTICE_TRIANGLE_TRACK_VERTICAL_TWIST = SPR_G2_LATTICE_TRIANGLE_TRACK_VERTICAL + 12, SPR_G2_LATTICE_TRIANGLE_TRACK_BARREL_ROLL = SPR_G2_LATTICE_TRIANGLE_TRACK_VERTICAL_TWIST + 12, From 0611c18bf65ff1fa80354d3cf9f779c71f928890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 3 Nov 2024 08:54:31 +0100 Subject: [PATCH 95/97] Update backtrace token for upcoming release --- src/openrct2/platform/Crash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/platform/Crash.cpp b/src/openrct2/platform/Crash.cpp index 69734b4377..5e64f16e56 100644 --- a/src/openrct2/platform/Crash.cpp +++ b/src/openrct2/platform/Crash.cpp @@ -57,7 +57,7 @@ static const wchar_t* _wszCommitSha1Short = WSZ(""); static const wchar_t* _wszArchitecture = WSZ(OPENRCT2_ARCHITECTURE); static std::map _uploadFiles; -# define BACKTRACE_TOKEN "880330550e07896abb0de50eca685eec04e0383e57393f315b977bf88688fcf2" +# define BACKTRACE_TOKEN "1a9becc5de031b0a24ecad5222d2b42820c3710863a0f1dba6ab378b02ca659a" using namespace OpenRCT2; From 1be5d78a52d8509bbd6f0f3db2a72afa80a4f362 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Sun, 3 Nov 2024 10:05:10 +0100 Subject: [PATCH 96/97] Update objects release to v0.4.10 (#23109) --- CMakeLists.txt | 4 +- openrct2.proj | 4 +- src/openrct2/scenario/ScenarioSources.cpp | 156 +++++++++++----------- 3 files changed, 83 insertions(+), 81 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 030ad0d81b..23b59933ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,9 +68,9 @@ set(TITLE_SEQUENCE_VERSION "0.4.14") set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v${TITLE_SEQUENCE_VERSION}/title-sequences.zip") set(TITLE_SEQUENCE_SHA1 "6c04781b959b468e1f65ec2d2f21f5aaa5e5724d") -set(OBJECTS_VERSION "1.4.9") +set(OBJECTS_VERSION "1.4.10") set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip") -set(OBJECTS_SHA1 "5e50b33ab556e7bf8ed80484b8ba05b593c191c2") +set(OBJECTS_SHA1 "e4953075d8dbe13ef48e8c4e87621cf3503a9d23") set(OPENSFX_VERSION "1.0.5") set(OPENSFX_URL "https://github.com/OpenRCT2/OpenSoundEffects/releases/download/v${OPENSFX_VERSION}/opensound.zip") diff --git a/openrct2.proj b/openrct2.proj index 8ca15283c4..1d96adb75c 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -45,8 +45,8 @@ 9984c1e317dcfb3aaf8e17f1db2ebb0f771e2373 https://github.com/OpenRCT2/title-sequences/releases/download/v0.4.14/title-sequences.zip 6c04781b959b468e1f65ec2d2f21f5aaa5e5724d - https://github.com/OpenRCT2/objects/releases/download/v1.4.9/objects.zip - 5e50b33ab556e7bf8ed80484b8ba05b593c191c2 + https://github.com/OpenRCT2/objects/releases/download/v1.4.10/objects.zip + e4953075d8dbe13ef48e8c4e87621cf3503a9d23 https://github.com/OpenRCT2/OpenSoundEffects/releases/download/v1.0.5/opensound.zip b1b1f1b241d2cbff63a1889c4dc5a09bdf769bfb https://github.com/OpenRCT2/OpenMusic/releases/download/v1.6/openmusic.zip diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp index e7e8d8287d..1735ca0d5c 100644 --- a/src/openrct2/scenario/ScenarioSources.cpp +++ b/src/openrct2/scenario/ScenarioSources.cpp @@ -148,71 +148,71 @@ namespace OpenRCT2::ScenarioSources // RCT: Added Attractions static constexpr ScenarioTitleDescriptor ScenarioTitlesRCT1AA[] = { - { SC_WHISPERING_CLIFFS, "Whispering Cliffs", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.whispering_cliffs" }, - { SC_THREE_MONKEYS_PARK, "Three Monkeys Park", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.three_monkeys_park" }, - { SC_CANARY_MINES, "Canary Mines", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.canary_mines" }, - { SC_BARONY_BRIDGE, "Barony Bridge", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.barony_bridge" }, - { SC_FUNTOPIA, "Funtopia", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.funtopia" }, - { SC_HAUNTED_HARBOUR, "Haunted Harbour", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.haunted_harbour" }, - { SC_FUN_FORTRESS, "Fun Fortress", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.fun_fortress" }, - { SC_FUTURE_WORLD, "Future World", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.future_world" }, - { SC_GENTLE_GLEN, "Gentle Glen", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.gentle_glen" }, - { SC_JOLLY_JUNGLE, "Jolly Jungle", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.jolly_jungle" }, - { SC_HYDRO_HILLS, "Hydro Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.hydro_hills" }, - { SC_SPRIGHTLY_PARK, "Sprightly Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.sprightly_park" }, - { SC_MAGIC_QUARTERS, "Magic Quarters", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.magic_quarters" }, - { SC_FRUIT_FARM, "Fruit Farm", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.fruit_farm" }, - { SC_BUTTERFLY_DAM, "Butterfly Dam", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.butterfly_dam" }, - { SC_COASTER_CANYON, "Coaster Canyon", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.coaster_canyon" }, - { SC_THUNDERSTORM_PARK, "Thunderstorm Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.thunderstorm_park" }, - { SC_HARMONIC_HILLS, "Harmonic Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.harmonic_hills" }, - { SC_ROMAN_VILLAGE, "Roman Village", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.roman_village" }, - { SC_SWAMP_COVE, "Swamp Cove", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.swamp_cove" }, - { SC_ADRENALINE_HEIGHTS, "Adrenaline Heights", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.adrenaline_heights" }, - { SC_UTOPIA_PARK, "Utopia Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.utopia_park" }, - { SC_ROTTING_HEIGHTS, "Rotting Heights", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.rotting_heights" }, - { SC_FIASCO_FOREST, "Fiasco Forest", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.fiasco_forest" }, - { SC_PICKLE_PARK, "Pickle Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.pickle_park" }, - { SC_GIGGLE_DOWNS, "Giggle Downs", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.giggle_downs" }, - { SC_MINERAL_PARK, "Mineral Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.mineral_park" }, - { SC_COASTER_CRAZY, "Coaster Crazy", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.coaster_crazy" }, - { SC_URBAN_PARK, "Urban Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.urban_park" }, - { SC_GEOFFREY_GARDENS, "Geoffrey Gardens", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.geoffrey_gardens" }, + { SC_WHISPERING_CLIFFS, "Whispering Cliffs", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.whispering_cliffs" }, + { SC_THREE_MONKEYS_PARK, "Three Monkeys Park", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.three_monkeys_park" }, + { SC_CANARY_MINES, "Canary Mines", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.canary_mines" }, + { SC_BARONY_BRIDGE, "Barony Bridge", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.barony_bridge" }, + { SC_FUNTOPIA, "Funtopia", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.funtopia" }, + { SC_HAUNTED_HARBOUR, "Haunted Harbour", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.haunted_harbour" }, + { SC_FUN_FORTRESS, "Fun Fortress", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.fun_fortress" }, + { SC_FUTURE_WORLD, "Future World", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.future_world" }, + { SC_GENTLE_GLEN, "Gentle Glen", SCENARIO_CATEGORY_BEGINNER, "rct1aa.scenario_text.gentle_glen" }, + { SC_JOLLY_JUNGLE, "Jolly Jungle", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.jolly_jungle" }, + { SC_HYDRO_HILLS, "Hydro Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.hydro_hills" }, + { SC_SPRIGHTLY_PARK, "Sprightly Park", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.sprightly_park" }, + { SC_MAGIC_QUARTERS, "Magic Quarters", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.magic_quarters" }, + { SC_FRUIT_FARM, "Fruit Farm", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.fruit_farm" }, + { SC_BUTTERFLY_DAM, "Butterfly Dam", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.butterfly_dam" }, + { SC_COASTER_CANYON, "Coaster Canyon", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.coaster_canyon" }, + { SC_THUNDERSTORM_PARK, "Thunderstorm Park", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.thunderstorm_park" }, + { SC_HARMONIC_HILLS, "Harmonic Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.harmonic_hills" }, + { SC_ROMAN_VILLAGE, "Roman Village", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.roman_village" }, + { SC_SWAMP_COVE, "Swamp Cove", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.swamp_cove" }, + { SC_ADRENALINE_HEIGHTS, "Adrenaline Heights", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.adrenaline_heights" }, + { SC_UTOPIA_PARK, "Utopia Park", SCENARIO_CATEGORY_CHALLENGING, "rct1aa.scenario_text.utopia_park" }, + { SC_ROTTING_HEIGHTS, "Rotting Heights", SCENARIO_CATEGORY_EXPERT, "rct1aa.scenario_text.rotting_heights" }, + { SC_FIASCO_FOREST, "Fiasco Forest", SCENARIO_CATEGORY_EXPERT, "rct1aa.scenario_text.fiasco_forest" }, + { SC_PICKLE_PARK, "Pickle Park", SCENARIO_CATEGORY_EXPERT, "rct1aa.scenario_text.pickle_park" }, + { SC_GIGGLE_DOWNS, "Giggle Downs", SCENARIO_CATEGORY_EXPERT, "rct1aa.scenario_text.giggle_downs" }, + { SC_MINERAL_PARK, "Mineral Park", SCENARIO_CATEGORY_EXPERT, "rct1aa.scenario_text.mineral_park" }, + { SC_COASTER_CRAZY, "Coaster Crazy", SCENARIO_CATEGORY_EXPERT, "rct1aa.scenario_text.coaster_crazy" }, + { SC_URBAN_PARK, "Urban Park", SCENARIO_CATEGORY_EXPERT, "rct1aa.scenario_text.urban_park" }, + { SC_GEOFFREY_GARDENS, "Geoffrey Gardens", SCENARIO_CATEGORY_EXPERT, "rct1aa.scenario_text.geoffrey_gardens" }, }; // RCT: Loopy Landscapes static constexpr ScenarioTitleDescriptor ScenarioTitlesRCT1LL[] = { - { SC_ICEBERG_ISLANDS, "Iceberg Islands", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.iceberg_islands" }, - { SC_VOLCANIA, "Volcania", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.volcania" }, - { SC_ARID_HEIGHTS, "Arid Heights", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.arid_heights" }, - { SC_RAZOR_ROCKS, "Razor Rocks", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.razor_rocks" }, - { SC_CRATER_LAKE, "Crater Lake", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.crater_lake" }, - { SC_VERTIGO_VIEWS, "Vertigo Views", SCENARIO_CATEGORY_BEGINNER, "rct1.scenario_text.vertigo_views" }, - { SC_PARADISE_PIER_2, "Paradise Pier 2", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.paradise_pier_2" }, - { SC_DRAGONS_COVE, "Dragon's Cove", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.dragons_cove" }, - { SC_GOOD_KNIGHT_PARK, "Good Knight Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.good_knight_park" }, - { SC_WACKY_WARREN, "Wacky Warren", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.wacky_warren" }, - { SC_GRAND_GLACIER, "Grand Glacier", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.grand_glacier" }, - { SC_CRAZY_CRATERS, "Crazy Craters", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.crazy_craters" }, - { SC_DUSTY_DESERT, "Dusty Desert", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.dusty_desert" }, - { SC_WOODWORM_PARK, "Woodworm Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.woodworm_park" }, - { SC_ICARUS_PARK, "Icarus Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.icarus_park" }, - { SC_SUNNY_SWAMPS, "Sunny Swamps", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.sunny_swamps" }, - { SC_FRIGHTMARE_HILLS, "Frightmare Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.frightmare_hills" }, - { SC_THUNDER_ROCKS, "Thunder Rocks", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.thunder_rocks" }, - { SC_OCTAGON_PARK, "Octagon Park", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.octagon_park" }, - { SC_PLEASURE_ISLAND, "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.pleasure_island" }, - { SC_ICICLE_WORLDS, "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING, "rct1.scenario_text.icicle_worlds" }, - { SC_SOUTHERN_SANDS, "Southern Sands", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.southern_sands" }, - { SC_TINY_TOWERS, "Tiny Towers", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.tiny_towers" }, - { SC_NEVERMORE_PARK, "Nevermore Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.nevermore_park" }, - { SC_PACIFICA, "Pacifica", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.pacifica" }, - { SC_URBAN_JUNGLE, "Urban Jungle", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.urban_jungle" }, - { SC_TERROR_TOWN, "Terror Town", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.terror_town" }, - { SC_MEGAWORLD_PARK, "Megaworld Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.megaworld_park" }, - { SC_VENUS_PONDS, "Venus Ponds", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.venus_ponds" }, - { SC_MICRO_PARK, "Micro Park", SCENARIO_CATEGORY_EXPERT, "rct1.scenario_text.micro_park" }, + { SC_ICEBERG_ISLANDS, "Iceberg Islands", SCENARIO_CATEGORY_BEGINNER, "rct1ll.scenario_text.iceberg_islands" }, + { SC_VOLCANIA, "Volcania", SCENARIO_CATEGORY_BEGINNER, "rct1ll.scenario_text.volcania" }, + { SC_ARID_HEIGHTS, "Arid Heights", SCENARIO_CATEGORY_BEGINNER, "rct1ll.scenario_text.arid_heights" }, + { SC_RAZOR_ROCKS, "Razor Rocks", SCENARIO_CATEGORY_BEGINNER, "rct1ll.scenario_text.razor_rocks" }, + { SC_CRATER_LAKE, "Crater Lake", SCENARIO_CATEGORY_BEGINNER, "rct1ll.scenario_text.crater_lake" }, + { SC_VERTIGO_VIEWS, "Vertigo Views", SCENARIO_CATEGORY_BEGINNER, "rct1ll.scenario_text.vertigo_views" }, + { SC_PARADISE_PIER_2, "Paradise Pier 2", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.paradise_pier_2" }, + { SC_DRAGONS_COVE, "Dragon's Cove", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.dragons_cove" }, + { SC_GOOD_KNIGHT_PARK, "Good Knight Park", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.good_knight_park" }, + { SC_WACKY_WARREN, "Wacky Warren", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.wacky_warren" }, + { SC_GRAND_GLACIER, "Grand Glacier", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.grand_glacier" }, + { SC_CRAZY_CRATERS, "Crazy Craters", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.crazy_craters" }, + { SC_DUSTY_DESERT, "Dusty Desert", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.dusty_desert" }, + { SC_WOODWORM_PARK, "Woodworm Park", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.woodworm_park" }, + { SC_ICARUS_PARK, "Icarus Park", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.icarus_park" }, + { SC_SUNNY_SWAMPS, "Sunny Swamps", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.sunny_swamps" }, + { SC_FRIGHTMARE_HILLS, "Frightmare Hills", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.frightmare_hills" }, + { SC_THUNDER_ROCKS, "Thunder Rocks", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.thunder_rocks" }, + { SC_OCTAGON_PARK, "Octagon Park", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.octagon_park" }, + { SC_PLEASURE_ISLAND, "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.pleasure_island" }, + { SC_ICICLE_WORLDS, "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING, "rct1ll.scenario_text.icicle_worlds" }, + { SC_SOUTHERN_SANDS, "Southern Sands", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.southern_sands" }, + { SC_TINY_TOWERS, "Tiny Towers", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.tiny_towers" }, + { SC_NEVERMORE_PARK, "Nevermore Park", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.nevermore_park" }, + { SC_PACIFICA, "Pacifica", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.pacifica" }, + { SC_URBAN_JUNGLE, "Urban Jungle", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.urban_jungle" }, + { SC_TERROR_TOWN, "Terror Town", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.terror_town" }, + { SC_MEGAWORLD_PARK, "Megaworld Park", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.megaworld_park" }, + { SC_VENUS_PONDS, "Venus Ponds", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.venus_ponds" }, + { SC_MICRO_PARK, "Micro Park", SCENARIO_CATEGORY_EXPERT, "rct1ll.scenario_text.micro_park" }, }; // RCT2 @@ -302,9 +302,9 @@ namespace OpenRCT2::ScenarioSources // Real parks static constexpr ScenarioTitleDescriptor ScenarioTitlesRealParks[] = { - { SC_ALTON_TOWERS, "Alton Towers", SCENARIO_CATEGORY_REAL, "rct1.scenario_text.alton_towers" }, - { SC_HEIDE_PARK, "Heide-Park", SCENARIO_CATEGORY_REAL, "rct1.scenario_text.heidepark" }, - { SC_BLACKPOOL_PLEASURE_BEACH, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL, "rct1.scenario_text.blackpool_pleasure_beach" }, + { SC_ALTON_TOWERS, "Alton Towers", SCENARIO_CATEGORY_REAL, "rct1ll.scenario_text.alton_towers" }, + { SC_HEIDE_PARK, "Heide-Park", SCENARIO_CATEGORY_REAL, "rct1ll.scenario_text.heidepark" }, + { SC_BLACKPOOL_PLEASURE_BEACH, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL, "rct1ll.scenario_text.blackpool_pleasure_beach" }, { SC_UNIDENTIFIED, "Six Flags Belgium", SCENARIO_CATEGORY_REAL, "rct2.scenario_text.six_flags_belgium" }, { SC_UNIDENTIFIED, "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL, "rct2.scenario_text.six_flags_great_adventure" }, { SC_UNIDENTIFIED, "Six Flags Holland", SCENARIO_CATEGORY_REAL, "rct2.scenario_text.six_flags_holland" }, @@ -315,11 +315,11 @@ namespace OpenRCT2::ScenarioSources // Other parks static constexpr ScenarioTitleDescriptor ScenarioTitlesExtrasParks[] = { - { SC_FORT_ANACHRONISM, "Fort Anachronism", SCENARIO_CATEGORY_DLC, "rct1.scenario_text.fort_anachronism" }, + { SC_FORT_ANACHRONISM, "Fort Anachronism", SCENARIO_CATEGORY_DLC, "rct1dlc.scenario_text.fort_anachronism" }, { SC_PCPLAYER, "PC Player", SCENARIO_CATEGORY_DLC, {} }, { SC_PCGW, "PC Gaming World", SCENARIO_CATEGORY_DLC, {} }, { SC_GAMEPLAY, "gameplay", SCENARIO_CATEGORY_DLC, {} }, - { SC_UNIDENTIFIED, "Panda World", SCENARIO_CATEGORY_DLC, "rct2.scenario_text.panda_world" }, + { SC_UNIDENTIFIED, "Panda World", SCENARIO_CATEGORY_DLC, "rct2dlc.scenario_text.panda_world" }, { SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_belgium" }, { SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_great_adventure" }, { SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_BUILD_YOUR_OWN, "rct2.scenario_text.build_your_own_six_flags_holland" }, @@ -425,17 +425,6 @@ namespace OpenRCT2::ScenarioSources u8string NormaliseName(u8string_view input) { - // American scenario titles should be converted to British name - // Don't worry, names will be translated using language packs later - for (const ScenarioAlias& alias : ScenarioAliases) - { - if (String::Equals(alias.Alternative, input)) - { - LOG_VERBOSE("Found alias: %s; will treat as: %s", input, alias.Original); - return u8string(alias.Original); - } - } - u8string normalisedName; // Strip "RCT(1|2)?" prefix off scenario names. if (input.starts_with("RCT")) @@ -456,6 +445,19 @@ namespace OpenRCT2::ScenarioSources } // Trim (for the sake of the above and WW / TT scenarios) - return String::TrimStart(normalisedName); + normalisedName = String::TrimStart(normalisedName); + + // American scenario titles should be converted to British name + // Don't worry, names will be translated using language packs later + for (const ScenarioAlias& alias : ScenarioAliases) + { + if (String::Equals(alias.Alternative, normalisedName)) + { + LOG_VERBOSE("Found alias: %s; will treat as: %s", normalisedName.c_str(), alias.Original); + return u8string(alias.Original); + } + } + + return normalisedName; } } // namespace OpenRCT2::ScenarioSources From 9be7b89d8f0581d9db12d4dc0708c2cf3af8e10e Mon Sep 17 00:00:00 2001 From: AuraSpecs Date: Sun, 3 Nov 2024 10:50:25 +0100 Subject: [PATCH 97/97] Quick patch for About screen (#23117) It seems there's a bigger issue going on atm. This fixes the problem for now, but when we add more names we will have to extend this more. Reason being that the it centers the text in the line, rather than extending it further downwards. I personally do not know how to fix that, but this should suffice for now. --- src/openrct2-ui/windows/About.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2-ui/windows/About.cpp b/src/openrct2-ui/windows/About.cpp index e03aab27f8..1ff71fe021 100644 --- a/src/openrct2-ui/windows/About.cpp +++ b/src/openrct2-ui/windows/About.cpp @@ -233,7 +233,7 @@ namespace OpenRCT2::Ui::Windows textCoords += ScreenCoordsXY( 0, DrawTextWrapped(dpi, textCoords, textWidth, STR_ABOUT_FAIRGROUND_ORGAN, ft2, tp) + 5); // Fairground organ textCoords += ScreenCoordsXY( - 0, DrawTextWrapped(dpi, textCoords, textWidth, STR_ABOUT_SPECIAL_THANKS_1, ft2, tp)); // Special Thanks + 0, DrawTextWrapped(dpi, textCoords, textWidth, STR_ABOUT_SPECIAL_THANKS_1, ft2, tp) + 7); // Special Thanks textCoords += ScreenCoordsXY( 0, DrawTextWrapped(dpi, textCoords, textWidth, STR_ABOUT_SPECIAL_THANKS_2, ft2, tp)); // Company names }