From bf0bc77dfcbe2ab6a737adc777ccf8012aa5f6fb Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Thu, 7 Sep 2017 21:29:30 +0200 Subject: [PATCH] Refactor SetParkEntranceFeeAction to use constructor for parameters. Add RideSetNameAction. Support of string serialisation. Check requested status for ride in Query. Add RideDemolishAction. --- openrct2.sln | 8 +- .../windows/DemolishRidePrompt.cpp | 2 +- src/openrct2/actions/GameActionCompat.cpp | 24 +- .../actions/GameActionRegistration.cpp | 2 + src/openrct2/actions/RideDemolishAction.hpp | 212 ++++++++++++++++++ src/openrct2/actions/RideSetName.hpp | 6 - src/openrct2/ride/TrackDesign.cpp | 4 +- src/openrct2/ride/ride.c | 158 +------------ src/openrct2/ride/ride.h | 3 + 9 files changed, 244 insertions(+), 175 deletions(-) create mode 100644 src/openrct2/actions/RideDemolishAction.hpp diff --git a/openrct2.sln b/openrct2.sln index 75d8a67625..8283dd4ee9 100644 --- a/openrct2.sln +++ b/openrct2.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.16 +VisualStudioVersion = 15.0.26228.9 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openrct2-dll", "src\openrct2-dll\openrct2-dll.vcxproj", "{7B8DB129-79EF-417E-B372-8A18E009D261}" ProjectSection(ProjectDependencies) = postProject @@ -38,9 +38,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openrct2-cli", "src\openrct EndProjectSection EndProject Global - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 @@ -108,7 +105,4 @@ Global {8DD8AB7D-2EA6-44E3-8265-BAF08E832951} = {2202A816-377D-4FA0-A7AF-7D4105F8A4FB} {B6808F71-30B4-4499-8FF6-0B1C86391842} = {2202A816-377D-4FA0-A7AF-7D4105F8A4FB} EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection EndGlobal diff --git a/src/openrct2-ui/windows/DemolishRidePrompt.cpp b/src/openrct2-ui/windows/DemolishRidePrompt.cpp index 96b705bab5..722fece068 100644 --- a/src/openrct2-ui/windows/DemolishRidePrompt.cpp +++ b/src/openrct2-ui/windows/DemolishRidePrompt.cpp @@ -104,7 +104,7 @@ static void window_ride_demolish_mouseup(rct_window *w, rct_widgetindex widgetIn switch (widgetIndex) { case WIDX_DEMOLISH: gGameCommandErrorTitle = STR_CANT_DEMOLISH_RIDE; - game_do_command(0, 1, 0, w->number, GAME_COMMAND_DEMOLISH_RIDE, 0, 1); // Set ebp to 1 to be used to log demolish from window prompt + ride_demolish(w->number, GAME_COMMAND_FLAG_APPLY); // Prevents demolished rides sticking around in the ride list window window = window_find_by_class(WC_RIDE_LIST); diff --git a/src/openrct2/actions/GameActionCompat.cpp b/src/openrct2/actions/GameActionCompat.cpp index 1bcf0ea7a7..d6ad29757c 100644 --- a/src/openrct2/actions/GameActionCompat.cpp +++ b/src/openrct2/actions/GameActionCompat.cpp @@ -20,6 +20,7 @@ #include "RideCreateAction.hpp" #include "RideSetStatus.hpp" #include "RideSetName.hpp" +#include "RideDemolishAction.hpp" extern "C" { @@ -164,7 +165,7 @@ extern "C" #pragma endregion -#pragma region RideSetName +#pragma region RideSetNameAction void ride_set_name(sint32 rideIndex, const char *name) { auto gameAction = RideSetNameAction(rideIndex, name); @@ -179,6 +180,25 @@ extern "C" { Guard::Assert(false, "GAME_COMMAND_SET_RIDE_NAME DEPRECATED"); } -#pragma endregion +#pragma endregion + +#pragma region RideDemolishAction + void ride_demolish(sint32 rideIndex, sint32 flags) + { + auto gameAction = RideDemolishAction(rideIndex); + gameAction.SetFlags(flags); + + GameActions::Execute(&gameAction); + } + + /** + * + * rct2: 0x006B49D9 + */ + void game_command_demolish_ride(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp) + { + Guard::Assert(false, "GAME_COMMAND_DEMOLISH_RIDE DEPRECATED"); + } +#pragma endregion } diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 19260d6d12..3a9451f1a1 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -20,6 +20,7 @@ #include "RideCreateAction.hpp" #include "RideSetStatus.hpp" #include "RideSetName.hpp" +#include "RideDemolishAction.hpp" namespace GameActions { @@ -30,5 +31,6 @@ namespace GameActions Register(); Register(); Register(); + Register(); } } diff --git a/src/openrct2/actions/RideDemolishAction.hpp b/src/openrct2/actions/RideDemolishAction.hpp new file mode 100644 index 0000000000..0433faa1a9 --- /dev/null +++ b/src/openrct2/actions/RideDemolishAction.hpp @@ -0,0 +1,212 @@ +#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers +/***************************************************************************** +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* OpenRCT2 is the work of many authors, a full list can be found in contributors.md +* For more information, visit https://github.com/OpenRCT2/OpenRCT2 +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* A full copy of the GNU General Public License can be found in licence.txt +*****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../core/MemoryStream.h" +#include "GameAction.h" + +extern "C" +{ + #include "../cheats.h" + #include "../interface/window.h" + #include "../localisation/localisation.h" + #include "../ride/ride.h" + #include "../world/park.h" +} + +struct RideDemolishAction : public GameActionBase +{ +private: + sint32 _rideIndex; + +public: + RideDemolishAction() {} + RideDemolishAction(sint32 rideIndex) + : _rideIndex(rideIndex) + { + } + + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser& stream) override + { + GameAction::Serialise(stream); + + stream << _rideIndex; + } + + GameActionResult::Ptr Query() const override + { + rct_ride *ride = get_ride(_rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", _rideIndex); + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) + { + return std::make_unique(GA_ERROR::NO_CLEARANCE, + STR_LOCAL_AUTHORITY_FORBIDS_DEMOLITION_OR_MODIFICATIONS_TO_THIS_RIDE); + } + + return std::make_unique(); + } + + GameActionResult::Ptr Execute() const override + { + rct_ride *ride = get_ride(_rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", _rideIndex); + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + sint32 refundPrice = ride_get_refund_price(_rideIndex); + + ride_clear_for_construction(_rideIndex); + ride_remove_peeps(_rideIndex); + ride_stop_peeps_queuing(_rideIndex); + + sub_6CB945(_rideIndex); + news_item_disable_news(NEWS_ITEM_RIDE, _rideIndex); + + for (sint32 i = 0; i < MAX_BANNERS; i++) + { + rct_banner *banner = &gBanners[i]; + if (banner->type != BANNER_NULL && + banner->flags & BANNER_FLAG_LINKED_TO_RIDE && + banner->colour == _rideIndex) + { + banner->flags &= 0xFB; + banner->string_idx = STR_DEFAULT_SIGN; + } + } + + uint16 spriteIndex; + rct_peep *peep; + FOR_ALL_GUESTS(spriteIndex, peep) + { + uint8 ride_id_bit = _rideIndex % 8; + uint8 ride_id_offset = _rideIndex / 8; + + // clear ride from potentially being in rides_been_on + peep->rides_been_on[ride_id_offset] &= ~(1 << ride_id_bit); + if (peep->state == PEEP_STATE_WATCHING) + { + if (peep->current_ride == _rideIndex) + { + peep->current_ride = MAX_RIDES; + if (peep->time_to_stand >= 50) + { + // make peep stop watching the ride + peep->time_to_stand = 50; + } + } + } + + // remove any free voucher for this ride from peep + if (peep->item_standard_flags & PEEP_ITEM_VOUCHER) + { + if (peep->voucher_type == VOUCHER_TYPE_RIDE_FREE && + peep->voucher_arguments == _rideIndex) + { + peep->item_standard_flags &= ~(PEEP_ITEM_VOUCHER); + } + } + + // remove any photos of this ride from peep + if (peep->item_standard_flags & PEEP_ITEM_PHOTO) + { + if (peep->photo1_ride_ref == _rideIndex) + { + peep->item_standard_flags &= ~PEEP_ITEM_PHOTO; + } + } + if (peep->item_extra_flags & PEEP_ITEM_PHOTO2) + { + if (peep->photo2_ride_ref == _rideIndex) + { + peep->item_extra_flags &= ~PEEP_ITEM_PHOTO2; + } + } + if (peep->item_extra_flags & PEEP_ITEM_PHOTO3) + { + if (peep->photo3_ride_ref == _rideIndex) + { + peep->item_extra_flags &= ~PEEP_ITEM_PHOTO3; + } + } + if (peep->item_extra_flags & PEEP_ITEM_PHOTO4) + { + if (peep->photo4_ride_ref == _rideIndex) + { + peep->item_extra_flags &= ~PEEP_ITEM_PHOTO4; + } + } + + if (peep->guest_heading_to_ride_id == _rideIndex) + { + peep->guest_heading_to_ride_id = MAX_RIDES; + } + if (peep->favourite_ride == _rideIndex) + { + peep->favourite_ride = MAX_RIDES; + } + + for (sint32 i = 0; i < PEEP_MAX_THOUGHTS; i++) + { + if (peep->thoughts[i].item == _rideIndex) + { + // Clear top thought, push others up + memmove(&peep->thoughts[i], &peep->thoughts[i + 1], sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1)); + peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE; + } + } + } + + user_string_free(ride->name); + ride->type = RIDE_TYPE_NULL; + gParkValue = calculate_park_value(); + + auto res = std::make_unique(); + res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + res->Cost = refundPrice; + + 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 = map_element_height(x, y); + + res->Position = { x, y, z }; + } + + window_close_by_number(WC_RIDE_CONSTRUCTION, _rideIndex); + window_close_by_number(WC_RIDE, _rideIndex); + window_close_by_number(WC_DEMOLISH_RIDE_PROMPT, _rideIndex); + window_close_by_class(WC_NEW_CAMPAIGN); + + window_invalidate_by_class(WC_RIDE_LIST); + + return res; + } +}; + diff --git a/src/openrct2/actions/RideSetName.hpp b/src/openrct2/actions/RideSetName.hpp index 35d83879b5..edfda82a67 100644 --- a/src/openrct2/actions/RideSetName.hpp +++ b/src/openrct2/actions/RideSetName.hpp @@ -82,12 +82,6 @@ public: GameActionResult::Ptr Execute() const override { rct_string_id newUserStringId = user_string_allocate(USER_STRING_HIGH_ID_NUMBER | USER_STRING_DUPLICATION_PERMITTED, _name.c_str()); - if (newUserStringId == 0) - { - // FIXME: Regardless of Query this can still happen, - // if the server has sent new commands before our own fired. - return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - } rct_ride *ride = get_ride(_rideIndex); if (ride->type == RIDE_TYPE_NULL) diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index c33ce10d44..8f272d66b8 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -1347,7 +1347,7 @@ static sint32 track_design_place_maze(rct_track_td6 * td6, sint16 x, sint16 y, s if (_trackDesignPlaceOperation == PTD_OPERATION_CLEAR_OUTLINES) { - game_do_command(0, 0x69, 0, rideIndex, GAME_COMMAND_DEMOLISH_RIDE, 0, 0); + ride_demolish(rideIndex, GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_GHOST); } gTrackPreviewOrigin.x = x; @@ -1931,7 +1931,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; - game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, rideIndex, GAME_COMMAND_DEMOLISH_RIDE, 0, 0); + ride_demolish(rideIndex, GAME_COMMAND_FLAG_APPLY); gGameCommandErrorText = error_reason; gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; *outRideIndex = rideIndex; diff --git a/src/openrct2/ride/ride.c b/src/openrct2/ride/ride.c index 69dcd099f3..a87e16537a 100644 --- a/src/openrct2/ride/ride.c +++ b/src/openrct2/ride/ride.c @@ -5541,7 +5541,7 @@ sint32 ride_get_refund_price(sint32 ride_id) * * rct2: 0x00696707 */ -static void ride_stop_peeps_queuing(sint32 rideIndex) +void ride_stop_peeps_queuing(sint32 rideIndex) { uint16 spriteIndex; rct_peep *peep; @@ -5903,162 +5903,6 @@ void game_command_callback_ride_remove_track_piece(sint32 eax, sint32 ebx, sint3 window_ride_construction_mouseup_demolish_next_piece(x, y, z, direction, type); } -/** - * - * rct2: 0x006B49D9 - */ -void game_command_demolish_ride(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp) -{ - uint8 ride_id = *(uint8*)edx; - if (ride_id >= MAX_RIDES) - { - log_warning("Invalid game command for ride %u", ride_id); - *ebx = MONEY32_UNDEFINED; - return; - } - - gCommandPosition.x = 0; - gCommandPosition.y = 0; - gCommandPosition.z = 0; - Ride *ride = get_ride(ride_id); - if (ride->type == RIDE_TYPE_NULL) - { - log_warning("Invalid game command for ride %u", ride_id); - *ebx = MONEY32_UNDEFINED; - return; - } - sint32 x = 0, y = 0, z = 0; - if (ride->overall_view.xy != RCT_XY8_UNDEFINED) - { - x = (ride->overall_view.x * 32) + 16; - y = (ride->overall_view.y * 32) + 16; - z = map_element_height(x, y); - gCommandPosition.x = x; - gCommandPosition.y = y; - gCommandPosition.z = z; - } - if (!(*ebx & 0x40) && game_is_paused() && !gCheatsBuildInPauseMode) - { - gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - *ebx = MONEY32_UNDEFINED; - return; - } - else if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) - { - gGameCommandErrorText = STR_LOCAL_AUTHORITY_FORBIDS_DEMOLITION_OR_MODIFICATIONS_TO_THIS_RIDE; - *ebx = MONEY32_UNDEFINED; - return; - } - else - { - if (*ebx & GAME_COMMAND_FLAG_APPLY) - { - if (ride->overall_view.xy != RCT_XY8_UNDEFINED) { - rct_xyz16 coord; - coord.x = ride->overall_view.x * 32 + 16; - coord.y = ride->overall_view.y * 32 + 16; - coord.z = map_element_height(coord.x, coord.y); - network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); - } - - if (!(*ebx & 8)) { - window_close_by_number(WC_RIDE_CONSTRUCTION, ride_id); - } - window_close_by_number(WC_RIDE, ride_id); - window_close_by_number(WC_DEMOLISH_RIDE_PROMPT, ride_id); - window_close_by_class(WC_NEW_CAMPAIGN); - ride_clear_for_construction(ride_id); - ride_remove_peeps(ride_id); - ride_stop_peeps_queuing(ride_id); - *ebx = ride_get_refund_price(ride_id); - - sub_6CB945(ride_id); - news_item_disable_news(NEWS_ITEM_RIDE, ride_id); - - for (sint32 i = 0; i < MAX_BANNERS; i++) { - rct_banner *banner = &gBanners[i]; - if (banner->type != BANNER_NULL && banner->flags & BANNER_FLAG_LINKED_TO_RIDE && banner->colour == ride_id) { - banner->flags &= 0xFB; - banner->string_idx = STR_DEFAULT_SIGN; - } - } - - uint16 spriteIndex; - rct_peep *peep; - FOR_ALL_GUESTS(spriteIndex, peep) - { - uint8 ride_id_bit = ride_id % 8; - uint8 ride_id_offset = ride_id / 8; - peep->rides_been_on[ride_id_offset] &= ~(1 << ride_id_bit); // clear ride from potentially being in rides_been_on - if (peep->state == PEEP_STATE_WATCHING) { - if (peep->current_ride == ride_id) { - peep->current_ride = MAX_RIDES; - if (peep->time_to_stand >= 50) { // make peep stop watching the ride - peep->time_to_stand = 50; - } - } - } - // remove any free voucher for this ride from peep - if (peep->item_standard_flags & PEEP_ITEM_VOUCHER) { - if (peep->voucher_type == VOUCHER_TYPE_RIDE_FREE && peep->voucher_arguments == ride_id) { - peep->item_standard_flags &= ~(PEEP_ITEM_VOUCHER); - } - } - // remove any photos of this ride from peep - if (peep->item_standard_flags & PEEP_ITEM_PHOTO) { - if (peep->photo1_ride_ref == ride_id) { - peep->item_standard_flags &= ~PEEP_ITEM_PHOTO; - } - } - if (peep->item_extra_flags & PEEP_ITEM_PHOTO2) { - if (peep->photo2_ride_ref == ride_id) { - peep->item_extra_flags &= ~PEEP_ITEM_PHOTO2; - } - } - if (peep->item_extra_flags & PEEP_ITEM_PHOTO3) { - if (peep->photo3_ride_ref == ride_id) { - peep->item_extra_flags &= ~PEEP_ITEM_PHOTO3; - } - } - if (peep->item_extra_flags & PEEP_ITEM_PHOTO4) { - if (peep->photo4_ride_ref == ride_id) { - peep->item_extra_flags &= ~PEEP_ITEM_PHOTO4; - } - } - if (peep->guest_heading_to_ride_id == ride_id) { - peep->guest_heading_to_ride_id = MAX_RIDES; - } - if (peep->favourite_ride == ride_id) { - peep->favourite_ride = MAX_RIDES; - } - for (sint32 i = 0; i < PEEP_MAX_THOUGHTS; i++) { - if (peep->thoughts[i].item == ride_id) { - // Clear top thought, push others up - memmove(&peep->thoughts[i], &peep->thoughts[i + 1], sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1)); - peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE; - } - } - } - - user_string_free(ride->name); - ride->type = RIDE_TYPE_NULL; - window_invalidate_by_class(WC_RIDE_LIST); - gParkValue = calculate_park_value(); - gCommandPosition.x = x; - gCommandPosition.y = y; - gCommandPosition.z = z; - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; - return; - } - else - { - *ebx = 0; - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; - return; - } - } -} - /** * * rct2: 0x006B2FC5 diff --git a/src/openrct2/ride/ride.h b/src/openrct2/ride/ride.h index eb471d9b78..082b658c66 100644 --- a/src/openrct2/ride/ride.h +++ b/src/openrct2/ride/ride.h @@ -1208,6 +1208,9 @@ 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_stop_peeps_queuing(sint32 rideIndex); + #ifdef __cplusplus } #endif