Merge pull request #8668 from duncanspumpkin/staff_order_action

Implement Game Action Staff Set Order
This commit is contained in:
Duncan 2019-02-06 03:50:11 +00:00 committed by GitHub
commit 2cf4a9afb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 235 additions and 91 deletions

View File

@ -21,6 +21,8 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
2AA050322209A8E300D3A922 /* StaffSetCostumeAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2AA050302209A8E300D3A922 /* StaffSetCostumeAction.hpp */; };
2AA050332209A8E300D3A922 /* StaffSetOrdersAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2AA050312209A8E300D3A922 /* StaffSetOrdersAction.hpp */; };
4C29DEB3218C6AE500E8707F /* RCT12.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C29DEB2218C6AE500E8707F /* RCT12.cpp */; };
4C358E5221C445F700ADE6BC /* ReplayManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C358E5021C445F700ADE6BC /* ReplayManager.cpp */; };
4C3B4236205914F7000C5BB7 /* InGameConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B4234205914F7000C5BB7 /* InGameConsole.cpp */; };
@ -613,6 +615,8 @@
/* Begin PBXFileReference section */
2A5354EB22099D7700A5440F /* SignSetStyleAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SignSetStyleAction.hpp; sourceTree = "<group>"; };
2AA050302209A8E300D3A922 /* StaffSetCostumeAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaffSetCostumeAction.hpp; sourceTree = "<group>"; };
2AA050312209A8E300D3A922 /* StaffSetOrdersAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaffSetOrdersAction.hpp; sourceTree = "<group>"; };
4C04D69F2056AA9600F82EBA /* linenoise.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = linenoise.hpp; sourceTree = "<group>"; };
4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneryObject.cpp; sourceTree = "<group>"; };
4C29DEB2218C6AE500E8707F /* RCT12.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RCT12.cpp; sourceTree = "<group>"; };
@ -1992,6 +1996,8 @@
isa = PBXGroup;
children = (
2A5354EB22099D7700A5440F /* SignSetStyleAction.hpp */,
2AA050302209A8E300D3A922 /* StaffSetCostumeAction.hpp */,
2AA050312209A8E300D3A922 /* StaffSetOrdersAction.hpp */,
C6352B881F477032006CCEE3 /* GameAction.cpp */,
C6352B891F477032006CCEE3 /* GameAction.h */,
C6352B8A1F477032006CCEE3 /* GameActionCompat.cpp */,
@ -3291,11 +3297,13 @@
939A359F20C12FDE00630B3F /* Paint.Surface.h in Headers */,
C67B28192002D7F200109C93 /* Window_internal.h in Headers */,
C6352B971F477032006CCEE3 /* SetParkEntranceFeeAction.hpp in Headers */,
2AA050332209A8E300D3A922 /* StaffSetOrdersAction.hpp in Headers */,
933F2CBB20935668001B33FD /* LocalisationService.h in Headers */,
C6352B861F477022006CCEE3 /* Endianness.h in Headers */,
93CBA4CC20A7504500867D56 /* ImageImporter.h in Headers */,
C6352B941F477032006CCEE3 /* PlaceParkEntranceAction.hpp in Headers */,
C6352B911F477032006CCEE3 /* GameAction.h in Headers */,
2AA050322209A8E300D3A922 /* StaffSetCostumeAction.hpp in Headers */,
C62D838B1FD36D6F008C04F1 /* EditorObjectSelectionSession.h in Headers */,
9344BEF920C1E6180047D165 /* Crypt.h in Headers */,
939A35A220C12FFD00630B3F /* InteractiveConsole.h in Headers */,

View File

@ -16,6 +16,8 @@
#include <openrct2/Context.h>
#include <openrct2/Game.h>
#include <openrct2/Input.h>
#include <openrct2/actions/StaffSetCostumeAction.hpp>
#include <openrct2/actions/StaffSetOrdersAction.hpp>
#include <openrct2/config/Config.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/management/Finance.h>
@ -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);
}

View File

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

View File

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

View File

@ -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<SignSetStyleAction>();
Register<StaffSetColourAction>();
Register<StaffSetNameAction>();
Register<StaffSetOrdersAction>();
Register<StaffSetCostumeAction>();
Register<WallRemoveAction>();
Register<SmallSceneryRemoveAction>();
Register<LargeSceneryRemoveAction>();

View File

@ -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<GameActionResult>(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<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
}
auto spriteType = static_cast<PeepSpriteType>(_costume + 4);
if (spriteType > std::size(peep_slow_walking_types))
{
log_warning("Invalid game command for sprite %u", _spriteIndex);
return std::make_unique<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
}
return std::make_unique<GameActionResult>();
}
GameActionResult::Ptr Execute() const override
{
rct_peep* peep = GET_PEEP(_spriteIndex);
auto spriteType = static_cast<PeepSpriteType>(_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<GameActionResult>();
res->Position.x = peep->x;
res->Position.y = peep->y;
res->Position.z = peep->z;
return res;
}
};

View File

@ -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<GameActionResult>(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<GameActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
}
return std::make_unique<GameActionResult>();
}
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<GameActionResult>();
res->Position.x = peep->x;
res->Position.y = peep->y;
res->Position.z = peep->z;
return res;
}
};

View File

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

View File

@ -30,7 +30,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 "27"
#define NETWORK_STREAM_VERSION "28"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
static rct_peep* _pickup_peep = nullptr;

View File

@ -178,7 +178,8 @@ const std::vector<NetworkAction> 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,

View File

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

View File

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