Merge pull request #7961 from IntelOrca/edge-objects-2

Add new object types: station, terrain edge and terrain surface
This commit is contained in:
Ted John 2018-12-10 01:18:56 +00:00 committed by GitHub
commit 4863b7c671
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 1233 additions and 824 deletions

View File

@ -21,8 +21,8 @@ set(CMAKE_MACOSX_RPATH 1)
set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip")
set(TITLE_SEQUENCE_SHA1 "1136ef92bfb05cd1cba9831ba6dc4a653d87a246")
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.6/objects.zip")
set(OBJECTS_SHA1 "61c70237814dc0f5aee5e9219f2ff232ea1a6111")
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.7/objects.zip")
set(OBJECTS_SHA1 "c9acbbd16c649d8a9fc308ee5b02ecb7f89c8565")
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
option(WITH_TESTS "Build tests")

View File

@ -72,6 +72,9 @@
93CBA4CC20A7504500867D56 /* ImageImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 93CBA4C820A7504500867D56 /* ImageImporter.h */; };
93DE9751209C3C1000FB1CC8 /* GameState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93DE974E209C3C0F00FB1CC8 /* GameState.cpp */; };
93DE9753209C3C1000FB1CC8 /* GameState.h in Headers */ = {isa = PBXBuildFile; fileRef = 93DE974F209C3C0F00FB1CC8 /* GameState.h */; };
93F6004C213DD7DD00EEB83E /* TerrainSurfaceObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F60049213DD7DC00EEB83E /* TerrainSurfaceObject.cpp */; };
93F6004D213DD7DD00EEB83E /* TerrainEdgeObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F6004A213DD7DC00EEB83E /* TerrainEdgeObject.cpp */; };
93F60050213DD7E400EEB83E /* StationObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F6004F213DD7E300EEB83E /* StationObject.cpp */; };
93F76EED20BFF6F900D4512C /* Drawing.Sprite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F76EEB20BFF6F900D4512C /* Drawing.Sprite.cpp */; };
93F76EEE20BFF6F900D4512C /* Drawing.String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F76EEC20BFF6F900D4512C /* Drawing.String.cpp */; };
93F76EF020BFF71700D4512C /* InteractiveConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F76EEF20BFF71700D4512C /* InteractiveConsole.cpp */; };
@ -1122,6 +1125,12 @@
93CBA4C820A7504500867D56 /* ImageImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageImporter.h; sourceTree = "<group>"; };
93DE974E209C3C0F00FB1CC8 /* GameState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameState.cpp; sourceTree = "<group>"; };
93DE974F209C3C0F00FB1CC8 /* GameState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameState.h; sourceTree = "<group>"; };
93F60048213DD7DC00EEB83E /* TerrainSurfaceObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TerrainSurfaceObject.h; sourceTree = "<group>"; };
93F60049213DD7DC00EEB83E /* TerrainSurfaceObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TerrainSurfaceObject.cpp; sourceTree = "<group>"; };
93F6004A213DD7DC00EEB83E /* TerrainEdgeObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TerrainEdgeObject.cpp; sourceTree = "<group>"; };
93F6004B213DD7DD00EEB83E /* TerrainEdgeObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TerrainEdgeObject.h; sourceTree = "<group>"; };
93F6004E213DD7E300EEB83E /* StationObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StationObject.h; sourceTree = "<group>"; };
93F6004F213DD7E300EEB83E /* StationObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StationObject.cpp; sourceTree = "<group>"; };
93F76EEB20BFF6F900D4512C /* Drawing.Sprite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Drawing.Sprite.cpp; sourceTree = "<group>"; };
93F76EEC20BFF6F900D4512C /* Drawing.String.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Drawing.String.cpp; sourceTree = "<group>"; };
93F76EEF20BFF71700D4512C /* InteractiveConsole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InteractiveConsole.cpp; sourceTree = "<group>"; };
@ -2645,8 +2654,14 @@
F76C842A1EC4E7CC00FA49E2 /* SceneryObject.h */,
F76C842B1EC4E7CC00FA49E2 /* SmallSceneryObject.cpp */,
F76C842C1EC4E7CC00FA49E2 /* SmallSceneryObject.h */,
93F6004F213DD7E300EEB83E /* StationObject.cpp */,
93F6004E213DD7E300EEB83E /* StationObject.h */,
F76C842F1EC4E7CC00FA49E2 /* StringTable.cpp */,
F76C84301EC4E7CC00FA49E2 /* StringTable.h */,
93F6004A213DD7DC00EEB83E /* TerrainEdgeObject.cpp */,
93F6004B213DD7DD00EEB83E /* TerrainEdgeObject.h */,
93F60049213DD7DC00EEB83E /* TerrainSurfaceObject.cpp */,
93F60048213DD7DC00EEB83E /* TerrainSurfaceObject.h */,
F76C84311EC4E7CC00FA49E2 /* WallObject.cpp */,
F76C84321EC4E7CC00FA49E2 /* WallObject.h */,
F76C84331EC4E7CC00FA49E2 /* WaterObject.cpp */,
@ -3432,7 +3447,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "version=\"1.0.6\"\nzipname=\"objects.zip\"\nliburl=\"https://github.com/OpenRCT2/objects/releases/download/v$version/$zipname\"\n\n[[ ! -d \"${SRCROOT}/data/object\" || ! -e \"${SRCROOT}/objectsversion\" || $(head -n 1 \"${SRCROOT}/objectsversion\") != $version ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]]; then\nif [[ -d \"${SRCROOT}/data/object\" ]]; then rm -r \"${SRCROOT}/data/object\"; fi\nmkdir -p \"${SRCROOT}/data/object\"\n\ncurl -L -o \"${SRCROOT}/data/object/$zipname\" \"$liburl\"\nunzip -uaq -d \"${SRCROOT}/data/object\" \"${SRCROOT}/data/object/$zipname\"\nrm \"${SRCROOT}/data/object/$zipname\"\n\necho $version > \"${SRCROOT}/objectsversion\"\nfi";
shellScript = "version=\"1.0.7\"\nzipname=\"objects.zip\"\nliburl=\"https://github.com/OpenRCT2/objects/releases/download/v$version/$zipname\"\n\n[[ ! -d \"${SRCROOT}/data/object\" || ! -e \"${SRCROOT}/objectsversion\" || $(head -n 1 \"${SRCROOT}/objectsversion\") != $version ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]]; then\nif [[ -d \"${SRCROOT}/data/object\" ]]; then rm -r \"${SRCROOT}/data/object\"; fi\nmkdir -p \"${SRCROOT}/data/object\"\n\ncurl -L -o \"${SRCROOT}/data/object/$zipname\" \"$liburl\"\nunzip -uaq -d \"${SRCROOT}/data/object\" \"${SRCROOT}/data/object/$zipname\"\nrm \"${SRCROOT}/data/object/$zipname\"\n\necho $version > \"${SRCROOT}/objectsversion\"\nfi";
};
C68B2D471EC790710020651C /* Download Libraries */ = {
isa = PBXShellScriptBuildPhase;
@ -3622,6 +3637,7 @@
93CBA4C420A7502E00867D56 /* Imaging.cpp in Sources */,
C6D2BEE61F9BAACE008B557C /* TrackList.cpp in Sources */,
C666EE701F37ACB10061AA04 /* LandRights.cpp in Sources */,
93F6004D213DD7DD00EEB83E /* TerrainEdgeObject.cpp in Sources */,
C666EE781F37ACB10061AA04 /* ServerList.cpp in Sources */,
C654DF341F69C0430040F43D /* NewCampaign.cpp in Sources */,
F76C887D1EC5324E00FA49E2 /* CursorData.cpp in Sources */,
@ -3640,6 +3656,7 @@
C68313D51FDB4F4C006DB3D8 /* Graph.cpp in Sources */,
C685E51D1F8907850090598F /* Research.cpp in Sources */,
C64644FB1F3FA4120026AC2D /* EditorScenarioOptions.cpp in Sources */,
93F60050213DD7E400EEB83E /* StationObject.cpp in Sources */,
C654DF321F69C0430040F43D /* InstallTrack.cpp in Sources */,
C64644FF1F3FA4120026AC2D /* StaffList.cpp in Sources */,
4C29DEB3218C6AE500E8707F /* RCT12.cpp in Sources */,
@ -3683,6 +3700,7 @@
C685E51A1F8907850090598F /* Staff.cpp in Sources */,
F76C888C1EC5324E00FA49E2 /* UiContext.cpp in Sources */,
C666EE7D1F37ACB10061AA04 /* TitleMenu.cpp in Sources */,
93F6004C213DD7DD00EEB83E /* TerrainSurfaceObject.cpp in Sources */,
933CBDB520CB1ACD00134678 /* Widget.cpp in Sources */,
9308D9FE209908090079EE96 /* TileElement.cpp in Sources */,
F76C888D1EC5324E00FA49E2 /* UiContext.Linux.cpp in Sources */,

View File

@ -2330,18 +2330,6 @@ STR_3074 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You hav
STR_3075 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have only 2 weeks to raise the park rating, or your park will be closed down
STR_3076 :{RED}FINAL WARNING: Your park rating is still below 700 !{NEWLINE}In just 7 days your park will be closed down unless you can raise the rating
STR_3077 :{RED}CLOSURE NOTICE: Your park has been closed down !
STR_3078 :Plain entrance
STR_3079 :Wooden entrance
STR_3080 :Canvas tent entrance
STR_3081 :Castle entrance (grey)
STR_3082 :Castle entrance (brown)
STR_3083 :Jungle entrance
STR_3084 :Log cabin entrance
STR_3085 :Classical/Roman entrance
STR_3086 :Abstract entrance
STR_3087 :Snow/Ice entrance
STR_3088 :Pagoda entrance
STR_3089 :Space entrance
STR_3090 :{SMALLFONT}{BLACK}Select style of entrance, exit, and station
STR_3091 :You are not allowed to remove this section!
STR_3092 :You are not allowed to move or modify the station for this ride!
@ -2989,7 +2977,6 @@ STR_5484 :{BLACK}({COMMA16} week remaining)
STR_5485 :{SMALLFONT}{STRING}
STR_5486 :{BLACK}{COMMA16}
STR_5487 :{SMALLFONT}{BLACK}Show recent messages
STR_5488 :No entrance (OpenRCT2 only!)
STR_5489 :{SMALLFONT}{BLACK}Show only tracked guests
STR_5490 :Disable audio on focus loss
STR_5491 :Inventions list
@ -3730,6 +3717,10 @@ STR_6266 :Open custom content folder
STR_6267 :Open tile inspector
STR_6268 :Advance to next tick
STR_6269 :Invalid climate ID
STR_6270 :Terrain Surfaces
STR_6271 :Terrain Edges
STR_6272 :Stations
STR_6273 :Music
#############
# Scenarios #

View File

@ -13,6 +13,7 @@
- Feature: [#8190] Allow building footpaths on 'corner down' terrain.
- Feature: [#8191] Allow building on-ride photos and water S-bends on the Water Coaster.
- Feature: [#8259] Add say command to in-game console.
- Change: [#7961] Add new object types: station, terrain surface, and terrain edge.
- Change: [#8222] The climate setting has been moved from objective options to scenario options.
- Fix: [#6191] OpenRCT2 fails to run when the path has an emoji in it.
- Fix: [#7439] Placement messages have mixed strings

View File

@ -70,8 +70,8 @@
<GtestSha1>058b9df80244c03f1633cb06e9f70471a29ebb8e</GtestSha1>
<TitleSequencesUrl>https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip</TitleSequencesUrl>
<TitleSequencesSha1>1136ef92bfb05cd1cba9831ba6dc4a653d87a246</TitleSequencesSha1>
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.0.6/objects.zip</ObjectsUrl>
<ObjectsSha1>61c70237814dc0f5aee5e9219f2ff232ea1a6111</ObjectsSha1>
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.0.7/objects.zip</ObjectsUrl>
<ObjectsSha1>c9acbbd16c649d8a9fc308ee5b02ecb7f89c8565</ObjectsSha1>
</PropertyGroup>
<ItemGroup>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 776 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

View File

@ -380,61 +380,6 @@
"x_offset": 0,
"y_offset": 15
},
{
"path": "edge/brick.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/rust.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/white_stucco.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/yellow_stucco.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/red_stucco.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/purple_stucco.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/green_stucco.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/brown_sandstone.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/grey_sandstone.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/skyscraper_a.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "edge/skyscraper_b.png",
"x_offset": 2,
"y_offset": 2
},
{
"path": "icons/eyedropper.png",
"x_offset": 5,

View File

@ -98,7 +98,7 @@ android.applicationVariants.all { variant ->
into "$variant.mergeAssets.outputDir/data/title"
}
download {
src 'https://github.com/OpenRCT2/objects/releases/download/v1.0.6/objects.zip'
src 'https://github.com/OpenRCT2/objects/releases/download/v1.0.7/objects.zip'
dest new File(buildDir, 'objects.zip')
}
copy {

View File

@ -11,11 +11,17 @@
#include <openrct2-ui/interface/LandTool.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/Context.h>
#include <openrct2/Input.h>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/object/TerrainEdgeObject.h>
#include <openrct2/object/TerrainSurfaceObject.h>
#include <openrct2/world/Map.h>
#include <openrct2/world/Surface.h>
using namespace OpenRCT2;
// clang-format off
static uint16_t toolSizeSpriteIndices[] =
{
@ -28,40 +34,6 @@ static uint16_t toolSizeSpriteIndices[] =
SPR_LAND_TOOL_SIZE_6,
SPR_LAND_TOOL_SIZE_7,
};
static uint32_t FloorTextureOrder[] =
{
TERRAIN_SAND_DARK, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_GRASS_CLUMPS, TERRAIN_GRASS,
TERRAIN_ROCK, TERRAIN_SAND, TERRAIN_MARTIAN, TERRAIN_CHECKERBOARD, TERRAIN_ICE,
TERRAIN_GRID_RED, TERRAIN_GRID_YELLOW, TERRAIN_GRID_BLUE, TERRAIN_GRID_GREEN
};
uint32_t WallTextureOrder[] =
{
TERRAIN_EDGE_ROCK, TERRAIN_EDGE_WOOD_RED, TERRAIN_EDGE_WOOD_BLACK, TERRAIN_EDGE_ICE, TERRAIN_EDGE_BRICK,
TERRAIN_EDGE_GREY, TERRAIN_EDGE_YELLOW, TERRAIN_EDGE_RED, TERRAIN_EDGE_PURPLE, TERRAIN_EDGE_GREEN,
TERRAIN_EDGE_IRON, TERRAIN_EDGE_STONE_BROWN, TERRAIN_EDGE_STONE_GREY, TERRAIN_EDGE_SKYSCRAPER_A, TERRAIN_EDGE_SKYSCRAPER_B,
0, 0
};
uint32_t WallTexturePreviews[] =
{
SPR_WALL_TEXTURE_ROCK,
SPR_WALL_TEXTURE_WOOD_RED,
SPR_WALL_TEXTURE_WOOD_BLACK,
SPR_WALL_TEXTURE_ICE,
SPR_G2_WALL_TEXTURE_BRICK,
SPR_G2_WALL_TEXTURE_IRON,
SPR_G2_WALL_TEXTURE_GREY,
SPR_G2_WALL_TEXTURE_YELLOW,
SPR_G2_WALL_TEXTURE_RED,
SPR_G2_WALL_TEXTURE_PURPLE,
SPR_G2_WALL_TEXTURE_GREEN,
SPR_G2_WALL_TEXTURE_STONE_BROWN,
SPR_G2_WALL_TEXTURE_STONE_GREY,
SPR_G2_WALL_TEXTURE_SKYSCRAPER_A,
SPR_G2_WALL_TEXTURE_SKYSCRAPER_B,
};
// clang-format on
uint16_t gLandToolSize;
@ -86,38 +58,58 @@ uint32_t land_tool_size_to_sprite_index(uint16_t size)
void land_tool_show_surface_style_dropdown(rct_window* w, rct_widget* widget, uint8_t currentSurfaceType)
{
uint8_t defaultIndex = 0;
auto& objManager = GetContext()->GetObjectManager();
for (uint8_t i = 0; i < TERRAIN_COUNT_REGULAR; i++)
auto defaultIndex = 0;
auto itemIndex = 0;
for (size_t i = 0; i < MAX_TERRAIN_SURFACE_OBJECTS; i++)
{
gDropdownItemsFormat[i] = DROPDOWN_FORMAT_LAND_PICKER;
gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + FloorTextureOrder[i];
if (FloorTextureOrder[i] == currentSurfaceType)
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_SURFACE, i));
if (surfaceObj != nullptr)
{
defaultIndex = i;
gDropdownItemsFormat[itemIndex] = DROPDOWN_FORMAT_LAND_PICKER;
gDropdownItemsArgs[itemIndex] = surfaceObj->IconImageId;
if (surfaceObj->Colour != 255)
{
gDropdownItemsArgs[itemIndex] |= surfaceObj->Colour << 19 | IMAGE_TYPE_REMAP;
}
if (i == currentSurfaceType)
{
defaultIndex = itemIndex;
}
itemIndex++;
}
}
auto surfaceCount = itemIndex;
window_dropdown_show_image(
w->x + widget->left, w->y + widget->top, widget->bottom - widget->top, w->colours[2], 0, TERRAIN_COUNT_REGULAR, 47, 36,
gAppropriateImageDropdownItemsPerRow[TERRAIN_COUNT_REGULAR]);
w->x + widget->left, w->y + widget->top, widget->bottom - widget->top, w->colours[2], 0, surfaceCount, 47, 36,
gAppropriateImageDropdownItemsPerRow[surfaceCount]);
gDropdownDefaultIndex = defaultIndex;
}
void land_tool_show_edge_style_dropdown(rct_window* w, rct_widget* widget, uint8_t currentEdgeType)
{
uint8_t defaultIndex = 0;
// Do not show RCT1 edge styles if the player does not have RCT1.
const uint8_t edgeCount = is_csg_loaded() ? TERRAIN_EDGE_COUNT : TERRAIN_EDGE_RCT2_COUNT;
auto& objManager = GetContext()->GetObjectManager();
for (uint8_t i = 0; i < edgeCount; i++)
auto defaultIndex = 0;
auto itemIndex = 0;
for (size_t i = 0; i < MAX_TERRAIN_EDGE_OBJECTS; i++)
{
gDropdownItemsFormat[i] = DROPDOWN_FORMAT_LAND_PICKER;
gDropdownItemsArgs[i] = WallTexturePreviews[WallTextureOrder[i]];
if (WallTextureOrder[i] == currentEdgeType)
defaultIndex = i;
const auto edgeObj = static_cast<TerrainEdgeObject*>(objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_EDGE, i));
if (edgeObj != nullptr)
{
gDropdownItemsFormat[itemIndex] = DROPDOWN_FORMAT_LAND_PICKER;
gDropdownItemsArgs[itemIndex] = edgeObj->IconImageId;
if (i == currentEdgeType)
{
defaultIndex = itemIndex;
}
itemIndex++;
}
}
auto edgeCount = itemIndex;
window_dropdown_show_image(
w->x + widget->left, w->y + widget->top, widget->bottom - widget->top, w->colours[2], 0, edgeCount, 47, 36,

View File

@ -26,9 +26,6 @@ extern uint8_t gLandToolTerrainEdge;
extern money32 gWaterToolRaiseCost;
extern money32 gWaterToolLowerCost;
extern uint32_t WallTextureOrder[];
extern uint32_t WallTexturePreviews[];
uint32_t land_tool_size_to_sprite_index(uint16_t size);
void land_tool_show_surface_style_dropdown(rct_window* w, rct_widget* widget, uint8_t currentSurfaceType);
void land_tool_show_edge_style_dropdown(rct_window* w, rct_widget* widget, uint8_t currentEdgeType);

View File

@ -86,7 +86,7 @@ struct ObjectPageDesc
bool IsAdvanced;
};
static constexpr const ObjectPageDesc ObjectSelectionPages[OBJECT_TYPE_COUNT] = {
static constexpr const ObjectPageDesc ObjectSelectionPages[] = {
{ STR_OBJECT_SELECTION_RIDE_VEHICLES_ATTRACTIONS, SPR_TAB_RIDE_16, false },
{ STR_OBJECT_SELECTION_SMALL_SCENERY, SPR_TAB_SCENERY_TREES, true },
{ STR_OBJECT_SELECTION_LARGE_SCENERY, SPR_TAB_SCENERY_URBAN, true },
@ -97,7 +97,15 @@ static constexpr const ObjectPageDesc ObjectSelectionPages[OBJECT_TYPE_COUNT] =
{ STR_OBJECT_SELECTION_SCENERY_GROUPS, SPR_TAB_SCENERY_STATUES, false },
{ STR_OBJECT_SELECTION_PARK_ENTRANCE, SPR_TAB_PARK, false },
{ STR_OBJECT_SELECTION_WATER, SPR_TAB_WATER, false },
{ STR_OBJECT_SELECTION_SCENARIO_DESCRIPTION, SPR_TAB_STATS, false },
// No longer supported:
// { STR_OBJECT_SELECTION_SCENARIO_DESCRIPTION, SPR_TAB_STATS, false },
// Currently hidden until new save format arrives:
// { STR_OBJECT_SELECTION_TERRAIN_SURFACES, SPR_G2_TAB_LAND, false },
// { STR_OBJECT_SELECTION_TERRAIN_EDGES, SPR_G2_TAB_LAND, false },
// { STR_OBJECT_SELECTION_STATIONS, SPR_TAB_PARK, false },
// { STR_OBJECT_SELECTION_MUSIC, SPR_TAB_MUSIC_0, false },
};
#pragma region Widgets
@ -778,7 +786,7 @@ static void window_editor_object_selection_scroll_mouseover(rct_window* w, int32
*/
static void window_editor_object_selection_tooltip(rct_window* w, rct_widgetindex widgetIndex, rct_string_id* stringId)
{
if (widgetIndex >= WIDX_TAB_1 && widgetIndex < WIDX_TAB_1 + OBJECT_TYPE_COUNT)
if (widgetIndex >= WIDX_TAB_1 && (size_t)widgetIndex < WIDX_TAB_1 + std::size(ObjectSelectionPages))
{
set_format_arg(0, rct_string_id, ObjectSelectionPages[(widgetIndex - WIDX_TAB_1)].Caption);
}
@ -838,7 +846,7 @@ static void window_editor_object_selection_invalidate(rct_window* w)
// Align tabs, hide advanced ones
bool advancedMode = (w->list_information_type & 1) != 0;
int32_t x = 3;
for (int32_t i = 0; i < OBJECT_TYPE_COUNT; i++)
for (size_t i = 0; i < std::size(ObjectSelectionPages); i++)
{
auto widget = &w->widgets[WIDX_TAB_1 + i];
if (!advancedMode && ObjectSelectionPages[i].IsAdvanced)
@ -945,14 +953,14 @@ static void window_editor_object_selection_invalidate(rct_window* w)
*/
static void window_editor_object_selection_paint(rct_window* w, rct_drawpixelinfo* dpi)
{
int32_t i, x, y, width;
int32_t x, y, width;
rct_widget* widget;
rct_string_id stringId;
window_draw_widgets(w, dpi);
// Draw tabs
for (i = 0; i < OBJECT_TYPE_COUNT; i++)
for (size_t i = 0; i < std::size(ObjectSelectionPages); i++)
{
widget = &w->widgets[WIDX_TAB_1 + i];
if (widget->type != WWT_EMPTY)
@ -973,7 +981,7 @@ static void window_editor_object_selection_paint(rct_window* w, rct_drawpixelinf
// Draw ride tabs
if (get_selected_object_type(w) == OBJECT_TYPE_RIDE)
{
for (i = 0; i < 7; i++)
for (int32_t i = 0; i < 7; i++)
{
widget = &w->widgets[WIDX_FILTER_RIDE_TAB_ALL + i];
if (widget->type == WWT_EMPTY)

View File

@ -15,9 +15,14 @@
#include <openrct2/Context.h>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/object/TerrainEdgeObject.h>
#include <openrct2/object/TerrainSurfaceObject.h>
#include <openrct2/world/Park.h>
#include <openrct2/world/Surface.h>
using namespace OpenRCT2;
// clang-format off
enum WINDOW_LAND_WIDGET_IDX {
WIDX_BACKGROUND,
@ -214,8 +219,7 @@ static void window_land_dropdown(rct_window* w, rct_widgetindex widgetIndex, int
if (dropdownIndex == -1)
dropdownIndex = gDropdownHighlightedIndex;
type = (dropdownIndex == -1) ? _selectedFloorTexture
: (uint32_t)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS;
type = (dropdownIndex == -1) ? _selectedFloorTexture : dropdownIndex;
if (gLandToolTerrainSurface == type)
{
@ -232,7 +236,7 @@ static void window_land_dropdown(rct_window* w, rct_widgetindex widgetIndex, int
if (dropdownIndex == -1)
dropdownIndex = gDropdownHighlightedIndex;
type = (dropdownIndex == -1) ? _selectedWallTexture : WallTextureOrder[dropdownIndex];
type = (dropdownIndex == -1) ? _selectedWallTexture : dropdownIndex;
if (gLandToolTerrainEdge == type)
{
@ -290,6 +294,27 @@ static void window_land_update(rct_window* w)
*/
static void window_land_invalidate(rct_window* w)
{
auto surfaceImage = (uint32_t)SPR_NONE;
auto edgeImage = (uint32_t)SPR_NONE;
auto& objManager = GetContext()->GetObjectManager();
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(
objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_SURFACE, _selectedFloorTexture));
if (surfaceObj != nullptr)
{
surfaceImage = surfaceObj->IconImageId;
if (surfaceObj->Colour != 255)
{
surfaceImage |= surfaceObj->Colour << 19 | IMAGE_TYPE_REMAP;
}
}
const auto edgeObj = static_cast<TerrainEdgeObject*>(
objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_EDGE, _selectedWallTexture));
if (edgeObj != nullptr)
{
edgeImage = edgeObj->IconImageId;
}
w->pressed_widgets = (1 << WIDX_PREVIEW);
if (gLandToolTerrainSurface != 255)
w->pressed_widgets |= (1 << WIDX_FLOOR);
@ -300,8 +325,8 @@ static void window_land_invalidate(rct_window* w)
if (gLandPaintMode)
w->pressed_widgets |= (1 << WIDX_PAINTMODE);
window_land_widgets[WIDX_FLOOR].image = SPR_FLOOR_TEXTURE_GRASS + _selectedFloorTexture;
window_land_widgets[WIDX_WALL].image = WallTexturePreviews[_selectedWallTexture];
window_land_widgets[WIDX_FLOOR].image = surfaceImage;
window_land_widgets[WIDX_WALL].image = edgeImage;
// Update the preview image (for tool sizes up to 7)
window_land_widgets[WIDX_PREVIEW].image = land_tool_size_to_sprite_index(gLandToolSize);
}
@ -349,7 +374,15 @@ static void window_land_paint(rct_window* w, rct_drawpixelinfo* dpi)
numTiles = gLandToolSize * gLandToolSize;
price = 0;
if (gLandToolTerrainSurface != 255)
price += numTiles * TerrainPricing[gLandToolTerrainSurface];
{
auto& objManager = GetContext()->GetObjectManager();
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(
objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_SURFACE, gLandToolTerrainSurface));
if (surfaceObj != nullptr)
{
price += numTiles * surfaceObj->Price;
}
}
if (gLandToolTerrainEdge != 255)
price += numTiles * 100;

View File

@ -16,11 +16,16 @@
#include <openrct2/Input.h>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/object/TerrainEdgeObject.h>
#include <openrct2/object/TerrainSurfaceObject.h>
#include <openrct2/util/Util.h>
#include <openrct2/windows/Intent.h>
#include <openrct2/world/MapGen.h>
#include <openrct2/world/Surface.h>
using namespace OpenRCT2;
// clang-format off
enum {
WINDOW_MAPGEN_PAGE_BASE,
@ -652,8 +657,7 @@ static void window_mapgen_base_dropdown(rct_window* w, rct_widgetindex widgetInd
if (dropdownIndex == -1)
dropdownIndex = gDropdownHighlightedIndex;
type = (dropdownIndex == -1) ? _floorTexture
: (uint32_t)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS;
type = (dropdownIndex == -1) ? _floorTexture : dropdownIndex;
if (gLandToolTerrainSurface == type)
{
@ -670,7 +674,7 @@ static void window_mapgen_base_dropdown(rct_window* w, rct_widgetindex widgetInd
if (dropdownIndex == -1)
dropdownIndex = gDropdownHighlightedIndex;
type = (dropdownIndex == -1) ? _wallTexture : WallTextureOrder[dropdownIndex];
type = (dropdownIndex == -1) ? _wallTexture : dropdownIndex;
if (gLandToolTerrainEdge == type)
{
@ -730,14 +734,34 @@ static void window_mapgen_textinput(rct_window* w, rct_widgetindex widgetIndex,
static void window_mapgen_base_invalidate(rct_window* w)
{
auto surfaceImage = (uint32_t)SPR_NONE;
auto edgeImage = (uint32_t)SPR_NONE;
auto& objManager = GetContext()->GetObjectManager();
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(
objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_SURFACE, _floorTexture));
if (surfaceObj != nullptr)
{
surfaceImage = surfaceObj->IconImageId;
if (surfaceObj->Colour != 255)
{
surfaceImage |= surfaceObj->Colour << 19 | IMAGE_TYPE_REMAP;
}
}
const auto edgeObj = static_cast<TerrainEdgeObject*>(objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_EDGE, _wallTexture));
if (edgeObj != nullptr)
{
edgeImage = edgeObj->IconImageId;
}
if (w->widgets != PageWidgets[WINDOW_MAPGEN_PAGE_BASE])
{
w->widgets = PageWidgets[WINDOW_MAPGEN_PAGE_BASE];
window_init_scroll_widgets(w);
}
w->widgets[WIDX_FLOOR_TEXTURE].image = SPR_FLOOR_TEXTURE_GRASS + _floorTexture;
w->widgets[WIDX_WALL_TEXTURE].image = WallTexturePreviews[_wallTexture];
w->widgets[WIDX_FLOOR_TEXTURE].image = surfaceImage;
w->widgets[WIDX_WALL_TEXTURE].image = edgeImage;
window_mapgen_set_pressed_tab(w);
}
@ -965,8 +989,7 @@ static void window_mapgen_simplex_dropdown(rct_window* w, rct_widgetindex widget
if (dropdownIndex == -1)
dropdownIndex = gDropdownHighlightedIndex;
type = (dropdownIndex == -1) ? _floorTexture
: (uint32_t)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS;
type = (dropdownIndex == -1) ? _floorTexture : dropdownIndex;
if (gLandToolTerrainSurface == type)
{
@ -983,7 +1006,7 @@ static void window_mapgen_simplex_dropdown(rct_window* w, rct_widgetindex widget
if (dropdownIndex == -1)
dropdownIndex = gDropdownHighlightedIndex;
type = (dropdownIndex == -1) ? _wallTexture : WallTextureOrder[dropdownIndex];
type = (dropdownIndex == -1) ? _wallTexture : dropdownIndex;
if (gLandToolTerrainEdge == type)
{
@ -1009,14 +1032,34 @@ static void window_mapgen_simplex_update(rct_window* w)
static void window_mapgen_simplex_invalidate(rct_window* w)
{
auto surfaceImage = (uint32_t)SPR_NONE;
auto edgeImage = (uint32_t)SPR_NONE;
auto& objManager = GetContext()->GetObjectManager();
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(
objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_SURFACE, _floorTexture));
if (surfaceObj != nullptr)
{
surfaceImage = surfaceObj->IconImageId;
if (surfaceObj->Colour != 255)
{
surfaceImage |= surfaceObj->Colour << 19 | IMAGE_TYPE_REMAP;
}
}
const auto edgeObj = static_cast<TerrainEdgeObject*>(objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_EDGE, _wallTexture));
if (edgeObj != nullptr)
{
edgeImage = edgeObj->IconImageId;
}
if (w->widgets != PageWidgets[WINDOW_MAPGEN_PAGE_SIMPLEX])
{
w->widgets = PageWidgets[WINDOW_MAPGEN_PAGE_SIMPLEX];
window_init_scroll_widgets(w);
}
w->widgets[WIDX_SIMPLEX_FLOOR_TEXTURE].image = SPR_FLOOR_TEXTURE_GRASS + _floorTexture;
w->widgets[WIDX_SIMPLEX_WALL_TEXTURE].image = WallTexturePreviews[_wallTexture];
w->widgets[WIDX_SIMPLEX_FLOOR_TEXTURE].image = surfaceImage;
w->widgets[WIDX_SIMPLEX_WALL_TEXTURE].image = edgeImage;
widget_set_checkbox_value(w, WIDX_SIMPLEX_RANDOM_TERRAIN_CHECKBOX, _randomTerrain != 0);
widget_set_checkbox_value(w, WIDX_SIMPLEX_PLACE_TREES_CHECKBOX, _placeTrees != 0);

View File

@ -31,6 +31,7 @@
#include <openrct2/network/network.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/object/ObjectRepository.h>
#include <openrct2/object/StationObject.h>
#include <openrct2/peep/Staff.h>
#include <openrct2/rct1/RCT1.h>
#include <openrct2/ride/RideData.h>
@ -44,6 +45,8 @@
#include <openrct2/windows/Intent.h>
#include <openrct2/world/Park.h>
using namespace OpenRCT2;
enum
{
WINDOW_RIDE_PAGE_MAIN,
@ -4225,14 +4228,6 @@ static void window_ride_maintenance_paint(rct_window* w, rct_drawpixelinfo* dpi)
#pragma region Colour
static constexpr const uint8_t window_ride_entrance_style_list[] = {
RIDE_ENTRANCE_STYLE_PLAIN, RIDE_ENTRANCE_STYLE_CANVAS_TENT, RIDE_ENTRANCE_STYLE_WOODEN,
RIDE_ENTRANCE_STYLE_CASTLE_BROWN, RIDE_ENTRANCE_STYLE_CASTLE_GREY, RIDE_ENTRANCE_STYLE_LOG_CABIN,
RIDE_ENTRANCE_STYLE_JUNGLE, RIDE_ENTRANCE_STYLE_CLASSICAL_ROMAN, RIDE_ENTRANCE_STYLE_ABSTRACT,
RIDE_ENTRANCE_STYLE_SNOW_ICE, RIDE_ENTRANCE_STYLE_PAGODA, RIDE_ENTRANCE_STYLE_SPACE,
RIDE_ENTRANCE_STYLE_NONE
};
static uint32_t window_ride_get_colour_button_image(int32_t colour)
{
return IMAGE_TYPE_TRANSPARENT | SPRITE_ID_PALETTE_COLOUR_1(colour) | SPR_PALETTE_BTN;
@ -4240,15 +4235,24 @@ static uint32_t window_ride_get_colour_button_image(int32_t colour)
static int32_t window_ride_has_track_colour(Ride* ride, int32_t trackColour)
{
uint16_t colourUse = RideEntranceDefinitions[ride->entrance_style].colour_use_flags;
// Get station flags (shops don't have them)
auto stationObjFlags = 0;
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
{
auto stationObj = ride_get_station_object(ride);
if (stationObj != nullptr)
{
stationObjFlags = stationObj->Flags;
}
}
switch (trackColour)
{
case 0:
return ((colourUse & 1) && !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
return (stationObjFlags & STATION_OBJECT_FLAGS::HAS_PRIMARY_COLOUR)
|| ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN);
case 1:
return ((colourUse & 2) && !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
return (stationObjFlags & STATION_OBJECT_FLAGS::HAS_SECONDARY_COLOUR)
|| ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_ADDITIONAL);
case 2:
return ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS);
@ -4352,7 +4356,7 @@ static void window_ride_colour_mousedown(rct_window* w, rct_widgetindex widgetIn
vehicle_colour vehicleColour;
rct_widget* dropdownWidget;
rct_ride_entry* rideEntry;
int32_t i, numItems, checkedIndex;
int32_t i, numItems;
rct_string_id stringId;
ride = get_ride(w->number);
@ -4398,28 +4402,29 @@ static void window_ride_colour_mousedown(rct_window* w, rct_widgetindex widgetIn
dropdown_set_checked(ride->track_colour_supports[colourSchemeIndex], true);
break;
case WIDX_ENTRANCE_STYLE_DROPDOWN:
checkedIndex = -1;
for (i = 0; i < (int32_t)std::size(window_ride_entrance_style_list); i++)
{
auto ddIndex = 0;
auto& objManager = GetContext()->GetObjectManager();
for (i = 0; i < MAX_STATION_OBJECTS; i++)
{
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = RideEntranceDefinitions[window_ride_entrance_style_list[i]].string_id;
if (ride->entrance_style == window_ride_entrance_style_list[i])
auto stationObj = static_cast<StationObject*>(objManager.GetLoadedObject(OBJECT_TYPE_STATION, i));
if (stationObj != nullptr)
{
checkedIndex = i;
gDropdownItemsFormat[ddIndex] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[ddIndex] = stationObj->NameStringId;
if (ride->entrance_style == i)
{
gDropdownItemsFormat[ddIndex] = STR_DROPDOWN_MENU_LABEL_SELECTED;
}
ddIndex++;
}
}
window_dropdown_show_text_custom_width(
w->x + dropdownWidget->left, w->y + dropdownWidget->top, dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, std::size(window_ride_entrance_style_list),
widget->right - dropdownWidget->left);
if (checkedIndex != -1)
{
dropdown_set_checked(checkedIndex, true);
}
w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, ddIndex, widget->right - dropdownWidget->left);
break;
}
case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN:
for (i = 0; i < 3; i++)
{
@ -4502,10 +4507,24 @@ static void window_ride_colour_dropdown(rct_window* w, rct_widgetindex widgetInd
0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0);
break;
case WIDX_ENTRANCE_STYLE_DROPDOWN:
game_do_command(
0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number,
GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
{
auto ddIndex = 0;
auto& objManager = GetContext()->GetObjectManager();
for (auto i = 0; i < MAX_STATION_OBJECTS; i++)
{
auto stationObj = static_cast<StationObject*>(objManager.GetLoadedObject(OBJECT_TYPE_STATION, i));
if (stationObj != nullptr)
{
if (ddIndex == dropdownIndex)
{
game_do_command(0, (6 << 8) | 1, 0, (ddIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
break;
}
ddIndex++;
}
}
break;
}
case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN:
game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
w->vehicleIndex = 0;
@ -4669,7 +4688,13 @@ static void window_ride_colour_invalidate(rct_window* w)
window_ride_colour_widgets[WIDX_ENTRANCE_STYLE].type = WWT_DROPDOWN;
window_ride_colour_widgets[WIDX_ENTRANCE_STYLE_DROPDOWN].type = WWT_BUTTON;
window_ride_colour_widgets[WIDX_ENTRANCE_STYLE].text = RideEntranceDefinitions[ride->entrance_style].string_id;
auto stringId = STR_NONE;
auto stationObj = ride_get_station_object(ride);
if (stationObj != nullptr)
{
stringId = stationObj->NameStringId;
}
window_ride_colour_widgets[WIDX_ENTRANCE_STYLE].text = stringId;
}
else
{
@ -4861,18 +4886,17 @@ static void window_ride_colour_paint(rct_window* w, rct_drawpixelinfo* dpi)
{
gfx_clear(&clippedDpi, PALETTE_INDEX_12);
if (ride->entrance_style != RIDE_ENTRANCE_STYLE_NONE)
auto stationObj = ride_get_station_object(ride);
if (stationObj != nullptr && stationObj->BaseImageId != 0)
{
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
int32_t terniaryColour = 0;
if (entranceStyle->base_image_id & IMAGE_TYPE_TRANSPARENT)
if (stationObj->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT)
{
terniaryColour = IMAGE_TYPE_TRANSPARENT | (GlassPaletteIds[trackColour.main] << 19);
}
int32_t spriteIndex = SPRITE_ID_PALETTE_COLOUR_2(trackColour.main, trackColour.additional);
spriteIndex += RideEntranceDefinitions[ride->entrance_style].sprite_index;
spriteIndex += stationObj->BaseImageId;
// Back
gfx_draw_sprite(&clippedDpi, spriteIndex, 34, 20, terniaryColour);

View File

@ -19,8 +19,10 @@
#include "audio/audio.h"
#include "interface/Viewport.h"
#include "localisation/Localisation.h"
#include "localisation/LocalisationService.h"
#include "management/NewsItem.h"
#include "object/ObjectManager.h"
#include "object/ObjectRepository.h"
#include "peep/Staff.h"
#include "rct1/RCT1.h"
#include "scenario/Scenario.h"
@ -52,6 +54,20 @@ namespace Editor
static bool ReadS6(const char* path);
static void ClearMapForEditing(bool fromSave);
static void object_list_load()
{
// Scan objects if necessary
auto context = GetContext();
const auto& localisationService = context->GetLocalisationService();
auto& objectRepository = context->GetObjectRepository();
objectRepository.LoadOrConstruct(localisationService.GetCurrentLanguage());
// Reset loaded objects to just defaults
auto& objectManager = context->GetObjectManager();
objectManager.UnloadAll();
objectManager.LoadDefaultObjects();
}
/**
*
* rct2: 0x0066FFE1

View File

@ -105,12 +105,16 @@ static void setup_track_designer_objects()
*/
void setup_in_use_selection_flags()
{
auto& objectMgr = OpenRCT2::GetContext()->GetObjectManager();
for (uint8_t objectType = 0; objectType < OBJECT_TYPE_COUNT; objectType++)
{
for (int32_t i = 0; i < object_entry_group_counts[objectType]; i++)
{
Editor::ClearSelectedObject(objectType, i, OBJECT_SELECTION_FLAG_ALL);
if (object_entry_get_chunk(objectType, i) != nullptr)
auto loadedObj = objectMgr.GetLoadedObject(objectType, i);
if (loadedObj != nullptr)
{
Editor::SetSelectedObject(objectType, i, OBJECT_SELECTION_FLAG_2);
}

View File

@ -295,7 +295,7 @@ public:
ride->income_per_hour = MONEY32_UNDEFINED;
ride->profit = MONEY32_UNDEFINED;
ride->connected_message_throttle = 0;
ride->entrance_style = RIDE_ENTRANCE_STYLE_PLAIN;
ride->entrance_style = 0;
ride->num_block_brakes = 0;
ride->guests_favourite = 0;

View File

@ -128,7 +128,7 @@ static void read_and_convert_gxdat(IStream* stream, size_t count, bool is_rctc,
if (src.flags & G1_FLAG_HAS_ZOOM_SPRITE)
{
elements[i].zoomed_offset = (uint16_t)(i - rctc_to_rct2_index(rctc - src.zoomed_offset));
elements[i].zoomed_offset = (int32_t)(i - rctc_to_rct2_index(rctc - src.zoomed_offset));
}
else
{
@ -379,9 +379,9 @@ bool gfx_load_csg()
{
_csg.elements[i].offset += (uintptr_t)_csg.data;
// RCT1 used zoomed offsets that counted from the beginning of the file, rather than from the current sprite.
if (_csg.elements[i].zoomed_offset != 0)
if (_csg.elements[i].flags & G1_FLAG_HAS_ZOOM_SPRITE)
{
_csg.elements[i].zoomed_offset = i - (SPR_CSG_BEGIN + _csg.elements[i].zoomed_offset);
_csg.elements[i].zoomed_offset = i - _csg.elements[i].zoomed_offset;
}
}
_csgLoaded = true;

View File

@ -20,13 +20,13 @@ namespace OpenRCT2
struct rct_g1_element
{
uint8_t* offset; // 0x00
int16_t width; // 0x04
int16_t height; // 0x06
int16_t x_offset; // 0x08
int16_t y_offset; // 0x0A
uint16_t flags; // 0x0C
uint16_t zoomed_offset; // 0x0E
uint8_t* offset; // 0x00
int16_t width; // 0x04
int16_t height; // 0x06
int16_t x_offset; // 0x08
int16_t y_offset; // 0x0A
uint16_t flags; // 0x0C
int32_t zoomed_offset; // 0x0E
};
struct rct_drawpixelinfo

View File

@ -556,7 +556,7 @@ enum
STR_SELECT_VEHICLE_COLOUR_SCHEME_TIP = 1140,
STR_SELECT_VEHICLE_TO_MODIFY_TIP = 1141,
STR_DROPDOWN_MENU_LABEL = 1142,
// STR_1143 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRINGID}
STR_DROPDOWN_MENU_LABEL_SELECTED = 1143,
STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION = 1144,
STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION = 1145,
STR_ENTRANCE_NOT_YET_BUILT = 1146,
@ -2413,18 +2413,6 @@ enum
STR_PARK_RATING_WARNING_2_WEEKS_REMAINING = 3075,
STR_PARK_RATING_WARNING_1_WEEK_REMAINING = 3076,
STR_PARK_HAS_BEEN_CLOSED_DOWN = 3077,
STR_PLAIN_ENTRANCE = 3078,
STR_WOODEN_ENTRANCE = 3079,
STR_CANVAS_TENT_ENTRANCE = 3080,
STR_CASTLE_ENTRANCE_GREY = 3081,
STR_CASTLE_ENTRANCE_BROWN = 3082,
STR_JUNGLE_ENTRANCE = 3083,
STR_LOG_CABIN_ENTRANCE = 3084,
STR_CLASSICAL_ROMAN_ENTRANCE = 3085,
STR_ABSTRACT_ENTRANCE = 3086,
STR_SNOW_ICE_ENTRANCE = 3087,
STR_PAGODA_ENTRANCE = 3088,
STR_SPACE_ENTRANCE = 3089,
STR_SELECT_STYLE_OF_ENTRANCE_EXIT_STATION_TIP = 3090,
STR_YOU_ARE_NOT_ALLOWED_TO_REMOVE_THIS_SECTION = 3091,
STR_NOT_ALLOWED_TO_MODIFY_STATION = 3092,
@ -3084,7 +3072,6 @@ enum
STR_BOTTOM_TOOLBAR_NEWS_TEXT = 5485,
STR_LAND_TOOL_SIZE_VALUE = 5486,
STR_SHOW_RECENT_MESSAGES_TIP = 5487,
STR_ENTRANCE_NONE = 5488,
STR_TRACKED_GUESTS_ONLY_TIP = 5489,
STR_AUDIO_FOCUS = 5490,
STR_DEBUG_DROPDOWN_INVENTIONS_LIST = 5491,
@ -3899,6 +3886,11 @@ enum
STR_INVALID_CLIMATE_ID = 6269,
STR_OBJECT_SELECTION_TERRAIN_SURFACES = 6270,
STR_OBJECT_SELECTION_TERRAIN_EDGES = 6271,
STR_OBJECT_SELECTION_STATIONS = 6272,
STR_OBJECT_SELECTION_MUSIC = 6273,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@ -16,6 +16,7 @@
#include "ObjectLimits.h"
#include <algorithm>
#include <stdexcept>
Object::Object(const rct_object_entry& entry)
{
@ -36,6 +37,16 @@ Object::~Object()
Memory::Free(_identifier);
}
void* Object::GetLegacyData()
{
throw std::runtime_error("Not supported.");
}
void Object::ReadLegacy(IReadObjectContext* context, IStream* stream)
{
throw std::runtime_error("Not supported.");
}
std::string Object::GetOverrideString(uint8_t index) const
{
const char* identifier = GetIdentifier();

View File

@ -30,6 +30,10 @@ enum OBJECT_TYPE
OBJECT_TYPE_PARK_ENTRANCE,
OBJECT_TYPE_WATER,
OBJECT_TYPE_SCENARIO_TEXT,
OBJECT_TYPE_TERRAIN_SURFACE,
OBJECT_TYPE_TERRAIN_EDGE,
OBJECT_TYPE_STATION,
OBJECT_TYPE_MUSIC,
OBJECT_TYPE_COUNT
};
@ -192,12 +196,12 @@ public:
{
return &_objectEntry;
}
virtual void* GetLegacyData() abstract;
virtual void* GetLegacyData();
virtual void ReadJson(IReadObjectContext* /*context*/, const json_t* /*root*/)
{
}
virtual void ReadLegacy(IReadObjectContext* context, IStream* stream) abstract;
virtual void ReadLegacy(IReadObjectContext* context, IStream* stream);
virtual void Load() abstract;
virtual void Unload() abstract;
@ -245,8 +249,6 @@ enum OBJECT_ERROR : uint32_t
extern int32_t object_entry_group_counts[];
extern int32_t object_entry_group_encoding[];
void object_list_load();
bool object_entry_is_empty(const rct_object_entry* entry);
bool object_entry_compare(const rct_object_entry* a, const rct_object_entry* b);
int32_t object_calculate_checksum(const rct_object_entry* entry, const void* data, size_t dataLength);

View File

@ -31,6 +31,9 @@
#include "RideObject.h"
#include "SceneryGroupObject.h"
#include "SmallSceneryObject.h"
#include "StationObject.h"
#include "TerrainEdgeObject.h"
#include "TerrainSurfaceObject.h"
#include "WallObject.h"
#include "WaterObject.h"
@ -298,6 +301,15 @@ namespace ObjectFactory
case OBJECT_TYPE_SCENARIO_TEXT:
result = nullptr;
break;
case OBJECT_TYPE_TERRAIN_SURFACE:
result = new TerrainSurfaceObject(entry);
break;
case OBJECT_TYPE_TERRAIN_EDGE:
result = new TerrainEdgeObject(entry);
break;
case OBJECT_TYPE_STATION:
result = new StationObject(entry);
break;
default:
throw std::runtime_error("Invalid object type");
}
@ -326,6 +338,12 @@ namespace ObjectFactory
return OBJECT_TYPE_PARK_ENTRANCE;
if (s == "water")
return OBJECT_TYPE_WATER;
if (s == "terrain_surface")
return OBJECT_TYPE_TERRAIN_SURFACE;
if (s == "terrain_edge")
return OBJECT_TYPE_TERRAIN_EDGE;
if (s == "station")
return OBJECT_TYPE_STATION;
return 0xFF;
}

View File

@ -35,6 +35,59 @@ using namespace OpenRCT2::Drawing;
namespace ObjectJsonHelpers
{
/**
* Container for a G1 image, additional information and RAII.
*/
struct RequiredImage
{
rct_g1_element g1{};
std::unique_ptr<RequiredImage> next_zoom;
bool HasData() const
{
return g1.offset != nullptr;
}
RequiredImage() = default;
RequiredImage(const RequiredImage&) = delete;
RequiredImage(const rct_g1_element& orig)
{
auto length = g1_calculate_data_size(&orig);
g1 = orig;
g1.offset = (uint8_t*)std::malloc(length);
std::memcpy(g1.offset, orig.offset, length);
g1.flags &= ~G1_FLAG_HAS_ZOOM_SPRITE;
}
RequiredImage(uint32_t idx, std::function<const rct_g1_element*(uint32_t)> getter)
{
auto orig = getter(idx);
if (orig != nullptr)
{
auto length = g1_calculate_data_size(orig);
g1 = *orig;
g1.offset = (uint8_t*)std::malloc(length);
std::memcpy(g1.offset, orig->offset, length);
if (g1.flags & G1_FLAG_HAS_ZOOM_SPRITE)
{
// Fetch image for next zoom level
next_zoom = std::make_unique<RequiredImage>((uint32_t)(idx - g1.zoomed_offset), getter);
if (!next_zoom->HasData())
{
next_zoom = nullptr;
g1.flags &= ~G1_FLAG_HAS_ZOOM_SPRITE;
}
}
}
}
~RequiredImage()
{
std::free(g1.offset);
}
};
bool GetBoolean(const json_t* obj, const std::string& name, bool defaultValue)
{
auto value = json_object_get(obj, name.c_str());
@ -112,6 +165,46 @@ namespace ObjectJsonHelpers
return result;
}
colour_t ParseColour(const std::string_view& s, colour_t defaultValue)
{
static const std::unordered_map<std::string_view, colour_t> LookupTable{
{ "black", COLOUR_BLACK },
{ "grey", COLOUR_GREY },
{ "white", COLOUR_WHITE },
{ "dark_purple", COLOUR_DARK_PURPLE },
{ "light_purple", COLOUR_LIGHT_PURPLE },
{ "bright_purple", COLOUR_BRIGHT_PURPLE },
{ "dark_blue", COLOUR_DARK_BLUE },
{ "light_blue", COLOUR_LIGHT_BLUE },
{ "icy_blue", COLOUR_ICY_BLUE },
{ "teal", COLOUR_TEAL },
{ "aquamarine", COLOUR_AQUAMARINE },
{ "saturated_green", COLOUR_SATURATED_GREEN },
{ "dark_green", COLOUR_DARK_GREEN },
{ "moss_green", COLOUR_MOSS_GREEN },
{ "bright_green", COLOUR_BRIGHT_GREEN },
{ "olive_green", COLOUR_OLIVE_GREEN },
{ "dark_olive_green", COLOUR_DARK_OLIVE_GREEN },
{ "bright_yellow", COLOUR_BRIGHT_YELLOW },
{ "yellow", COLOUR_YELLOW },
{ "dark_yellow", COLOUR_DARK_YELLOW },
{ "light_orange", COLOUR_LIGHT_ORANGE },
{ "dark_orange", COLOUR_DARK_ORANGE },
{ "light_brown", COLOUR_LIGHT_BROWN },
{ "saturated_brown", COLOUR_SATURATED_BROWN },
{ "dark_brown", COLOUR_DARK_BROWN },
{ "salmon_pink", COLOUR_SALMON_PINK },
{ "bordeaux_red", COLOUR_BORDEAUX_RED },
{ "saturated_red", COLOUR_SATURATED_RED },
{ "bright_red", COLOUR_BRIGHT_RED },
{ "dark_pink", COLOUR_DARK_PINK },
{ "bright_pink", COLOUR_BRIGHT_PINK },
{ "light_pink", COLOUR_LIGHT_PINK },
};
auto result = LookupTable.find(s);
return (result != LookupTable.end()) ? result->second : defaultValue;
}
uint8_t ParseCursor(const std::string& s, uint8_t defaultValue)
{
static const std::unordered_map<std::string, uint8_t> LookupTable{
@ -215,10 +308,10 @@ namespace ObjectJsonHelpers
return objectPath;
}
static std::vector<rct_g1_element> LoadObjectImages(
static std::vector<std::unique_ptr<RequiredImage>> LoadObjectImages(
IReadObjectContext* context, const std::string& name, const std::vector<int32_t>& range)
{
std::vector<rct_g1_element> result;
std::vector<std::unique_ptr<RequiredImage>> result;
auto objectPath = FindLegacyObject(name);
auto obj = ObjectFactory::CreateObjectFromLegacyFile(context->GetObjectRepository(), objectPath.c_str());
if (obj != nullptr)
@ -231,17 +324,12 @@ namespace ObjectJsonHelpers
{
if (i >= 0 && i < numImages)
{
auto& objg1 = images[i];
auto length = g1_calculate_data_size(&objg1);
auto g1 = objg1;
g1.offset = (uint8_t*)std::malloc(length);
std::memcpy(g1.offset, objg1.offset, length);
result.push_back(g1);
result.push_back(std::make_unique<RequiredImage>(
(uint32_t)(i), [images](uint32_t idx) -> const rct_g1_element* { return &images[idx]; }));
}
else
{
auto g1 = rct_g1_element{};
result.push_back(g1);
result.push_back(std::make_unique<RequiredImage>());
placeHoldersAdded++;
}
}
@ -258,18 +346,20 @@ namespace ObjectJsonHelpers
{
std::string msg = "Unable to open '" + objectPath + "'";
context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, msg.c_str());
result.resize(range.size());
for (size_t i = 0; i < range.size(); i++)
{
result.push_back(std::make_unique<RequiredImage>());
}
}
return result;
}
static std::vector<rct_g1_element> ParseImages(IReadObjectContext* context, std::string s)
static std::vector<std::unique_ptr<RequiredImage>> ParseImages(IReadObjectContext* context, std::string s)
{
std::vector<rct_g1_element> result;
std::vector<std::unique_ptr<RequiredImage>> result;
if (s.empty())
{
rct_g1_element emptyg1 = {};
result.push_back(emptyg1);
result.push_back(std::make_unique<RequiredImage>());
}
else if (String::StartsWith(s, "$CSG"))
{
@ -280,12 +370,9 @@ namespace ObjectJsonHelpers
{
for (auto i : range)
{
auto& csg1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i);
auto length = g1_calculate_data_size(&csg1);
auto g1 = csg1;
g1.offset = (uint8_t*)std::malloc(length);
std::memcpy(g1.offset, csg1.offset, length);
result.push_back(g1);
result.push_back(std::make_unique<RequiredImage>(
(uint32_t)(SPR_CSG_BEGIN + i),
[](uint32_t idx) -> const rct_g1_element* { return gfx_get_g1_element(idx); }));
}
}
}
@ -297,20 +384,8 @@ namespace ObjectJsonHelpers
{
for (auto i : range)
{
auto og1 = gfx_get_g1_element(i);
if (og1 == nullptr)
{
rct_g1_element g1{};
result.push_back(g1);
}
else
{
auto length = g1_calculate_data_size(og1);
auto g1 = *og1;
g1.offset = (uint8_t*)std::malloc(length);
std::memcpy(g1.offset, og1->offset, length);
result.push_back(g1);
}
result.push_back(std::make_unique<RequiredImage>(
(uint32_t)(i), [](uint32_t idx) -> const rct_g1_element* { return gfx_get_g1_element(idx); }));
}
}
}
@ -336,28 +411,27 @@ namespace ObjectJsonHelpers
ImageImporter importer;
auto importResult = importer.Import(image, 0, 0, ImageImporter::IMPORT_FLAGS::RLE);
result.push_back(importResult.Element);
result.push_back(std::make_unique<RequiredImage>(importResult.Element));
std::free(importResult.Buffer);
}
catch (const std::exception& e)
{
auto msg = String::StdFormat("Unable to load image '%s': %s", s.c_str(), e.what());
context->LogWarning(OBJECT_ERROR_BAD_IMAGE_TABLE, msg.c_str());
rct_g1_element emptyg1 = {};
result.push_back(emptyg1);
result.push_back(std::make_unique<RequiredImage>());
}
}
return result;
}
static std::vector<rct_g1_element> ParseImages(IReadObjectContext* context, json_t* el)
static std::vector<std::unique_ptr<RequiredImage>> ParseImages(IReadObjectContext* context, json_t* el)
{
auto path = GetString(el, "path");
auto x = GetInteger(el, "x");
auto y = GetInteger(el, "y");
auto raw = (GetString(el, "format") == "raw");
std::vector<rct_g1_element> result;
std::vector<std::unique_ptr<RequiredImage>> result;
try
{
auto flags = ImageImporter::IMPORT_FLAGS::NONE;
@ -373,15 +447,14 @@ namespace ObjectJsonHelpers
auto g1Element = importResult.Element;
g1Element.x_offset = x;
g1Element.y_offset = y;
result.push_back(g1Element);
result.push_back(std::make_unique<RequiredImage>(g1Element));
std::free(importResult.Buffer);
}
catch (const std::exception& e)
{
auto msg = String::StdFormat("Unable to load image '%s': %s", path.c_str(), e.what());
context->LogWarning(OBJECT_ERROR_BAD_IMAGE_TABLE, msg.c_str());
rct_g1_element emptyg1 = {};
result.push_back(emptyg1);
result.push_back(std::make_unique<RequiredImage>());
}
return result;
}
@ -434,7 +507,7 @@ namespace ObjectJsonHelpers
json_t* el;
json_array_foreach(jsonImages, i, el)
{
std::vector<rct_g1_element> images;
std::vector<std::unique_ptr<RequiredImage>> images;
if (json_is_string(el))
{
auto s = json_string_value(el);
@ -444,10 +517,38 @@ namespace ObjectJsonHelpers
{
images = ParseImages(context, el);
}
for (const auto& g1 : images)
auto imagesStartIndex = imageTable.GetCount();
for (const auto& img : images)
{
const auto& g1 = img->g1;
imageTable.AddImage(&g1);
std::free(g1.offset);
}
// Add zoom images here
for (size_t j = 0; j < images.size(); j++)
{
const auto tableIndex = imagesStartIndex + j;
const auto* img = images[j].get();
if (img->next_zoom != nullptr)
{
img = img->next_zoom.get();
// Set old image zoom offset to zoom image which we are about to add
auto g1a = (rct_g1_element*)(&imageTable.GetImages()[tableIndex]);
g1a->zoomed_offset = (int32_t)tableIndex - (int32_t)imageTable.GetCount();
while (img != nullptr)
{
auto g1b = img->g1;
if (img->next_zoom != nullptr)
{
g1b.zoomed_offset = -1;
}
imageTable.AddImage(&g1b);
img = img->next_zoom.get();
}
}
}
}
}

View File

@ -12,6 +12,7 @@
#include "../common.h"
#include "../core/Json.hpp"
#include "../drawing/Drawing.h"
#include "../interface/Colour.h"
#include "../object/Object.h"
#include "ImageTable.h"
#include "StringTable.h"
@ -30,6 +31,7 @@ namespace ObjectJsonHelpers
float GetFloat(const json_t* obj, const std::string& name, const float& defaultValue = 0);
std::vector<std::string> GetJsonStringArray(const json_t* arr);
std::vector<int32_t> GetJsonIntegerArray(const json_t* arr);
colour_t ParseColour(const std::string_view& s, colour_t defaultValue = COLOUR_BLACK);
uint8_t ParseCursor(const std::string& s, uint8_t defaultValue);
rct_object_entry ParseObjectEntry(const std::string& s);
void LoadStrings(const json_t* root, StringTable& stringTable);
@ -37,12 +39,12 @@ namespace ObjectJsonHelpers
template<typename T> static T GetFlags(const json_t* obj, std::initializer_list<std::pair<std::string, T>> list)
{
T flags = 0;
T flags{};
for (const auto& item : list)
{
if (GetBoolean(obj, item.first))
{
flags |= item.second;
flags = (T)(flags | item.second);
}
}
return flags;

View File

@ -20,5 +20,9 @@
#define MAX_PARK_ENTRANCE_OBJECTS 1
#define MAX_WATER_OBJECTS 1
#define MAX_SCENARIO_TEXT_OBJECTS 1
#define MAX_TERRAIN_SURFACE_OBJECTS 14
#define MAX_TERRAIN_EDGE_OBJECTS 255
#define MAX_STATION_OBJECTS 255
#define MAX_MUSIC_OBJECTS 0
#define DAT_NAME_LENGTH 8

View File

@ -33,7 +33,11 @@ int32_t object_entry_group_counts[] = {
MAX_SCENERY_GROUP_OBJECTS, // scenery sets
MAX_PARK_ENTRANCE_OBJECTS, // park entrance
MAX_WATER_OBJECTS, // water
MAX_SCENARIO_TEXT_OBJECTS // scenario text
MAX_SCENARIO_TEXT_OBJECTS, // scenario text
MAX_TERRAIN_SURFACE_OBJECTS,
MAX_TERRAIN_EDGE_OBJECTS,
MAX_STATION_OBJECTS,
MAX_MUSIC_OBJECTS,
};
// 98DA2C
@ -98,10 +102,12 @@ bool find_object_in_entry_group(const rct_object_entry* entry, uint8_t* entry_ty
return false;
}
auto& objectMgr = OpenRCT2::GetContext()->GetObjectManager();
auto maxObjects = object_entry_group_counts[objectType];
for (int32_t i = 0; i < maxObjects; i++)
{
if (object_entry_get_chunk(objectType, i) != nullptr)
auto loadedObj = objectMgr.GetLoadedObject(objectType, i);
if (loadedObj != nullptr)
{
auto thisEntry = object_entry_get_entry(objectType, i);
if (object_entry_compare(thisEntry, entry))

View File

@ -214,6 +214,54 @@ public:
{
// We currently will load new object types here that apply to all
// loaded RCT1 and RCT2 save files.
// Surfaces
LoadObject("#RCT2SGR");
LoadObject("#RCT2SSY");
LoadObject("#RCT2SDI");
LoadObject("#RCT2SRO");
LoadObject("#RCT2SMA");
LoadObject("#RCT2SCH");
LoadObject("#RCT2SGC");
LoadObject("#RCT2SIC");
LoadObject("#RCT2SIR");
LoadObject("#RCT2SIY");
LoadObject("#RCT2SIP");
LoadObject("#RCT2SIG");
LoadObject("#RCT2SSR");
LoadObject("#RCT2SSA");
// Edges
LoadObject("#RCT2ERO");
LoadObject("#RCT2EWR");
LoadObject("#RCT2EWB");
LoadObject("#RCT2EIC");
LoadObject("#RCT1EBR");
LoadObject("#RCT1EIR");
LoadObject("#RCT1EGY");
LoadObject("#RCT1EYE");
LoadObject("#RCT1ERE");
LoadObject("#RCT1EPU");
LoadObject("#RCT1EGR");
LoadObject("#RCT1ESN");
LoadObject("#RCT1ESG");
LoadObject("#RCT1ESA");
LoadObject("#RCT1ESB");
// Stations
LoadObject("#RCT2STN");
LoadObject("#RCT2STW");
LoadObject("#RCT2STV");
LoadObject("#RCT2ST3");
LoadObject("#RCT2ST4");
LoadObject("#RCT2STJ");
LoadObject("#RCT2STL");
LoadObject("#RCT2STC");
LoadObject("#RCT2STA");
LoadObject("#RCT2STS");
LoadObject("#RCT2STP");
LoadObject("#RCT2STE");
LoadObject("#ORCT2SN");
}
static rct_string_id GetObjectSourceGameString(const uint8_t sourceGame)

View File

@ -643,17 +643,6 @@ const rct_object_entry* object_list_find(rct_object_entry* entry)
return result;
}
void object_list_load()
{
auto context = GetContext();
const auto& localisationService = context->GetLocalisationService();
auto& objectRepository = context->GetObjectRepository();
objectRepository.LoadOrConstruct(localisationService.GetCurrentLanguage());
auto& objectManager = context->GetObjectManager();
objectManager.UnloadAll();
}
void* object_repository_load_object(const rct_object_entry* objectEntry)
{
Object* object = nullptr;

View File

@ -918,16 +918,16 @@ std::vector<vehicle_colour> RideObject::ReadJsonColourConfiguration(const json_t
auto colours = ObjectJsonHelpers::GetJsonStringArray(jColours);
if (colours.size() >= 1)
{
carColour.main = ParseColour(colours[0]);
carColour.main = ObjectJsonHelpers::ParseColour(colours[0]);
carColour.additional_1 = carColour.main;
carColour.additional_2 = carColour.main;
if (colours.size() >= 2)
{
carColour.additional_1 = ParseColour(colours[1]);
carColour.additional_1 = ObjectJsonHelpers::ParseColour(colours[1]);
}
if (colours.size() >= 3)
{
carColour.additional_2 = ParseColour(colours[2]);
carColour.additional_2 = ObjectJsonHelpers::ParseColour(colours[2]);
}
}
config.push_back(carColour);
@ -1097,43 +1097,3 @@ uint8_t RideObject::ParseShopItem(const std::string& s)
auto result = LookupTable.find(s);
return (result != LookupTable.end()) ? result->second : SHOP_ITEM_NONE;
}
colour_t RideObject::ParseColour(const std::string& s)
{
static const std::unordered_map<std::string, colour_t> LookupTable{
{ "black", COLOUR_BLACK },
{ "grey", COLOUR_GREY },
{ "white", COLOUR_WHITE },
{ "dark_purple", COLOUR_DARK_PURPLE },
{ "light_purple", COLOUR_LIGHT_PURPLE },
{ "bright_purple", COLOUR_BRIGHT_PURPLE },
{ "dark_blue", COLOUR_DARK_BLUE },
{ "light_blue", COLOUR_LIGHT_BLUE },
{ "icy_blue", COLOUR_ICY_BLUE },
{ "teal", COLOUR_TEAL },
{ "aquamarine", COLOUR_AQUAMARINE },
{ "saturated_green", COLOUR_SATURATED_GREEN },
{ "dark_green", COLOUR_DARK_GREEN },
{ "moss_green", COLOUR_MOSS_GREEN },
{ "bright_green", COLOUR_BRIGHT_GREEN },
{ "olive_green", COLOUR_OLIVE_GREEN },
{ "dark_olive_green", COLOUR_DARK_OLIVE_GREEN },
{ "bright_yellow", COLOUR_BRIGHT_YELLOW },
{ "yellow", COLOUR_YELLOW },
{ "dark_yellow", COLOUR_DARK_YELLOW },
{ "light_orange", COLOUR_LIGHT_ORANGE },
{ "dark_orange", COLOUR_DARK_ORANGE },
{ "light_brown", COLOUR_LIGHT_BROWN },
{ "saturated_brown", COLOUR_SATURATED_BROWN },
{ "dark_brown", COLOUR_DARK_BROWN },
{ "salmon_pink", COLOUR_SALMON_PINK },
{ "bordeaux_red", COLOUR_BORDEAUX_RED },
{ "saturated_red", COLOUR_SATURATED_RED },
{ "bright_red", COLOUR_BRIGHT_RED },
{ "dark_pink", COLOUR_DARK_PINK },
{ "bright_pink", COLOUR_BRIGHT_PINK },
{ "light_pink", COLOUR_LIGHT_PINK },
};
auto result = LookupTable.find(s);
return (result != LookupTable.end()) ? result->second : COLOUR_BLACK;
}

View File

@ -0,0 +1,94 @@
/*****************************************************************************
* Copyright (c) 2014-2018 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 "StationObject.h"
#include "../core/IStream.hpp"
#include "../core/String.hpp"
#include "../drawing/Drawing.h"
#include "../localisation/Localisation.h"
#include "ObjectJsonHelpers.h"
void StationObject::Load()
{
GetStringTable().Sort();
NameStringId = language_allocate_object_string(GetName());
auto numImages = GetImageTable().GetCount();
if (numImages != 0)
{
BaseImageId = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount());
uint32_t shelterOffset = (Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT) ? 32 : 16;
if (numImages > shelterOffset)
{
ShelterImageId = BaseImageId + shelterOffset;
}
}
}
void StationObject::Unload()
{
language_free_object_string(NameStringId);
gfx_object_free_images(BaseImageId, GetImageTable().GetCount());
NameStringId = 0;
BaseImageId = 0;
ShelterImageId = 0;
}
void StationObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{
int32_t x = width / 2;
int32_t y = (height / 2) + 16;
auto colour0 = COLOUR_LIGHT_BLUE;
auto colour1 = COLOUR_BORDEAUX_RED;
auto tcolour0 = GlassPaletteIds[colour0];
uint32_t imageId = BaseImageId;
uint32_t tImageId = BaseImageId + 16;
if (Flags & STATION_OBJECT_FLAGS::HAS_PRIMARY_COLOUR)
{
imageId |= (colour0 << 19) | IMAGE_TYPE_REMAP;
tImageId |= (GlassPaletteIds[tcolour0] << 19) | IMAGE_TYPE_TRANSPARENT;
}
if (Flags & STATION_OBJECT_FLAGS::HAS_SECONDARY_COLOUR)
{
imageId |= (colour1 << 24) | IMAGE_TYPE_REMAP_2_PLUS;
tImageId |= (colour1 << 24) | IMAGE_TYPE_REMAP_2_PLUS;
}
gfx_draw_sprite(dpi, imageId + 0, x, y, 0);
if (Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT)
{
gfx_draw_sprite(dpi, tImageId, x, y, 0);
}
gfx_draw_sprite(dpi, imageId + 4, x, y, 0);
if (Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT)
{
gfx_draw_sprite(dpi, tImageId + 4, x, y, 0);
}
}
void StationObject::ReadJson(IReadObjectContext* context, const json_t* root)
{
auto properties = json_object_get(root, "properties");
Height = ObjectJsonHelpers::GetInteger(properties, "height", 0);
ScrollingMode = ObjectJsonHelpers::GetInteger(properties, "scrollingMode", 0xFF);
Flags = ObjectJsonHelpers::GetFlags<uint32_t>(
properties,
{ { "hasPrimaryColour", STATION_OBJECT_FLAGS::HAS_PRIMARY_COLOUR },
{ "hasSecondaryColour", STATION_OBJECT_FLAGS::HAS_SECONDARY_COLOUR },
{ "isTransparent", STATION_OBJECT_FLAGS::IS_TRANSPARENT } });
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
}

View File

@ -0,0 +1,41 @@
/*****************************************************************************
* Copyright (c) 2014-2018 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.h"
namespace STATION_OBJECT_FLAGS
{
const uint32_t HAS_PRIMARY_COLOUR = 1 << 0;
const uint32_t HAS_SECONDARY_COLOUR = 1 << 1;
const uint32_t IS_TRANSPARENT = 1 << 2;
} // namespace STATION_OBJECT_FLAGS
class StationObject final : public Object
{
public:
rct_string_id NameStringId{};
uint32_t BaseImageId{};
uint32_t ShelterImageId{};
uint32_t Flags;
int32_t Height;
uint8_t ScrollingMode;
explicit StationObject(const rct_object_entry& entry)
: Object(entry)
{
}
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override;
void Unload() override;
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
};

View File

@ -0,0 +1,54 @@
/*****************************************************************************
* Copyright (c) 2014-2018 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 "TerrainEdgeObject.h"
#include "../core/IStream.hpp"
#include "../core/String.hpp"
#include "../drawing/Drawing.h"
#include "../localisation/Localisation.h"
#include "ObjectJsonHelpers.h"
void TerrainEdgeObject::Load()
{
GetStringTable().Sort();
NameStringId = language_allocate_object_string(GetName());
IconImageId = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount());
// First image is icon followed by edge images
BaseImageId = IconImageId + 1;
}
void TerrainEdgeObject::Unload()
{
language_free_object_string(NameStringId);
gfx_object_free_images(IconImageId, GetImageTable().GetCount());
NameStringId = 0;
IconImageId = 0;
BaseImageId = 0;
}
void TerrainEdgeObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{
int32_t x = width / 2;
int32_t y = height / 2;
uint32_t imageId = BaseImageId;
gfx_draw_sprite(dpi, imageId + 5, x + 8, y - 8, 0);
gfx_draw_sprite(dpi, imageId + 5, x + 8, y + 8, 0);
}
void TerrainEdgeObject::ReadJson(IReadObjectContext* context, const json_t* root)
{
// auto properties = json_object_get(root, "properties");
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
}

View File

@ -0,0 +1,32 @@
/*****************************************************************************
* Copyright (c) 2014-2018 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.h"
class TerrainEdgeObject final : public Object
{
private:
public:
rct_string_id NameStringId{};
uint32_t IconImageId{};
uint32_t BaseImageId{};
explicit TerrainEdgeObject(const rct_object_entry& entry)
: Object(entry)
{
}
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override;
void Unload() override;
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
};

View File

@ -0,0 +1,140 @@
/*****************************************************************************
* Copyright (c) 2014-2018 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 warning(disable : 4706) // assignment within conditional expression
#include "TerrainSurfaceObject.h"
#include "../core/IStream.hpp"
#include "../core/String.hpp"
#include "../drawing/Drawing.h"
#include "../localisation/Localisation.h"
#include "ObjectJsonHelpers.h"
void TerrainSurfaceObject::Load()
{
GetStringTable().Sort();
NameStringId = language_allocate_object_string(GetName());
IconImageId = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount());
if ((Flags & SMOOTH_WITH_SELF) || (Flags & SMOOTH_WITH_OTHER))
{
PatternBaseImageId = IconImageId + 1;
EntryBaseImageId = PatternBaseImageId + 6;
}
else
{
EntryBaseImageId = IconImageId + 1;
}
NumEntries = (GetImageTable().GetCount() - EntryBaseImageId) / NUM_IMAGES_IN_ENTRY;
}
void TerrainSurfaceObject::Unload()
{
language_free_object_string(NameStringId);
gfx_object_free_images(IconImageId, GetImageTable().GetCount());
NameStringId = 0;
IconImageId = 0;
PatternBaseImageId = 0;
EntryBaseImageId = 0;
NumEntries = 0;
}
void TerrainSurfaceObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
{
uint32_t imageId = GetImageId({}, 1, 0, 0, false, false);
if (Colour != 255)
{
imageId |= Colour << 19 | IMAGE_TYPE_REMAP;
}
int32_t x0 = 0;
int32_t y = -16;
for (int32_t i = 0; i < 8; i++)
{
int32_t x = x0;
if (i % 2 == 0)
{
x -= 32;
}
for (int32_t j = 0; j < 4; j++)
{
gfx_draw_sprite(dpi, imageId, x, y, 0);
x += 64;
}
y += 16;
}
}
void TerrainSurfaceObject::ReadJson(IReadObjectContext* context, const json_t* root)
{
auto properties = json_object_get(root, "properties");
Colour = ObjectJsonHelpers::ParseColour(ObjectJsonHelpers::GetString(properties, "colour"), 255);
Rotations = ObjectJsonHelpers::GetInteger(properties, "rotations", 1);
Price = ObjectJsonHelpers::GetInteger(properties, "price", 0);
Flags = ObjectJsonHelpers::GetFlags<TERRAIN_SURFACE_FLAGS>(
properties,
{ { "smoothWithSelf", TERRAIN_SURFACE_FLAGS::SMOOTH_WITH_SELF },
{ "smoothWithOther", TERRAIN_SURFACE_FLAGS::SMOOTH_WITH_OTHER } });
auto jDefault = json_object_get(root, "default");
if (json_is_object(jDefault))
{
DefaultEntry = ObjectJsonHelpers::GetInteger(properties, "normal");
DefaultGridEntry = ObjectJsonHelpers::GetInteger(properties, "grid");
DefaultUndergroundEntry = ObjectJsonHelpers::GetInteger(properties, "underground");
}
else
{
DefaultEntry = 0;
DefaultGridEntry = 1;
DefaultUndergroundEntry = 2;
}
auto jSpecialArray = json_object_get(properties, "special");
if (json_is_array(jSpecialArray))
{
size_t i;
json_t* el;
json_array_foreach(jSpecialArray, i, el)
{
SpecialEntry entry;
entry.Index = ObjectJsonHelpers::GetInteger(el, "index");
entry.Length = ObjectJsonHelpers::GetInteger(el, "length", -1);
entry.Rotation = ObjectJsonHelpers::GetInteger(el, "rotation", -1);
entry.Variation = ObjectJsonHelpers::GetInteger(el, "variation", -1);
entry.Grid = ObjectJsonHelpers::GetBoolean(el, "grid");
entry.Underground = ObjectJsonHelpers::GetBoolean(el, "underground");
SpecialEntries.push_back(std::move(entry));
}
}
ObjectJsonHelpers::LoadStrings(root, GetStringTable());
ObjectJsonHelpers::LoadImages(context, root, GetImageTable());
}
uint32_t TerrainSurfaceObject::GetImageId(
const CoordsXY& position, int32_t length, int32_t rotation, int32_t offset, bool grid, bool underground) const
{
uint32_t result = (underground ? DefaultUndergroundEntry : (grid ? DefaultGridEntry : DefaultEntry));
// Look for a matching special
auto variation = ((position.x << 1) & 0b10) | (position.y & 0b01);
for (const auto& special : SpecialEntries)
{
if ((special.Length == -1 || special.Length == length) && (special.Rotation == -1 || special.Rotation == rotation)
&& (special.Variation == -1 || special.Variation == variation) && special.Grid == grid
&& special.Underground == underground)
{
result = special.Index;
break;
}
}
return EntryBaseImageId + (result * NUM_IMAGES_IN_ENTRY) + offset;
}

View File

@ -0,0 +1,68 @@
/*****************************************************************************
* Copyright (c) 2014-2018 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 "../world/Location.hpp"
#include "Object.h"
enum TERRAIN_SURFACE_FLAGS
{
NONE = 0,
SMOOTH_WITH_SELF = 1 << 0,
SMOOTH_WITH_OTHER = 1 << 1,
};
class TerrainSurfaceObject final : public Object
{
private:
struct SpecialEntry
{
uint32_t Index{};
int32_t Length{};
int32_t Rotation{};
int32_t Variation{};
bool Grid{};
bool Underground{};
};
static constexpr auto NUM_IMAGES_IN_ENTRY = 19;
public:
rct_string_id NameStringId{};
uint32_t IconImageId{};
uint32_t PatternBaseImageId{};
uint32_t EntryBaseImageId{};
uint32_t NumEntries{};
uint32_t DefaultEntry{};
uint32_t DefaultGridEntry{};
uint32_t DefaultUndergroundEntry{};
std::vector<SpecialEntry> SpecialEntries;
std::vector<uint32_t> SpecialEntryMap;
colour_t Colour{};
uint8_t Rotations{};
money32 Price{};
TERRAIN_SURFACE_FLAGS Flags{};
explicit TerrainSurfaceObject(const rct_object_entry& entry)
: Object(entry)
{
}
void ReadJson(IReadObjectContext* context, const json_t* root) override;
void Load() override;
void Unload() override;
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
uint32_t GetImageId(
const CoordsXY& position, int32_t length, int32_t rotation, int32_t offset, bool grid, bool underground) const;
};

View File

@ -12,6 +12,7 @@
#include "../../drawing/LightFX.h"
#include "../../interface/Viewport.h"
#include "../../localisation/Localisation.h"
#include "../../object/StationObject.h"
#include "../../ride/RideData.h"
#include "../../ride/TrackDesign.h"
#include "../../world/Entrance.h"
@ -68,14 +69,15 @@ static void ride_entrance_exit_paint(paint_session* session, uint8_t direction,
#endif
Ride* ride = get_ride(tile_element->AsEntrance()->GetRideIndex());
if (ride->entrance_style == RIDE_ENTRANCE_STYLE_NONE)
auto stationObj = ride_get_station_object(ride);
if (stationObj == nullptr || stationObj->BaseImageId == 0)
{
return;
const rct_ride_entrance_definition* style = &RideEntranceDefinitions[ride->entrance_style];
}
uint8_t colour_1, colour_2;
uint32_t transparant_image_id = 0, image_id = 0;
if (style->base_image_id & IMAGE_TYPE_TRANSPARENT)
if (stationObj->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT)
{
colour_1 = GlassPaletteIds[ride->track_colour_main[0]];
transparant_image_id = (colour_1 << 19) | IMAGE_TYPE_TRANSPARENT;
@ -99,11 +101,11 @@ static void ride_entrance_exit_paint(paint_session* session, uint8_t direction,
if (is_exit)
{
image_id |= style->sprite_index + direction + 8;
image_id |= stationObj->BaseImageId + direction + 8;
}
else
{
image_id |= style->sprite_index + direction;
image_id |= stationObj->BaseImageId + direction;
}
// Format modified to stop repeated code
@ -122,11 +124,11 @@ static void ride_entrance_exit_paint(paint_session* session, uint8_t direction,
{
if (is_exit)
{
transparant_image_id |= style->sprite_index + direction + 24;
transparant_image_id |= stationObj->BaseImageId + direction + 24;
}
else
{
transparant_image_id |= style->sprite_index + direction + 16;
transparant_image_id |= stationObj->BaseImageId + direction + 16;
}
sub_98199C(session, transparant_image_id, 0, 0, lengthX, lengthY, ah, height, 2, 2, height);
@ -154,7 +156,8 @@ static void ride_entrance_exit_paint(paint_session* session, uint8_t direction,
paint_util_push_tunnel_left(session, height, TUNNEL_6);
}
if (!is_exit && !(tile_element->flags & TILE_ELEMENT_FLAG_GHOST) && tile_element->AsEntrance()->GetRideIndex() != 0xFF)
if (!is_exit && !(tile_element->flags & TILE_ELEMENT_FLAG_GHOST) && tile_element->AsEntrance()->GetRideIndex() != 0xFF
&& stationObj->ScrollingMode != 0xFF)
{
set_format_arg(0, uint32_t, 0);
set_format_arg(4, uint32_t, 0);
@ -185,8 +188,8 @@ static void ride_entrance_exit_paint(paint_session* session, uint8_t direction,
uint16_t scroll = (gCurrentTicks / 2) % string_width;
sub_98199C(
session, scrolling_text_setup(session, string_id, scroll, style->scrolling_mode), 0, 0, 0x1C, 0x1C, 0x33,
height + style->height, 2, 2, height + style->height);
session, scrolling_text_setup(session, string_id, scroll, stationObj->ScrollingMode), 0, 0, 0x1C, 0x1C, 0x33,
height + stationObj->Height, 2, 2, height + stationObj->Height);
}
image_id = _unk9E32BC;

View File

@ -10,12 +10,16 @@
#include "Paint.Surface.h"
#include "../../Cheats.h"
#include "../../Context.h"
#include "../../OpenRCT2.h"
#include "../../config/Config.h"
#include "../../core/Guard.hpp"
#include "../../drawing/Drawing.h"
#include "../../interface/Colour.h"
#include "../../interface/Viewport.h"
#include "../../object/ObjectManager.h"
#include "../../object/TerrainEdgeObject.h"
#include "../../object/TerrainSurfaceObject.h"
#include "../../paint/Paint.h"
#include "../../peep/Staff.h"
#include "../../ride/TrackDesign.h"
@ -203,220 +207,12 @@ static constexpr const uint8_t byte_97B5B0[TUNNEL_TYPE_COUNT] = {
16, 17, 18, 19, 20, 21, 22
};
#define EDGE_SPRITE_TYPE_COUNT 4
#define DEFINE_EDGE_SPRITES(base) { \
(base) + 0, \
(base) + 20, \
(base) + 10, \
(base) + 30, \
}
#define DEFINE_EDGE_TUNNEL_SPRITES(base) { \
(base) + 36, \
(base) + 40, \
(base) + 44, \
(base) + 48, \
(base) + 52, \
(base) + 56, \
(base) + 60, \
(base) + 64, \
(base) + 68, \
(base) + 72, \
(base) + 76, \
(base) + 80, \
(base) + 36, \
(base) + 48, \
(base) + 60, \
(base) + 72, \
(base) + 36, \
(base) + 36, \
(base) + 36, \
(base) + 36, \
(base) + 36, \
(base) + 36, \
(base) + 36, \
}
#define DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(base) { \
(base) + 36, \
(base) + 40, \
(base) + 44, \
(base) + 48, \
(base) + 52, \
(base) + 56, \
(base) + 60, \
(base) + 64, \
(base) + 68, \
(base) + 72, \
(base) + 76, \
(base) + 80, \
(base) + 36, \
(base) + 48, \
(base) + 60, \
(base) + 72, \
(base) + 76, \
(base) + 80, \
(base) + 84, \
(base) + 88, \
(base) + 92, \
(base) + 96, \
(base) + 100, \
}
static constexpr const uint32_t _terrainEdgeSpriteIds[][EDGE_SPRITE_TYPE_COUNT] =
{
DEFINE_EDGE_SPRITES(SPR_EDGE_ROCK_BASE),
DEFINE_EDGE_SPRITES(SPR_EDGE_WOOD_RED_BASE),
DEFINE_EDGE_SPRITES(SPR_EDGE_WOOD_BLACK_BASE),
DEFINE_EDGE_SPRITES(SPR_EDGE_ICE_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_BRICK_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_IRON_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_GREY_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_YELLOW_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_RED_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_PURPLE_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_GREEN_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_STONE_BROWN_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_STONE_GREY_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_SKYSCRAPER_A_BASE),
DEFINE_EDGE_SPRITES(SPR_CSG_EDGE_SKYSCRAPER_B_BASE),
};
static constexpr const uint32_t _terrainEdgeTunnelSpriteIds[][TUNNEL_TYPE_COUNT] =
{
DEFINE_EDGE_TUNNEL_SPRITES(SPR_EDGE_ROCK_BASE),
DEFINE_EDGE_TUNNEL_SPRITES(SPR_EDGE_WOOD_RED_BASE),
DEFINE_EDGE_TUNNEL_SPRITES(SPR_EDGE_WOOD_BLACK_BASE),
DEFINE_EDGE_TUNNEL_SPRITES(SPR_EDGE_ICE_BASE),
DEFINE_EDGE_TUNNEL_SPRITES(SPR_CSG_EDGE_BRICK_BASE),
DEFINE_EDGE_TUNNEL_SPRITES(SPR_CSG_EDGE_IRON_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_GREY_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_YELLOW_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_RED_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_PURPLE_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_GREEN_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_STONE_BROWN_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_STONE_GREY_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_SKYSCRAPER_A_BASE),
DEFINE_EDGE_TUNNEL_SPRITES_WITH_DOORS(SPR_CSG_EDGE_SKYSCRAPER_B_BASE),
};
static constexpr const uint8_t byte_97B740[] =
{
0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
0, 3, 0, 1, 4, 0
};
static constexpr const uint32_t dword_97B750[][2] =
{
{ SPR_TERRAIN_GRASS, SPR_TERRAIN_GRASS_GRID },
{ SPR_TERRAIN_SAND_YELLOW, SPR_TERRAIN_SAND_YELLOW_GRID },
{ SPR_TERRAIN_DIRT, SPR_TERRAIN_DIRT_GRID },
{ SPR_TERRAIN_ROCK, SPR_TERRAIN_ROCK_GRID },
{ SPR_TERRAIN_MARTIAN, SPR_TERRAIN_MARTIAN_GRID },
{ SPR_TERRAIN_CHECKERBOARD, SPR_TERRAIN_CHECKERBOARD_GRID },
{ SPR_TERRAIN_GRASS_CLUMPS, SPR_TERRAIN_GRASS_CLUMPS_GRID },
{ SPR_TERRAIN_ICE, SPR_TERRAIN_ICE_GRID },
{ SPR_TERRAIN_GRID | COLOUR_BRIGHT_RED << 19 | IMAGE_TYPE_REMAP, SPR_TERRAIN_GRID_GRID | COLOUR_BRIGHT_RED << 19 | IMAGE_TYPE_REMAP },
{ SPR_TERRAIN_GRID | COLOUR_YELLOW << 19 | IMAGE_TYPE_REMAP, SPR_TERRAIN_GRID_GRID | COLOUR_YELLOW << 19 | IMAGE_TYPE_REMAP },
{ SPR_TERRAIN_GRID | COLOUR_BRIGHT_PURPLE << 19 | IMAGE_TYPE_REMAP, SPR_TERRAIN_GRID_GRID | COLOUR_BRIGHT_PURPLE << 19 | IMAGE_TYPE_REMAP },
{ SPR_TERRAIN_GRID | COLOUR_BRIGHT_GREEN << 19 | IMAGE_TYPE_REMAP, SPR_TERRAIN_GRID_GRID | COLOUR_BRIGHT_GREEN << 19 | IMAGE_TYPE_REMAP },
{ SPR_TERRAIN_SAND_RED, SPR_TERRAIN_SAND_RED_GRID },
{ SPR_TERRAIN_SAND, SPR_TERRAIN_SAND_GRID },
{ SPR_TERRAIN_CHECKERBOARD_INVERTED, SPR_TERRAIN_CHECKERBOARD_INVERTED_GRID },
};
static constexpr const uint32_t dword_97B7C8[] =
{
SPR_TERRAIN_GRASS_UNDERGROUND,
SPR_TERRAIN_SAND_YELLOW_UNDERGROUND,
SPR_TERRAIN_DIRT_UNDERGROUND,
SPR_TERRAIN_ROCK_UNDERGROUND,
SPR_TERRAIN_MARTIAN_UNDERGROUND,
SPR_TERRAIN_CHECKERBOARD_UNDERGROUND,
SPR_TERRAIN_GRASS_CLUMPS_UNDERGROUND,
SPR_TERRAIN_ICE_UNDERGROUND,
SPR_TERRAIN_GRID_UNDERGROUND | COLOUR_BRIGHT_RED << 19 | IMAGE_TYPE_REMAP,
SPR_TERRAIN_GRID_UNDERGROUND | COLOUR_YELLOW << 19 | IMAGE_TYPE_REMAP,
SPR_TERRAIN_GRID_UNDERGROUND | COLOUR_BRIGHT_PURPLE << 19 | IMAGE_TYPE_REMAP,
SPR_TERRAIN_GRID_UNDERGROUND | COLOUR_BRIGHT_GREEN << 19 | IMAGE_TYPE_REMAP,
SPR_TERRAIN_SAND_RED_UNDERGROUND,
SPR_TERRAIN_SAND_UNDERGROUND,
SPR_TERRAIN_CHECKERBOARD_INVERTED_UNDERGROUND,
};
static constexpr const uint32_t dword_97B804[] =
{
SPR_TERRAIN_PATTERN_GRASS,
SPR_TERRAIN_PATTERN_SAND_YELLOW,
SPR_TERRAIN_PATTERN_DIRT,
SPR_TERRAIN_PATTERN_ROCK,
SPR_TERRAIN_PATTERN_MARTIAN,
SPR_TERRAIN_PATTERN_GRASS,
SPR_TERRAIN_PATTERN_GRASS_CLUMPS,
SPR_TERRAIN_PATTERN_ICE,
SPR_TERRAIN_PATTERN_GRASS,
SPR_TERRAIN_PATTERN_GRASS,
SPR_TERRAIN_PATTERN_GRASS,
SPR_TERRAIN_PATTERN_GRASS,
SPR_TERRAIN_PATTERN_SAND_RED,
SPR_TERRAIN_PATTERN_SAND
};
enum
{
FLAG_DONT_SMOOTHEN = (1 << 0),
FLAG_DONT_SMOOTHEN_SELF = (1 << 1),
};
static constexpr const uint8_t byte_97B83C[] =
{
0,
0,
0,
FLAG_DONT_SMOOTHEN_SELF,
FLAG_DONT_SMOOTHEN_SELF,
FLAG_DONT_SMOOTHEN_SELF | FLAG_DONT_SMOOTHEN,
0,
0,
FLAG_DONT_SMOOTHEN_SELF | FLAG_DONT_SMOOTHEN,
FLAG_DONT_SMOOTHEN_SELF | FLAG_DONT_SMOOTHEN,
FLAG_DONT_SMOOTHEN_SELF | FLAG_DONT_SMOOTHEN,
FLAG_DONT_SMOOTHEN_SELF | FLAG_DONT_SMOOTHEN,
0,
0
};
static constexpr const uint8_t byte_97B84A[] =
{
0, 1, 2, 3, 4, 14, 6, 7, 8, 9,
10, 11, 12, 13
};
static constexpr const uint32_t dword_97B858[][2] =
{
{ SPR_TERRAIN_GRASS_LENGTH_4_VARIANT_1, SPR_TERRAIN_GRASS_LENGTH_4_VARIANT_1_GRID },
{ SPR_TERRAIN_GRASS_LENGTH_4_VARIANT_2, SPR_TERRAIN_GRASS_LENGTH_4_VARIANT_2_GRID },
{ SPR_TERRAIN_GRASS_LENGTH_4_VARIANT_3, SPR_TERRAIN_GRASS_LENGTH_4_VARIANT_3_GRID },
{ SPR_TERRAIN_GRASS_LENGTH_4_VARIANT_4, SPR_TERRAIN_GRASS_LENGTH_4_VARIANT_4_GRID },
};
static constexpr const uint32_t dword_97B878[][2] =
{
{ SPR_TERRAIN_GRASS_LENGTH_6_VARIANT_1, SPR_TERRAIN_GRASS_LENGTH_6_VARIANT_1_GRID },
{ SPR_TERRAIN_GRASS_LENGTH_6_VARIANT_2, SPR_TERRAIN_GRASS_LENGTH_6_VARIANT_2_GRID },
{ SPR_TERRAIN_GRASS_LENGTH_6_VARIANT_3, SPR_TERRAIN_GRASS_LENGTH_6_VARIANT_3_GRID },
{ SPR_TERRAIN_GRASS_LENGTH_6_VARIANT_4, SPR_TERRAIN_GRASS_LENGTH_6_VARIANT_4_GRID },
};
static constexpr const uint32_t dword_97B898[][2] =
{
{ SPR_TERRAIN_GRASS_MOWED_90, SPR_TERRAIN_GRASS_MOWED_90_GRID },
{ SPR_TERRAIN_GRASS_MOWED, SPR_TERRAIN_GRASS_MOWED_GRID },
{ SPR_TERRAIN_GRASS_MOWED_90, SPR_TERRAIN_GRASS_MOWED_90_GRID },
{ SPR_TERRAIN_GRASS_MOWED, SPR_TERRAIN_GRASS_MOWED_GRID }
};
struct tile_descriptor
{
TileCoordsXY tile_coords;
@ -495,14 +291,113 @@ static constexpr const tile_surface_boundary_data _tileSurfaceBoundaries[4] =
};
// clang-format on
static const TerrainSurfaceObject* get_surface_object(size_t index)
{
TerrainSurfaceObject* result{};
auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objMgr.GetLoadedObject(OBJECT_TYPE_TERRAIN_SURFACE, index);
if (obj != nullptr)
{
return static_cast<TerrainSurfaceObject*>(obj);
}
return result;
}
static uint32_t get_surface_image(
const paint_session* session, uint8_t index, int32_t offset, uint8_t rotation, int32_t grassLength, bool grid,
bool underground)
{
auto image = (uint32_t)SPR_NONE;
auto obj = get_surface_object(index);
if (obj != nullptr)
{
image = obj->GetImageId(
{ session->MapPosition.x >> 5, session->MapPosition.y >> 5 }, grassLength, rotation, offset, grid, underground);
if (obj->Colour != 255)
{
image |= obj->Colour << 19 | IMAGE_TYPE_REMAP;
}
}
return image;
}
static uint32_t get_surface_pattern(uint8_t index, int32_t offset)
{
auto image = (uint32_t)SPR_NONE;
auto obj = get_surface_object(index);
if (obj != nullptr)
{
image = obj->PatternBaseImageId + offset;
if (obj->Colour != 255)
{
image |= obj->Colour << 19 | IMAGE_TYPE_REMAP;
}
}
return image;
}
static bool surface_should_smooth_self(uint8_t index)
{
auto obj = get_surface_object(index);
if (obj != nullptr)
{
return obj->Flags & TERRAIN_SURFACE_FLAGS::SMOOTH_WITH_SELF;
}
return false;
}
static bool surface_should_smooth(uint8_t index)
{
auto obj = get_surface_object(index);
if (obj != nullptr)
{
return obj->Flags & TERRAIN_SURFACE_FLAGS::SMOOTH_WITH_OTHER;
}
return false;
}
static uint32_t get_edge_image_with_offset(uint8_t index, uint32_t offset)
{
uint32_t result = 0;
auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objMgr.GetLoadedObject(OBJECT_TYPE_TERRAIN_EDGE, index);
if (obj != nullptr)
{
auto tobj = static_cast<TerrainEdgeObject*>(obj);
return tobj->BaseImageId + offset;
}
return result;
}
static uint32_t get_edge_image(uint8_t index, uint8_t type)
{
return _terrainEdgeSpriteIds[index][type];
static constexpr uint32_t offsets[] = {
0,
20,
10,
30,
};
uint32_t result = 0;
if (type < std::size(offsets))
{
result = get_edge_image_with_offset(index, offsets[type]);
}
return result;
}
static uint32_t get_tunnel_image(uint8_t index, uint8_t type)
{
return _terrainEdgeTunnelSpriteIds[index][type];
static constexpr uint32_t offsets[] = {
36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 36, 48, 60, 72,
};
uint32_t result = 0;
if (type < std::size(offsets))
{
result = get_edge_image_with_offset(index, offsets[type]);
}
return result;
}
static uint8_t viewport_surface_paint_setup_get_relative_slope(const TileElement* tileElement, int32_t rotation)
@ -595,15 +490,15 @@ static void viewport_surface_smoothen_edge(
if (cl == dh)
return;
if (byte_97B83C[self.terrain] & FLAG_DONT_SMOOTHEN_SELF)
if (!surface_should_smooth_self(self.terrain))
return;
}
else
{
if (byte_97B83C[self.terrain] & FLAG_DONT_SMOOTHEN)
if (!surface_should_smooth(self.terrain))
return;
if (byte_97B83C[neighbour.terrain] & FLAG_DONT_SMOOTHEN)
if (!surface_should_smooth(neighbour.terrain))
return;
}
@ -613,7 +508,7 @@ static void viewport_surface_smoothen_edge(
{
attached_paint_struct* out = session->UnkF1AD2C;
// set content and enable masking
out->colour_image_id = dword_97B804[neighbour.terrain] + cl;
out->colour_image_id = get_surface_pattern(neighbour.terrain, cl);
out->flags |= PAINT_STRUCT_FLAG_IS_MASKED;
}
}
@ -1104,81 +999,30 @@ void surface_paint(paint_session* session, uint8_t direction, uint16_t height, c
{
const bool showGridlines = (session->ViewFlags & VIEWPORT_FLAG_GRIDLINES);
int32_t branch = -1;
if (tileElement->AsSurface()->GetSurfaceStyle() == TERRAIN_GRASS)
auto grassLength = -1;
if (zoomLevel == 0)
{
if (tileElement->GetDirection() == 0)
if ((session->ViewFlags & (VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_UNDERGROUND_INSIDE)) == 0)
{
if (zoomLevel == 0)
{
if ((session->ViewFlags & (VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_UNDERGROUND_INSIDE)) == 0)
{
branch = tileElement->AsSurface()->GetGrassLength() & 0x7;
}
}
grassLength = tileElement->AsSurface()->GetGrassLength() & 0x7;
}
}
assert(surfaceShape < std::size(byte_97B444));
const uint8_t image_offset = byte_97B444[surfaceShape];
int32_t image_id;
uint32_t ebp = terrain_type;
switch (branch)
auto imageId = get_surface_image(session, terrain_type, image_offset, rotation, grassLength, showGridlines, false);
if (gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))
{
case 0:
// loc_660C90
image_id = dword_97B898[rotation][showGridlines ? 1 : 0] + image_offset;
break;
case 1:
case 2:
case 3:
default:
// loc_660C9F
if (rotation & 1)
{
assert(ebp < std::size(byte_97B84A));
ebp = byte_97B84A[ebp];
}
assert(ebp < std::size(dword_97B750));
image_id = dword_97B750[ebp][showGridlines ? 1 : 0] + image_offset;
if (gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))
{
image_id = SPR_TERRAIN_TRACK_DESIGNER;
}
if (session->ViewFlags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE))
{
image_id &= 0xDC07FFFF; // remove colour
image_id |= 0x41880000;
}
break;
case 4:
case 5:
// loc_660C44
case 6:
// loc_660C6A
{
const int16_t x = session->MapPosition.x & 0x20;
const int16_t y = session->MapPosition.y & 0x20;
const int32_t index = (y | (x << 1)) >> 5;
if (branch == 6)
{
image_id = dword_97B878[index][showGridlines ? 1 : 0] + image_offset;
}
else
{
image_id = dword_97B858[index][showGridlines ? 1 : 0] + image_offset;
}
}
break;
imageId = SPR_TERRAIN_TRACK_DESIGNER;
}
if (session->ViewFlags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE))
{
imageId &= 0xDC07FFFF; // remove colour
imageId |= 0x41880000;
}
sub_98196C(session, image_id, 0, 0, 32, 32, -1, height);
sub_98196C(session, imageId, 0, 0, 32, 32, -1, height);
has_surface = true;
}
@ -1381,12 +1225,7 @@ void surface_paint(paint_session* session, uint8_t direction, uint16_t height, c
&& !(gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)))
{
const uint8_t image_offset = byte_97B444[surfaceShape];
uint32_t base_image = terrain_type;
if (rotation & 1)
{
base_image = byte_97B84A[terrain_type];
}
const uint32_t image_id = dword_97B7C8[base_image] + image_offset;
const uint32_t image_id = get_surface_image(session, terrain_type, image_offset, rotation, 1, false, true);
paint_attach_to_previous_ps(session, image_id, 0, 0);
}

View File

@ -143,22 +143,22 @@ namespace RCT1
{
static constexpr const uint8_t map[] =
{
TERRAIN_EDGE_ROCK,
TERRAIN_EDGE_BRICK,
TERRAIN_EDGE_IRON,
TERRAIN_EDGE_WOOD_RED,
TERRAIN_EDGE_GREY,
TERRAIN_EDGE_YELLOW,
TERRAIN_EDGE_WOOD_BLACK,
TERRAIN_EDGE_RED,
TERRAIN_EDGE_ICE,
TERRAIN_EDGE_PURPLE,
TERRAIN_EDGE_GREEN,
TERRAIN_EDGE_STONE_BROWN,
TERRAIN_EDGE_STONE_GREY,
TERRAIN_EDGE_SKYSCRAPER_A,
TERRAIN_EDGE_SKYSCRAPER_B,
TERRAIN_EDGE_ROCK // Unused
TERRAIN_EDGE_ROCK, // #RCT2ERO
TERRAIN_EDGE_BRICK, // #RCT1EBR
TERRAIN_EDGE_IRON, // #RCT1EIR
TERRAIN_EDGE_WOOD_RED, // #RCT2EWR
TERRAIN_EDGE_GREY, // #RCT1EGY
TERRAIN_EDGE_YELLOW, // #RCT1EYE
TERRAIN_EDGE_WOOD_BLACK, // #RCT2EWB
TERRAIN_EDGE_RED, // #RCT1ERE
TERRAIN_EDGE_ICE, // #RCT2EIC
TERRAIN_EDGE_PURPLE, // #RCT2EIC
TERRAIN_EDGE_GREEN, // #RCT1EGR
TERRAIN_EDGE_STONE_BROWN, // #RCT1ESN
TERRAIN_EDGE_STONE_GREY, // #RCT1ESG
TERRAIN_EDGE_SKYSCRAPER_A, // #RCT1ESA
TERRAIN_EDGE_SKYSCRAPER_B, // #RCT1ESB
TERRAIN_EDGE_ROCK // #RCT2ERO (Unused)
};
Guard::ArgumentInRange<size_t>(terrainEdge, 0, std::size(map), "Unsupported RCT1 terrain edge.");
return map[terrainEdge];

View File

@ -29,6 +29,7 @@
#include "../network/network.h"
#include "../object/ObjectList.h"
#include "../object/ObjectManager.h"
#include "../object/StationObject.h"
#include "../paint/VirtualFloor.h"
#include "../peep/Peep.h"
#include "../peep/Staff.h"
@ -8535,6 +8536,12 @@ bool ride_has_adjacent_station(Ride* ride)
return found;
}
bool ride_has_station_shelter(Ride* ride)
{
auto stationObj = ride_get_station_object(ride);
return stationObj != nullptr && stationObj->BaseImageId != 0;
}
bool ride_has_ratings(const Ride* ride)
{
return ride->excitement != RIDE_RATING_UNDEFINED;
@ -8775,6 +8782,12 @@ int32_t ride_get_entry_index(int32_t rideType, int32_t rideSubType)
return subType;
}
StationObject* ride_get_station_object(const Ride* ride)
{
auto& objManager = GetContext()->GetObjectManager();
return static_cast<StationObject*>(objManager.GetLoadedObject(OBJECT_TYPE_STATION, ride->entrance_style));
}
LocationXY16 ride_get_rotated_coords(int16_t x, int16_t y, int16_t z)
{
LocationXY16 rotatedCoords = { 0, 0 };

View File

@ -19,6 +19,7 @@
#include "Vehicle.h"
interface IObjectManager;
class StationObject;
#define MAX_RIDE_TYPES_PER_RIDE_ENTRY 3
// The max number of different types of vehicle.
@ -732,25 +733,6 @@ enum
VEHICLE_COLOUR_SCHEME_PER_VEHICLE
};
enum
{
RIDE_ENTRANCE_STYLE_PLAIN,
RIDE_ENTRANCE_STYLE_WOODEN,
RIDE_ENTRANCE_STYLE_CANVAS_TENT,
RIDE_ENTRANCE_STYLE_CASTLE_GREY,
RIDE_ENTRANCE_STYLE_CASTLE_BROWN,
RIDE_ENTRANCE_STYLE_JUNGLE,
RIDE_ENTRANCE_STYLE_LOG_CABIN,
RIDE_ENTRANCE_STYLE_CLASSICAL_ROMAN,
RIDE_ENTRANCE_STYLE_ABSTRACT,
RIDE_ENTRANCE_STYLE_SNOW_ICE,
RIDE_ENTRANCE_STYLE_PAGODA,
RIDE_ENTRANCE_STYLE_SPACE,
RIDE_ENTRANCE_STYLE_NONE,
RIDE_ENTRANCE_STYLE_COUNT
};
enum
{
RIDE_INSPECTION_EVERY_10_MINUTES,
@ -1193,6 +1175,7 @@ money16 ride_get_price(Ride* ride);
TileElement* get_station_platform(int32_t x, int32_t y, int32_t z, int32_t z_tolerance);
bool ride_has_adjacent_station(Ride* ride);
bool ride_has_station_shelter(Ride* ride);
bool ride_has_ratings(const Ride* ride);
const char* ride_type_get_enum_name(int32_t rideType);
@ -1204,6 +1187,7 @@ void fix_invalid_vehicle_sprite_sizes();
bool ride_entry_has_category(const rct_ride_entry* rideEntry, uint8_t category);
int32_t ride_get_entry_index(int32_t rideType, int32_t rideSubType);
StationObject* ride_get_station_object(const Ride* ride);
void ride_action_modify(int32_t rideIndex, int32_t modifyType, int32_t flags);
void ride_stop_peeps_queuing(int32_t rideIndex);

View File

@ -1105,23 +1105,6 @@ const uint8_t RideAvailableBreakdowns[] = {
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE) // 5a LIM Launched Roller Coaster
};
// rct2: 0x00993E7C and 0x00993E1C
const rct_ride_entrance_definition RideEntranceDefinitions[RIDE_ENTRANCE_STYLE_COUNT] = {
{ 22664, 32, 2, 0x00000000, STR_PLAIN_ENTRANCE, 0, }, // RIDE_ENTRANCE_STYLE_PLAIN
{ 22760, 31, 21, 0x000057A1, STR_WOODEN_ENTRANCE, 0, }, // RIDE_ENTRANCE_STYLE_WOODEN
{ 22680, 43, 2, 0x800057AD, STR_CANVAS_TENT_ENTRANCE, 3, }, // RIDE_ENTRANCE_STYLE_CANVAS_TENT
{ 22728, 43, 19, 0x000057B9, STR_CASTLE_ENTRANCE_GREY, 0, }, // RIDE_ENTRANCE_STYLE_CASTLE_GREY
{ 22712, 43, 19, 0x000057C5, STR_CASTLE_ENTRANCE_BROWN, 0, }, // RIDE_ENTRANCE_STYLE_CASTLE_BROWN
{ 22776, 33, 19, 0x000057D1, STR_JUNGLE_ENTRANCE, 0, }, // RIDE_ENTRANCE_STYLE_JUNGLE
{ 22744, 32, 20, 0x000057DD, STR_LOG_CABIN_ENTRANCE, 0, }, // RIDE_ENTRANCE_STYLE_LOG_CABIN
{ 22696, 34, 19, 0x000057E9, STR_CLASSICAL_ROMAN_ENTRANCE, 0, }, // RIDE_ENTRANCE_STYLE_CLASSICAL_ROMAN
{ 22792, 40, 22, 0x400057F5, STR_ABSTRACT_ENTRANCE, 1, }, // RIDE_ENTRANCE_STYLE_ABSTRACT
{ 22824, 35, 23, 0x0000580D, STR_SNOW_ICE_ENTRANCE, 0, }, // RIDE_ENTRANCE_STYLE_SNOW_ICE
{ 22840, 33, 19, 0x00005819, STR_PAGODA_ENTRANCE, 0, }, // RIDE_ENTRANCE_STYLE_PAGODA
{ 22856, 33, 2, 0x00005825, STR_SPACE_ENTRANCE, 0, }, // RIDE_ENTRANCE_STYLE_SPACE
{ 0, 0, 2, 0x00000000, STR_ENTRANCE_NONE, 0, } // RIDE_ENTRANCE_STYLE_NONE
};
// rct2: 0x0097D4F0, 0x0097D4F1, 0x0097D4F2, 0x0097D4F4, 0x0097D4F5
const rct_ride_data_4 RideData4[RIDE_TYPE_COUNT] = {
{ 20, 20, RIDE_TYPE_FLAG4_ALLOW_MUSIC | RIDE_TYPE_FLAG4_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG4_HAS_ENTRANCE_EXIT | RIDE_TYPE_FLAG4_HAS_AIR_TIME | RIDE_TYPE_FLAG4_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG4_SHOW_IN_TRACK_DESIGNER | RIDE_TYPE_FLAG4_INTERESTING_TO_LOOK_AT, MUSIC_STYLE_ROCK_STYLE_3, 0 }, // RIDE_TYPE_SPIRAL_ROLLER_COASTER

View File

@ -50,16 +50,6 @@ struct rct_ride_name_convention
RIDE_COMPONENT_TYPE station;
};
struct rct_ride_entrance_definition
{
uint32_t sprite_index;
uint16_t height;
uint16_t scrolling_mode;
uint32_t base_image_id;
rct_string_id string_id;
uint16_t colour_use_flags;
};
struct rct_ride_data_4
{
uint8_t price;
@ -138,7 +128,6 @@ extern const uint8_t RideAvailableModes[];
extern const uint8_t AllRideModesAvailable[];
extern const uint8_t RideAvailableBreakdowns[];
extern const rct_ride_entrance_definition RideEntranceDefinitions[RIDE_ENTRANCE_STYLE_COUNT];
extern const rct_ride_lift_data RideLiftData[RIDE_TYPE_COUNT];
extern const rct_ride_data_4 RideData4[RIDE_TYPE_COUNT];

View File

@ -14,6 +14,7 @@
#include "../interface/Viewport.h"
#include "../interface/Window.h"
#include "../localisation/Localisation.h"
#include "../object/StationObject.h"
#include "../paint/Paint.h"
#include "../paint/Supports.h"
#include "../paint/tile_element/Paint.TileElement.h"
@ -325,7 +326,7 @@ static void track_paint_util_draw_station_impl(
{
LocationXY16 position = session->MapPosition;
Ride* ride = get_ride(rideIndex);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
const bool hasGreenLight = tileElement->AsTrack()->HasGreenLight();
bool hasFence;
@ -363,7 +364,7 @@ static void track_paint_util_draw_station_impl(
}
sub_98196C(session, imageId, 0, 0, 32, 8, 1, height + fenceOffsetA);
// height -= 5 (height)
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, entranceStyle, coverHeight);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, stationObj, coverHeight);
// height += 5 (height + 5)
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_END_STATION && direction == 0)
@ -412,7 +413,7 @@ static void track_paint_util_draw_station_impl(
sub_98196C(session, imageId, 31, 23, 1, 8, 7, height + fenceOffsetB);
}
// height -= 7 (height)
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, entranceStyle, coverHeight);
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, stationObj, coverHeight);
// height += 7 (height + 7)
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_BEGIN_STATION && direction == 0)
@ -458,7 +459,7 @@ static void track_paint_util_draw_station_impl(
}
sub_98196C(session, imageId, 0, 0, 8, 32, 1, height + fenceOffsetA);
// height -= 5 (height)
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, entranceStyle, coverHeight);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, stationObj, coverHeight);
// height += 5 (height + 5)
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_END_STATION && direction == 3)
@ -508,7 +509,7 @@ static void track_paint_util_draw_station_impl(
}
// height -= 7 (height)
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, entranceStyle, coverHeight);
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, stationObj, coverHeight);
// height += 7 (height + 7)
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_BEGIN_STATION && direction == 3)
@ -530,7 +531,7 @@ void track_paint_util_draw_station_inverted(
{
LocationXY16 position = session->MapPosition;
Ride* ride = get_ride(rideIndex);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
const bool hasGreenLight = tileElement->AsTrack()->HasGreenLight();
bool hasFence;
@ -568,7 +569,7 @@ void track_paint_util_draw_station_inverted(
}
sub_98196C(session, imageId, 0, 0, 32, 8, 1, height + 6);
// height -= 5 (height)
track_paint_util_draw_station_covers_2(session, EDGE_NW, hasFence, entranceStyle, height, stationVariant);
track_paint_util_draw_station_covers_2(session, EDGE_NW, hasFence, stationObj, height, stationVariant);
// height += 5 (height + 5)
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_END_STATION && direction == 0)
@ -617,7 +618,7 @@ void track_paint_util_draw_station_inverted(
sub_98196C(session, imageId, 31, 23, 1, 8, 7, height + 8);
}
// height -= 7 (height)
track_paint_util_draw_station_covers_2(session, EDGE_SE, hasFence, entranceStyle, height, stationVariant);
track_paint_util_draw_station_covers_2(session, EDGE_SE, hasFence, stationObj, height, stationVariant);
// height += 7 (height + 7)
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_BEGIN_STATION && direction == 0)
@ -663,7 +664,7 @@ void track_paint_util_draw_station_inverted(
}
sub_98196C(session, imageId, 0, 0, 8, 32, 1, height + 6);
// height -= 5 (height)
track_paint_util_draw_station_covers_2(session, EDGE_NE, hasFence, entranceStyle, height, stationVariant);
track_paint_util_draw_station_covers_2(session, EDGE_NE, hasFence, stationObj, height, stationVariant);
// height += 5 (height + 5)
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_END_STATION && direction == 3)
@ -713,7 +714,7 @@ void track_paint_util_draw_station_inverted(
}
// height -= 7 (height)
track_paint_util_draw_station_covers_2(session, EDGE_SW, hasFence, entranceStyle, height, stationVariant);
track_paint_util_draw_station_covers_2(session, EDGE_SW, hasFence, stationObj, height, stationVariant);
// height += 7 (height + 7)
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_BEGIN_STATION && direction == 3)
@ -730,15 +731,20 @@ void track_paint_util_draw_station_inverted(
}
bool track_paint_util_draw_station_covers(
paint_session* session, enum edge_t edge, bool hasFence, const rct_ride_entrance_definition* entranceStyle, uint16_t height)
paint_session* session, enum edge_t edge, bool hasFence, const StationObject* stationObject, uint16_t height)
{
return track_paint_util_draw_station_covers_2(session, edge, hasFence, entranceStyle, height, STATION_VARIANT_BASIC);
return track_paint_util_draw_station_covers_2(session, edge, hasFence, stationObject, height, STATION_VARIANT_BASIC);
}
bool track_paint_util_draw_station_covers_2(
paint_session* session, enum edge_t edge, bool hasFence, const rct_ride_entrance_definition* entranceStyle, uint16_t height,
paint_session* session, enum edge_t edge, bool hasFence, const StationObject* stationObject, uint16_t height,
uint8_t stationVariant)
{
if (stationObject == nullptr)
{
return false;
}
if (!(session->Unk141E9DB & (G141E9DB_FLAG_1 | G141E9DB_FLAG_2)))
{
return false;
@ -751,7 +757,16 @@ bool track_paint_util_draw_station_covers_2(
};
uint32_t imageId;
uint32_t baseImageId = entranceStyle->base_image_id;
uint32_t baseImageId = stationObject->ShelterImageId;
if (stationObject->Flags & STATION_OBJECT_FLAGS::HAS_SECONDARY_COLOUR)
{
baseImageId |= IMAGE_TYPE_REMAP_2_PLUS;
}
if (stationObject->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT)
{
baseImageId |= IMAGE_TYPE_TRANSPARENT;
}
int32_t imageOffset = 0;
LocationXYZ16 offset, bounds = { 0, 0, 0 }, boundsOffset = { 0, 0, 0 };
@ -823,14 +838,14 @@ void track_paint_util_draw_station_platform(
paint_session* session, Ride* ride, uint8_t direction, int32_t height, int32_t zOffset, const TileElement* tileElement)
{
LocationXY16 position = session->MapPosition;
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
if (direction & 1)
{
bool hasFence = track_paint_util_has_fence(EDGE_NE, position, tileElement, ride, session->CurrentRotation);
uint32_t imageId = (hasFence ? SPR_STATION_NARROW_EDGE_FENCED_NE : SPR_STATION_NARROW_EDGE_NE)
| session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 0, 0, 8, 32, 1, height + zOffset);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, stationObj, height);
imageId = SPR_STATION_NARROW_EDGE_SW | session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 24, 0, 8, 32, 1, height + zOffset);
@ -841,7 +856,7 @@ void track_paint_util_draw_station_platform(
imageId = SPR_STATION_FENCE_NW_SE | session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 31, 0, 1, 32, 7, height + zOffset + 2);
}
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, stationObj, height);
}
else
{
@ -849,7 +864,7 @@ void track_paint_util_draw_station_platform(
uint32_t imageId = (hasFence ? SPR_STATION_NARROW_EDGE_FENCED_NW : SPR_STATION_NARROW_EDGE_NW)
| session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 0, 0, 32, 8, 1, height + zOffset);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, stationObj, height);
imageId = SPR_STATION_NARROW_EDGE_SE | session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 0, 24, 32, 8, 1, height + zOffset);
@ -860,13 +875,13 @@ void track_paint_util_draw_station_platform(
imageId = SPR_STATION_FENCE_SW_NE | session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 0, 31, 32, 1, 7, height + zOffset + 2);
}
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, stationObj, height);
}
}
void track_paint_util_draw_pier(
paint_session* session, Ride* ride, const rct_ride_entrance_definition* entranceStyle, LocationXY16 position,
uint8_t direction, int32_t height, const TileElement* tileElement, uint8_t rotation)
paint_session* session, Ride* ride, const StationObject* stationObj, LocationXY16 position, uint8_t direction,
int32_t height, const TileElement* tileElement, uint8_t rotation)
{
bool hasFence;
uint32_t imageId;
@ -877,7 +892,7 @@ void track_paint_util_draw_pier(
imageId = (hasFence ? SPR_STATION_PIER_EDGE_NE_FENCED : SPR_STATION_PIER_EDGE_NE)
| session->TrackColours[SCHEME_SUPPORTS];
sub_98197C(session, imageId, 0, 0, 6, 32, 1, height, 2, 0, height);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, stationObj, height);
imageId = SPR_STATION_PIER_EDGE_SW | session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 24, 0, 8, 32, 1, height);
@ -888,7 +903,7 @@ void track_paint_util_draw_pier(
imageId = SPR_STATION_PIER_FENCE_SW | session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 31, 0, 1, 32, 7, height + 2);
}
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, stationObj, height);
}
else
{
@ -896,7 +911,7 @@ void track_paint_util_draw_pier(
imageId = (hasFence ? SPR_STATION_PIER_EDGE_NW_FENCED : SPR_STATION_PIER_EDGE_NW)
| session->TrackColours[SCHEME_SUPPORTS];
sub_98197C(session, imageId, 0, 0, 32, 6, 1, height, 0, 2, height);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, stationObj, height);
imageId = SPR_STATION_PIER_EDGE_SE | session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 0, 24, 32, 8, 1, height);
@ -907,7 +922,7 @@ void track_paint_util_draw_pier(
imageId = SPR_STATION_PIER_FENCE_SE | session->TrackColours[SCHEME_SUPPORTS];
sub_98196C(session, imageId, 0, 31, 32, 1, 7, height + 2);
}
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, stationObj, height);
}
}
@ -2149,14 +2164,6 @@ void track_paint(paint_session* session, uint8_t direction, int32_t height, cons
return;
}
// HACK Set entrance style to plain if none to stop glitch until entrance track piece is implemented
bool isEntranceStyleNone = false;
if (ride->entrance_style == RIDE_ENTRANCE_STYLE_NONE)
{
isEntranceStyleNone = true;
ride->entrance_style = RIDE_ENTRANCE_STYLE_PLAIN;
}
rct_drawpixelinfo* dpi = session->DPI;
if ((!gTrackDesignSaveMode || rideIndex == gTrackDesignSaveRideIndex)
@ -2212,9 +2219,4 @@ void track_paint(paint_session* session, uint8_t direction, int32_t height, cons
}
}
}
if (isEntranceStyleNone)
{
ride->entrance_style = RIDE_ENTRANCE_STYLE_NONE;
}
}

View File

@ -16,6 +16,8 @@
#include "../world/Map.h"
#include "RideData.h"
class StationObject;
extern const uint8_t track_map_2x2[][4];
extern const uint8_t edges_2x2[];
@ -284,10 +286,9 @@ void track_paint_util_paint_fences(
paint_session* session, uint8_t edges, LocationXY16 position, const TileElement* tileElement, Ride* ride,
uint32_t colourFlags, uint16_t height, const uint32_t fenceSprites[4], uint8_t rotation);
bool track_paint_util_draw_station_covers(
paint_session* session, enum edge_t edge, bool hasFence, const rct_ride_entrance_definition* entranceStyle,
uint16_t height);
paint_session* session, enum edge_t edge, bool hasFence, const StationObject* stationObject, uint16_t height);
bool track_paint_util_draw_station_covers_2(
paint_session* session, enum edge_t edge, bool hasFence, const rct_ride_entrance_definition* entranceStyle, uint16_t height,
paint_session* session, enum edge_t edge, bool hasFence, const StationObject* stationObject, uint16_t height,
uint8_t stationVariant);
void track_paint_util_draw_station_platform(
paint_session* session, Ride* ride, uint8_t direction, int32_t height, int32_t zOffset, const TileElement* tileElement);
@ -304,8 +305,8 @@ void track_paint_util_draw_station_inverted(
uint8_t stationVariant);
bool track_paint_util_should_paint_supports(LocationXY16 position);
void track_paint_util_draw_pier(
paint_session* session, Ride* ride, const rct_ride_entrance_definition* entranceStyle, LocationXY16 position,
uint8_t direction, int32_t height, const TileElement* tileElement, uint8_t rotation);
paint_session* session, Ride* ride, const StationObject* stationObject, LocationXY16 position, uint8_t direction,
int32_t height, const TileElement* tileElement, uint8_t rotation);
void track_paint_util_draw_station_metal_supports(paint_session* session, uint8_t direction, uint16_t height, uint32_t colour);
void track_paint_util_draw_station_metal_supports_2(
paint_session* session, uint8_t direction, uint16_t height, uint32_t colour, uint8_t type);

View File

@ -7282,7 +7282,7 @@ static void vehicle_update_additional_animation(rct_vehicle* vehicle)
if (al != ah)
{
Ride* ride = get_ride(vehicle->ride);
if (ride->entrance_style == RIDE_ENTRANCE_STYLE_PLAIN
if (!ride_has_station_shelter(ride)
|| (vehicle->status != VEHICLE_STATUS_MOVING_TO_END_OF_STATION
&& vehicle->status != VEHICLE_STATUS_ARRIVING))
{

View File

@ -132,28 +132,28 @@ static void multi_dimension_rc_track_station(
track_paint_util_draw_station_metal_supports_2(session, direction, height, session->TrackColours[SCHEME_SUPPORTS], 11);
Ride* ride = get_ride(rideIndex);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
bool hasFence;
if (direction == 0 || direction == 2)
{
hasFence = track_paint_util_has_fence(EDGE_NW, position, tileElement, ride, session->CurrentRotation);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, stationObj, height);
}
else
{
hasFence = track_paint_util_has_fence(EDGE_NE, position, tileElement, ride, session->CurrentRotation);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, stationObj, height);
}
if (direction == 0 || direction == 2)
{
hasFence = track_paint_util_has_fence(EDGE_SE, position, tileElement, ride, session->CurrentRotation);
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, stationObj, height);
}
else
{
hasFence = track_paint_util_has_fence(EDGE_SW, position, tileElement, ride, session->CurrentRotation);
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, stationObj, height);
}
paint_util_push_tunnel_rotated(session, direction, height, TUNNEL_6);

View File

@ -675,7 +675,7 @@ static void paint_mini_golf_station(
{
LocationXY16 position = session->MapPosition;
Ride* ride = get_ride(rideIndex);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
uint32_t imageId;
bool hasFence;
@ -698,8 +698,8 @@ static void paint_mini_golf_station(
sub_98197C(session, imageId, 10, 0, 1, 32, 7, height, 31, 0, height + 2);
}
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SW, hasSWFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, stationObj, height);
track_paint_util_draw_station_covers(session, EDGE_SW, hasSWFence, stationObj, height);
// Was leftwards tunnel in game, seems odd
paint_util_push_tunnel_right(session, height, TUNNEL_6);
@ -720,8 +720,8 @@ static void paint_mini_golf_station(
sub_98197C(session, imageId, 0, 10, 32, 1, 7, height, 0, 31, height + 2);
}
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SE, hasSEFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, stationObj, height);
track_paint_util_draw_station_covers(session, EDGE_SE, hasSEFence, stationObj, height);
paint_util_push_tunnel_left(session, height, TUNNEL_6);
}

View File

@ -349,7 +349,7 @@ static void paint_go_karts_station(
{
LocationXY16 position = session->MapPosition;
Ride* ride = get_ride(rideIndex);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
bool hasFence;
uint32_t imageId;
@ -373,12 +373,12 @@ static void paint_go_karts_station(
if (direction == 0 || direction == 2)
{
hasFence = track_paint_util_has_fence(EDGE_NW, position, tileElement, ride, session->CurrentRotation);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, stationObj, height);
}
else
{
hasFence = track_paint_util_has_fence(EDGE_NE, position, tileElement, ride, session->CurrentRotation);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, stationObj, height);
}
imageId = sprites[direction][1] | session->TrackColours[SCHEME_TRACK];
@ -398,12 +398,12 @@ static void paint_go_karts_station(
if (direction == 0 || direction == 2)
{
hasFence = track_paint_util_has_fence(EDGE_SE, position, tileElement, ride, session->CurrentRotation);
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, stationObj, height);
}
else
{
hasFence = track_paint_util_has_fence(EDGE_SW, position, tileElement, ride, session->CurrentRotation);
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, stationObj, height);
}
if (tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_END_STATION)

View File

@ -184,7 +184,7 @@ static void chairlift_paint_station_ne_sw(
;
bool isEnd = chairlift_paint_util_is_last_track(rideIndex, tileElement, pos, trackType);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
wooden_a_supports_paint_setup(session, 0, 0, height, session->TrackColours[SCHEME_MISC], nullptr);
@ -203,7 +203,7 @@ static void chairlift_paint_station_ne_sw(
imageId = SPR_FENCE_METAL_NW | session->TrackColours[SCHEME_TRACK];
sub_98199C(session, imageId, 0, 0, 32, 1, 7, height, 0, 2, height + 2);
}
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, stationObj, height);
if ((direction == 2 && isStart) || (direction == 0 && isEnd))
{
@ -217,7 +217,7 @@ static void chairlift_paint_station_ne_sw(
imageId = SPR_FENCE_METAL_SE | session->TrackColours[SCHEME_TRACK];
sub_98197C(session, imageId, 0, 0, 32, 1, 27, height, 0, 30, height + 2);
}
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SE, hasFence, stationObj, height);
bool drawFrontColumn = true;
bool drawBackColumn = true;
@ -275,7 +275,7 @@ static void chairlift_paint_station_se_nw(
;
bool isEnd = chairlift_paint_util_is_last_track(rideIndex, tileElement, pos, trackType);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
wooden_a_supports_paint_setup(session, 1, 0, height, session->TrackColours[SCHEME_MISC], nullptr);
@ -294,7 +294,7 @@ static void chairlift_paint_station_se_nw(
imageId = SPR_FENCE_METAL_NE | session->TrackColours[SCHEME_TRACK];
sub_98199C(session, imageId, 0, 0, 1, 32, 7, height, 2, 0, height + 2);
}
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, stationObj, height);
if ((direction == 1 && isStart) || (direction == 3 && isEnd))
{
@ -308,7 +308,7 @@ static void chairlift_paint_station_se_nw(
imageId = SPR_FENCE_METAL_SW | session->TrackColours[SCHEME_TRACK];
sub_98197C(session, imageId, 0, 0, 1, 32, 27, height, 30, 0, height + 2);
}
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, entranceStyle, height);
track_paint_util_draw_station_covers(session, EDGE_SW, hasFence, stationObj, height);
bool drawRightColumn = true;
bool drawLeftColumn = true;

View File

@ -65,19 +65,19 @@ static void paint_boat_hire_station(
{
LocationXY16 position = session->MapPosition;
Ride* ride = get_ride(rideIndex);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
if (direction & 1)
{
paint_util_push_tunnel_right(session, height, TUNNEL_6);
track_paint_util_draw_pier(
session, ride, entranceStyle, position, direction, height, tileElement, session->CurrentRotation);
session, ride, stationObj, position, direction, height, tileElement, session->CurrentRotation);
}
else
{
paint_util_push_tunnel_left(session, height, TUNNEL_6);
track_paint_util_draw_pier(
session, ride, entranceStyle, position, direction, height, tileElement, session->CurrentRotation);
session, ride, stationObj, position, direction, height, tileElement, session->CurrentRotation);
}
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);

View File

@ -80,7 +80,7 @@ static void submarine_ride_paint_track_station(
{
LocationXY16 position = session->MapPosition;
Ride* ride = get_ride(rideIndex);
const rct_ride_entrance_definition* entranceStyle = &RideEntranceDefinitions[ride->entrance_style];
auto stationObj = ride_get_station_object(ride);
int32_t heightLower = height - 16;
uint32_t imageId;
@ -91,7 +91,7 @@ static void submarine_ride_paint_track_station(
paint_util_push_tunnel_right(session, height, TUNNEL_6);
track_paint_util_draw_pier(
session, ride, entranceStyle, position, direction, height, tileElement, session->CurrentRotation);
session, ride, stationObj, position, direction, height, tileElement, session->CurrentRotation);
}
else
{
@ -100,7 +100,7 @@ static void submarine_ride_paint_track_station(
paint_util_push_tunnel_left(session, height, TUNNEL_6);
track_paint_util_draw_pier(
session, ride, entranceStyle, position, direction, height, tileElement, session->CurrentRotation);
session, ride, stationObj, position, direction, height, tileElement, session->CurrentRotation);
}
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);

View File

@ -159,7 +159,7 @@ void scenario_begin()
park_calculate_size();
map_count_remaining_land_rights();
staff_reset_stats();
gLastEntranceStyle = RIDE_ENTRANCE_STYLE_PLAIN;
gLastEntranceStyle = 0;
memset(gMarketingCampaignDaysLeft, 0, 20);
gParkRatingCasualtyPenalty = 0;

View File

@ -826,21 +826,9 @@ enum
SPR_G2_SELECTION_EDGE_SW = SPR_G2_BEGIN + 110,
SPR_G2_SELECTION_EDGE_SE = SPR_G2_BEGIN + 111,
SPR_G2_WALL_TEXTURE_BRICK = SPR_G2_BEGIN + 112,
SPR_G2_WALL_TEXTURE_IRON = SPR_G2_BEGIN + 113,
SPR_G2_WALL_TEXTURE_GREY = SPR_G2_BEGIN + 114,
SPR_G2_WALL_TEXTURE_YELLOW = SPR_G2_BEGIN + 115,
SPR_G2_WALL_TEXTURE_RED = SPR_G2_BEGIN + 116,
SPR_G2_WALL_TEXTURE_PURPLE = SPR_G2_BEGIN + 117,
SPR_G2_WALL_TEXTURE_GREEN = SPR_G2_BEGIN + 118,
SPR_G2_WALL_TEXTURE_STONE_BROWN = SPR_G2_BEGIN + 119,
SPR_G2_WALL_TEXTURE_STONE_GREY = SPR_G2_BEGIN + 120,
SPR_G2_WALL_TEXTURE_SKYSCRAPER_A = SPR_G2_BEGIN + 121,
SPR_G2_WALL_TEXTURE_SKYSCRAPER_B = SPR_G2_BEGIN + 122,
SPR_G2_EYEDROPPER = SPR_G2_BEGIN + 112,
SPR_G2_EYEDROPPER = SPR_G2_BEGIN + 123,
SPR_G2_CHAR_BEGIN = SPR_G2_BEGIN + 124,
SPR_G2_CHAR_BEGIN = SPR_G2_BEGIN + 113,
SPR_G2_AE_UPPER = SPR_G2_CHAR_BEGIN,
SPR_G2_AE_LOWER = SPR_G2_CHAR_BEGIN + 1,
@ -938,30 +926,6 @@ enum
// of the last possible range of image ID values that is large enough to fit all csg1 sprites.
SPR_CSG_BEGIN = 393216,
SPR_CSG_EDGE_BRICK_BASE = SPR_CSG_BEGIN + 40506,
SPR_CSG_EDGE_IRON_BASE = SPR_CSG_BEGIN + 40590,
SPR_CSG_EDGE_RED_BASE = SPR_CSG_BEGIN + 40926,
SPR_CSG_EDGE_YELLOW_BASE = SPR_CSG_BEGIN + 41030,
SPR_CSG_EDGE_GREY_BASE = SPR_CSG_BEGIN + 41134,
SPR_CSG_EDGE_PURPLE_BASE = SPR_CSG_BEGIN + 41238,
SPR_CSG_EDGE_GREEN_BASE = SPR_CSG_BEGIN + 41342,
SPR_CSG_EDGE_STONE_BROWN_BASE = SPR_CSG_BEGIN + 41446,
SPR_CSG_EDGE_STONE_GREY_BASE = SPR_CSG_BEGIN + 41550,
SPR_CSG_EDGE_SKYSCRAPER_A_BASE = SPR_CSG_BEGIN + 41654,
SPR_CSG_EDGE_SKYSCRAPER_B_BASE = SPR_CSG_BEGIN + 41758,
SPR_CSG_WALL_TEXTURE_BRICK = SPR_CSG_BEGIN + 47365,
SPR_CSG_WALL_TEXTURE_IRON = SPR_CSG_BEGIN + 47366,
SPR_CSG_WALL_TEXTURE_GREY = SPR_CSG_BEGIN + 47368,
SPR_CSG_WALL_TEXTURE_YELLOW = SPR_CSG_BEGIN + 47369,
SPR_CSG_WALL_TEXTURE_RED = SPR_CSG_BEGIN + 47371,
SPR_CSG_WALL_TEXTURE_PURPLE = SPR_CSG_BEGIN + 47373,
SPR_CSG_WALL_TEXTURE_GREEN = SPR_CSG_BEGIN + 47374,
SPR_CSG_WALL_TEXTURE_STONE_BROWN = SPR_CSG_BEGIN + 47375,
SPR_CSG_WALL_TEXTURE_STONE_GREY = SPR_CSG_BEGIN + 47376,
SPR_CSG_WALL_TEXTURE_SKYSCRAPER_A = SPR_CSG_BEGIN + 47377,
SPR_CSG_WALL_TEXTURE_SKYSCRAPER_B = SPR_CSG_BEGIN + 47378,
SPR_CSG_ICE_CREAM_STALL_BEGIN = SPR_CSG_BEGIN + 60625,
SPR_CSG_TOILETS_BEGIN = SPR_CSG_BEGIN + 61289,

View File

@ -25,6 +25,8 @@
#include "../localisation/Localisation.h"
#include "../management/Finance.h"
#include "../network/network.h"
#include "../object/ObjectManager.h"
#include "../object/TerrainSurfaceObject.h"
#include "../ride/RideData.h"
#include "../ride/Track.h"
#include "../ride/TrackData.h"
@ -47,6 +49,8 @@
#include <algorithm>
#include <iterator>
using namespace OpenRCT2;
/**
* Replaces 0x00993CCC, 0x00993CCE
*/
@ -56,24 +60,6 @@ const CoordsXY CoordsDirectionDelta[] = { { -32, 0 }, { 0, +32 }, { +32, 0 }
const TileCoordsXY TileDirectionDelta[] = { { -1, 0 }, { 0, +1 }, { +1, 0 }, { 0, -1 },
{ -1, +1 }, { +1, +1 }, { +1, -1 }, { -1, -1 } };
/** rct2: 0x0097B8B8 */
const money32 TerrainPricing[] = {
300, // TERRAIN_GRASS
100, // TERRAIN_SAND
80, // TERRAIN_DIRT
120, // TERRAIN_ROCK
100, // TERRAIN_MARTIAN
100, // TERRAIN_CHECKERBOARD
110, // TERRAIN_GRASS_CLUMPS
130, // TERRAIN_ICE
110, // TERRAIN_GRID_RED
110, // TERRAIN_GRID_YELLOW
110, // TERRAIN_GRID_BLUE
110, // TERRAIN_GRID_GREEN
110, // TERRAIN_SAND_DARK
110, // TERRAIN_SAND_LIGHT
};
uint16_t gMapSelectFlags;
uint16_t gMapSelectType;
LocationXY16 gMapSelectPositionA;
@ -1309,11 +1295,13 @@ static money32 map_change_surface_style(
// Prevent network-originated value of surfaceStyle from causing
// invalid access.
uint8_t style = surfaceStyle & 0x1F;
if (style >= std::size(TerrainPricing))
auto& objManager = GetContext()->GetObjectManager();
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(
objManager.GetLoadedObject(OBJECT_TYPE_TERRAIN_SURFACE, style));
if (surfaceObj != nullptr)
{
return MONEY32_UNDEFINED;
surfaceCost += surfaceObj->Price;
}
surfaceCost += TerrainPricing[style];
if (flags & GAME_COMMAND_FLAG_APPLY)
{

View File

@ -81,7 +81,6 @@ enum
extern const CoordsXY CoordsDirectionDelta[];
extern const TileCoordsXY TileDirectionDelta[];
extern const money32 TerrainPricing[];
extern uint16_t gWidePathTileLoopX;
extern uint16_t gWidePathTileLoopY;

View File

@ -9,8 +9,10 @@
#include "MapAnimation.h"
#include "../Context.h"
#include "../Game.h"
#include "../interface/Viewport.h"
#include "../object/StationObject.h"
#include "../ride/Ride.h"
#include "../ride/RideData.h"
#include "../ride/Track.h"
@ -103,11 +105,7 @@ void map_animation_invalidate_all()
*/
static bool map_animation_invalidate_ride_entrance(int32_t x, int32_t y, int32_t baseZ)
{
TileElement* tileElement;
Ride* ride;
const rct_ride_entrance_definition* entranceDefinition;
tileElement = map_get_first_element_at(x >> 5, y >> 5);
auto tileElement = map_get_first_element_at(x >> 5, y >> 5);
do
{
if (tileElement->base_height != baseZ)
@ -117,11 +115,16 @@ static bool map_animation_invalidate_ride_entrance(int32_t x, int32_t y, int32_t
if (tileElement->AsEntrance()->GetEntranceType() != ENTRANCE_TYPE_RIDE_ENTRANCE)
continue;
ride = get_ride(tileElement->AsEntrance()->GetRideIndex());
entranceDefinition = &RideEntranceDefinitions[ride->entrance_style];
int32_t height = (tileElement->base_height * 8) + entranceDefinition->height + 8;
map_invalidate_tile_zoom1(x, y, height, height + 16);
auto ride = get_ride(tileElement->AsEntrance()->GetRideIndex());
if (ride != nullptr)
{
auto stationObj = ride_get_station_object(ride);
if (stationObj != nullptr)
{
int32_t height = (tileElement->base_height * 8) + stationObj->Height + 8;
map_invalidate_tile_zoom1(x, y, height, height + 16);
}
}
return false;
} while (!(tileElement++)->IsLastForTile());

View File

@ -20,6 +20,8 @@
#include <openrct2/world/Sprite.h>
#include <openrct2/world/Surface.h>
class StationObject;
#define gRideEntries RCT2_ADDRESS(0x009ACFA4, rct_ride_entry*)
#define gTileElementTilePointers RCT2_ADDRESS(0x013CE9A4, TileElement*)
rct_sprite* sprite_list = RCT2_ADDRESS(0x010E63BC, rct_sprite);
@ -418,3 +420,8 @@ uint8_t PathElement::GetEdges() const
{
return edges & 0xF;
}
StationObject* ride_get_station_object(const Ride* ride)
{
return nullptr;
}

View File

@ -47,7 +47,7 @@ namespace TestPaint
{
Ride ride = {};
ride.entrance_style = RIDE_ENTRANCE_STYLE_PLAIN;
ride.entrance_style = 0;
static rct_ride_entry rideEntry = {};
rct_ride_entry_vehicle vehicleEntry{};
vehicleEntry.base_image_id = 0x70000;
@ -57,7 +57,7 @@ namespace TestPaint
}
{
rct2_ride ride = {};
ride.entrance_style = RIDE_ENTRANCE_STYLE_PLAIN;
ride.entrance_style = 0;
RCT2_Rides[0] = ride;
}

View File

@ -167,7 +167,7 @@ public:
int Variations(uint8_t rideType, uint8_t trackType) override
{
return RIDE_ENTRANCE_STYLE_COUNT - 1;
return 12;
}
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override