mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #9222 from IntelOrca/implement/485-ghost-train-simulation
Implement #485: ghost train simulation
This commit is contained in:
commit
f1ac847fce
|
@ -3770,6 +3770,10 @@ STR_6319 :{WINDOW_COLOUR_2}Block Brake Closed
|
|||
STR_6320 :{WINDOW_COLOUR_2}Indestructible
|
||||
STR_6321 :{WINDOW_COLOUR_2}Addition is broken
|
||||
STR_6322 :{WINDOW_COLOUR_2}Sprite Id: {BLACK}{INT32}
|
||||
STR_6323 :Simulating
|
||||
STR_6324 :Simulate
|
||||
STR_6325 :{SMALLFONT}{BLACK}Simulate ride/attraction
|
||||
STR_6326 :Can't simulate {POP16}{POP16}{POP16}{STRINGID}...
|
||||
|
||||
#############
|
||||
# Scenarios #
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
0.2.2+ (in development)
|
||||
------------------------------------------------------------------------
|
||||
- Feature: [#485] Rides can now be simulated with ghost trains during construction.
|
||||
- Feature: [#2339] Find local servers automatically when fetching servers.
|
||||
- Feature: [#7296] Allow assigning a keyboard shortcut for the scenery picker.
|
||||
- Feature: [#8029] Add the Hungarian Forint (HUF) to the list of available currencies.
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 541 B |
Binary file not shown.
After Width: | Height: | Size: 500 B |
Binary file not shown.
After Width: | Height: | Size: 574 B |
Binary file not shown.
After Width: | Height: | Size: 569 B |
Binary file not shown.
After Width: | Height: | Size: 811 B |
|
@ -430,6 +430,23 @@
|
|||
{
|
||||
"path": "icons/multiplayer_desync.png"
|
||||
},
|
||||
{
|
||||
"path": "icons/simulate.png",
|
||||
"x_offset": 2,
|
||||
"y_offset": 2
|
||||
},
|
||||
{
|
||||
"path": "icons/rct1_simulate_off.png"
|
||||
},
|
||||
{
|
||||
"path": "icons/rct1_simulate_off_pressed.png"
|
||||
},
|
||||
{
|
||||
"path": "icons/rct1_simulate_on.png"
|
||||
},
|
||||
{
|
||||
"path": "icons/rct1_simulate_on_pressed.png"
|
||||
},
|
||||
{
|
||||
"path": "font/latin/ae-uc-small.png",
|
||||
"y_offset": 0,
|
||||
|
|
|
@ -173,7 +173,6 @@ enum WINDOW_OPTIONS_WIDGET_IDX {
|
|||
|
||||
// Advanced
|
||||
WIDX_DEBUGGING_TOOLS = WIDX_PAGE_START,
|
||||
WIDX_TEST_UNFINISHED_TRACKS,
|
||||
WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM,
|
||||
WIDX_SAVE_PLUGIN_DATA_CHECKBOX,
|
||||
WIDX_STAY_CONNECTED_AFTER_DESYNC,
|
||||
|
@ -359,17 +358,16 @@ static rct_widget window_options_misc_widgets[] = {
|
|||
static rct_widget window_options_advanced_widgets[] = {
|
||||
MAIN_OPTIONS_WIDGETS,
|
||||
{ WWT_CHECKBOX, 2, 10, 299, 54, 65, STR_ENABLE_DEBUGGING_TOOLS, STR_ENABLE_DEBUGGING_TOOLS_TIP }, // Enable debugging tools
|
||||
{ WWT_CHECKBOX, 2, 10, 299, 69, 80, STR_TEST_UNFINISHED_TRACKS, STR_TEST_UNFINISHED_TRACKS_TIP }, // Test unfinished tracks
|
||||
{ WWT_CHECKBOX, 2, 10, 299, 84, 95, STR_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM, STR_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM_TIP }, // Allow loading with incorrect checksum
|
||||
{ WWT_CHECKBOX, 2, 10, 299, 99, 110, STR_SAVE_PLUGIN_DATA, STR_SAVE_PLUGIN_DATA_TIP }, // Export plug-in objects with saved games
|
||||
{ WWT_CHECKBOX, 2, 10, 299, 114, 125, STR_STAY_CONNECTED_AFTER_DESYNC, STR_STAY_CONNECTED_AFTER_DESYNC_TIP }, // Do not disconnect after the client desynchronises with the server
|
||||
{ WWT_CHECKBOX, 1, 10, 299, 129, 140, STR_ALWAYS_NATIVE_LOADSAVE, STR_ALWAYS_NATIVE_LOADSAVE_TIP }, // Use native load/save window
|
||||
{ WWT_DROPDOWN, 1, 165, 299, 145, 157, STR_NONE, STR_NONE }, // Autosave dropdown
|
||||
{ WWT_BUTTON, 1, 288, 298, 146, 156, STR_DROPDOWN_GLYPH, STR_AUTOSAVE_FREQUENCY_TIP }, // Autosave dropdown button
|
||||
SPINNER_WIDGETS (1, 165, 299, 165, 176, STR_NONE, STR_AUTOSAVE_AMOUNT_TIP ), // Autosave amount spinner
|
||||
{ WWT_LABEL, 1, 23, 298, 184, 195, STR_PATH_TO_RCT1, STR_PATH_TO_RCT1_TIP }, // RCT 1 path text
|
||||
{ WWT_BUTTON, 1, 24, 289, 199, 212, STR_NONE, STR_STRING_TOOLTIP }, // RCT 1 path button
|
||||
{ WWT_BUTTON, 1, 289, 299, 199, 212, STR_CLOSE_X, STR_PATH_TO_RCT1_CLEAR_TIP }, // RCT 1 path clear button
|
||||
{ WWT_CHECKBOX, 2, 10, 299, 69, 80, STR_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM, STR_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM_TIP }, // Allow loading with incorrect checksum
|
||||
{ WWT_CHECKBOX, 2, 10, 299, 84, 95, STR_SAVE_PLUGIN_DATA, STR_SAVE_PLUGIN_DATA_TIP }, // Export plug-in objects with saved games
|
||||
{ WWT_CHECKBOX, 2, 10, 299, 99, 110, STR_STAY_CONNECTED_AFTER_DESYNC, STR_STAY_CONNECTED_AFTER_DESYNC_TIP }, // Do not disconnect after the client desynchronises with the server
|
||||
{ WWT_CHECKBOX, 1, 10, 299, 114, 125, STR_ALWAYS_NATIVE_LOADSAVE, STR_ALWAYS_NATIVE_LOADSAVE_TIP }, // Use native load/save window
|
||||
{ WWT_DROPDOWN, 1, 165, 299, 130, 142, STR_NONE, STR_NONE }, // Autosave dropdown
|
||||
{ WWT_BUTTON, 1, 288, 298, 131, 141, STR_DROPDOWN_GLYPH, STR_AUTOSAVE_FREQUENCY_TIP }, // Autosave dropdown button
|
||||
SPINNER_WIDGETS (1, 165, 299, 150, 161, STR_NONE, STR_AUTOSAVE_AMOUNT_TIP ), // Autosave amount spinner
|
||||
{ WWT_LABEL, 1, 23, 298, 169, 180, STR_PATH_TO_RCT1, STR_PATH_TO_RCT1_TIP }, // RCT 1 path text
|
||||
{ WWT_BUTTON, 1, 24, 289, 184, 197, STR_NONE, STR_STRING_TOOLTIP }, // RCT 1 path button
|
||||
{ WWT_BUTTON, 1, 289, 299, 184, 197, STR_CLOSE_X, STR_PATH_TO_RCT1_CLEAR_TIP }, // RCT 1 path clear button
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
|
@ -601,7 +599,6 @@ static uint64_t window_options_page_enabled_widgets[] = {
|
|||
|
||||
MAIN_OPTIONS_ENABLED_WIDGETS |
|
||||
(1 << WIDX_DEBUGGING_TOOLS) |
|
||||
(1 << WIDX_TEST_UNFINISHED_TRACKS) |
|
||||
(1 << WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM) |
|
||||
(1 << WIDX_SAVE_PLUGIN_DATA_CHECKBOX) |
|
||||
(1 << WIDX_STAY_CONNECTED_AFTER_DESYNC) |
|
||||
|
@ -924,11 +921,6 @@ static void window_options_mouseup(rct_window* w, rct_widgetindex widgetIndex)
|
|||
config_save_default();
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
case WIDX_TEST_UNFINISHED_TRACKS:
|
||||
gConfigGeneral.test_unfinished_tracks ^= 1;
|
||||
config_save_default();
|
||||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM:
|
||||
gConfigGeneral.allow_loading_with_incorrect_checksum = !gConfigGeneral
|
||||
.allow_loading_with_incorrect_checksum;
|
||||
|
@ -1926,7 +1918,6 @@ static void window_options_invalidate(rct_window* w)
|
|||
|
||||
case WINDOW_OPTIONS_PAGE_ADVANCED:
|
||||
widget_set_checkbox_value(w, WIDX_DEBUGGING_TOOLS, gConfigGeneral.debugging_tools);
|
||||
widget_set_checkbox_value(w, WIDX_TEST_UNFINISHED_TRACKS, gConfigGeneral.test_unfinished_tracks);
|
||||
widget_set_checkbox_value(
|
||||
w, WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM, gConfigGeneral.allow_loading_with_incorrect_checksum);
|
||||
widget_set_checkbox_value(w, WIDX_SAVE_PLUGIN_DATA_CHECKBOX, gConfigGeneral.save_plugin_data);
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
WIDX_LOCATE,
|
||||
WIDX_DEMOLISH,
|
||||
WIDX_CLOSE_LIGHT,
|
||||
WIDX_SIMULATE_LIGHT,
|
||||
WIDX_TEST_LIGHT,
|
||||
WIDX_OPEN_LIGHT,
|
||||
WIDX_RIDE_TYPE,
|
||||
|
@ -231,6 +232,7 @@ static rct_widget window_ride_main_widgets[] = {
|
|||
{ WWT_FLATBTN, 1, 291, 314, 118, 141, SPR_LOCATE, STR_LOCATE_SUBJECT_TIP },
|
||||
{ WWT_FLATBTN, 1, 291, 314, 142, 165, SPR_DEMOLISH, STR_DEMOLISH_RIDE_TIP },
|
||||
{ WWT_IMGBTN, 1, 296, 309, 48, 61, SPR_G2_RCT1_CLOSE_BUTTON_0, STR_CLOSE_RIDE_TIP },
|
||||
{ WWT_IMGBTN, 1, 296, 309, 62, 75, SPR_G2_RCT1_TEST_BUTTON_0, STR_SIMULATE_RIDE_TIP },
|
||||
{ WWT_IMGBTN, 1, 296, 309, 62, 75, SPR_G2_RCT1_TEST_BUTTON_0, STR_TEST_RIDE_TIP },
|
||||
{ WWT_IMGBTN, 1, 296, 309, 76, 89, SPR_G2_RCT1_OPEN_BUTTON_0, STR_OPEN_RIDE_TIP },
|
||||
{ WWT_DROPDOWN, 1, 3, 307, 180, 191, STR_ARG_6_STRINGID, STR_NONE },
|
||||
|
@ -397,6 +399,7 @@ static constexpr const uint64_t window_ride_page_enabled_widgets[] = {
|
|||
(1ULL << WIDX_LOCATE) |
|
||||
(1ULL << WIDX_DEMOLISH) |
|
||||
(1ULL << WIDX_CLOSE_LIGHT) |
|
||||
(1ULL << WIDX_SIMULATE_LIGHT) |
|
||||
(1ULL << WIDX_TEST_LIGHT) |
|
||||
(1ULL << WIDX_OPEN_LIGHT) |
|
||||
(1ULL << WIDX_RIDE_TYPE) |
|
||||
|
@ -2024,6 +2027,7 @@ static void window_ride_main_mouseup(rct_window* w, rct_widgetindex widgetIndex)
|
|||
context_open_detail_window(WD_DEMOLISH_RIDE, w->number);
|
||||
break;
|
||||
case WIDX_CLOSE_LIGHT:
|
||||
case WIDX_SIMULATE_LIGHT:
|
||||
case WIDX_TEST_LIGHT:
|
||||
case WIDX_OPEN_LIGHT:
|
||||
switch (widgetIndex)
|
||||
|
@ -2032,6 +2036,9 @@ static void window_ride_main_mouseup(rct_window* w, rct_widgetindex widgetIndex)
|
|||
case WIDX_CLOSE_LIGHT:
|
||||
status = RIDE_STATUS_CLOSED;
|
||||
break;
|
||||
case WIDX_SIMULATE_LIGHT:
|
||||
status = RIDE_STATUS_SIMULATING;
|
||||
break;
|
||||
case WIDX_TEST_LIGHT:
|
||||
status = RIDE_STATUS_TESTING;
|
||||
break;
|
||||
|
@ -2055,12 +2062,32 @@ static void window_ride_main_mouseup(rct_window* w, rct_widgetindex widgetIndex)
|
|||
*/
|
||||
static void window_ride_main_resize(rct_window* w)
|
||||
{
|
||||
const int32_t offset = gCheatsAllowArbitraryRideTypeChanges ? 15 : 0;
|
||||
w->flags |= WF_RESIZABLE;
|
||||
int32_t minHeight = 180 + offset;
|
||||
int32_t minHeight = 180;
|
||||
if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE)
|
||||
minHeight = 200 + offset + RCT1_LIGHT_OFFSET
|
||||
- (ride_type_has_flag(get_ride(w->number)->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? 14 : 0);
|
||||
{
|
||||
minHeight += 20 + RCT1_LIGHT_OFFSET;
|
||||
|
||||
auto ride = get_ride(w->number);
|
||||
if (ride != nullptr)
|
||||
{
|
||||
#ifdef __SIMULATE_IN_RIDE_WINDOW__
|
||||
if (ride->SupportsStatus(RIDE_STATUS_SIMULATING))
|
||||
{
|
||||
minHeight += 14;
|
||||
}
|
||||
#endif
|
||||
if (ride->SupportsStatus(RIDE_STATUS_TESTING))
|
||||
{
|
||||
minHeight += 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gCheatsAllowArbitraryRideTypeChanges)
|
||||
{
|
||||
minHeight += 15;
|
||||
}
|
||||
|
||||
w->flags |= WF_RESIZABLE;
|
||||
window_set_resize(w, 316, minHeight, 500, 450);
|
||||
window_ride_init_viewport(w);
|
||||
}
|
||||
|
@ -2123,78 +2150,80 @@ static void window_ride_show_view_dropdown(rct_window* w, rct_widget* widget)
|
|||
dropdown_set_checked(w->ride.view, true);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AF64C
|
||||
*/
|
||||
static void window_ride_show_open_dropdown(rct_window* w, rct_widget* widget)
|
||||
static uint8_t window_ride_get_next_default_status(const Ride* ride)
|
||||
{
|
||||
Ride* ride;
|
||||
int32_t numItems, highlightedIndex = 0, checkedIndex;
|
||||
|
||||
ride = get_ride(w->number);
|
||||
|
||||
numItems = 0;
|
||||
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
|
||||
gDropdownItemsArgs[numItems] = STR_CLOSE_RIDE;
|
||||
numItems++;
|
||||
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE))
|
||||
{
|
||||
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
|
||||
gDropdownItemsArgs[numItems] = STR_TEST_RIDE;
|
||||
numItems++;
|
||||
}
|
||||
|
||||
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
|
||||
gDropdownItemsArgs[numItems] = STR_OPEN_RIDE;
|
||||
numItems++;
|
||||
|
||||
window_dropdown_show_text(
|
||||
w->x + widget->left, w->y + widget->top, widget->bottom - widget->top + 1, w->colours[1], 0, numItems);
|
||||
|
||||
checkedIndex = ride->status;
|
||||
switch (ride->status)
|
||||
{
|
||||
default:
|
||||
case RIDE_STATUS_CLOSED:
|
||||
highlightedIndex = 0;
|
||||
if ((ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)
|
||||
|| (ride->lifecycle_flags & RIDE_LIFECYCLE_HAS_STALLED_VEHICLE))
|
||||
break;
|
||||
|
||||
highlightedIndex = 2;
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE))
|
||||
break;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)
|
||||
break;
|
||||
|
||||
highlightedIndex = 1;
|
||||
break;
|
||||
{
|
||||
return RIDE_STATUS_CLOSED;
|
||||
}
|
||||
else if (ride->SupportsStatus(RIDE_STATUS_TESTING) && !(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
{
|
||||
return RIDE_STATUS_TESTING;
|
||||
}
|
||||
else
|
||||
{
|
||||
return RIDE_STATUS_OPEN;
|
||||
}
|
||||
case RIDE_STATUS_SIMULATING:
|
||||
return RIDE_STATUS_TESTING;
|
||||
case RIDE_STATUS_TESTING:
|
||||
highlightedIndex = 2;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)
|
||||
break;
|
||||
|
||||
highlightedIndex = 0;
|
||||
break;
|
||||
return (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) ? RIDE_STATUS_OPEN : RIDE_STATUS_CLOSED;
|
||||
case RIDE_STATUS_OPEN:
|
||||
highlightedIndex = 0;
|
||||
break;
|
||||
return RIDE_STATUS_CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkedIndex != RIDE_STATUS_CLOSED)
|
||||
checkedIndex = 3 - checkedIndex;
|
||||
struct RideStatusDropdownInfo
|
||||
{
|
||||
struct Ride* Ride{};
|
||||
uint8_t CurrentStatus{};
|
||||
uint8_t DefaultStatus{};
|
||||
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE))
|
||||
int32_t NumItems{};
|
||||
int32_t CheckedIndex = -1;
|
||||
int32_t DefaultIndex = -1;
|
||||
};
|
||||
|
||||
static void window_ride_set_dropdown(RideStatusDropdownInfo& info, uint8_t status, rct_string_id text)
|
||||
{
|
||||
if (info.Ride->SupportsStatus(status))
|
||||
{
|
||||
if (checkedIndex != 0)
|
||||
checkedIndex--;
|
||||
if (highlightedIndex != 0)
|
||||
highlightedIndex--;
|
||||
auto index = info.NumItems;
|
||||
gDropdownItemsFormat[index] = STR_DROPDOWN_MENU_LABEL;
|
||||
gDropdownItemsArgs[index] = text;
|
||||
if (info.CurrentStatus == status)
|
||||
{
|
||||
info.CheckedIndex = index;
|
||||
}
|
||||
if (info.DefaultStatus == status)
|
||||
{
|
||||
info.DefaultIndex = index;
|
||||
}
|
||||
info.NumItems++;
|
||||
}
|
||||
}
|
||||
|
||||
dropdown_set_checked(checkedIndex, true);
|
||||
gDropdownDefaultIndex = highlightedIndex;
|
||||
static void window_ride_show_open_dropdown(rct_window* w, rct_widget* widget)
|
||||
{
|
||||
RideStatusDropdownInfo info;
|
||||
info.Ride = get_ride(w->number);
|
||||
info.CurrentStatus = info.Ride->status;
|
||||
info.DefaultStatus = window_ride_get_next_default_status(info.Ride);
|
||||
window_ride_set_dropdown(info, RIDE_STATUS_CLOSED, STR_CLOSE_RIDE);
|
||||
#ifdef __SIMULATE_IN_RIDE_WINDOW__
|
||||
window_ride_set_dropdown(info, RIDE_STATUS_SIMULATING, STR_SIMULATE_RIDE);
|
||||
#endif
|
||||
window_ride_set_dropdown(info, RIDE_STATUS_TESTING, STR_TEST_RIDE);
|
||||
window_ride_set_dropdown(info, RIDE_STATUS_OPEN, STR_OPEN_RIDE);
|
||||
window_dropdown_show_text(
|
||||
w->x + widget->left, w->y + widget->top, widget->bottom - widget->top + 1, w->colours[1], 0, info.NumItems);
|
||||
dropdown_set_checked(info.CheckedIndex, true);
|
||||
gDropdownDefaultIndex = info.DefaultIndex;
|
||||
}
|
||||
|
||||
static void populate_ride_type_dropdown()
|
||||
|
@ -2383,23 +2412,25 @@ static void window_ride_main_mousedown(rct_window* w, rct_widgetindex widgetInde
|
|||
*/
|
||||
static void window_ride_main_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex)
|
||||
{
|
||||
Ride* ride;
|
||||
int32_t status = 0;
|
||||
|
||||
switch (widgetIndex)
|
||||
{
|
||||
case WIDX_VIEW_DROPDOWN:
|
||||
if (dropdownIndex == -1)
|
||||
{
|
||||
dropdownIndex = w->ride.view;
|
||||
ride = get_ride(w->number);
|
||||
dropdownIndex++;
|
||||
if (dropdownIndex != 0 && dropdownIndex <= ride->num_vehicles
|
||||
&& !(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK))
|
||||
dropdownIndex = ride->num_vehicles + 1;
|
||||
|
||||
if (dropdownIndex >= gDropdownNumItems)
|
||||
dropdownIndex = 0;
|
||||
dropdownIndex = w->ride.view + 1;
|
||||
auto ride = get_ride(w->number);
|
||||
if (ride != nullptr)
|
||||
{
|
||||
if (dropdownIndex != 0 && dropdownIndex <= ride->num_vehicles
|
||||
&& !(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK))
|
||||
{
|
||||
dropdownIndex = ride->num_vehicles + 1;
|
||||
}
|
||||
if (dropdownIndex >= gDropdownNumItems)
|
||||
{
|
||||
dropdownIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
w->ride.view = dropdownIndex;
|
||||
|
@ -2407,27 +2438,37 @@ static void window_ride_main_dropdown(rct_window* w, rct_widgetindex widgetIndex
|
|||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_OPEN:
|
||||
if (dropdownIndex == -1)
|
||||
dropdownIndex = gDropdownHighlightedIndex;
|
||||
|
||||
ride = get_ride(w->number);
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) && dropdownIndex != 0)
|
||||
dropdownIndex++;
|
||||
|
||||
switch (dropdownIndex)
|
||||
{
|
||||
auto ride = get_ride(w->number);
|
||||
if (ride != nullptr)
|
||||
{
|
||||
case 0:
|
||||
status = RIDE_STATUS_CLOSED;
|
||||
break;
|
||||
case 1:
|
||||
status = RIDE_STATUS_TESTING;
|
||||
break;
|
||||
case 2:
|
||||
status = RIDE_STATUS_OPEN;
|
||||
break;
|
||||
auto status = RIDE_STATUS_CLOSED;
|
||||
if (dropdownIndex < 0)
|
||||
{
|
||||
dropdownIndex = gDropdownHighlightedIndex;
|
||||
}
|
||||
if (dropdownIndex < (int32_t)std::size(gDropdownItemsArgs))
|
||||
{
|
||||
switch (gDropdownItemsArgs[dropdownIndex])
|
||||
{
|
||||
case STR_CLOSE_RIDE:
|
||||
status = RIDE_STATUS_CLOSED;
|
||||
break;
|
||||
case STR_SIMULATE_RIDE:
|
||||
status = RIDE_STATUS_SIMULATING;
|
||||
break;
|
||||
case STR_TEST_RIDE:
|
||||
status = RIDE_STATUS_TESTING;
|
||||
break;
|
||||
case STR_OPEN_RIDE:
|
||||
status = RIDE_STATUS_OPEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ride_set_status(ride, status);
|
||||
}
|
||||
ride_set_status(ride, status);
|
||||
break;
|
||||
}
|
||||
case WIDX_RIDE_TYPE_DROPDOWN:
|
||||
if (dropdownIndex != -1 && dropdownIndex < RIDE_TYPE_COUNT)
|
||||
{
|
||||
|
@ -2533,13 +2574,26 @@ static void window_ride_main_invalidate(rct_window* w)
|
|||
SPR_CLOSED,
|
||||
SPR_OPEN,
|
||||
SPR_TESTING,
|
||||
SPR_G2_SIMULATE,
|
||||
};
|
||||
window_ride_main_widgets[WIDX_OPEN].image = spriteIds[ride->status];
|
||||
|
||||
#ifdef __SIMULATE_IN_RIDE_WINDOW__
|
||||
window_ride_main_widgets[WIDX_CLOSE_LIGHT].image = SPR_G2_RCT1_CLOSE_BUTTON_0 + (ride->status == RIDE_STATUS_CLOSED) * 2
|
||||
+ widget_is_pressed(w, WIDX_CLOSE_LIGHT);
|
||||
window_ride_main_widgets[WIDX_SIMULATE_LIGHT].image = SPR_G2_RCT1_SIMULATE_BUTTON_0
|
||||
+ (ride->status == RIDE_STATUS_SIMULATING) * 2 + widget_is_pressed(w, WIDX_SIMULATE_LIGHT);
|
||||
window_ride_main_widgets[WIDX_TEST_LIGHT].image = SPR_G2_RCT1_TEST_BUTTON_0 + (ride->status == RIDE_STATUS_TESTING) * 2
|
||||
+ widget_is_pressed(w, WIDX_TEST_LIGHT);
|
||||
#else
|
||||
window_ride_main_widgets[WIDX_CLOSE_LIGHT].image = SPR_G2_RCT1_CLOSE_BUTTON_0 + (ride->status == RIDE_STATUS_CLOSED) * 2
|
||||
+ widget_is_pressed(w, WIDX_CLOSE_LIGHT);
|
||||
|
||||
auto baseSprite = ride->status == RIDE_STATUS_SIMULATING ? SPR_G2_RCT1_SIMULATE_BUTTON_0 : SPR_G2_RCT1_TEST_BUTTON_0;
|
||||
window_ride_main_widgets[WIDX_TEST_LIGHT].image = baseSprite
|
||||
+ (ride->status == RIDE_STATUS_TESTING || ride->status == RIDE_STATUS_SIMULATING) * 2
|
||||
+ widget_is_pressed(w, WIDX_TEST_LIGHT);
|
||||
#endif
|
||||
window_ride_main_widgets[WIDX_OPEN_LIGHT].image = SPR_G2_RCT1_OPEN_BUTTON_0 + (ride->status == RIDE_STATUS_OPEN) * 2
|
||||
+ widget_is_pressed(w, WIDX_OPEN_LIGHT);
|
||||
|
||||
|
@ -2580,11 +2634,21 @@ static void window_ride_main_invalidate(rct_window* w)
|
|||
{
|
||||
window_ride_main_widgets[WIDX_OPEN].type = WWT_EMPTY;
|
||||
window_ride_main_widgets[WIDX_CLOSE_LIGHT].type = WWT_IMGBTN;
|
||||
window_ride_main_widgets[WIDX_TEST_LIGHT].type
|
||||
= (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? WWT_EMPTY : WWT_IMGBTN);
|
||||
window_ride_main_widgets[WIDX_SIMULATE_LIGHT].type = WWT_EMPTY;
|
||||
#ifdef __SIMULATE_IN_RIDE_WINDOW__
|
||||
if (ride->SupportsStatus(RIDE_STATUS_SIMULATING))
|
||||
window_ride_main_widgets[WIDX_SIMULATE_LIGHT].type = WWT_IMGBTN;
|
||||
#endif
|
||||
window_ride_main_widgets[WIDX_TEST_LIGHT].type = ride->SupportsStatus(RIDE_STATUS_TESTING) ? WWT_IMGBTN : WWT_EMPTY;
|
||||
window_ride_main_widgets[WIDX_OPEN_LIGHT].type = WWT_IMGBTN;
|
||||
|
||||
height = 62;
|
||||
if (window_ride_main_widgets[WIDX_SIMULATE_LIGHT].type != WWT_EMPTY)
|
||||
{
|
||||
window_ride_main_widgets[WIDX_SIMULATE_LIGHT].top = height;
|
||||
window_ride_main_widgets[WIDX_SIMULATE_LIGHT].bottom = height + 13;
|
||||
height += 14;
|
||||
}
|
||||
if (window_ride_main_widgets[WIDX_TEST_LIGHT].type != WWT_EMPTY)
|
||||
{
|
||||
window_ride_main_widgets[WIDX_TEST_LIGHT].top = height;
|
||||
|
@ -2594,15 +2658,12 @@ static void window_ride_main_invalidate(rct_window* w)
|
|||
window_ride_main_widgets[WIDX_OPEN_LIGHT].top = height;
|
||||
window_ride_main_widgets[WIDX_OPEN_LIGHT].bottom = height + 13;
|
||||
height += 14 - 24 + RCT1_LIGHT_OFFSET;
|
||||
|
||||
w->min_height = 200 + RCT1_LIGHT_OFFSET - (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? 14 : 0);
|
||||
if (w->height < w->min_height)
|
||||
window_event_resize_call(w);
|
||||
}
|
||||
else
|
||||
{
|
||||
window_ride_main_widgets[WIDX_OPEN].type = WWT_FLATBTN;
|
||||
window_ride_main_widgets[WIDX_CLOSE_LIGHT].type = WWT_EMPTY;
|
||||
window_ride_main_widgets[WIDX_SIMULATE_LIGHT].type = WWT_EMPTY;
|
||||
window_ride_main_widgets[WIDX_TEST_LIGHT].type = WWT_EMPTY;
|
||||
window_ride_main_widgets[WIDX_OPEN_LIGHT].type = WWT_EMPTY;
|
||||
height = 46;
|
||||
|
|
|
@ -79,6 +79,7 @@ enum {
|
|||
WIDX_SEAT_ROTATION_ANGLE_SPINNER,
|
||||
WIDX_SEAT_ROTATION_ANGLE_SPINNER_UP,
|
||||
WIDX_SEAT_ROTATION_ANGLE_SPINNER_DOWN,
|
||||
WIDX_SIMULATE,
|
||||
};
|
||||
|
||||
validate_global_widx(WC_RIDE_CONSTRUCTION, WIDX_CONSTRUCT);
|
||||
|
@ -113,8 +114,8 @@ static rct_widget window_ride_construction_widgets[] = {
|
|||
{ WWT_IMGBTN, 1, 3, 162, 164, 333, 0xFFFFFFFF, STR_RIDE_CONSTRUCTION_CONSTRUCT_SELECTED_SECTION_TIP },
|
||||
{ WWT_FLATBTN, 1, 60, 105, 338, 361, SPR_DEMOLISH_CURRENT_SECTION, STR_RIDE_CONSTRUCTION_REMOVE_HIGHLIGHTED_SECTION_TIP },
|
||||
{ WWT_FLATBTN, 1, 50, 71, 29, 52, SPR_RIDE_CONSTRUCTION_LEFT_CURVE_LARGE, STR_RIDE_CONSTRUCTION_LEFT_CURVE_LARGE_TIP },
|
||||
{ WWT_FLATBTN, 1, 20, 43, 338, 361, SPR_PREVIOUS, STR_RIDE_CONSTRUCTION_MOVE_TO_PREVIOUS_SECTION_TIP },
|
||||
{ WWT_FLATBTN, 1, 122, 145, 338, 361, SPR_NEXT, STR_RIDE_CONSTRUCTION_MOVE_TO_NEXT_SECTION_TIP },
|
||||
{ WWT_FLATBTN, 1, 30, 53, 338, 361, SPR_PREVIOUS, STR_RIDE_CONSTRUCTION_MOVE_TO_PREVIOUS_SECTION_TIP },
|
||||
{ WWT_FLATBTN, 1, 112, 135, 338, 361, SPR_NEXT, STR_RIDE_CONSTRUCTION_MOVE_TO_NEXT_SECTION_TIP },
|
||||
{ WWT_GROUPBOX, 0, 3, 162, 362, 389, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_BUTTON, 1, 9, 78, 372, 383, STR_RIDE_CONSTRUCTION_ENTRANCE, STR_RIDE_CONSTRUCTION_ENTRANCE_TIP },
|
||||
{ WWT_BUTTON, 1, 87, 156, 372, 383, STR_RIDE_CONSTRUCTION_EXIT, STR_RIDE_CONSTRUCTION_EXIT_TIP },
|
||||
|
@ -124,6 +125,7 @@ static rct_widget window_ride_construction_widgets[] = {
|
|||
{ WWT_FLATBTN, 1, 123, 146, 132, 155, SPR_RIDE_CONSTRUCTION_O_SHAPED_TRACK, STR_RIDE_CONSTRUCTION_O_SHAPED_ENCLOSED_TRACK_TIP },
|
||||
{ WWT_GROUPBOX, 0, 96, 162, 120, 160, STR_RIDE_CONSTRUCTION_SEAT_ROT, STR_NONE },
|
||||
SPINNER_WIDGETS (1, 101, 158, 138, 149, 0, STR_RIDE_CONSTRUCTION_SELECT_SEAT_ROTATION_ANGLE_TIP),
|
||||
{ WWT_FLATBTN, 1, 139, 162, 338, 361, SPR_G2_SIMULATE, STR_SIMULATE_RIDE_TIP },
|
||||
{ WIDGETS_END }
|
||||
};
|
||||
|
||||
|
@ -540,8 +542,8 @@ rct_window* window_ride_construction_open()
|
|||
| (1ULL << WIDX_SLOPE_DOWN) | (1ULL << WIDX_LEVEL) | (1ULL << WIDX_SLOPE_UP) | (1ULL << WIDX_SLOPE_UP_STEEP)
|
||||
| (1ULL << WIDX_CHAIN_LIFT) | (1ULL << WIDX_BANK_LEFT) | (1ULL << WIDX_BANK_STRAIGHT) | (1ULL << WIDX_BANK_RIGHT)
|
||||
| (1ULL << WIDX_CONSTRUCT) | (1ULL << WIDX_DEMOLISH) | (1ULL << WIDX_LEFT_CURVE_LARGE) | (1ULL << WIDX_PREVIOUS_SECTION)
|
||||
| (1ULL << WIDX_NEXT_SECTION) | (1ULL << WIDX_ENTRANCE) | (1ULL << WIDX_EXIT) | (1ULL << WIDX_RIGHT_CURVE_LARGE)
|
||||
| (1ULL << WIDX_ROTATE) | (1ULL << WIDX_U_TRACK) | (1ULL << WIDX_O_TRACK)
|
||||
| (1ULL << WIDX_NEXT_SECTION) | (1ULL << WIDX_SIMULATE) | (1ULL << WIDX_ENTRANCE) | (1ULL << WIDX_EXIT)
|
||||
| (1ULL << WIDX_RIGHT_CURVE_LARGE) | (1ULL << WIDX_ROTATE) | (1ULL << WIDX_U_TRACK) | (1ULL << WIDX_O_TRACK)
|
||||
| (1ULL << WIDX_SEAT_ROTATION_ANGLE_SPINNER_UP) | (1ULL << WIDX_SEAT_ROTATION_ANGLE_SPINNER_DOWN);
|
||||
|
||||
window_init_scroll_widgets(w);
|
||||
|
@ -674,6 +676,16 @@ static void window_ride_construction_mouseup(rct_window* w, rct_widgetindex widg
|
|||
case WIDX_EXIT:
|
||||
window_ride_construction_exit_click(w);
|
||||
break;
|
||||
case WIDX_SIMULATE:
|
||||
{
|
||||
auto ride = get_ride(_currentRideIndex);
|
||||
if (ride != nullptr)
|
||||
{
|
||||
auto status = ride->status == RIDE_STATUS_SIMULATING ? RIDE_STATUS_CLOSED : RIDE_STATUS_SIMULATING;
|
||||
ride_set_status(ride, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2029,7 +2041,7 @@ static void window_ride_construction_update(rct_window* w)
|
|||
|
||||
// Close construction window if ride is not closed,
|
||||
// editing ride while open will cause many issues until properly handled
|
||||
if (ride->status != RIDE_STATUS_CLOSED)
|
||||
if (ride->status != RIDE_STATUS_CLOSED && ride->status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
window_close(w);
|
||||
return;
|
||||
|
@ -2255,6 +2267,22 @@ static void window_ride_construction_invalidate(rct_window* w)
|
|||
window_ride_construction_widgets[WIDX_SEAT_ROTATION_ANGLE_SPINNER].text = RideConstructionSeatAngleRotationStrings
|
||||
[_currentSeatRotationAngle];
|
||||
|
||||
// Simulate button
|
||||
auto& simulateWidget = w->widgets[WIDX_SIMULATE];
|
||||
simulateWidget.type = WWT_EMPTY;
|
||||
if (ride->SupportsStatus(RIDE_STATUS_SIMULATING))
|
||||
{
|
||||
simulateWidget.type = WWT_FLATBTN;
|
||||
if (ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
w->pressed_widgets |= (1ULL << WIDX_SIMULATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
w->pressed_widgets &= ~(1ULL << WIDX_SIMULATE);
|
||||
}
|
||||
}
|
||||
|
||||
// Set window title arguments
|
||||
set_format_arg(4, rct_string_id, ride->name);
|
||||
set_format_arg(6, uint32_t, ride->name_arguments);
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
|
||||
if (_modifyType == RIDE_MODIFY_RENEW)
|
||||
{
|
||||
if (ride->status != RIDE_STATUS_CLOSED)
|
||||
if (ride->status != RIDE_STATUS_CLOSED && ride->status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
return std::make_unique<GameActionResult>(
|
||||
GA_ERROR::DISALLOWED, STR_CANT_REFURBISH_RIDE, STR_MUST_BE_CLOSED_FIRST);
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle);
|
||||
}
|
||||
|
||||
if (ride->status != RIDE_STATUS_CLOSED)
|
||||
if (ride->status != RIDE_STATUS_CLOSED && ride->status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
return MakeResult(GA_ERROR::NOT_CLOSED, errorTitle, STR_MUST_BE_CLOSED_FIRST);
|
||||
}
|
||||
|
@ -89,9 +89,6 @@ public:
|
|||
return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_NOT_ALLOWED_TO_MODIFY_STATION);
|
||||
}
|
||||
|
||||
ride_clear_for_construction(ride);
|
||||
ride_remove_peeps(ride);
|
||||
|
||||
const auto location = _isExit ? ride_get_exit_location(ride, _stationNum)
|
||||
: ride_get_entrance_location(ride, _stationNum);
|
||||
|
||||
|
@ -156,8 +153,11 @@ public:
|
|||
return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle);
|
||||
}
|
||||
|
||||
ride_clear_for_construction(ride);
|
||||
ride_remove_peeps(ride);
|
||||
if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST))
|
||||
{
|
||||
ride_clear_for_construction(ride);
|
||||
ride_remove_peeps(ride);
|
||||
}
|
||||
|
||||
const auto location = _isExit ? ride_get_exit_location(ride, _stationNum)
|
||||
: ride_get_entrance_location(ride, _stationNum);
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
return std::make_unique<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
|
||||
}
|
||||
|
||||
if (ride->status != RIDE_STATUS_CLOSED)
|
||||
if (ride->status != RIDE_STATUS_CLOSED && ride->status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_MUST_BE_CLOSED_FIRST);
|
||||
}
|
||||
|
@ -123,9 +123,12 @@ public:
|
|||
return std::make_unique<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
|
||||
}
|
||||
|
||||
ride_clear_for_construction(ride);
|
||||
ride_remove_peeps(ride);
|
||||
invalidate_test_results(ride);
|
||||
if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST))
|
||||
{
|
||||
ride_clear_for_construction(ride);
|
||||
ride_remove_peeps(ride);
|
||||
invalidate_test_results(ride);
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
TileElement* tileElement = map_get_first_element_at(_loc.x / 32, _loc.y / 32);
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
GA_ERROR::DISALLOWED, STR_CANT_CHANGE_OPERATING_MODE, STR_HAS_BROKEN_DOWN_AND_REQUIRES_FIXING);
|
||||
}
|
||||
|
||||
if (ride->status != RIDE_STATUS_CLOSED)
|
||||
if (ride->status != RIDE_STATUS_CLOSED && ride->status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
return MakeResult(GA_ERROR::DISALLOWED, STR_CANT_CHANGE_OPERATING_MODE, STR_MUST_BE_CLOSED_FIRST);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ static rct_string_id _StatusErrorTitles[] = {
|
|||
STR_CANT_CLOSE,
|
||||
STR_CANT_OPEN,
|
||||
STR_CANT_TEST,
|
||||
STR_CANT_SIMULATE,
|
||||
};
|
||||
|
||||
DEFINE_GAME_ACTION(RideSetStatusAction, GAME_COMMAND_SET_RIDE_STATUS, GameActionResult)
|
||||
|
@ -73,9 +74,16 @@ public:
|
|||
|
||||
if (_status != ride->status)
|
||||
{
|
||||
if (_status == RIDE_STATUS_TESTING)
|
||||
if (_status == RIDE_STATUS_SIMULATING && (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
|
||||
{
|
||||
if (!ride_is_valid_for_test(ride, _status == RIDE_STATUS_OPEN, 0))
|
||||
// Simulating will force clear the track, so make sure player can't cheat around a break down
|
||||
res->Error = GA_ERROR::DISALLOWED;
|
||||
res->ErrorMessage = STR_HAS_BROKEN_DOWN_AND_REQUIRES_FIXING;
|
||||
return res;
|
||||
}
|
||||
else if (_status == RIDE_STATUS_TESTING || _status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
if (!ride_is_valid_for_test(ride, _status, false))
|
||||
{
|
||||
res->Error = GA_ERROR::UNKNOWN;
|
||||
res->ErrorMessage = gGameCommandErrorText;
|
||||
|
@ -84,7 +92,7 @@ public:
|
|||
}
|
||||
else if (_status == RIDE_STATUS_OPEN)
|
||||
{
|
||||
if (!ride_is_valid_for_open(ride, _status == RIDE_STATUS_OPEN, 0))
|
||||
if (!ride_is_valid_for_open(ride, _status == RIDE_STATUS_OPEN, false))
|
||||
{
|
||||
res->Error = GA_ERROR::UNKNOWN;
|
||||
res->ErrorMessage = gGameCommandErrorText;
|
||||
|
@ -123,7 +131,7 @@ public:
|
|||
switch (_status)
|
||||
{
|
||||
case RIDE_STATUS_CLOSED:
|
||||
if (ride->status == _status)
|
||||
if (ride->status == _status || ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
|
||||
{
|
||||
|
@ -139,6 +147,29 @@ public:
|
|||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
|
||||
window_invalidate_by_number(WC_RIDE, _rideIndex);
|
||||
break;
|
||||
case RIDE_STATUS_SIMULATING:
|
||||
{
|
||||
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_CRASHED;
|
||||
ride_clear_for_construction(ride);
|
||||
ride_remove_peeps(ride);
|
||||
|
||||
if (!ride_is_valid_for_test(ride, _status, true))
|
||||
{
|
||||
res->Error = GA_ERROR::UNKNOWN;
|
||||
res->ErrorMessage = gGameCommandErrorText;
|
||||
return res;
|
||||
}
|
||||
|
||||
ride->status = _status;
|
||||
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING;
|
||||
ride->race_winner = SPRITE_INDEX_NULL;
|
||||
ride->current_issues = 0;
|
||||
ride->last_issue_time = 0;
|
||||
ride_get_measurement(ride, nullptr);
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
|
||||
window_invalidate_by_number(WC_RIDE, _rideIndex);
|
||||
break;
|
||||
}
|
||||
case RIDE_STATUS_TESTING:
|
||||
case RIDE_STATUS_OPEN:
|
||||
{
|
||||
|
@ -147,6 +178,12 @@ public:
|
|||
return res;
|
||||
}
|
||||
|
||||
if (ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
ride_clear_for_construction(ride);
|
||||
ride_remove_peeps(ride);
|
||||
}
|
||||
|
||||
// Fix #3183: Make sure we close the construction window so the ride finishes any editing code before opening
|
||||
// otherwise vehicles get added to the ride incorrectly (such as to a ghost station)
|
||||
rct_window* constructionWindow = window_find_by_number(WC_RIDE_CONSTRUCTION, _rideIndex);
|
||||
|
@ -157,14 +194,14 @@ public:
|
|||
|
||||
if (_status == RIDE_STATUS_TESTING)
|
||||
{
|
||||
if (!ride_is_valid_for_test(ride, _status == RIDE_STATUS_OPEN, 1))
|
||||
if (!ride_is_valid_for_test(ride, _status, true))
|
||||
{
|
||||
res->Error = GA_ERROR::UNKNOWN;
|
||||
res->ErrorMessage = gGameCommandErrorText;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else if (!ride_is_valid_for_open(ride, _status == RIDE_STATUS_OPEN, 1))
|
||||
else if (!ride_is_valid_for_open(ride, _status == RIDE_STATUS_OPEN, true))
|
||||
{
|
||||
res->Error = GA_ERROR::UNKNOWN;
|
||||
res->ErrorMessage = gGameCommandErrorText;
|
||||
|
|
|
@ -92,7 +92,7 @@ public:
|
|||
return std::make_unique<GameActionResult>(GA_ERROR::BROKEN, errTitle, STR_HAS_BROKEN_DOWN_AND_REQUIRES_FIXING);
|
||||
}
|
||||
|
||||
if (ride->status != RIDE_STATUS_CLOSED)
|
||||
if (ride->status != RIDE_STATUS_CLOSED && ride->status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
return std::make_unique<GameActionResult>(GA_ERROR::NOT_CLOSED, errTitle, STR_MUST_BE_CLOSED_FIRST);
|
||||
}
|
||||
|
|
|
@ -170,11 +170,6 @@ namespace Config
|
|||
model->use_vsync = reader->GetBoolean("use_vsync", true);
|
||||
model->virtual_floor_style = reader->GetEnum<int32_t>(
|
||||
"virtual_floor_style", VIRTUAL_FLOOR_STYLE_GLASSY, Enum_VirtualFloorStyle);
|
||||
|
||||
// Default config setting is false until ghost trains are implemented #4540
|
||||
model->test_unfinished_tracks = reader->GetBoolean("test_unfinished_tracks", false);
|
||||
|
||||
model->no_test_crashes = reader->GetBoolean("no_test_crashes", false);
|
||||
model->date_format = reader->GetEnum<int32_t>("date_format", platform_get_locale_date_format(), Enum_DateFormat);
|
||||
model->auto_staff_placement = reader->GetBoolean("auto_staff", true);
|
||||
model->handymen_mow_default = reader->GetBoolean("handymen_mow_default", false);
|
||||
|
@ -250,8 +245,6 @@ namespace Config
|
|||
writer->WriteEnum<int32_t>("drawing_engine", model->drawing_engine, Enum_DrawingEngine);
|
||||
writer->WriteBoolean("uncap_fps", model->uncap_fps);
|
||||
writer->WriteBoolean("use_vsync", model->use_vsync);
|
||||
writer->WriteBoolean("test_unfinished_tracks", model->test_unfinished_tracks);
|
||||
writer->WriteBoolean("no_test_crashes", model->no_test_crashes);
|
||||
writer->WriteEnum<int32_t>("date_format", model->date_format, Enum_DateFormat);
|
||||
writer->WriteBoolean("auto_staff", model->auto_staff_placement);
|
||||
writer->WriteBoolean("handymen_mow_default", model->handymen_mow_default);
|
||||
|
|
|
@ -70,8 +70,6 @@ struct GeneralConfiguration
|
|||
int32_t window_snap_proximity;
|
||||
bool allow_loading_with_incorrect_checksum;
|
||||
bool save_plugin_data;
|
||||
bool test_unfinished_tracks;
|
||||
bool no_test_crashes;
|
||||
bool debugging_tools;
|
||||
int32_t autosave_frequency;
|
||||
int32_t autosave_amount;
|
||||
|
|
|
@ -650,14 +650,6 @@ static int32_t cc_get(InteractiveConsole& console, const arguments_t& argv)
|
|||
{
|
||||
console.WriteFormatLine("console_small_font %d", gConfigInterface.console_small_font);
|
||||
}
|
||||
else if (argv[0] == "test_unfinished_tracks")
|
||||
{
|
||||
console.WriteFormatLine("test_unfinished_tracks %d", gConfigGeneral.test_unfinished_tracks);
|
||||
}
|
||||
else if (argv[0] == "no_test_crashes")
|
||||
{
|
||||
console.WriteFormatLine("no_test_crashes %d", gConfigGeneral.no_test_crashes);
|
||||
}
|
||||
else if (argv[0] == "location")
|
||||
{
|
||||
rct_window* w = window_get_main();
|
||||
|
@ -916,18 +908,6 @@ static int32_t cc_set(InteractiveConsole& console, const arguments_t& argv)
|
|||
config_save_default();
|
||||
console.Execute("get console_small_font");
|
||||
}
|
||||
else if (argv[0] == "test_unfinished_tracks" && invalidArguments(&invalidArgs, int_valid[0]))
|
||||
{
|
||||
gConfigGeneral.test_unfinished_tracks = (int_val[0] != 0);
|
||||
config_save_default();
|
||||
console.Execute("get test_unfinished_tracks");
|
||||
}
|
||||
else if (argv[0] == "no_test_crashes" && invalidArguments(&invalidArgs, int_valid[0]))
|
||||
{
|
||||
gConfigGeneral.no_test_crashes = (int_val[0] != 0);
|
||||
config_save_default();
|
||||
console.Execute("get no_test_crashes");
|
||||
}
|
||||
else if (argv[0] == "location" && invalidArguments(&invalidArgs, int_valid[0] && int_valid[1]))
|
||||
{
|
||||
rct_window* w = window_get_main();
|
||||
|
@ -1673,8 +1653,6 @@ static constexpr const utf8* console_variable_table[] = {
|
|||
"climate",
|
||||
"game_speed",
|
||||
"console_small_font",
|
||||
"test_unfinished_tracks",
|
||||
"no_test_crashes",
|
||||
"location",
|
||||
"window_scale",
|
||||
"window_limit",
|
||||
|
|
|
@ -2741,8 +2741,6 @@ enum
|
|||
STR_LOCALE_DECIMAL_POINT = 5152,
|
||||
STR_EDIT_THEMES_BUTTON = 5153,
|
||||
STR_HARDWARE_DISPLAY = 5154, // Unused
|
||||
STR_TEST_UNFINISHED_TRACKS = 5155,
|
||||
STR_TEST_UNFINISHED_TRACKS_TIP = 5156,
|
||||
STR_CHEAT_UNLOCK_PRICES = 5157,
|
||||
STR_QUIT_TO_MENU = 5158,
|
||||
STR_EXIT_OPENRCT2 = 5159,
|
||||
|
@ -3959,6 +3957,11 @@ enum
|
|||
|
||||
STR_DESYNC_REPORT = 6318,
|
||||
|
||||
STR_SIMULATING = 6323,
|
||||
STR_SIMULATE_RIDE = 6324,
|
||||
STR_SIMULATE_RIDE_TIP = 6325,
|
||||
STR_CANT_SIMULATE = 6326,
|
||||
|
||||
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
|
||||
STR_COUNT = 32768
|
||||
};
|
||||
|
|
|
@ -182,7 +182,7 @@ extern LocationXY8 gClipSelectionA;
|
|||
extern LocationXY8 gClipSelectionB;
|
||||
|
||||
/** rct2: 0x00993CC4. The white ghost that indicates not-yet-built elements. */
|
||||
#define CONSTRUCTION_MARKER (COLOUR_DARK_GREEN << 19 | COLOUR_GREY << 24 | IMAGE_TYPE_REMAP);
|
||||
#define CONSTRUCTION_MARKER (COLOUR_DARK_GREEN << 19 | COLOUR_GREY << 24 | IMAGE_TYPE_REMAP)
|
||||
extern bool gShowDirtyVisuals;
|
||||
extern bool gPaintBoundingBoxes;
|
||||
extern bool gPaintBlockedTiles;
|
||||
|
|
|
@ -5404,7 +5404,7 @@ void Guest::UpdateQueuing()
|
|||
return;
|
||||
}
|
||||
Ride* ride = get_ride(current_ride);
|
||||
if (ride->status == RIDE_STATUS_CLOSED || ride->status == RIDE_STATUS_TESTING)
|
||||
if (ride->status != RIDE_STATUS_OPEN)
|
||||
{
|
||||
RemoveFromQueue();
|
||||
SetState(PEEP_STATE_1);
|
||||
|
|
|
@ -897,7 +897,12 @@ void ride_get_status(const Ride* ride, rct_string_id* formatSecondary, int32_t*
|
|||
|
||||
return;
|
||||
}
|
||||
if (ride->status == RIDE_STATUS_TESTING)
|
||||
else if (ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
*formatSecondary = STR_SIMULATING;
|
||||
return;
|
||||
}
|
||||
else if (ride->status == RIDE_STATUS_TESTING)
|
||||
{
|
||||
*formatSecondary = STR_TEST_RUN;
|
||||
return;
|
||||
|
@ -968,6 +973,23 @@ bool Ride::CanHaveMultipleCircuits() const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Ride::SupportsStatus(int32_t s) const
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case RIDE_STATUS_CLOSED:
|
||||
case RIDE_STATUS_OPEN:
|
||||
return true;
|
||||
case RIDE_STATUS_SIMULATING:
|
||||
return (
|
||||
!ride_type_has_flag(type, RIDE_TYPE_FLAG_NO_TEST_MODE) && ride_type_has_flag(type, RIDE_TYPE_FLAG_HAS_TRACK));
|
||||
case RIDE_STATUS_TESTING:
|
||||
return !ride_type_has_flag(type, RIDE_TYPE_FLAG_NO_TEST_MODE);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma region Initialisation functions
|
||||
|
||||
/**
|
||||
|
@ -1024,7 +1046,7 @@ static int32_t ride_check_if_construction_allowed(Ride* ride)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (ride->status != RIDE_STATUS_CLOSED)
|
||||
if (ride->status != RIDE_STATUS_CLOSED && ride->status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
set_format_arg(6, rct_string_id, ride->name);
|
||||
set_format_arg(8, uint32_t, ride->name_arguments);
|
||||
|
@ -1985,7 +2007,10 @@ int32_t ride_modify(CoordsXYE* input)
|
|||
}
|
||||
|
||||
// Stop the ride again to clear all vehicles and peeps (compatible with network games)
|
||||
ride_set_status(ride, RIDE_STATUS_CLOSED);
|
||||
if (ride->status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
ride_set_status(ride, RIDE_STATUS_CLOSED);
|
||||
}
|
||||
|
||||
// Check if element is a station entrance or exit
|
||||
if (tileElement.element->GetType() == TILE_ELEMENT_TYPE_ENTRANCE)
|
||||
|
@ -2192,24 +2217,10 @@ void Ride::Update()
|
|||
|
||||
ride_inspection_update(this);
|
||||
|
||||
if (status == RIDE_STATUS_TESTING && gConfigGeneral.no_test_crashes)
|
||||
// If ride is simulating but crashed, reset the vehicles
|
||||
if (status == RIDE_STATUS_SIMULATING && (lifecycle_flags & RIDE_LIFECYCLE_CRASHED))
|
||||
{
|
||||
for (int32_t i = 0; i < num_vehicles; i++)
|
||||
{
|
||||
uint16_t spriteIndex = vehicles[i];
|
||||
if (spriteIndex == SPRITE_INDEX_NULL)
|
||||
continue;
|
||||
|
||||
rct_vehicle* vehicle = GET_VEHICLE(spriteIndex);
|
||||
|
||||
if (vehicle->status == VEHICLE_STATUS_CRASHED || vehicle->status == VEHICLE_STATUS_CRASHING)
|
||||
{
|
||||
ride_set_status(this, RIDE_STATUS_CLOSED);
|
||||
ride_set_status(this, RIDE_STATUS_CLOSED);
|
||||
ride_set_status(this, RIDE_STATUS_TESTING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ride_set_status(this, RIDE_STATUS_SIMULATING);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2472,7 +2483,7 @@ static void ride_breakdown_update(Ride* ride)
|
|||
|
||||
if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED))
|
||||
return;
|
||||
if (ride->status == RIDE_STATUS_CLOSED)
|
||||
if (ride->status == RIDE_STATUS_CLOSED || ride->status == RIDE_STATUS_SIMULATING)
|
||||
return;
|
||||
|
||||
if (!ride->CanBreakDown())
|
||||
|
@ -3141,7 +3152,7 @@ void ride_measurements_update()
|
|||
continue;
|
||||
|
||||
Ride* ride = get_ride(measurement->ride_index);
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK))
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) || ride->status == RIDE_STATUS_SIMULATING)
|
||||
continue;
|
||||
|
||||
if (measurement->flags & RIDE_MEASUREMENT_FLAG_RUNNING)
|
||||
|
@ -5396,7 +5407,7 @@ static TileElement* loc_6B4F6B(ride_id_t rideIndex, int32_t x, int32_t y)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int32_t ride_is_valid_for_test(Ride* ride, int32_t goingToBeOpen, int32_t isApplying)
|
||||
int32_t ride_is_valid_for_test(Ride* ride, int32_t status, bool isApplying)
|
||||
{
|
||||
int32_t stationIndex;
|
||||
CoordsXYE trackElement, problematicTrackElement = {};
|
||||
|
@ -5407,7 +5418,10 @@ int32_t ride_is_valid_for_test(Ride* ride, int32_t goingToBeOpen, int32_t isAppl
|
|||
return 0;
|
||||
}
|
||||
|
||||
window_close_by_number(WC_RIDE_CONSTRUCTION, ride->id);
|
||||
if (status != RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
window_close_by_number(WC_RIDE_CONSTRUCTION, ride->id);
|
||||
}
|
||||
|
||||
stationIndex = ride_mode_check_station_present(ride);
|
||||
if (stationIndex == -1)
|
||||
|
@ -5416,13 +5430,13 @@ int32_t ride_is_valid_for_test(Ride* ride, int32_t goingToBeOpen, int32_t isAppl
|
|||
if (!ride_mode_check_valid_station_numbers(ride))
|
||||
return 0;
|
||||
|
||||
if (!ride_check_for_entrance_exit(ride->id))
|
||||
if (status != RIDE_STATUS_SIMULATING && !ride_check_for_entrance_exit(ride->id))
|
||||
{
|
||||
loc_6B51C0(ride);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (goingToBeOpen && isApplying)
|
||||
if (status == RIDE_STATUS_OPEN && isApplying)
|
||||
{
|
||||
sub_6B5952(ride);
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_EVER_BEEN_OPENED;
|
||||
|
@ -5443,7 +5457,7 @@ int32_t ride_is_valid_for_test(Ride* ride, int32_t goingToBeOpen, int32_t isAppl
|
|||
|| ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED || ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED)
|
||||
{
|
||||
if (ride_find_track_gap(ride, &trackElement, &problematicTrackElement)
|
||||
&& (!gConfigGeneral.test_unfinished_tracks || ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED
|
||||
&& (status != RIDE_STATUS_SIMULATING || ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED
|
||||
|| ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED))
|
||||
{
|
||||
gGameCommandErrorText = STR_TRACK_IS_NOT_A_COMPLETE_CIRCUIT;
|
||||
|
@ -5532,7 +5546,7 @@ int32_t ride_is_valid_for_test(Ride* ride, int32_t goingToBeOpen, int32_t isAppl
|
|||
*
|
||||
* rct2: 0x006B4EEA
|
||||
*/
|
||||
int32_t ride_is_valid_for_open(Ride* ride, int32_t goingToBeOpen, int32_t isApplying)
|
||||
int32_t ride_is_valid_for_open(Ride* ride, int32_t goingToBeOpen, bool isApplying)
|
||||
{
|
||||
int32_t stationIndex;
|
||||
CoordsXYE trackElement, problematicTrackElement = {};
|
||||
|
|
|
@ -382,6 +382,7 @@ public:
|
|||
bool IsPoweredLaunched() const;
|
||||
bool IsBlockSectioned() const;
|
||||
bool CanHaveMultipleCircuits() const;
|
||||
bool SupportsStatus(int32_t s) const;
|
||||
|
||||
void StopGuestsQueuing();
|
||||
|
||||
|
@ -631,7 +632,8 @@ enum
|
|||
{
|
||||
RIDE_STATUS_CLOSED,
|
||||
RIDE_STATUS_OPEN,
|
||||
RIDE_STATUS_TESTING
|
||||
RIDE_STATUS_TESTING,
|
||||
RIDE_STATUS_SIMULATING,
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -1073,8 +1075,8 @@ void ride_measurements_update();
|
|||
rct_ride_measurement* ride_get_measurement(Ride* ride, rct_string_id* message);
|
||||
void ride_breakdown_add_news_item(Ride* ride);
|
||||
Peep* ride_find_closest_mechanic(Ride* ride, int32_t forInspection);
|
||||
int32_t ride_is_valid_for_open(Ride* ride, int32_t goingToBeOpen, int32_t isApplying);
|
||||
int32_t ride_is_valid_for_test(Ride* ride, int32_t goingToBeOpen, int32_t isApplying);
|
||||
int32_t ride_is_valid_for_open(Ride* ride, int32_t goingToBeOpen, bool isApplying);
|
||||
int32_t ride_is_valid_for_test(Ride* ride, int32_t status, bool isApplying);
|
||||
int32_t ride_initialise_construction_window(Ride* ride);
|
||||
void ride_construction_invalidate_current_track();
|
||||
int32_t sub_6C683D(
|
||||
|
|
|
@ -2285,7 +2285,7 @@ static void vehicle_update_waiting_for_passengers(rct_vehicle* vehicle)
|
|||
|
||||
num_seats_on_train &= 0x7F;
|
||||
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE))
|
||||
if (ride->SupportsStatus(RIDE_STATUS_TESTING))
|
||||
{
|
||||
if (vehicle->time_waiting < 20)
|
||||
{
|
||||
|
@ -3254,7 +3254,7 @@ static void vehicle_update_departing(rct_vehicle* vehicle)
|
|||
vehicle_update_test_finish(vehicle);
|
||||
}
|
||||
}
|
||||
else if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TEST_IN_PROGRESS))
|
||||
else if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TEST_IN_PROGRESS) && !vehicle->IsGhost())
|
||||
{
|
||||
vehicle_test_reset(vehicle);
|
||||
}
|
||||
|
@ -3520,6 +3520,15 @@ static void vehicle_check_if_missing(rct_vehicle* vehicle)
|
|||
news_item_add_to_queue(NEWS_ITEM_RIDE, STR_NEWS_VEHICLE_HAS_STALLED, vehicle->ride);
|
||||
}
|
||||
|
||||
static void vehicle_simulate_crash(rct_vehicle* vehicle)
|
||||
{
|
||||
auto ride = get_ride(vehicle->ride);
|
||||
if (ride != nullptr)
|
||||
{
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_CRASHED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup function for a vehicle colliding with
|
||||
* another vehicle.
|
||||
|
@ -3528,10 +3537,16 @@ static void vehicle_check_if_missing(rct_vehicle* vehicle)
|
|||
*/
|
||||
static void vehicle_update_collision_setup(rct_vehicle* vehicle)
|
||||
{
|
||||
auto ride = get_ride(vehicle->ride);
|
||||
if (ride != nullptr && ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
vehicle_simulate_crash(vehicle);
|
||||
return;
|
||||
}
|
||||
|
||||
vehicle->status = VEHICLE_STATUS_CRASHED;
|
||||
vehicle_invalidate_window(vehicle);
|
||||
|
||||
Ride* ride = get_ride(vehicle->ride);
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED))
|
||||
{
|
||||
auto frontVehicle = vehicle->GetHead();
|
||||
|
@ -3603,6 +3618,13 @@ static constexpr const LocationXY16 stru_9A3AC4[] = {
|
|||
*/
|
||||
static void vehicle_update_crash_setup(rct_vehicle* vehicle)
|
||||
{
|
||||
auto ride = get_ride(vehicle->ride);
|
||||
if (ride != nullptr && ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
vehicle_simulate_crash(vehicle);
|
||||
return;
|
||||
}
|
||||
|
||||
vehicle->status = VEHICLE_STATUS_CRASHING;
|
||||
vehicle_invalidate_window(vehicle);
|
||||
|
||||
|
@ -4216,7 +4238,7 @@ static void vehicle_update_travelling_cable_lift(rct_vehicle* vehicle)
|
|||
vehicle_update_test_finish(vehicle);
|
||||
}
|
||||
}
|
||||
else if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TEST_IN_PROGRESS))
|
||||
else if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TEST_IN_PROGRESS) && !vehicle->IsGhost())
|
||||
{
|
||||
vehicle_test_reset(vehicle);
|
||||
}
|
||||
|
@ -5266,10 +5288,16 @@ static void vehicle_kill_all_passengers(rct_vehicle* vehicle)
|
|||
|
||||
static void vehicle_crash_on_land(rct_vehicle* vehicle)
|
||||
{
|
||||
auto ride = get_ride(vehicle->ride);
|
||||
if (ride != nullptr && ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
vehicle_simulate_crash(vehicle);
|
||||
return;
|
||||
}
|
||||
|
||||
vehicle->status = VEHICLE_STATUS_CRASHED;
|
||||
vehicle_invalidate_window(vehicle);
|
||||
|
||||
Ride* ride = get_ride(vehicle->ride);
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED))
|
||||
{
|
||||
auto frontVehicle = vehicle->GetHead();
|
||||
|
@ -5320,10 +5348,16 @@ static void vehicle_crash_on_land(rct_vehicle* vehicle)
|
|||
|
||||
static void vehicle_crash_on_water(rct_vehicle* vehicle)
|
||||
{
|
||||
auto ride = get_ride(vehicle->ride);
|
||||
if (ride != nullptr && ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
vehicle_simulate_crash(vehicle);
|
||||
return;
|
||||
}
|
||||
|
||||
vehicle->status = VEHICLE_STATUS_CRASHED;
|
||||
vehicle_invalidate_window(vehicle);
|
||||
|
||||
Ride* ride = get_ride(vehicle->ride);
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED))
|
||||
{
|
||||
auto frontVehicle = vehicle->GetHead();
|
||||
|
@ -10014,3 +10048,9 @@ const rct_vehicle* rct_vehicle::GetCar(size_t carIndex) const
|
|||
}
|
||||
return car;
|
||||
}
|
||||
|
||||
bool rct_vehicle::IsGhost() const
|
||||
{
|
||||
auto r = get_ride(ride);
|
||||
return r != nullptr && r->status == RIDE_STATUS_SIMULATING;
|
||||
}
|
||||
|
|
|
@ -235,6 +235,7 @@ struct rct_vehicle : rct_sprite_common
|
|||
const rct_vehicle* GetHead() const;
|
||||
const rct_vehicle* GetCar(size_t carIndex) const;
|
||||
void Invalidate();
|
||||
bool IsGhost() const;
|
||||
};
|
||||
|
||||
struct train_ref
|
||||
|
|
|
@ -909,6 +909,12 @@ static void vehicle_sprite_paint(
|
|||
}
|
||||
int32_t image_id = baseImage_id | (vehicle->colours.body_colour << 19) | (vehicle->colours.trim_colour << 24)
|
||||
| IMAGE_TYPE_REMAP_2_PLUS;
|
||||
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
image_id &= 0x7FFFF;
|
||||
image_id |= CONSTRUCTION_MARKER;
|
||||
}
|
||||
paint_struct* ps = sub_98197C(
|
||||
session, image_id, 0, 0, bb.length_x, bb.length_y, bb.length_z, z, bb.offset_x, bb.offset_y, bb.offset_z + z);
|
||||
if (ps != nullptr)
|
||||
|
@ -930,6 +936,13 @@ static void vehicle_sprite_paint(
|
|||
{
|
||||
image_id += (vehicleEntry->no_vehicle_images * vehicle->animation_frame);
|
||||
}
|
||||
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
image_id &= 0x7FFFF;
|
||||
image_id |= CONSTRUCTION_MARKER;
|
||||
}
|
||||
|
||||
sub_98199C(
|
||||
session, image_id, 0, 0, bb.length_x, bb.length_y, bb.length_z, z, bb.offset_x, bb.offset_y,
|
||||
bb.offset_z + z);
|
||||
|
|
|
@ -196,10 +196,14 @@ void vehicle_visual_virginia_reel(
|
|||
|
||||
const vehicle_boundbox* bb = &_virginiaReelBoundbox[j];
|
||||
image_id = baseImage_id | SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | CONSTRUCTION_MARKER;
|
||||
}
|
||||
sub_98197C(
|
||||
session, image_id, 0, 0, bb->length_x, bb->length_y, bb->length_z, z, bb->offset_x, bb->offset_y, bb->offset_z + z);
|
||||
|
||||
if (session->DPI.zoom_level < 2 && vehicle->num_peeps > 0)
|
||||
if (session->DPI.zoom_level < 2 && vehicle->num_peeps > 0 && !vehicle->IsGhost())
|
||||
{
|
||||
uint8_t riding_peep_sprites[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
for (int32_t i = 0; i < vehicle->num_peeps; i++)
|
||||
|
|
|
@ -54,8 +54,11 @@ void vehicle_visual_observation_tower(
|
|||
baseImage_id = (vehicle->animation_frame * 2) + vehicleEntry->base_image_id + 8;
|
||||
}
|
||||
|
||||
image_id = baseImage_id | (vehicle->colours.body_colour << 19) | (vehicle->colours.trim_colour << 24)
|
||||
| IMAGE_TYPE_REMAP_2_PLUS;
|
||||
image_id = baseImage_id | SPRITE_ID_PALETTE_COLOUR_3(vehicle->colours.body_colour, vehicle->colours.trim_colour << 24);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | CONSTRUCTION_MARKER;
|
||||
}
|
||||
paint_struct* ps = sub_98197C(session, image_id, 0, 0, 2, 2, 41, z, -11, -11, z + 1);
|
||||
if (ps != nullptr)
|
||||
{
|
||||
|
|
|
@ -35,48 +35,50 @@ void vehicle_visual_launched_freefall(
|
|||
paint_session* session, int32_t x, int32_t imageDirection, int32_t y, int32_t z, const rct_vehicle* vehicle,
|
||||
const rct_ride_entry_vehicle* vehicleEntry)
|
||||
{
|
||||
int32_t image_id;
|
||||
int32_t baseImage_id = vehicleEntry->base_image_id + ((vehicle->restraints_position / 64) * 2);
|
||||
auto imageFlags = SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
imageFlags = CONSTRUCTION_MARKER;
|
||||
}
|
||||
|
||||
// Draw back:
|
||||
image_id = (baseImage_id + 2) | SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
int32_t baseImage_id = vehicleEntry->base_image_id + ((vehicle->restraints_position / 64) * 2);
|
||||
auto image_id = (baseImage_id + 2) | imageFlags;
|
||||
sub_98197C(session, image_id, 0, 0, 2, 2, 41, z, -11, -11, z + 1);
|
||||
|
||||
// Draw front:
|
||||
image_id = (baseImage_id + 1) | SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
image_id = (baseImage_id + 1) | imageFlags;
|
||||
sub_98197C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
|
||||
// Draw peeps:
|
||||
if (session->DPI.zoom_level < 2)
|
||||
if (session->DPI.zoom_level < 2 && vehicle->num_peeps > 0 && !vehicle->IsGhost())
|
||||
{
|
||||
if (vehicle->num_peeps > 0)
|
||||
baseImage_id = vehicleEntry->base_image_id + 9;
|
||||
if ((vehicle->restraints_position / 64) == 3)
|
||||
{
|
||||
baseImage_id = vehicleEntry->base_image_id + 9;
|
||||
if ((vehicle->restraints_position / 64) == 3)
|
||||
{
|
||||
baseImage_id += 2; // Draw peeps sitting without transparent area between them for restraints
|
||||
}
|
||||
image_id = (baseImage_id + ((((imageDirection / 8) + 0) & 3) * 3))
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[0], vehicle->peep_tshirt_colours[1]);
|
||||
baseImage_id += 2; // Draw peeps sitting without transparent area between them for restraints
|
||||
}
|
||||
auto directionOffset = imageDirection / 8;
|
||||
image_id = (baseImage_id + (((directionOffset + 0) & 3) * 3))
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[0], vehicle->peep_tshirt_colours[1]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
if (vehicle->num_peeps > 2)
|
||||
{
|
||||
image_id = (baseImage_id + (((directionOffset + 1) & 3) * 3))
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[2], vehicle->peep_tshirt_colours[3]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
}
|
||||
if (vehicle->num_peeps > 4)
|
||||
{
|
||||
image_id = (baseImage_id + (((directionOffset + 2) & 3) * 3))
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[4], vehicle->peep_tshirt_colours[5]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
}
|
||||
if (vehicle->num_peeps > 6)
|
||||
{
|
||||
image_id = (baseImage_id + (((directionOffset + 3) & 3) * 3))
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[6], vehicle->peep_tshirt_colours[7]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
if (vehicle->num_peeps > 2)
|
||||
{
|
||||
image_id = (baseImage_id + ((((imageDirection / 8) + 1) & 3) * 3))
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[2], vehicle->peep_tshirt_colours[3]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
}
|
||||
if (vehicle->num_peeps > 4)
|
||||
{
|
||||
image_id = (baseImage_id + ((((imageDirection / 8) + 2) & 3) * 3))
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[4], vehicle->peep_tshirt_colours[5]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
}
|
||||
if (vehicle->num_peeps > 6)
|
||||
{
|
||||
image_id = (baseImage_id + ((((imageDirection / 8) + 3) & 3) * 3))
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[6], vehicle->peep_tshirt_colours[7]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,12 @@ void vehicle_visual_roto_drop(
|
|||
paint_session* session, int32_t x, int32_t imageDirection, int32_t y, int32_t z, const rct_vehicle* vehicle,
|
||||
const rct_ride_entry_vehicle* vehicleEntry)
|
||||
{
|
||||
auto imageFlags = SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
imageFlags = CONSTRUCTION_MARKER;
|
||||
}
|
||||
|
||||
int32_t image_id;
|
||||
int32_t baseImage_id = (vehicleEntry->base_image_id + 4) + ((vehicle->animation_frame / 4) & 0x3);
|
||||
if (vehicle->restraints_position >= 64)
|
||||
|
@ -44,39 +50,42 @@ void vehicle_visual_roto_drop(
|
|||
}
|
||||
|
||||
// Draw back:
|
||||
image_id = baseImage_id | SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
image_id = baseImage_id | imageFlags;
|
||||
sub_98197C(session, image_id, 0, 0, 2, 2, 41, z, -11, -11, z + 1);
|
||||
|
||||
// Draw front:
|
||||
image_id = (baseImage_id + 4) | SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
image_id = (baseImage_id + 4) | imageFlags;
|
||||
sub_98197C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
|
||||
uint8_t riding_peep_sprites[64];
|
||||
std::fill_n(riding_peep_sprites, sizeof(riding_peep_sprites), 0xFF);
|
||||
for (int32_t i = 0; i < vehicle->num_peeps; i++)
|
||||
if (vehicle->num_peeps > 0 && !vehicle->IsGhost())
|
||||
{
|
||||
uint8_t cl = (i & 3) * 16;
|
||||
cl += (i & 0xFC);
|
||||
cl += vehicle->animation_frame / 4;
|
||||
cl += (imageDirection / 8) * 16;
|
||||
cl &= 0x3F;
|
||||
riding_peep_sprites[cl] = vehicle->peep_tshirt_colours[i];
|
||||
}
|
||||
|
||||
// Draw riding peep sprites in back to front order:
|
||||
for (int32_t j = 0; j <= 48; j++)
|
||||
{
|
||||
int32_t i = (j % 2) ? (48 - (j / 2)) : (j / 2);
|
||||
if (riding_peep_sprites[i] != 0xFF)
|
||||
uint8_t riding_peep_sprites[64];
|
||||
std::fill_n(riding_peep_sprites, sizeof(riding_peep_sprites), 0xFF);
|
||||
for (int32_t i = 0; i < vehicle->num_peeps; i++)
|
||||
{
|
||||
baseImage_id = vehicleEntry->base_image_id + 20 + i;
|
||||
if (vehicle->restraints_position >= 64)
|
||||
uint8_t cl = (i & 3) * 16;
|
||||
cl += (i & 0xFC);
|
||||
cl += vehicle->animation_frame / 4;
|
||||
cl += (imageDirection / 8) * 16;
|
||||
cl &= 0x3F;
|
||||
riding_peep_sprites[cl] = vehicle->peep_tshirt_colours[i];
|
||||
}
|
||||
|
||||
// Draw riding peep sprites in back to front order:
|
||||
for (int32_t j = 0; j <= 48; j++)
|
||||
{
|
||||
int32_t i = (j % 2) ? (48 - (j / 2)) : (j / 2);
|
||||
if (riding_peep_sprites[i] != 0xFF)
|
||||
{
|
||||
baseImage_id += 64;
|
||||
baseImage_id += vehicle->restraints_position / 64;
|
||||
baseImage_id = vehicleEntry->base_image_id + 20 + i;
|
||||
if (vehicle->restraints_position >= 64)
|
||||
{
|
||||
baseImage_id += 64;
|
||||
baseImage_id += vehicle->restraints_position / 64;
|
||||
}
|
||||
image_id = baseImage_id | SPRITE_ID_PALETTE_COLOUR_1(riding_peep_sprites[i]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
}
|
||||
image_id = baseImage_id | SPRITE_ID_PALETTE_COLOUR_1(riding_peep_sprites[i]);
|
||||
sub_98199C(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -223,10 +223,15 @@ void vehicle_visual_river_rapids(
|
|||
|
||||
const vehicle_boundbox* bb = &_riverRapidsBoundbox[j];
|
||||
image_id = baseImage_id | SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
image_id &= 0x7FFFF;
|
||||
image_id |= CONSTRUCTION_MARKER;
|
||||
}
|
||||
sub_98197C(
|
||||
session, image_id, 0, 0, bb->length_x, bb->length_y, bb->length_z, z, bb->offset_x, bb->offset_y, bb->offset_z + z);
|
||||
|
||||
if (session->DPI.zoom_level < 2 && vehicle->num_peeps > 0)
|
||||
if (session->DPI.zoom_level < 2 && vehicle->num_peeps > 0 && !vehicle->IsGhost())
|
||||
{
|
||||
// Draw peeps: (this particular vehicle doesn't sort them back to front like others so the back ones sometimes clip, but
|
||||
// that's how the original does it...)
|
||||
|
|
|
@ -24,6 +24,12 @@ void vehicle_visual_submarine(
|
|||
paint_session* session, int32_t x, int32_t imageDirection, int32_t y, int32_t z, const rct_vehicle* vehicle,
|
||||
const rct_ride_entry_vehicle* vehicleEntry)
|
||||
{
|
||||
auto imageFlags = SPRITE_ID_PALETTE_COLOUR_3(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
imageFlags = CONSTRUCTION_MARKER;
|
||||
}
|
||||
|
||||
int32_t baseImage_id = imageDirection;
|
||||
int32_t image_id;
|
||||
if (vehicle->restraints_position >= 64)
|
||||
|
@ -53,8 +59,7 @@ void vehicle_visual_submarine(
|
|||
|
||||
vehicle_boundbox bb = VehicleBoundboxes[vehicleEntry->draw_order][imageDirection / 2];
|
||||
|
||||
image_id = baseImage_id | (vehicle->colours.body_colour << 19) | (vehicle->colours.trim_colour << 24)
|
||||
| IMAGE_TYPE_REMAP_2_PLUS;
|
||||
image_id = baseImage_id | imageFlags;
|
||||
paint_struct* ps = sub_98197C(
|
||||
session, image_id, 0, 0, bb.length_x, bb.length_y, bb.length_z, z, bb.offset_x, bb.offset_y, bb.offset_z + z);
|
||||
if (ps != nullptr)
|
||||
|
@ -62,8 +67,7 @@ void vehicle_visual_submarine(
|
|||
ps->tertiary_colour = vehicle->colours_extended;
|
||||
}
|
||||
|
||||
image_id = (baseImage_id + 1) | (vehicle->colours.body_colour << 19) | (vehicle->colours.trim_colour << 24)
|
||||
| IMAGE_TYPE_REMAP_2_PLUS;
|
||||
image_id = (baseImage_id + 1) | imageFlags;
|
||||
ps = sub_98197C(session, image_id, 0, 0, bb.length_x, bb.length_y, 2, z, bb.offset_x, bb.offset_y, bb.offset_z + z - 10);
|
||||
if (ps != nullptr)
|
||||
{
|
||||
|
|
|
@ -843,7 +843,13 @@ enum
|
|||
SPR_G2_MULTIPLAYER_SYNC = SPR_G2_BEGIN + 124,
|
||||
SPR_G2_MULTIPLAYER_DESYNC = SPR_G2_BEGIN + 125,
|
||||
|
||||
SPR_G2_CHAR_BEGIN = SPR_G2_BEGIN + 126,
|
||||
SPR_G2_SIMULATE = SPR_G2_BEGIN + 126,
|
||||
SPR_G2_RCT1_SIMULATE_BUTTON_0 = SPR_G2_BEGIN + 127,
|
||||
SPR_G2_RCT1_SIMULATE_BUTTON_1 = SPR_G2_BEGIN + 128,
|
||||
SPR_G2_RCT1_SIMULATE_BUTTON_2 = SPR_G2_BEGIN + 129,
|
||||
SPR_G2_RCT1_SIMULATE_BUTTON_3 = SPR_G2_BEGIN + 130,
|
||||
|
||||
SPR_G2_CHAR_BEGIN = SPR_G2_BEGIN + 131,
|
||||
|
||||
SPR_G2_AE_UPPER = SPR_G2_CHAR_BEGIN,
|
||||
SPR_G2_AE_LOWER = SPR_G2_CHAR_BEGIN + 1,
|
||||
|
|
|
@ -435,3 +435,9 @@ StationObject* ride_get_station_object(const Ride* ride)
|
|||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool rct_vehicle::IsGhost() const
|
||||
{
|
||||
auto r = get_ride(ride);
|
||||
return r != nullptr && r->status == RIDE_STATUS_SIMULATING;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue