diff --git a/src/openrct2-ui/windows/Staff.cpp b/src/openrct2-ui/windows/Staff.cpp index 9cabf549c4..d7434b58b3 100644 --- a/src/openrct2-ui/windows/Staff.cpp +++ b/src/openrct2-ui/windows/Staff.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -629,10 +631,9 @@ static void window_staff_set_order(rct_window* w, int32_t order_id) { rct_peep* peep = GET_PEEP(w->number); - int32_t ax = peep->staff_orders ^ (1 << order_id); - int32_t flags = (ax << 8) | 1; - - game_do_command(peep->x, flags, peep->y, w->number, GAME_COMMAND_SET_STAFF_ORDER, 0, 0); + uint8_t newOrders = peep->staff_orders ^ (1 << order_id); + auto staffSetOrdersAction = StaffSetOrdersAction(w->number, newOrders); + GameActions::Execute(&staffSetOrdersAction); } /** @@ -1442,7 +1443,7 @@ void window_staff_options_dropdown(rct_window* w, rct_widgetindex widgetIndex, i if (dropdownIndex == -1) return; - rct_peep* peep = GET_PEEP(w->number); - int32_t costume = _availableCostumes[dropdownIndex] | 0x80; - game_do_command(peep->x, (costume << 8) | 1, peep->y, w->number, GAME_COMMAND_SET_STAFF_ORDER, 0, 0); + uint8_t costume = _availableCostumes[dropdownIndex]; + auto staffSetCostumeAction = StaffSetCostumeAction(w->number, costume); + GameActions::Execute(&staffSetCostumeAction); } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 96d2cc0a0e..409431dc5c 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1487,7 +1487,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = { game_command_hire_new_staff_member, game_command_set_staff_patrol, game_command_fire_staff_member, - game_command_set_staff_order, + nullptr, nullptr, game_command_set_park_open, game_command_buy_land_rights, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 7022c1f0f6..87500c0adf 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -51,8 +51,8 @@ enum GAME_COMMAND GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, GAME_COMMAND_SET_STAFF_PATROL, GAME_COMMAND_FIRE_STAFF_MEMBER, - GAME_COMMAND_SET_STAFF_ORDER, - GAME_COMMAND_SET_PARK_NAME, // GA + GAME_COMMAND_SET_STAFF_ORDERS, // GA + GAME_COMMAND_SET_PARK_NAME, // GA GAME_COMMAND_SET_PARK_OPEN, GAME_COMMAND_BUY_LAND_RIGHTS, GAME_COMMAND_PLACE_PARK_ENTRANCE, // GA @@ -93,6 +93,7 @@ enum GAME_COMMAND GAME_COMMAND_PLACE_PEEP_SPAWN, // GA, TODO: refactor to separate array for just game actions GAME_COMMAND_SET_CLIMATE, // GA GAME_COMMAND_SET_COLOUR_SCHEME, // GA + GAME_COMMAND_SET_STAFF_COSTUME, // GA GAME_COMMAND_COUNT, }; diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 82149ea81c..9ecba817be 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -31,7 +31,9 @@ #include "SignSetStyleAction.hpp" #include "SmallSceneryRemoveAction.hpp" #include "StaffSetColourAction.hpp" +#include "StaffSetCostumeAction.hpp" #include "StaffSetNameAction.hpp" +#include "StaffSetOrdersAction.hpp" #include "WallRemoveAction.hpp" namespace GameActions @@ -59,6 +61,8 @@ namespace GameActions Register(); Register(); Register(); + Register(); + Register(); Register(); Register(); Register(); diff --git a/src/openrct2/actions/StaffSetCostumeAction.hpp b/src/openrct2/actions/StaffSetCostumeAction.hpp new file mode 100644 index 0000000000..6fdc8b6432 --- /dev/null +++ b/src/openrct2/actions/StaffSetCostumeAction.hpp @@ -0,0 +1,117 @@ +/***************************************************************************** + * Copyright (c) 2014-2018 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../Context.h" +#include "../interface/Window.h" +#include "../localisation/Localisation.h" +#include "../localisation/StringIds.h" +#include "../peep/Staff.h" +#include "../windows/Intent.h" +#include "../world/Sprite.h" +#include "GameAction.h" + +/** rct2: 0x00982134 */ +constexpr const bool peep_slow_walking_types[] = { + false, // PEEP_SPRITE_TYPE_NORMAL + false, // PEEP_SPRITE_TYPE_HANDYMAN + false, // PEEP_SPRITE_TYPE_MECHANIC + false, // PEEP_SPRITE_TYPE_SECURITY + false, // PEEP_SPRITE_TYPE_ENTERTAINER_PANDA + false, // PEEP_SPRITE_TYPE_ENTERTAINER_TIGER + false, // PEEP_SPRITE_TYPE_ENTERTAINER_ELEPHANT + false, // PEEP_SPRITE_TYPE_ENTERTAINER_ROMAN + false, // PEEP_SPRITE_TYPE_ENTERTAINER_GORILLA + false, // PEEP_SPRITE_TYPE_ENTERTAINER_SNOWMAN + false, // PEEP_SPRITE_TYPE_ENTERTAINER_KNIGHT + true, // PEEP_SPRITE_TYPE_ENTERTAINER_ASTRONAUT + false, // PEEP_SPRITE_TYPE_ENTERTAINER_BANDIT + false, // PEEP_SPRITE_TYPE_ENTERTAINER_SHERIFF + true, // PEEP_SPRITE_TYPE_ENTERTAINER_PIRATE + true, // PEEP_SPRITE_TYPE_BALLOON +}; + +DEFINE_GAME_ACTION(StaffSetCostumeAction, GAME_COMMAND_SET_STAFF_COSTUME, GameActionResult) +{ +private: + uint16_t _spriteIndex; + uint8_t _costume; + +public: + StaffSetCostumeAction() + { + } + StaffSetCostumeAction(uint16_t spriteIndex, uint8_t costume) + : _spriteIndex(spriteIndex) + , _costume(costume) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + + stream << DS_TAG(_spriteIndex) << DS_TAG(_costume); + } + + GameActionResult::Ptr Query() const override + { + if (_spriteIndex >= MAX_SPRITES) + { + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + rct_peep* peep = GET_PEEP(_spriteIndex); + if (peep->type != PEEP_TYPE_STAFF || peep->staff_type != STAFF_TYPE_ENTERTAINER) + { + log_warning("Invalid game command for sprite %u", _spriteIndex); + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + auto spriteType = static_cast(_costume + 4); + if (spriteType > std::size(peep_slow_walking_types)) + { + log_warning("Invalid game command for sprite %u", _spriteIndex); + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + return std::make_unique(); + } + + GameActionResult::Ptr Execute() const override + { + rct_peep* peep = GET_PEEP(_spriteIndex); + + auto spriteType = static_cast(_costume + 4); + peep->sprite_type = spriteType; + peep->peep_flags &= ~PEEP_FLAGS_SLOW_WALK; + if (peep_slow_walking_types[spriteType]) + { + peep->peep_flags |= PEEP_FLAGS_SLOW_WALK; + } + peep->action_frame = 0; + peep->UpdateCurrentActionSpriteType(); + peep->Invalidate(); + + window_invalidate_by_number(WC_PEEP, _spriteIndex); + auto intent = Intent(INTENT_ACTION_REFRESH_STAFF_LIST); + context_broadcast_intent(&intent); + + auto res = std::make_unique(); + res->Position.x = peep->x; + res->Position.y = peep->y; + res->Position.z = peep->z; + return res; + } +}; diff --git a/src/openrct2/actions/StaffSetOrdersAction.hpp b/src/openrct2/actions/StaffSetOrdersAction.hpp new file mode 100644 index 0000000000..cf3be4e085 --- /dev/null +++ b/src/openrct2/actions/StaffSetOrdersAction.hpp @@ -0,0 +1,83 @@ +/***************************************************************************** + * Copyright (c) 2014-2018 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../Context.h" +#include "../interface/Window.h" +#include "../localisation/Localisation.h" +#include "../localisation/StringIds.h" +#include "../peep/Staff.h" +#include "../windows/Intent.h" +#include "../world/Sprite.h" +#include "GameAction.h" + +DEFINE_GAME_ACTION(StaffSetOrdersAction, GAME_COMMAND_SET_STAFF_ORDERS, GameActionResult) +{ +private: + uint16_t _spriteIndex; + uint8_t _ordersId; + +public: + StaffSetOrdersAction() + { + } + StaffSetOrdersAction(uint16_t spriteIndex, uint8_t ordersId) + : _spriteIndex(spriteIndex) + , _ordersId(ordersId) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + + stream << DS_TAG(_spriteIndex) << DS_TAG(_ordersId); + } + + GameActionResult::Ptr Query() const override + { + if (_spriteIndex >= MAX_SPRITES) + { + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + rct_peep* peep = GET_PEEP(_spriteIndex); + if (peep->type != PEEP_TYPE_STAFF + || (peep->staff_type != STAFF_TYPE_HANDYMAN && peep->staff_type != STAFF_TYPE_MECHANIC)) + { + log_warning("Invalid game command for sprite %u", _spriteIndex); + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + return std::make_unique(); + } + + GameActionResult::Ptr Execute() const override + { + rct_peep* peep = GET_PEEP(_spriteIndex); + + peep->staff_orders = _ordersId; + + window_invalidate_by_number(WC_PEEP, _spriteIndex); + auto intent = Intent(INTENT_ACTION_REFRESH_STAFF_LIST); + context_broadcast_intent(&intent); + + auto res = std::make_unique(); + res->Position.x = peep->x; + res->Position.y = peep->y; + res->Position.z = peep->z; + return res; + } +}; diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index 90b0891bc1..580ccc3599 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -16,6 +16,7 @@ #include "../ReplayManager.h" #include "../Version.h" #include "../actions/ClimateSetAction.hpp" +#include "../actions/StaffSetCostumeAction.hpp" #include "../config/Config.h" #include "../core/Guard.hpp" #include "../core/String.hpp" @@ -441,8 +442,8 @@ static int32_t cc_staff(InteractiveConsole& console, const arguments_t& argv) return 1; } - int32_t costume = int_val[1] | 0x80; - game_do_command(peep->x, (costume << 8) | 1, peep->y, int_val[0], GAME_COMMAND_SET_STAFF_ORDER, 0, 0); + uint8_t costume = int_val[1]; + auto staffSetCostumeAction = StaffSetCostumeAction(int_val[0], costume); } } } diff --git a/src/openrct2/network/NetworkAction.cpp b/src/openrct2/network/NetworkAction.cpp index c488387268..0557303d23 100644 --- a/src/openrct2/network/NetworkAction.cpp +++ b/src/openrct2/network/NetworkAction.cpp @@ -178,7 +178,8 @@ const std::vector NetworkActions::Actions = { GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, GAME_COMMAND_SET_STAFF_PATROL, GAME_COMMAND_FIRE_STAFF_MEMBER, - GAME_COMMAND_SET_STAFF_ORDER, + GAME_COMMAND_SET_STAFF_ORDERS, + GAME_COMMAND_SET_STAFF_COSTUME, GAME_COMMAND_SET_STAFF_COLOUR, GAME_COMMAND_SET_STAFF_NAME, GAME_COMMAND_PICKUP_STAFF, diff --git a/src/openrct2/peep/Staff.cpp b/src/openrct2/peep/Staff.cpp index 7e5adbb2c2..344eed44c7 100644 --- a/src/openrct2/peep/Staff.cpp +++ b/src/openrct2/peep/Staff.cpp @@ -12,6 +12,7 @@ #include "../Context.h" #include "../Game.h" #include "../Input.h" +#include "../actions/StaffSetOrdersAction.hpp" #include "../audio/audio.h" #include "../config/Config.h" #include "../interface/Viewport.h" @@ -360,77 +361,6 @@ void game_command_hire_new_staff_member( (*ebx & 0xFF00) >> 8, *ebx & 0xFF, *eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFFFF, (*ebx & 0xFF0000) >> 16, edi); } -/** rct2: 0x00982134 */ -static constexpr const bool peep_slow_walking_types[] = { - false, // PEEP_SPRITE_TYPE_NORMAL - false, // PEEP_SPRITE_TYPE_HANDYMAN - false, // PEEP_SPRITE_TYPE_MECHANIC - false, // PEEP_SPRITE_TYPE_SECURITY - false, // PEEP_SPRITE_TYPE_ENTERTAINER_PANDA - false, // PEEP_SPRITE_TYPE_ENTERTAINER_TIGER - false, // PEEP_SPRITE_TYPE_ENTERTAINER_ELEPHANT - false, // PEEP_SPRITE_TYPE_ENTERTAINER_ROMAN - false, // PEEP_SPRITE_TYPE_ENTERTAINER_GORILLA - false, // PEEP_SPRITE_TYPE_ENTERTAINER_SNOWMAN - false, // PEEP_SPRITE_TYPE_ENTERTAINER_KNIGHT - true, // PEEP_SPRITE_TYPE_ENTERTAINER_ASTRONAUT - false, // PEEP_SPRITE_TYPE_ENTERTAINER_BANDIT - false, // PEEP_SPRITE_TYPE_ENTERTAINER_SHERIFF - true, // PEEP_SPRITE_TYPE_ENTERTAINER_PIRATE - true, // PEEP_SPRITE_TYPE_BALLOON -}; - -/** - * - * rct2: 0x006C0BB5 - */ -void game_command_set_staff_order( - [[maybe_unused]] int32_t* eax, int32_t* ebx, [[maybe_unused]] int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, - [[maybe_unused]] int32_t* edi, [[maybe_unused]] int32_t* ebp) -{ - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_WAGES; - uint8_t order_id = *ebx >> 8; - uint16_t sprite_id = *edx; - if (sprite_id >= MAX_SPRITES) - { - log_warning("Invalid game command, sprite_id = %u", sprite_id); - *ebx = MONEY32_UNDEFINED; - return; - } - if (*ebx & GAME_COMMAND_FLAG_APPLY) - { - rct_peep* peep = &get_sprite(sprite_id)->peep; - if (order_id & 0x80) - { // change costume - auto sprite_type = static_cast((order_id & ~0x80) + 4); - if (sprite_type >= std::size(peep_slow_walking_types)) - { - log_error("Invalid change costume order for sprite_type %u", sprite_type); - *ebx = MONEY32_UNDEFINED; - return; - } - peep->sprite_type = sprite_type; - peep->peep_flags &= ~PEEP_FLAGS_SLOW_WALK; - if (peep_slow_walking_types[sprite_type]) - { - peep->peep_flags |= PEEP_FLAGS_SLOW_WALK; - } - peep->action_frame = 0; - peep->UpdateCurrentActionSpriteType(); - peep->Invalidate(); - window_invalidate_by_number(WC_PEEP, sprite_id); - window_invalidate_by_class(WC_STAFF_LIST); - } - else - { - peep->staff_orders = order_id; - window_invalidate_by_number(WC_PEEP, sprite_id); - window_invalidate_by_class(WC_STAFF_LIST); - } - } - *ebx = 0; -} - /** * * rct2: 0x006C09D1 @@ -548,10 +478,10 @@ uint16_t hire_new_staff_member(uint8_t staffType) if ((staffType == STAFF_TYPE_HANDYMAN) && gConfigGeneral.handymen_mow_default) { rct_peep* newPeep = GET_PEEP(new_sprite_index); - uint8_t new_orders = newPeep->staff_orders | STAFF_ORDERS_MOWING; - game_do_command( - newPeep->x, ((int32_t)new_orders << 8) | GAME_COMMAND_FLAG_APPLY, newPeep->y, new_sprite_index, - GAME_COMMAND_SET_STAFF_ORDER, 0, 0); + uint8_t newOrders = newPeep->staff_orders | STAFF_ORDERS_MOWING; + + auto staffSetOrdersAction = StaffSetOrdersAction(new_sprite_index, newOrders); + GameActions::Execute(&staffSetOrdersAction); } return new_sprite_index; diff --git a/src/openrct2/peep/Staff.h b/src/openrct2/peep/Staff.h index 585f0ddb2b..cc402fe369 100644 --- a/src/openrct2/peep/Staff.h +++ b/src/openrct2/peep/Staff.h @@ -75,8 +75,6 @@ void game_command_hire_new_staff_member( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); void game_command_callback_hire_new_staff_member( int32_t eax, int32_t ebx, int32_t ecx, int32_t edx, int32_t esi, int32_t edi, int32_t ebp); -void game_command_set_staff_order( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); void game_command_set_staff_patrol( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); void game_command_fire_staff_member(