diff --git a/src/openrct2/actions/GameAction.cpp b/src/openrct2/actions/GameAction.cpp index 8adb992433..b3ea4838dc 100644 --- a/src/openrct2/actions/GameAction.cpp +++ b/src/openrct2/actions/GameAction.cpp @@ -137,7 +137,7 @@ namespace GameActions if (network_get_mode() == NETWORK_MODE_CLIENT) { // As a client we have to wait or send it first. - if (!(actionFlags & GA_FLAGS::CLIENT_ONLY) && !(flags & GAME_COMMAND_FLAG_GHOST) && !(flags & GAME_COMMAND_FLAG_NETWORKED)) + if (!(actionFlags & GA_FLAGS::CLIENT_ONLY) && !(flags & GAME_COMMAND_FLAG_NETWORKED)) { log_info("[%s] GameAction::Execute\n", "cl"); @@ -150,7 +150,7 @@ namespace GameActions { // If player is the server it would execute right away as where clients execute the commands // at the beginning of the frame, so we have to put them into the queue. - if (!(actionFlags & GA_FLAGS::CLIENT_ONLY) && !(flags & GAME_COMMAND_FLAG_GHOST) && !(flags & GAME_COMMAND_FLAG_NETWORKED)) + if (!(actionFlags & GA_FLAGS::CLIENT_ONLY) && !(flags & GAME_COMMAND_FLAG_NETWORKED)) { log_info("[%s] GameAction::Execute\n", "sv-cl"); network_enqueue_game_action(action); diff --git a/src/openrct2/actions/GameAction.h b/src/openrct2/actions/GameAction.h index 4bc812d7d4..f95fd994bd 100644 --- a/src/openrct2/actions/GameAction.h +++ b/src/openrct2/actions/GameAction.h @@ -93,7 +93,6 @@ public: private: uint32 const _type; - uint16 const _actionFlags; uint32 _playerId = 0; // Callee uint32 _flags = 0; // GAME_COMMAND_FLAGS @@ -101,9 +100,8 @@ private: Callback_t _callback; public: - GameAction(uint32 type, uint16 actionFlags) - : _type(type), - _actionFlags(actionFlags) + GameAction(uint32 type) + : _type(type) { } @@ -122,9 +120,16 @@ public: /** * Gets the GA_FLAGS flags that are enabled for this game action. */ - uint16 GetActionFlags() const + virtual uint16 GetActionFlags() const { - return _actionFlags; + // Make sure we execute some things only on the client. + if ((GetFlags() & GAME_COMMAND_FLAG_GHOST) != 0 || + (GetFlags() & GAME_COMMAND_FLAG_5) != 0) + { + return GA_FLAGS::CLIENT_ONLY; + } + + return 0; } /** @@ -193,14 +198,16 @@ public: #pragma GCC diagnostic pop #endif -template +template struct GameActionBase : GameAction { public: + typedef TResultType Result; + static constexpr uint32 TYPE = TType; GameActionBase() - : GameAction(TYPE, TActionFlags) + : GameAction(TYPE) { } diff --git a/src/openrct2/actions/GameActionCompat.cpp b/src/openrct2/actions/GameActionCompat.cpp index 32cb14e2e4..cbb7135a6f 100644 --- a/src/openrct2/actions/GameActionCompat.cpp +++ b/src/openrct2/actions/GameActionCompat.cpp @@ -14,6 +14,7 @@ *****************************************************************************/ #pragma endregion +#include "GameAction.h" #include "PlaceParkEntranceAction.hpp" #include "SetParkEntranceFeeAction.hpp" #include "RideCreateAction.hpp" @@ -24,11 +25,7 @@ extern "C" #pragma region PlaceParkEntranceAction money32 place_park_entrance(sint16 x, sint16 y, sint16 z, uint8 direction) { - auto gameAction = PlaceParkEntranceAction(); - gameAction.x = x; - gameAction.y = y; - gameAction.z = z; - gameAction.direction = direction; + auto gameAction = PlaceParkEntranceAction(x, y, z, direction); auto result = GameActions::Execute(&gameAction); if (result->Error == GA_ERROR::OK) { @@ -63,11 +60,7 @@ extern "C" { park_entrance_remove_ghost(); - auto gameAction = PlaceParkEntranceAction(); - gameAction.x = x; - gameAction.y = y; - gameAction.z = z; - gameAction.direction = direction; + auto gameAction = PlaceParkEntranceAction(x, y, z, direction); gameAction.SetFlags(GAME_COMMAND_FLAG_GHOST); auto result = GameActions::Execute(&gameAction); @@ -106,13 +99,11 @@ extern "C" */ void ride_construct_new(ride_list_item listItem) { - auto gameAction = RideCreateAction(); - gameAction.rideType = listItem.type; - gameAction.rideSubType = listItem.entry_index; + sint32 rideEntryIndex = ride_get_entry_index(listItem.type, listItem.entry_index); + sint32 colour1 = ride_get_random_colour_preset_index(listItem.type); + sint32 colour2 = ride_get_unused_preset_vehicle_colour(listItem.type, rideEntryIndex); - sint32 rideEntryIndex = ride_get_entry_index(gameAction.rideType, gameAction.rideSubType); - gameAction.colourPreset1 = ride_get_random_colour_preset_index(gameAction.rideType); - gameAction.colourPreset2 = ride_get_unused_preset_vehicle_colour(gameAction.rideType, rideEntryIndex); + auto gameAction = RideCreateAction(listItem.type, listItem.entry_index, colour1, colour2); gameAction.SetCallback([](const GameAction *ga, const RideCreateGameActionResult * result) { @@ -125,6 +116,24 @@ extern "C" GameActions::Execute(&gameAction); } + money32 ride_create_command(sint32 type, sint32 subType, sint32 flags, uint8 *outRideIndex, uint8 *outRideColour) + { + sint32 rideEntryIndex = ride_get_entry_index(type, subType); + sint32 colour1 = ride_get_random_colour_preset_index(type); + sint32 colour2 = ride_get_unused_preset_vehicle_colour(type, rideEntryIndex); + + auto gameAction = RideCreateAction(type, subType, colour1, colour2); + gameAction.SetFlags(flags); + + auto r = GameActions::Execute(&gameAction); + const RideCreateGameActionResult *res = static_cast(r.get()); + + *outRideIndex = res->rideIndex; + *outRideColour = colour1; + + return res->Cost; + } + /** * * rct2: 0x006B3F0F @@ -140,10 +149,7 @@ extern "C" void ride_set_status(sint32 rideIndex, sint32 status) { - auto gameAction = RideSetStatusAction(); - gameAction.RideIndex = rideIndex; - gameAction.Status = status; - + auto gameAction = RideSetStatusAction(rideIndex, status); GameActions::Execute(&gameAction); } diff --git a/src/openrct2/actions/PlaceParkEntranceAction.hpp b/src/openrct2/actions/PlaceParkEntranceAction.hpp index 66d38abe18..2965083a3d 100644 --- a/src/openrct2/actions/PlaceParkEntranceAction.hpp +++ b/src/openrct2/actions/PlaceParkEntranceAction.hpp @@ -38,19 +38,34 @@ struct PlaceParkEntranceGameActionResult : public GameActionResult } }; -struct PlaceParkEntranceAction : public GameActionBase +struct PlaceParkEntranceAction : public GameActionBase { +private: + sint16 _x; + sint16 _y; + sint16 _z; + uint8 _direction; + public: - sint16 x; - sint16 y; - sint16 z; - uint8 direction; + PlaceParkEntranceAction() {} + PlaceParkEntranceAction(sint16 x, sint16 y, sint16 z, sint16 direction) : + _x(x), + _y(y), + _z(z), + _direction(direction) + { + } + + uint16 GetActionFlags() const override + { + return GameActionBase::GetActionFlags() | GA_FLAGS::EDITOR_ONLY; + } void Serialise(DataSerialiser& stream) override { GameAction::Serialise(stream); - stream << x << y << z << direction; + stream << _x << _y << _z << _direction; } GameActionResult::Ptr Query() const override @@ -62,16 +77,16 @@ public: gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LAND_PURCHASE; - gCommandPosition.x = x; - gCommandPosition.y = y; - gCommandPosition.z = z * 16; + gCommandPosition.x = _x; + gCommandPosition.y = _y; + gCommandPosition.z = _z * 16; if (!map_check_free_elements_and_reorganise(3)) { return std::make_unique(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE); } - if (x <= 32 || y <= 32 || x >= (gMapSizeUnits - 32) || y >= (gMapSizeUnits - 32)) + if (_x <= 32 || _y <= 32 || _x >= (gMapSizeUnits - 32) || _y >= (gMapSizeUnits - 32)) { return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_TOO_CLOSE_TO_EDGE_OF_MAP); } @@ -91,20 +106,20 @@ public: return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_ERR_TOO_MANY_PARK_ENTRANCES); } - sint8 zLow = z * 2; + sint8 zLow = _z * 2; sint8 zHigh = zLow + 12; - rct_xy16 entranceLoc = { x, y }; + rct_xy16 entranceLoc = { _x, _y }; for (uint8 index = 0; index < 3; index++) { if (index == 1) { - entranceLoc.x += TileDirectionDelta[(direction - 1) & 0x3].x; - entranceLoc.y += TileDirectionDelta[(direction - 1) & 0x3].y; + entranceLoc.x += TileDirectionDelta[(_direction - 1) & 0x3].x; + entranceLoc.y += TileDirectionDelta[(_direction - 1) & 0x3].y; } else if (index == 2) { - entranceLoc.x += TileDirectionDelta[(direction + 1) & 0x3].x * 2; - entranceLoc.y += TileDirectionDelta[(direction + 1) & 0x3].y * 2; + entranceLoc.x += TileDirectionDelta[(_direction + 1) & 0x3].x * 2; + entranceLoc.y += TileDirectionDelta[(_direction + 1) & 0x3].y * 2; } if (!gCheatsDisableClearanceChecks) @@ -132,9 +147,9 @@ public: gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LAND_PURCHASE; - gCommandPosition.x = x; - gCommandPosition.y = y; - gCommandPosition.z = z * 16; + gCommandPosition.x = _x; + gCommandPosition.y = _y; + gCommandPosition.z = _z * 16; sint8 entranceNum = -1; for (uint8 i = 0; i < MAX_PARK_ENTRANCES; ++i) @@ -148,25 +163,25 @@ public: Guard::Assert(entranceNum != -1); - gParkEntrances[entranceNum].x = x; - gParkEntrances[entranceNum].y = y; - gParkEntrances[entranceNum].z = z * 16; - gParkEntrances[entranceNum].direction = direction; + gParkEntrances[entranceNum].x = _x; + gParkEntrances[entranceNum].y = _y; + gParkEntrances[entranceNum].z = _z * 16; + gParkEntrances[entranceNum].direction = _direction; - sint8 zLow = z * 2; + sint8 zLow = _z * 2; sint8 zHigh = zLow + 12; - rct_xy16 entranceLoc = { x, y }; + rct_xy16 entranceLoc = { _x, _y }; for (uint8 index = 0; index < 3; index++) { if (index == 1) { - entranceLoc.x += TileDirectionDelta[(direction - 1) & 0x3].x; - entranceLoc.y += TileDirectionDelta[(direction - 1) & 0x3].y; + entranceLoc.x += TileDirectionDelta[(_direction - 1) & 0x3].x; + entranceLoc.y += TileDirectionDelta[(_direction - 1) & 0x3].y; } else if (index == 2) { - entranceLoc.x += TileDirectionDelta[(direction + 1) & 0x3].x * 2; - entranceLoc.y += TileDirectionDelta[(direction + 1) & 0x3].y * 2; + entranceLoc.x += TileDirectionDelta[(_direction + 1) & 0x3].x * 2; + entranceLoc.y += TileDirectionDelta[(_direction + 1) & 0x3].y * 2; } if (!(flags & GAME_COMMAND_FLAG_GHOST)) @@ -185,7 +200,7 @@ public: } newElement->type = MAP_ELEMENT_TYPE_ENTRANCE; - newElement->type |= direction; + newElement->type |= _direction; newElement->properties.entrance.index = index; newElement->properties.entrance.type = ENTRANCE_TYPE_PARK_ENTRANCE; newElement->properties.entrance.path_type = gFootpathSelectedId; diff --git a/src/openrct2/actions/RideCreateAction.hpp b/src/openrct2/actions/RideCreateAction.hpp index dce33bf342..a5d8b3032d 100644 --- a/src/openrct2/actions/RideCreateAction.hpp +++ b/src/openrct2/actions/RideCreateAction.hpp @@ -41,37 +41,52 @@ struct RideCreateGameActionResult : public GameActionResult sint32 rideIndex; }; -struct RideCreateAction : public GameActionBase +struct RideCreateAction : public GameActionBase { +private: + sint32 _rideType; + sint32 _subType; + uint8 _colour1; + uint8 _colour2; + public: - sint32 rideType; - sint32 rideSubType; - uint8 colourPreset1; - uint8 colourPreset2; + RideCreateAction() {} + RideCreateAction(sint32 rideType, sint32 subType, sint32 colour1, sint32 colour2) : + _rideType(rideType), + _subType(subType), + _colour1(colour1), + _colour2(colour2) + { + } + + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED;; + } void Serialise(DataSerialiser& stream) override { GameAction::Serialise(stream); - stream << rideType << rideSubType << colourPreset1 << colourPreset2; + stream << _rideType << _subType << _colour1 << _colour2; } GameActionResult::Ptr Query() const override { - if (rideType >= RIDE_TYPE_COUNT) + if (_rideType >= RIDE_TYPE_COUNT) { return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_RIDE_TYPE); } - sint32 rideEntryIndex = ride_get_entry_index(rideType, rideSubType); + sint32 rideEntryIndex = ride_get_entry_index(_rideType, _subType); if (rideEntryIndex >= 128) { return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_RIDE_TYPE); } - const track_colour_preset_list *colourPresets = &RideColourPresets[rideType]; - if (colourPreset1 >= colourPresets->count) + const track_colour_preset_list *colourPresets = &RideColourPresets[_rideType]; + if (_colour1 >= colourPresets->count) { // FIXME: Add new error string. return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_RIDE_TYPE); @@ -79,7 +94,7 @@ public: rct_ride_entry *rideEntry = get_ride_entry(rideEntryIndex); vehicle_colour_preset_list *presetList = rideEntry->vehicle_preset_list; - if (colourPreset2 >= presetList->count) + if (_colour2 >= presetList->count) { // FIXME: Add new error string. return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_RIDE_TYPE); @@ -93,7 +108,7 @@ public: rct_ride_entry * rideEntry; auto res = std::make_unique(); - sint32 rideEntryIndex = ride_get_entry_index(rideType, rideSubType); + sint32 rideEntryIndex = ride_get_entry_index(_rideType, _subType); sint32 rideIndex = ride_get_empty_slot(); res->rideIndex = rideIndex; @@ -108,9 +123,9 @@ public: return std::move(res); } - ride->type = rideType; + ride->type = _rideType; ride->subtype = rideEntryIndex; - ride_set_colour_preset(ride, colourPreset1); + ride_set_colour_preset(ride, _colour1); ride->overall_view.xy = RCT_XY8_UNDEFINED; // Ride name @@ -279,7 +294,7 @@ public: ride->num_circuits = 1; ride->mode = ride_get_default_mode(ride); ride->min_max_cars_per_train = (rideEntry->min_cars_in_train << 4) | rideEntry->max_cars_in_train; - ride_set_vehicle_colours_to_random_preset(ride, colourPreset2); + ride_set_vehicle_colours_to_random_preset(ride, _colour2); window_invalidate_by_class(WC_RIDE_LIST); res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; @@ -287,4 +302,4 @@ public: return std::move(res); } -}; +}; \ No newline at end of file diff --git a/src/openrct2/actions/RideSetStatus.hpp b/src/openrct2/actions/RideSetStatus.hpp index 159be38106..131ef7731e 100644 --- a/src/openrct2/actions/RideSetStatus.hpp +++ b/src/openrct2/actions/RideSetStatus.hpp @@ -28,25 +28,37 @@ extern "C" #include "../ride/ride.h" } -struct RideSetStatusAction : public GameActionBase +struct RideSetStatusAction : public GameActionBase { +private: + uint8 _rideIndex; + uint8 _status; + public: - uint8 RideIndex; - uint8 Status; + RideSetStatusAction() {} + RideSetStatusAction(uint8 rideIndex, uint8 status) : + _rideIndex(rideIndex), + _status(status) + { + } + + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } void Serialise(DataSerialiser& stream) override { GameAction::Serialise(stream); - stream << RideIndex; - stream << Status; + stream << _rideIndex << _status; } GameActionResult::Ptr Query() const override { - if (RideIndex >= MAX_RIDES) + if (_rideIndex >= MAX_RIDES) { - log_warning("Invalid game command for ride %u", RideIndex); + log_warning("Invalid game command for ride %u", _rideIndex); return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_SELECTION_OF_OBJECTS); } return std::make_unique(); @@ -57,11 +69,11 @@ public: GameActionResult::Ptr res = std::make_unique(); res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; - rct_ride *ride = get_ride(RideIndex); + rct_ride *ride = get_ride(_rideIndex); if (ride->type == RIDE_TYPE_NULL) { - log_warning("Invalid game command for ride %u", RideIndex); + log_warning("Invalid game command for ride %u", _rideIndex); return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_SELECTION_OF_OBJECTS); } @@ -72,15 +84,15 @@ public: res->Position.z = map_element_height(res->Position.x, res->Position.y); } - switch (Status) { + switch (_status) { case RIDE_STATUS_CLOSED: - if (ride->status == Status) + if (ride->status == _status) { if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)) { ride->lifecycle_flags &= ~RIDE_LIFECYCLE_CRASHED; - ride_clear_for_construction(RideIndex); - ride_remove_peeps(RideIndex); + ride_clear_for_construction(_rideIndex); + ride_remove_peeps(_rideIndex); } } @@ -88,47 +100,47 @@ public: ride->lifecycle_flags &= ~RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING; ride->race_winner = SPRITE_INDEX_NULL; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; - window_invalidate_by_number(WC_RIDE, RideIndex); + window_invalidate_by_number(WC_RIDE, _rideIndex); break; case RIDE_STATUS_TESTING: case RIDE_STATUS_OPEN: { - if (ride->status == Status) + if (ride->status == _status) { return res; } // 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); + rct_window *constructionWindow = window_find_by_number(WC_RIDE_CONSTRUCTION, _rideIndex); if (constructionWindow != nullptr) { window_close(constructionWindow); } - if (Status == RIDE_STATUS_TESTING) + if (_status == RIDE_STATUS_TESTING) { - if (!ride_is_valid_for_test(RideIndex, Status == RIDE_STATUS_OPEN, 1)) + if (!ride_is_valid_for_test(_rideIndex, _status == RIDE_STATUS_OPEN, 1)) { //*ebx = MONEY32_UNDEFINED; return res; } } - else if (!ride_is_valid_for_open(RideIndex, Status == RIDE_STATUS_OPEN, 1)) + else if (!ride_is_valid_for_open(_rideIndex, _status == RIDE_STATUS_OPEN, 1)) { //*ebx = MONEY32_UNDEFINED; return res; } ride->race_winner = SPRITE_INDEX_NULL; - ride->status = Status; - ride_get_measurement(RideIndex, nullptr); + ride->status = _status; + ride_get_measurement(_rideIndex, nullptr); ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; - window_invalidate_by_number(WC_RIDE, RideIndex); + window_invalidate_by_number(WC_RIDE, _rideIndex); break; } default: - Guard::Assert(false, "Invalid status passed: %u", Status); + Guard::Assert(false, "Invalid status passed: %u", _status); break; } return res; diff --git a/src/openrct2/actions/SetParkEntranceFeeAction.hpp b/src/openrct2/actions/SetParkEntranceFeeAction.hpp index 153cf58162..cf66b49b41 100644 --- a/src/openrct2/actions/SetParkEntranceFeeAction.hpp +++ b/src/openrct2/actions/SetParkEntranceFeeAction.hpp @@ -27,11 +27,16 @@ extern "C" #include "../world/park.h" } -struct SetParkEntranceFeeAction : public GameActionBase +struct SetParkEntranceFeeAction : public GameActionBase { public: money16 Fee; + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + void Serialise(DataSerialiser& stream) override { GameAction::Serialise(stream); diff --git a/src/openrct2/ride/ride.c b/src/openrct2/ride/ride.c index ed4b3193ab..95af5593e4 100644 --- a/src/openrct2/ride/ride.c +++ b/src/openrct2/ride/ride.c @@ -5839,21 +5839,6 @@ bool shop_item_has_common_price(sint32 shopItem) } } -money32 ride_create_command(sint32 type, sint32 subType, sint32 flags, uint8 *outRideIndex, uint8 *outRideColour) -{ - sint32 eax = 0; - sint32 ebx = flags; - sint32 ecx = 0; - sint32 edx = type | (subType << 8); - sint32 esi = 0; - sint32 edi = 0; - sint32 ebp = 0; - money32 cost = game_do_command_p(GAME_COMMAND_CREATE_RIDE, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - *outRideIndex = edi & 0xFF; - *outRideColour = eax; - return cost; -} - void ride_set_name_to_default(Ride * ride, rct_ride_entry * rideEntry) { if (!(rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) || rideTypeShouldLoseSeparateFlag(rideEntry)) {