From 417a2586b6b71e9dd95e8513970e35ab2215ff3a Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Sat, 24 Mar 2018 05:45:08 +0100 Subject: [PATCH] Implement game action for banner naming. --- src/openrct2-ui/windows/Banner.cpp | 9 +- src/openrct2/Game.cpp | 2 +- src/openrct2/Game.h | 2 +- src/openrct2/actions/BannerSetNameAction.hpp | 104 ++++++++++++++++++ .../actions/GameActionRegistration.cpp | 2 + src/openrct2/world/Banner.cpp | 77 ------------- 6 files changed, 113 insertions(+), 83 deletions(-) create mode 100644 src/openrct2/actions/BannerSetNameAction.hpp diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index 864dd09ffb..b94e899254 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #define WW 113 #define WH 96 @@ -286,10 +287,10 @@ static void window_banner_dropdown(rct_window *w, rct_widgetindex widgetIndex, s */ static void window_banner_textinput(rct_window *w, rct_widgetindex widgetIndex, char *text) { - if (widgetIndex == WIDX_BANNER_TEXT && text != nullptr) { - game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 0)), GAME_COMMAND_SET_BANNER_NAME, *((sint32*)(text + 8)), *((sint32*)(text + 4))); - game_do_command(2, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 12)), GAME_COMMAND_SET_BANNER_NAME, *((sint32*)(text + 20)), *((sint32*)(text + 16))); - game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 24)), GAME_COMMAND_SET_BANNER_NAME, *((sint32*)(text + 32)), *((sint32*)(text + 28))); + if (widgetIndex == WIDX_BANNER_TEXT && text != nullptr) + { + auto bannerSetNameAction = BannerSetNameAction(w->number, text); + GameActions::Execute(&bannerSetNameAction); } } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 7cfcbb7404..08325cd684 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1746,7 +1746,7 @@ GAME_COMMAND_POINTER * new_game_command_table[GAME_COMMAND_COUNT] = { game_command_set_banner_colour, game_command_set_land_ownership, game_command_clear_scenery, - game_command_set_banner_name, + nullptr, nullptr, game_command_set_banner_style, game_command_set_sign_style, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 4c3c533df7..90741498b6 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -82,7 +82,7 @@ enum GAME_COMMAND GAME_COMMAND_SET_BANNER_COLOUR, GAME_COMMAND_SET_LAND_OWNERSHIP, GAME_COMMAND_CLEAR_SCENERY, - GAME_COMMAND_SET_BANNER_NAME, + GAME_COMMAND_SET_BANNER_NAME, // GA GAME_COMMAND_SET_SIGN_NAME, // GA GAME_COMMAND_SET_BANNER_STYLE, GAME_COMMAND_SET_SIGN_STYLE, diff --git a/src/openrct2/actions/BannerSetNameAction.hpp b/src/openrct2/actions/BannerSetNameAction.hpp new file mode 100644 index 0000000000..a36660245b --- /dev/null +++ b/src/openrct2/actions/BannerSetNameAction.hpp @@ -0,0 +1,104 @@ +#pragma region Copyright (c) 2014-2018 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 "../Context.h" +#include "../core/MemoryStream.h" +#include "../core/String.hpp" +#include "../drawing/Drawing.h" +#include "../localisation/StringIds.h" +#include "../ui/UiContext.h" +#include "../world/Sprite.h" +#include "../world/Banner.h" +#include "../windows/Intent.h" +#include "GameAction.h" + +using namespace OpenRCT2; + +struct BannerSetNameAction : public GameActionBase +{ +private: + sint32 _bannerIndex; + std::string _name; + +public: + BannerSetNameAction() {} + BannerSetNameAction(sint32 bannerIndex, const std::string& name) + : _bannerIndex(bannerIndex), + _name(name) + { + } + + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser& stream) override + { + GameAction::Serialise(stream); + stream << _bannerIndex << _name; + } + + GameActionResult::Ptr Query() const override + { + if (_bannerIndex >= MAX_BANNERS || _bannerIndex < 0) + { + log_warning("Invalid game command for setting banner name, banner id = %d", _bannerIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + // Ensure user string space. + rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, _name.c_str()); + if (string_id != 0) + { + user_string_free(string_id); + } + else + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT); + } + + return MakeResult(); + } + + GameActionResult::Ptr Execute() const override + { + rct_banner* banner = &gBanners[_bannerIndex]; + + utf8 *buffer = gCommonStringFormatBuffer; + utf8 *dst = buffer; + dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); + String::Set(dst, sizeof(gCommonStringFormatBuffer) - (dst - buffer), _name.c_str(), _name.size()); + + rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); + if (string_id == 0) + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT); + } + + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = string_id; + user_string_free(prev_string_id); + + auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); + intent.putExtra(INTENT_EXTRA_BANNER_INDEX, _bannerIndex); + context_broadcast_intent(&intent); + + return MakeResult(); + } +}; diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index c10a3cec4e..d037884b37 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -31,6 +31,7 @@ #include "MazeSetTrackAction.hpp" #include "SignSetNameAction.hpp" #include "ParkSetNameAction.hpp" +#include "BannerSetNameAction.hpp" namespace GameActions { @@ -52,5 +53,6 @@ namespace GameActions Register(); Register(); Register(); + Register(); } } diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp index 47aa9f0641..52bbd57b30 100644 --- a/src/openrct2/world/Banner.cpp +++ b/src/openrct2/world/Banner.cpp @@ -285,71 +285,6 @@ static money32 BannerPlace(sint16 x, sint16 y, uint8 pathBaseHeight, uint8 direc return bannerEntry->banner.price; } -static money32 BannerSetName(uint8 bannerIndex, - uint16 nameChunkIndex, - uint32 nameChunk1, - uint32 nameChunk2, - uint32 nameChunk3, - uint8 flags) -{ - static char newName[128]; - - if (bannerIndex >= MAX_BANNERS) - { - log_warning("Invalid game command for setting banner name, banner id = %d", bannerIndex); - return MONEY32_UNDEFINED; - } - rct_banner* banner = &gBanners[bannerIndex]; - - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; - size_t indexToOffset[3] = { 24, 0, 12 }; - - if (nameChunkIndex > Util::CountOf(indexToOffset)) - { - log_warning("Invalid chunk index for setting banner name, banner id = %d, index = %d", bannerIndex, nameChunkIndex); - return MONEY32_UNDEFINED; - } - - size_t nameChunkOffset = std::min(indexToOffset[nameChunkIndex], Util::CountOf(newName) - 12); - std::memcpy(&newName[0 + nameChunkOffset], &nameChunk1, sizeof(uint32)); - std::memcpy(&newName[4 + nameChunkOffset], &nameChunk2, sizeof(uint32)); - std::memcpy(&newName[8 + nameChunkOffset], &nameChunk3, sizeof(uint32)); - - if (nameChunkIndex != 0) - { - return 0; - } - - if (!(flags & GAME_COMMAND_FLAG_APPLY)) - { - return 0; - } - - utf8 *buffer = gCommonStringFormatBuffer; - utf8 *dst = buffer; - dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); - String::Set(dst, 256, newName, 32); - - rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); - if (stringId != 0) - { - rct_string_id prevStringId = banner->string_idx; - banner->string_idx = stringId; - user_string_free(prevStringId); - - auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); - intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex); - context_broadcast_intent(&intent); - } - else - { - gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; - return MONEY32_UNDEFINED; - } - - return 0; -} - static money32 BannerSetStyle(uint8 bannerIndex, uint8 colour, uint8 textColour, uint8 bannerFlags, uint8 flags) { if (bannerIndex >= MAX_BANNERS) @@ -662,18 +597,6 @@ void game_command_place_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* ed ); } -void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) -{ - *ebx = BannerSetName( - *ecx & 0xFF, - *eax & 0xFFFF, - *edx, - *ebp, - *edi, - *ebx & 0xFF - ); -} - void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { *ebx = BannerSetStyle(