From 199a3e33f4752ca10fec2f36b0e91275b93bb591 Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Sat, 24 Mar 2018 04:52:47 +0100 Subject: [PATCH] Implement game action for sign naming. --- src/openrct2-ui/windows/Sign.cpp | 9 +- src/openrct2/Game.cpp | 2 +- src/openrct2/Game.h | 2 +- .../actions/GameActionRegistration.cpp | 2 + src/openrct2/actions/SignSetNameAction.hpp | 122 ++++++++++++++++++ src/openrct2/world/Map.cpp | 69 ---------- src/openrct2/world/Map.h | 1 - 7 files changed, 131 insertions(+), 76 deletions(-) create mode 100644 src/openrct2/actions/SignSetNameAction.hpp diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index 161f7491ff..6cb577b5d8 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #define WW 113 #define WH 96 @@ -316,10 +317,10 @@ static void window_sign_dropdown(rct_window *w, rct_widgetindex widgetIndex, sin */ static void window_sign_textinput(rct_window *w, rct_widgetindex widgetIndex, char *text) { - if (widgetIndex == WIDX_SIGN_TEXT && text != nullptr) { - game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 0)), GAME_COMMAND_SET_SIGN_NAME, *((sint32*)(text + 8)), *((sint32*)(text + 4))); - game_do_command(2, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 12)), GAME_COMMAND_SET_SIGN_NAME, *((sint32*)(text + 20)), *((sint32*)(text + 16))); - game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 24)), GAME_COMMAND_SET_SIGN_NAME, *((sint32*)(text + 32)), *((sint32*)(text + 28))); + if (widgetIndex == WIDX_SIGN_TEXT && text != nullptr) + { + auto signSetNameAction = SignSetNameAction(w->number, text); + GameActions::Execute(&signSetNameAction); } } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index b0f57a41d9..5cb7a105da 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1747,7 +1747,7 @@ GAME_COMMAND_POINTER * new_game_command_table[GAME_COMMAND_COUNT] = { game_command_set_land_ownership, game_command_clear_scenery, game_command_set_banner_name, - game_command_set_sign_name, + nullptr, game_command_set_banner_style, game_command_set_sign_style, game_command_set_player_group, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 27276b51f4..3c78ef9582 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -83,7 +83,7 @@ enum GAME_COMMAND GAME_COMMAND_SET_LAND_OWNERSHIP, GAME_COMMAND_CLEAR_SCENERY, GAME_COMMAND_SET_BANNER_NAME, - GAME_COMMAND_SET_SIGN_NAME, + GAME_COMMAND_SET_SIGN_NAME, // GA GAME_COMMAND_SET_BANNER_STYLE, GAME_COMMAND_SET_SIGN_STYLE, GAME_COMMAND_SET_PLAYER_GROUP, diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 38c8f25726..807331c41c 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -29,6 +29,7 @@ #include "RideDemolishAction.hpp" #include "PlacePeepSpawnAction.hpp" #include "MazeSetTrackAction.hpp" +#include "SignSetNameAction.hpp" namespace GameActions { @@ -48,5 +49,6 @@ namespace GameActions Register(); Register(); Register(); + Register(); } } diff --git a/src/openrct2/actions/SignSetNameAction.hpp b/src/openrct2/actions/SignSetNameAction.hpp new file mode 100644 index 0000000000..83c2e12564 --- /dev/null +++ b/src/openrct2/actions/SignSetNameAction.hpp @@ -0,0 +1,122 @@ +#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 "../drawing/Drawing.h" +#include "../localisation/StringIds.h" +#include "../ui/UiContext.h" +#include "../world/Sprite.h" +#include "../world/Banner.h" +#include "GameAction.h" + +using namespace OpenRCT2; + +struct SignSetNameAction : public GameActionBase +{ +private: + sint32 _bannerIndex; + std::string _name; + +public: + SignSetNameAction() {} + SignSetNameAction(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 sign 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]; + + sint32 x = banner->x << 5; + sint32 y = banner->y << 5; + + if (_name.empty() == false) + { + rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, _name.c_str()); + if (string_id != 0) + { + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = string_id; + user_string_free(prev_string_id); + + banner->flags &= ~(BANNER_FLAG_LINKED_TO_RIDE); + gfx_invalidate_screen(); + } + else + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT); + } + } + else + { + // If empty name take closest ride name. + sint32 rideIndex = banner_get_closest_ride_index(x, y, 16); + if (rideIndex == -1) + { + return MakeResult(); + } + + banner->colour = rideIndex; + banner->flags |= BANNER_FLAG_LINKED_TO_RIDE; + + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = STR_DEFAULT_SIGN; + user_string_free(prev_string_id); + + gfx_invalidate_screen(); + } + + return MakeResult(); + } +}; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 2c8307b5ba..833c0d97a7 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -4250,75 +4250,6 @@ void map_clear_all_elements() } } -void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { - static char newName[128]; - - if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) - { - log_warning("Invalid game command for setting sign name, banner id = %d", *ecx); - *ebx = MONEY32_UNDEFINED; - return; - } - rct_banner* banner = &gBanners[*ecx]; - sint32 x = banner->x << 5; - sint32 y = banner->y << 5; - - sint32 nameChunkIndex = *eax & 0xFFFF; - - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; - sint32 nameChunkOffset = nameChunkIndex - 1; - if (nameChunkOffset < 0) - nameChunkOffset = 2; - nameChunkOffset *= 12; - nameChunkOffset = std::min(nameChunkOffset, (sint32)Util::CountOf(newName) - 12); - memcpy(newName + nameChunkOffset + 0, edx, 4); - memcpy(newName + nameChunkOffset + 4, ebp, 4); - memcpy(newName + nameChunkOffset + 8, edi, 4); - - if (nameChunkIndex != 0) { - *ebx = 0; - return; - } - - if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { - *ebx = 0; - return; - } - - if (newName[0] != 0) { - rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, newName); - if (string_id != 0) { - rct_string_id prev_string_id = banner->string_idx; - banner->string_idx = string_id; - user_string_free(prev_string_id); - - banner->flags &= ~(BANNER_FLAG_LINKED_TO_RIDE); - gfx_invalidate_screen(); - } else { - gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; - *ebx = MONEY32_UNDEFINED; - return; - } - } - else{ - sint32 rideIndex = banner_get_closest_ride_index(x, y, 16); - if (rideIndex == -1) { - *ebx = 0; - return; - } - - banner->colour = rideIndex; - banner->flags |= BANNER_FLAG_LINKED_TO_RIDE; - - rct_string_id prev_string_id = banner->string_idx; - banner->string_idx = STR_DEFAULT_SIGN; - user_string_free(prev_string_id); - gfx_invalidate_screen(); - } - - *ebx = 0; -} - void game_command_set_sign_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { uint8 bannerId = *ecx & 0xFF; if (bannerId > Util::CountOf(gBanners)) { diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 760e98c8cb..d5406dd2e0 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -498,7 +498,6 @@ void game_command_place_wall(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, void game_command_place_large_scenery(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_place_park_entrance(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); -void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_set_sign_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_modify_tile(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp);