Refactor SetParkEntranceFeeAction to use constructor for parameters.

Add RideSetNameAction.
Support of string serialisation.
Check requested status for ride in Query.
Add RideDemolishAction.
This commit is contained in:
ZehMatt 2017-09-07 21:29:30 +02:00 committed by Michał Janiszewski
parent 995c0d0a6b
commit bf0bc77dfc
9 changed files with 244 additions and 175 deletions

View File

@ -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

View File

@ -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);

View File

@ -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
}

View File

@ -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<RideCreateAction>();
Register<RideSetStatusAction>();
Register<RideSetNameAction>();
Register<RideDemolishAction>();
}
}

View File

@ -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<GAME_COMMAND_DEMOLISH_RIDE, GameActionResult>
{
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<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
}
if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE)
{
return std::make_unique<GameActionResult>(GA_ERROR::NO_CLEARANCE,
STR_LOCAL_AUTHORITY_FORBIDS_DEMOLITION_OR_MODIFICATIONS_TO_THIS_RIDE);
}
return std::make_unique<GameActionResult>();
}
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<GameActionResult>(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<GameActionResult>();
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;
}
};

View File

@ -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<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
}
rct_ride *ride = get_ride(_rideIndex);
if (ride->type == RIDE_TYPE_NULL)

View File

@ -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;

View File

@ -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

View File

@ -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