mirror of https://github.com/OpenRCT2/OpenRCT2.git
Add and implement simulation mode for rides
This commit is contained in:
parent
46889b5381
commit
c4e18e570e
|
@ -3770,6 +3770,9 @@ 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
|
||||
|
||||
#############
|
||||
# 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.
|
||||
|
|
|
@ -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;
|
||||
|
@ -2060,7 +2067,7 @@ static void window_ride_main_resize(rct_window* w)
|
|||
int32_t minHeight = 180 + offset;
|
||||
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);
|
||||
- (ride_type_has_flag(get_ride(w->number)->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? 14 * 2 : 0);
|
||||
window_set_resize(w, 316, minHeight, 500, 450);
|
||||
window_ride_init_viewport(w);
|
||||
}
|
||||
|
@ -2130,7 +2137,7 @@ static void window_ride_show_view_dropdown(rct_window* w, rct_widget* widget)
|
|||
static void window_ride_show_open_dropdown(rct_window* w, rct_widget* widget)
|
||||
{
|
||||
Ride* ride;
|
||||
int32_t numItems, highlightedIndex = 0, checkedIndex;
|
||||
int32_t numItems, highlightedIndex = 0;
|
||||
|
||||
ride = get_ride(w->number);
|
||||
|
||||
|
@ -2141,6 +2148,10 @@ static void window_ride_show_open_dropdown(rct_window* w, rct_widget* widget)
|
|||
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE))
|
||||
{
|
||||
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
|
||||
gDropdownItemsArgs[numItems] = STR_SIMULATE_RIDE;
|
||||
numItems++;
|
||||
|
||||
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
|
||||
gDropdownItemsArgs[numItems] = STR_TEST_RIDE;
|
||||
numItems++;
|
||||
|
@ -2153,47 +2164,52 @@ static void window_ride_show_open_dropdown(rct_window* w, rct_widget* widget)
|
|||
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;
|
||||
auto checkedIndex = -1;
|
||||
switch (ride->status)
|
||||
{
|
||||
case RIDE_STATUS_CLOSED:
|
||||
checkedIndex = 0;
|
||||
highlightedIndex = 0;
|
||||
if ((ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)
|
||||
|| (ride->lifecycle_flags & RIDE_LIFECYCLE_HAS_STALLED_VEHICLE))
|
||||
break;
|
||||
|
||||
highlightedIndex = 3;
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE))
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
highlightedIndex = 2;
|
||||
break;
|
||||
case RIDE_STATUS_SIMULATING:
|
||||
checkedIndex = 1;
|
||||
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;
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
highlightedIndex = 0;
|
||||
break;
|
||||
case RIDE_STATUS_TESTING:
|
||||
highlightedIndex = 2;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)
|
||||
break;
|
||||
|
||||
highlightedIndex = 0;
|
||||
checkedIndex = 2;
|
||||
highlightedIndex = 3;
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
highlightedIndex = 3;
|
||||
break;
|
||||
case RIDE_STATUS_OPEN:
|
||||
checkedIndex = 3;
|
||||
highlightedIndex = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkedIndex != RIDE_STATUS_CLOSED)
|
||||
checkedIndex = 3 - checkedIndex;
|
||||
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE))
|
||||
{
|
||||
if (checkedIndex != 0)
|
||||
checkedIndex--;
|
||||
if (highlightedIndex != 0)
|
||||
highlightedIndex--;
|
||||
// Open item is now index 1
|
||||
if (checkedIndex == 3)
|
||||
checkedIndex = 1;
|
||||
if (highlightedIndex == 3)
|
||||
highlightedIndex = 1;
|
||||
}
|
||||
|
||||
dropdown_set_checked(checkedIndex, true);
|
||||
if (checkedIndex != -1)
|
||||
{
|
||||
dropdown_set_checked(checkedIndex, true);
|
||||
}
|
||||
gDropdownDefaultIndex = highlightedIndex;
|
||||
}
|
||||
|
||||
|
@ -2412,7 +2428,7 @@ static void window_ride_main_dropdown(rct_window* w, rct_widgetindex widgetIndex
|
|||
|
||||
ride = get_ride(w->number);
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) && dropdownIndex != 0)
|
||||
dropdownIndex++;
|
||||
dropdownIndex += 2;
|
||||
|
||||
switch (dropdownIndex)
|
||||
{
|
||||
|
@ -2420,9 +2436,12 @@ static void window_ride_main_dropdown(rct_window* w, rct_widgetindex widgetIndex
|
|||
status = RIDE_STATUS_CLOSED;
|
||||
break;
|
||||
case 1:
|
||||
status = RIDE_STATUS_TESTING;
|
||||
status = RIDE_STATUS_SIMULATING;
|
||||
break;
|
||||
case 2:
|
||||
status = RIDE_STATUS_TESTING;
|
||||
break;
|
||||
case 3:
|
||||
status = RIDE_STATUS_OPEN;
|
||||
break;
|
||||
}
|
||||
|
@ -2533,11 +2552,14 @@ static void window_ride_main_invalidate(rct_window* w)
|
|||
SPR_CLOSED,
|
||||
SPR_OPEN,
|
||||
SPR_TESTING,
|
||||
SPR_TESTING | (COLOUR_WHITE << 19 | COLOUR_WHITE << 24 | IMAGE_TYPE_REMAP),
|
||||
};
|
||||
window_ride_main_widgets[WIDX_OPEN].image = spriteIds[ride->status];
|
||||
|
||||
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_TEST_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);
|
||||
window_ride_main_widgets[WIDX_OPEN_LIGHT].image = SPR_G2_RCT1_OPEN_BUTTON_0 + (ride->status == RIDE_STATUS_OPEN) * 2
|
||||
|
@ -2580,11 +2602,19 @@ 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_SIMULATE_LIGHT].type
|
||||
= (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? WWT_EMPTY : 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_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;
|
||||
|
@ -2603,6 +2633,7 @@ static void window_ride_main_invalidate(rct_window* w)
|
|||
{
|
||||
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;
|
||||
|
|
|
@ -2026,7 +2026,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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -73,9 +73,9 @@ public:
|
|||
|
||||
if (_status != ride->status)
|
||||
{
|
||||
if (_status == RIDE_STATUS_TESTING)
|
||||
if (_status == RIDE_STATUS_TESTING || _status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
if (!ride_is_valid_for_test(ride, _status == RIDE_STATUS_OPEN, 0))
|
||||
if (!ride_is_valid_for_test(ride, _status, 0))
|
||||
{
|
||||
res->Error = GA_ERROR::UNKNOWN;
|
||||
res->ErrorMessage = gGameCommandErrorText;
|
||||
|
@ -123,7 +123,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 +139,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, 1))
|
||||
{
|
||||
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 +170,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,7 +186,7 @@ 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, 1))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -3959,6 +3959,10 @@ enum
|
|||
|
||||
STR_DESYNC_REPORT = 6318,
|
||||
|
||||
STR_SIMULATING = 6323,
|
||||
STR_SIMULATE_RIDE = 6324,
|
||||
STR_SIMULATE_RIDE_TIP = 6325,
|
||||
|
||||
// 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;
|
||||
|
@ -1024,7 +1029,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 +1990,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 +2200,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5396,7 +5390,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, int32_t isApplying)
|
||||
{
|
||||
int32_t stationIndex;
|
||||
CoordsXYE trackElement, problematicTrackElement = {};
|
||||
|
@ -5407,7 +5401,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)
|
||||
|
@ -5422,7 +5419,7 @@ int32_t ride_is_valid_for_test(Ride* ride, int32_t goingToBeOpen, int32_t isAppl
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (goingToBeOpen && isApplying)
|
||||
if (status == RIDE_STATUS_OPEN && isApplying)
|
||||
{
|
||||
sub_6B5952(ride);
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_EVER_BEEN_OPENED;
|
||||
|
@ -5443,7 +5440,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;
|
||||
|
|
|
@ -631,7 +631,8 @@ enum
|
|||
{
|
||||
RIDE_STATUS_CLOSED,
|
||||
RIDE_STATUS_OPEN,
|
||||
RIDE_STATUS_TESTING
|
||||
RIDE_STATUS_TESTING,
|
||||
RIDE_STATUS_SIMULATING,
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -1074,7 +1075,7 @@ 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_test(Ride* ride, int32_t status, int32_t isApplying);
|
||||
int32_t ride_initialise_construction_window(Ride* ride);
|
||||
void ride_construction_invalidate_current_track();
|
||||
int32_t sub_6C683D(
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
|
|
@ -899,6 +899,13 @@ static void vehicle_sprite_paint(
|
|||
}
|
||||
vehicle_boundbox bb = VehicleBoundboxes[vehicleEntry->draw_order][ecx];
|
||||
|
||||
bool isGhost = false;
|
||||
auto ride = get_ride(vehicle->ride);
|
||||
if (ride != nullptr && ride->status == RIDE_STATUS_SIMULATING)
|
||||
{
|
||||
isGhost = true;
|
||||
}
|
||||
|
||||
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES)
|
||||
{
|
||||
baseImage_id += (vehicle->spin_sprite / 8) & 31;
|
||||
|
@ -909,6 +916,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 (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 +943,13 @@ static void vehicle_sprite_paint(
|
|||
{
|
||||
image_id += (vehicleEntry->no_vehicle_images * vehicle->animation_frame);
|
||||
}
|
||||
|
||||
if (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);
|
||||
|
|
Loading…
Reference in New Issue