Merge pull request #3473 from jensj12/RenewRidesButton

Added button to renew ride
This commit is contained in:
Aaron van Geffen 2018-05-24 00:09:12 +02:00 committed by GitHub
commit b763a32b44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 348 additions and 151 deletions

View File

@ -4549,6 +4549,15 @@ STR_6239 :Vertical Clipping
STR_6240 :Horizontal Clipping
STR_6241 :Select area
STR_6242 :Clear selection
STR_6243 :{SMALLFONT}{BLACK}Refurbishes the ride,{NEWLINE}makes it like new
STR_6244 :Can't refurbish ride...
STR_6245 :{SMALLFONT}{BLACK}Ride doesn't need refurbishing
STR_6246 :Refurbish
STR_6247 :Refurbish ride/attraction
STR_6248 :{WINDOW_COLOUR_1}Do you want to refurbish {STRINGID} for {BLACK}{CURRENCY}?
STR_6249 :{WINDOW_COLOUR_1}Do you want to refurbish {STRINGID}?
STR_6250 :{WINDOW_COLOUR_1}Are you sure you want to completely demolish {STRINGID} and gain {BLACK}{CURRENCY}?
STR_6251 :Ride is not empty yet
#############
# Scenarios #

View File

@ -2,6 +2,7 @@
------------------------------------------------------------------------
- Feature: [#1417] Allow saving track designs for flat rides.
- Feature: [#1675] Auto-rotate shops to face footpaths.
- Feature: [#3473] Add button in ride window's maintainance tab to refurbish the ride.
- Feature: [#6510] Ability to select edges or a row of tiles by holding down Ctrl using the land tool.
- Feature: [#7187] Option for early scenario completion.
- Feature: [#7266] Make headless instances use an interactive terminal with access to the in-game console API.

View File

@ -179,6 +179,8 @@ public:
return window_banner_open(id);
case WD_DEMOLISH_RIDE:
return window_ride_demolish_prompt_open(id);
case WD_REFURBISH_RIDE:
return window_ride_refurbish_prompt_open(id);
case WD_NEW_CAMPAIGN:
return window_new_campaign_open(id);
case WD_SIGN:

View File

@ -14,23 +14,27 @@
*****************************************************************************/
#pragma endregion
#include <openrct2/Game.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/windows/Intent.h>
#include <openrct2/Context.h>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/Game.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/windows/Intent.h>
#include <openrct2/world/Park.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#define WW 200
#define WH 100
static money32 _demolishRideCost;
// clang-format off
enum WINDOW_RIDE_DEMOLISH_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_DEMOLISH,
WIDX_DEMOLISH = 3,
WIDX_REFURBISH = 3,
WIDX_CANCEL
};
@ -44,8 +48,19 @@ static rct_widget window_ride_demolish_widgets[] = {
{ WIDGETS_END }
};
static rct_widget window_ride_refurbish_widgets[] = {
{ WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, STR_NONE, STR_NONE },
{ WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_REFURBISH_RIDE, STR_WINDOW_TITLE_TIP },
{ WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X_WHITE, STR_CLOSE_WINDOW_TIP },
{ WWT_BUTTON, 0, 10, 94, WH - 20, WH - 9, STR_REFURBISH, STR_NONE },
{ WWT_BUTTON, 0, WW - 95, WW - 11, WH - 20, WH - 9, STR_SAVE_PROMPT_CANCEL, STR_NONE },
{ WIDGETS_END }
};
static void window_ride_demolish_mouseup(rct_window *w, rct_widgetindex widgetIndex);
static void window_ride_demolish_paint(rct_window *w, rct_drawpixelinfo *dpi);
static void window_ride_refurbish_mouseup(rct_window *w, rct_widgetindex widgetIndex);
static void window_ride_refurbish_paint(rct_window *w, rct_drawpixelinfo *dpi);
//0x0098E2E4
static rct_window_event_list window_ride_demolish_events = {
@ -80,24 +95,89 @@ static rct_window_event_list window_ride_demolish_events = {
};
// clang-format on
static rct_window_event_list window_ride_refurbish_events = {
nullptr,
window_ride_refurbish_mouseup,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
window_ride_refurbish_paint,
nullptr
};
/** Based off of rct2: 0x006B486A */
rct_window * window_ride_demolish_prompt_open(sint32 rideIndex)
{
rct_window *w;
w = window_bring_to_front_by_number(WC_DEMOLISH_RIDE_PROMPT, rideIndex);
w = window_find_by_class(WC_DEMOLISH_RIDE_PROMPT);
if (w != nullptr)
return w;
{
int x = w->x;
int y = w->y;
window_close(w);
w = window_create(x, y, WW, WH, &window_ride_demolish_events, WC_DEMOLISH_RIDE_PROMPT, WF_TRANSPARENT);
}
else
{
w = window_create_centred(WW, WH, &window_ride_demolish_events, WC_DEMOLISH_RIDE_PROMPT, WF_TRANSPARENT);
}
w = window_create_centred(WW, WH, &window_ride_demolish_events, WC_DEMOLISH_RIDE_PROMPT, WF_TRANSPARENT);
w->widgets = window_ride_demolish_widgets;
w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_CANCEL) | (1 << WIDX_DEMOLISH);
window_init_scroll_widgets(w);
w->number = rideIndex;
_demolishRideCost = -ride_get_refund_price(rideIndex);
return w;
}
rct_window * window_ride_refurbish_prompt_open(sint32 rideIndex)
{
rct_window *w;
w = window_find_by_class(WC_DEMOLISH_RIDE_PROMPT);
if (w != nullptr)
{
int x = w->x;
int y = w->y;
window_close(w);
w = window_create(x, y, WW, WH, &window_ride_refurbish_events, WC_DEMOLISH_RIDE_PROMPT, WF_TRANSPARENT);
}
else
{
w = window_create_centred(WW, WH, &window_ride_refurbish_events, WC_DEMOLISH_RIDE_PROMPT, WF_TRANSPARENT);
}
w->widgets = window_ride_refurbish_widgets;
w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_CANCEL) | (1 << WIDX_REFURBISH);
window_init_scroll_widgets(w);
w->number = rideIndex;
_demolishRideCost = -ride_get_refund_price(rideIndex);
return w;
}
/**
*
@ -108,7 +188,22 @@ static void window_ride_demolish_mouseup(rct_window *w, rct_widgetindex widgetIn
switch (widgetIndex) {
case WIDX_DEMOLISH:
{
ride_demolish(w->number, GAME_COMMAND_FLAG_APPLY);
ride_action_modify(w->number, RIDE_MODIFY_DEMOLISH, GAME_COMMAND_FLAG_APPLY);
break;
}
case WIDX_CANCEL:
case WIDX_CLOSE:
window_close(w);
break;
}
}
static void window_ride_refurbish_mouseup(rct_window *w, rct_widgetindex widgetIndex)
{
switch (widgetIndex) {
case WIDX_REFURBISH:
{
ride_action_modify(w->number, RIDE_MODIFY_RENEW, GAME_COMMAND_FLAG_APPLY);
break;
}
case WIDX_CANCEL:
@ -130,9 +225,40 @@ static void window_ride_demolish_paint(rct_window *w, rct_drawpixelinfo *dpi)
set_format_arg(0, rct_string_id, ride->name);
set_format_arg(2, uint32, ride->name_arguments);
set_format_arg(6, money32, _demolishRideCost);
sint32 x = w->x + WW / 2;
sint32 y = w->y + (WH / 2) - 3;
gfx_draw_string_centred_wrapped(dpi, gCommonFormatArgs, x, y, WW - 4, STR_DEMOLISH_RIDE_ID, COLOUR_BLACK);
if (gParkFlags & PARK_FLAGS_NO_MONEY)
{
gfx_draw_string_centred_wrapped(dpi, gCommonFormatArgs, x, y, WW - 4, STR_DEMOLISH_RIDE_ID, COLOUR_BLACK);
}
else
{
gfx_draw_string_centred_wrapped(dpi, gCommonFormatArgs, x, y, WW - 4, STR_DEMOLISH_RIDE_ID_MONEY, COLOUR_BLACK);
}
}
static void window_ride_refurbish_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
Ride* ride = get_ride(w->number);
set_format_arg(0, rct_string_id, ride->name);
set_format_arg(2, uint32, ride->name_arguments);
set_format_arg(6, money32, _demolishRideCost / 2);
sint32 x = w->x + WW / 2;
sint32 y = w->y + (WH / 2) - 3;
if (gParkFlags & PARK_FLAGS_NO_MONEY)
{
gfx_draw_string_centred_wrapped(dpi, gCommonFormatArgs, x, y, WW - 4, STR_REFURBISH_RIDE_ID_NO_MONEY, COLOUR_BLACK);
}
else
{
gfx_draw_string_centred_wrapped(dpi, gCommonFormatArgs, x, y, WW - 4, STR_REFURBISH_RIDE_ID_MONEY, COLOUR_BLACK);
}
}

View File

@ -187,7 +187,7 @@ static void window_maze_construction_close(rct_window *w)
if (ride->overall_view.xy == RCT_XY8_UNDEFINED) {
sint32 savedPausedState = gGamePaused;
gGamePaused = 0;
ride_demolish(rideIndex, GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
ride_action_modify(rideIndex, RIDE_MODIFY_DEMOLISH, GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
gGamePaused = savedPausedState;
} else {
auto intent = Intent(WC_RIDE);

View File

@ -142,6 +142,7 @@ enum {
WIDX_INSPECTION_INTERVAL = 14,
WIDX_INSPECTION_INTERVAL_DROPDOWN,
WIDX_LOCATE_MECHANIC,
WIDX_REFURBISH_RIDE,
WIDX_FORCE_BREAKDOWN,
WIDX_TRACK_PREVIEW = 14,
@ -293,7 +294,8 @@ static rct_widget window_ride_maintenance_widgets[] = {
{ WWT_DROPDOWN, 1, 107, 308, 71, 82, 0, STR_SELECT_HOW_OFTEN_A_MECHANIC_SHOULD_CHECK_THIS_RIDE },
{ WWT_BUTTON, 1, 297, 307, 72, 81, STR_DROPDOWN_GLYPH, STR_SELECT_HOW_OFTEN_A_MECHANIC_SHOULD_CHECK_THIS_RIDE },
{ WWT_FLATBTN, 1, 289, 312, 108, 131, 0xFFFFFFFF, STR_LOCATE_NEAREST_AVAILABLE_MECHANIC_TIP },
{ WWT_FLATBTN, 1, 265, 288, 108, 131, SPR_NO_ENTRY, STR_DEBUG_FORCE_BREAKDOWN_TIP },
{ WWT_FLATBTN, 1, 265, 288, 108, 131, SPR_CONSTRUCTION, STR_REFURBISH_RIDE_TIP },
{ WWT_FLATBTN, 1, 241, 264, 108, 131, SPR_NO_ENTRY, STR_DEBUG_FORCE_BREAKDOWN_TIP },
{ WIDGETS_END },
};
@ -454,6 +456,7 @@ static constexpr const uint64 window_ride_page_enabled_widgets[] = {
(1ULL << WIDX_INSPECTION_INTERVAL) |
(1ULL << WIDX_INSPECTION_INTERVAL_DROPDOWN) |
(1ULL << WIDX_LOCATE_MECHANIC) |
(1ULL << WIDX_REFURBISH_RIDE) |
(1ULL << WIDX_FORCE_BREAKDOWN),
MAIN_RIDE_ENABLED_WIDGETS |
(1ULL << WIDX_TRACK_COLOUR_SCHEME_DROPDOWN) |
@ -3688,6 +3691,9 @@ static void window_ride_maintenance_mouseup(rct_window *w, rct_widgetindex widge
case WIDX_LOCATE_MECHANIC:
window_ride_locate_mechanic(w);
break;
case WIDX_REFURBISH_RIDE:
context_open_detail_window(WD_REFURBISH_RIDE, w->number);
break;
}
}
@ -3930,12 +3936,24 @@ static void window_ride_maintenance_invalidate(rct_window *w)
window_ride_anchor_border_widgets(w);
window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10);
if (gConfigGeneral.debugging_tools && network_get_mode() == NETWORK_MODE_NONE) {
if (gConfigGeneral.debugging_tools && network_get_mode() == NETWORK_MODE_NONE)
{
window_ride_maintenance_widgets[WIDX_FORCE_BREAKDOWN].type = WWT_FLATBTN;
}
else {
else
{
window_ride_maintenance_widgets[WIDX_FORCE_BREAKDOWN].type = WWT_EMPTY;
}
if (RideAvailableBreakdowns[ride->type] == 0 || !(ride->lifecycle_flags & RIDE_LIFECYCLE_EVER_BEEN_OPENED))
{
w->disabled_widgets |= (1 << WIDX_REFURBISH_RIDE);
window_ride_maintenance_widgets[WIDX_REFURBISH_RIDE].tooltip = STR_CANT_REFURBISH_NOT_NEEDED;
}
else
{
w->disabled_widgets &= ~(1 << WIDX_REFURBISH_RIDE);
window_ride_maintenance_widgets[WIDX_REFURBISH_RIDE].tooltip = STR_REFURBISH_RIDE_TIP;
}
}

View File

@ -677,7 +677,7 @@ static void window_ride_construction_close(rct_window *w)
{
sint32 previousPauseState = gGamePaused;
gGamePaused = 0;
ride_demolish(rideIndex, GAME_COMMAND_FLAG_APPLY);
ride_action_modify(rideIndex, RIDE_MODIFY_DEMOLISH, GAME_COMMAND_FLAG_APPLY);
gGamePaused = previousPauseState;
}
}

View File

@ -456,7 +456,7 @@ static void window_ride_list_scrollmousedown(rct_window *w, sint32 scrollIndex,
// Open ride window
uint8 rideIndex = w->list_item_positions[index];
if (_quickDemolishMode && network_get_mode() != NETWORK_MODE_CLIENT) {
ride_demolish(rideIndex, GAME_COMMAND_FLAG_APPLY);
ride_action_modify(rideIndex, RIDE_MODIFY_DEMOLISH, GAME_COMMAND_FLAG_APPLY);
window_ride_list_refresh_list(w);
}
else {

View File

@ -78,6 +78,7 @@ rct_window * window_park_rating_open();
rct_window * window_banner_open(rct_windownumber number);
rct_window * window_ride_demolish_prompt_open(sint32 rideIndex);
rct_window * window_ride_refurbish_prompt_open(sint32 rideIndex);
rct_window * window_sign_open(rct_windownumber number);
rct_window * window_sign_small_open(rct_windownumber number);
rct_window * window_player_open(uint8 id);

View File

@ -214,10 +214,10 @@
}
#pragma endregion
#pragma region RideDemolishAction
void ride_demolish(sint32 rideIndex, sint32 flags)
#pragma region RideModifyAction
void ride_action_modify(sint32 rideIndex, sint32 modifyType, sint32 flags)
{
auto gameAction = RideDemolishAction(rideIndex);
auto gameAction = RideDemolishAction(rideIndex, modifyType);
gameAction.SetFlags(flags);
GameActions::Execute(&gameAction);

View File

@ -37,11 +37,13 @@ struct RideDemolishAction : public GameActionBase<GAME_COMMAND_DEMOLISH_RIDE, Ga
{
private:
sint32 _rideIndex = -1;
uint8 _modifyType = RIDE_MODIFY_DEMOLISH;
public:
RideDemolishAction() {}
RideDemolishAction(sint32 rideIndex)
: _rideIndex(rideIndex)
RideDemolishAction(sint32 rideIndex, uint8 modifyType) :
_rideIndex(rideIndex),
_modifyType(modifyType)
{
}
@ -54,7 +56,7 @@ public:
{
GameAction::Serialise(stream);
stream << _rideIndex;
stream << _rideIndex << _modifyType;
}
GameActionResult::Ptr Query() const override
@ -66,13 +68,39 @@ public:
return std::make_unique<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_CANT_DEMOLISH_RIDE, STR_NONE);
}
if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE)
if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE && _modifyType == RIDE_MODIFY_DEMOLISH)
{
return std::make_unique<GameActionResult>(GA_ERROR::NO_CLEARANCE, STR_CANT_DEMOLISH_RIDE,
STR_LOCAL_AUTHORITY_FORBIDS_DEMOLITION_OR_MODIFICATIONS_TO_THIS_RIDE);
}
return std::make_unique<GameActionResult>();
GameActionResult::Ptr result = std::make_unique<GameActionResult>();
if (_modifyType == RIDE_MODIFY_RENEW)
{
if (ride->status != RIDE_STATUS_CLOSED)
{
return std::make_unique<GameActionResult>(GA_ERROR::DISALLOWED, STR_CANT_REFURBISH_RIDE,
STR_MUST_BE_CLOSED_FIRST);
}
if (ride->num_riders > 0)
{
return std::make_unique<GameActionResult>(GA_ERROR::DISALLOWED, STR_CANT_REFURBISH_RIDE,
STR_RIDE_NOT_YET_EMPTY);
}
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_EVER_BEEN_OPENED) || RideAvailableBreakdowns[ride->type] == 0)
{
return std::make_unique<GameActionResult>(GA_ERROR::DISALLOWED, STR_CANT_REFURBISH_RIDE,
STR_CANT_REFURBISH_NOT_NEEDED);
}
result->ErrorTitle = STR_CANT_REFURBISH_RIDE;
result->Cost = GetRefurbishPrice();
}
return result;
}
GameActionResult::Ptr Execute() const override
@ -84,6 +112,20 @@ public:
return std::make_unique<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_CANT_DEMOLISH_RIDE, STR_NONE);
}
switch (_modifyType) {
case RIDE_MODIFY_DEMOLISH:
return DemolishRide(ride);
case RIDE_MODIFY_RENEW:
return RefurbishRide(ride);
}
return std::make_unique<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_CANT_DO_THIS);
}
private:
GameActionResult::Ptr DemolishRide(Ride * ride) const
{
money32 refundPrice = DemolishTracks();
ride_clear_for_construction(_rideIndex);
@ -224,8 +266,6 @@ public:
return res;
}
private:
money32 MazeRemoveTrack(uint16 x, uint16 y, uint16 z, uint8 direction) const
{
auto setMazeTrack = MazeSetTrackAction(x, y, z, false, direction, _rideIndex, GC_SET_MAZE_TRACK_FILL);
@ -312,4 +352,41 @@ private:
gGamePaused = oldpaused;
return refundPrice;
}
GameActionResult::Ptr RefurbishRide(Ride * ride) const
{
auto res = std::make_unique<GameActionResult>();
res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
res->Cost = GetRefurbishPrice();
ride_renew(ride);
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_EVER_BEEN_OPENED;
ride->last_crash_type = RIDE_CRASH_TYPE_NONE;
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE | RIDE_INVALIDATE_RIDE_CUSTOMER;
if (ride->overall_view.xy != RCT_XY8_UNDEFINED)
{
sint32 x = (ride->overall_view.x * 32) + 16;
sint32 y = (ride->overall_view.y * 32) + 16;
sint32 z = tile_element_height(x, y);
res->Position = { x, y, z };
}
window_close_by_number(WC_DEMOLISH_RIDE_PROMPT, _rideIndex);
return res;
}
money32 GetRefurbishPrice() const
{
return -GetRefundPrice() / 2;
}
money32 GetRefundPrice() const
{
return ride_get_refund_price(_rideIndex);
}
};

View File

@ -431,6 +431,7 @@ enum {
WD_BANNER,
WD_NEW_CAMPAIGN,
WD_DEMOLISH_RIDE,
WD_REFURBISH_RIDE,
WD_SIGN,
WD_SIGN_SMALL,

View File

@ -3910,6 +3910,16 @@ enum {
STR_VIEW_CLIPPING_SELECT_AREA = 6241,
STR_VIEW_CLIPPING_CLEAR_SELECTION = 6242,
STR_REFURBISH_RIDE_TIP = 6243,
STR_CANT_REFURBISH_RIDE = 6244,
STR_CANT_REFURBISH_NOT_NEEDED = 6245,
STR_REFURBISH = 6246,
STR_REFURBISH_RIDE = 6247,
STR_REFURBISH_RIDE_ID_MONEY = 6248,
STR_REFURBISH_RIDE_ID_NO_MONEY = 6249,
STR_DEMOLISH_RIDE_ID_MONEY = 6250,
STR_RIDE_NOT_YET_EMPTY = 6251,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@ -34,7 +34,7 @@
// This string specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "14"
#define NETWORK_STREAM_VERSION "15"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
static rct_peep* _pickup_peep = nullptr;

View File

@ -5476,114 +5476,77 @@ sint32 ride_is_valid_for_open(sint32 rideIndex, sint32 goingToBeOpen, sint32 isA
return 1;
}
/**
* Given a track element of the ride, find the start of the track.
* It has to do this as a backwards loop in case this is an incomplete track.
*/
void ride_get_start_of_track(CoordsXYE * output)
{
track_begin_end trackBeginEnd;
CoordsXYE trackElement = *output;
if (track_block_get_previous(trackElement.x, trackElement.y, trackElement.element, &trackBeginEnd)) {
rct_tile_element* initial_map = trackElement.element;
do {
CoordsXYE lastGood = {
/* .x = */ trackBeginEnd.begin_x,
/* .y = */ trackBeginEnd.begin_y,
/* .element = */ trackBeginEnd.begin_element
};
if (!track_block_get_previous(trackBeginEnd.end_x, trackBeginEnd.end_y, trackBeginEnd.begin_element, &trackBeginEnd)) {
trackElement = lastGood;
break;
}
} while (initial_map != trackBeginEnd.begin_element);
}
output = &trackElement;
}
/**
*
* rct2: 0x006CB7FB
*/
sint32 ride_get_refund_price(sint32 ride_id)
{
uint8 oldpaused = gGamePaused;
gGamePaused = 0;
money32 refundPrice = 0;
CoordsXYE trackElement;
money32 addedcost, cost = 0;
tile_element_iterator it;
tile_element_iterator_begin(&it);
while (tile_element_iterator_next(&it)) {
if (it.element->GetType() != TILE_ELEMENT_TYPE_TRACK)
continue;
if (track_element_get_ride_index(it.element) != ride_id)
continue;
sint32 x = it.x * 32, y = it.y * 32;
sint32 z = it.element->base_height * 8;
uint8 rotation = tile_element_get_direction(it.element);
uint8 type = track_element_get_type(it.element);
if (type != TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP){
money32 removePrice = game_do_command(
x,
GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_APPLY | (rotation << 8),
y,
type | (tile_element_get_track_sequence(it.element) << 8),
GAME_COMMAND_REMOVE_TRACK,
z,
0);
if (removePrice == MONEY32_UNDEFINED) {
tile_element_remove(it.element);
} else {
refundPrice += removePrice;
}
tile_element_iterator_restart_for_tile(&it);
continue;
}
// Using GAME_COMMAND_FLAG_2 for below commands as a HACK to stop fences from being removed
refundPrice += game_do_command(
x,
GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_2 | (0 << 8),
y,
ride_id | (2 << 8),
GAME_COMMAND_SET_MAZE_TRACK,
z,
0);
// Above gamecommand may remove the tile element which will cause the next game command to
// return MONEY32_UNDEFINED as it does not need to be called.
money32 removePrice = game_do_command(
x,
GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_2 | (1 << 8),
y + 16,
ride_id | (2 << 8),
GAME_COMMAND_SET_MAZE_TRACK,
z,
0);
if (removePrice == MONEY32_UNDEFINED &&
gGameCommandErrorText == 0)
{
tile_element_iterator_restart_for_tile(&it);
continue;
}
refundPrice += removePrice;
removePrice = game_do_command(
x + 16,
GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_2 | (2 << 8),
y + 16,
ride_id | (2 << 8),
GAME_COMMAND_SET_MAZE_TRACK,
z,
0);
if (refundPrice == MONEY32_UNDEFINED &&
gGameCommandErrorText == 0)
{
tile_element_iterator_restart_for_tile(&it);
continue;
}
refundPrice += removePrice;
removePrice = game_do_command(
x + 16,
GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_2 | (3 << 8),
y,
ride_id | (2 << 8),
GAME_COMMAND_SET_MAZE_TRACK,
z,
0);
if (removePrice != MONEY32_UNDEFINED)
{
refundPrice += removePrice;
}
tile_element_iterator_restart_for_tile(&it);
if (!ride_try_get_origin_element(ride_id, &trackElement)) {
gGameCommandErrorText = STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY;
return MONEY32_UNDEFINED;
}
gGamePaused = oldpaused;
return refundPrice;
// Find the start in case it is not a complete circuit
ride_get_start_of_track(&trackElement);
uint8 direction = tile_element_get_direction(trackElement.element);
// Used in the following loop to know when we have
// completed all of the elements and are back at the
// start.
rct_tile_element *initial_map = trackElement.element;
do {
addedcost = game_do_command(
trackElement.x,
GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | (direction << 8),
trackElement.y,
trackElement.element->properties.track.type | ((trackElement.element->properties.track.sequence & 0xF) << 8),
GAME_COMMAND_REMOVE_TRACK,
trackElement.element->base_height * 8,
0
);
cost += (addedcost == MONEY32_UNDEFINED) ? 0 : addedcost;
if (!track_block_get_next(&trackElement, &trackElement, NULL, NULL))
break;
direction = tile_element_get_direction(trackElement.element);
} while (trackElement.element != initial_map);
return cost;
}
/**

View File

@ -844,6 +844,11 @@ enum {
TRACK_SELECTION_FLAG_RECHECK = 1 << 3,
};
enum {
RIDE_MODIFY_DEMOLISH,
RIDE_MODIFY_RENEW
};
struct rct_ride_properties {
uint32 flags;
uint8 min_value;
@ -1059,6 +1064,8 @@ bool track_block_get_next_from_zero(sint16 x, sint16 y, sint16 z_start, uint8 ri
bool track_block_get_previous(sint32 x, sint32 y, rct_tile_element *tileElement, track_begin_end *outTrackBeginEnd);
bool track_block_get_previous_from_zero(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8 direction, track_begin_end *outTrackBeginEnd);
void ride_get_start_of_track(CoordsXYE * output);
void window_ride_construction_update_active_elements();
void ride_construction_remove_ghosts();
money32 ride_entrance_exit_place_ghost(sint32 rideIndex, sint32 x, sint32 y, sint32 direction, sint32 placeType, sint32 stationNum);
@ -1124,7 +1131,7 @@ bool ride_entry_has_category(const rct_ride_entry * rideEntry, uint8 category);
sint32 ride_get_entry_index(sint32 rideType, sint32 rideSubType);
void ride_demolish(sint32 rideIndex, sint32 flags);
void ride_action_modify(sint32 rideIndex, sint32 modifyType, sint32 flags);
void ride_stop_peeps_queuing(sint32 rideIndex);
LocationXY16 ride_get_rotated_coords(sint16 x, sint16 y, sint16 z);

View File

@ -1377,7 +1377,7 @@ static sint32 track_design_place_maze(rct_track_td6 * td6, sint16 x, sint16 y, s
if (_trackDesignPlaceOperation == PTD_OPERATION_CLEAR_OUTLINES)
{
ride_demolish(rideIndex, GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_GHOST);
ride_action_modify(rideIndex, RIDE_MODIFY_DEMOLISH, GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_GHOST);
}
gTrackPreviewOrigin.x = x;
@ -1974,7 +1974,7 @@ static money32 place_track_design(sint16 x, sint16 y, sint16 z, uint8 flags, uin
if (cost == MONEY32_UNDEFINED || !(flags & GAME_COMMAND_FLAG_APPLY))
{
rct_string_id error_reason = gGameCommandErrorText;
ride_demolish(rideIndex, GAME_COMMAND_FLAG_APPLY);
ride_action_modify(rideIndex, RIDE_MODIFY_DEMOLISH, GAME_COMMAND_FLAG_APPLY);
gGameCommandErrorText = error_reason;
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
*outRideIndex = rideIndex;

View File

@ -935,33 +935,15 @@ static bool track_design_save_to_td6_for_tracked_ride(uint8 rideIndex, rct_track
{
Ride *ride = get_ride(rideIndex);
CoordsXYE trackElement;
track_begin_end trackBeginEnd;
if (!ride_try_get_origin_element(rideIndex, &trackElement)) {
gGameCommandErrorText = STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY;
return false;
}
sint32 z = 0;
// Find the start of the track.
// It has to do this as a backwards loop in case this is an incomplete track.
if (track_block_get_previous(trackElement.x, trackElement.y, trackElement.element, &trackBeginEnd)) {
rct_tile_element* initial_map = trackElement.element;
do {
CoordsXYE lastGood = {
/* .x = */ trackBeginEnd.begin_x,
/* .y = */ trackBeginEnd.begin_y,
/* .element = */ trackBeginEnd.begin_element
};
ride_get_start_of_track(&trackElement);
if (!track_block_get_previous(trackBeginEnd.end_x, trackBeginEnd.end_y, trackBeginEnd.begin_element, &trackBeginEnd)) {
trackElement = lastGood;
break;
}
} while (initial_map != trackBeginEnd.begin_element);
}
z = trackElement.element->base_height * 8;
sint32 z = trackElement.element->base_height * 8;
uint8 track_type = track_element_get_type(trackElement.element);
uint8 direction = tile_element_get_direction(trackElement.element);
_trackSaveDirection = direction;