diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index ac85fdd530..b70c6d74a9 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -612,6 +612,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2A5354EB22099D7700A5440F /* SignSetStyleAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SignSetStyleAction.hpp; sourceTree = ""; }; 4C04D69F2056AA9600F82EBA /* linenoise.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = linenoise.hpp; sourceTree = ""; }; 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneryObject.cpp; sourceTree = ""; }; 4C29DEB2218C6AE500E8707F /* RCT12.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RCT12.cpp; sourceTree = ""; }; @@ -1990,6 +1991,7 @@ C6352B871F477032006CCEE3 /* actions */ = { isa = PBXGroup; children = ( + 2A5354EB22099D7700A5440F /* SignSetStyleAction.hpp */, C6352B881F477032006CCEE3 /* GameAction.cpp */, C6352B891F477032006CCEE3 /* GameAction.h */, C6352B8A1F477032006CCEE3 /* GameActionCompat.cpp */, diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index c8a9705e91..3182ba2892 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -280,18 +281,23 @@ static void window_sign_dropdown(rct_window* w, rct_widgetindex widgetIndex, int switch (widgetIndex) { case WIDX_MAIN_COLOUR: + { if (dropdownIndex == -1) return; w->list_information_type = dropdownIndex; - game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_SIGN_STYLE, w->var_492, 1); + auto signSetStyleAction = SignSetStyleAction(w->number, dropdownIndex, w->var_492, true); + GameActions::Execute(&signSetStyleAction); break; + } case WIDX_TEXT_COLOUR: + { if (dropdownIndex == -1) return; w->var_492 = dropdownIndex; - game_do_command( - 1, GAME_COMMAND_FLAG_APPLY, w->number, w->list_information_type, GAME_COMMAND_SET_SIGN_STYLE, dropdownIndex, 1); + auto signSetStyleAction = SignSetStyleAction(w->number, w->list_information_type, dropdownIndex, true); + GameActions::Execute(&signSetStyleAction); break; + } default: return; } @@ -512,18 +518,23 @@ static void window_sign_small_dropdown(rct_window* w, rct_widgetindex widgetInde switch (widgetIndex) { case WIDX_MAIN_COLOUR: + { if (dropdownIndex == -1) return; w->list_information_type = dropdownIndex; - game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_SIGN_STYLE, w->var_492, 0); + auto signSetStyleAction = SignSetStyleAction(w->number, dropdownIndex, w->var_492, false); + GameActions::Execute(&signSetStyleAction); break; + } case WIDX_TEXT_COLOUR: + { if (dropdownIndex == -1) return; w->var_492 = dropdownIndex; - game_do_command( - 1, GAME_COMMAND_FLAG_APPLY, w->number, w->list_information_type, GAME_COMMAND_SET_SIGN_STYLE, dropdownIndex, 0); + auto signSetStyleAction = SignSetStyleAction(w->number, w->list_information_type, dropdownIndex, false); + GameActions::Execute(&signSetStyleAction); break; + } default: return; } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 04bb2b5924..96d2cc0a0e 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1516,7 +1516,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = { nullptr, nullptr, game_command_set_banner_style, - game_command_set_sign_style, + nullptr, game_command_set_player_group, game_command_modify_groups, game_command_kick_player, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index a5026ee75c..7022c1f0f6 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -80,7 +80,7 @@ enum GAME_COMMAND GAME_COMMAND_SET_BANNER_NAME, // GA GAME_COMMAND_SET_SIGN_NAME, // GA GAME_COMMAND_SET_BANNER_STYLE, - GAME_COMMAND_SET_SIGN_STYLE, + GAME_COMMAND_SET_SIGN_STYLE, // GA GAME_COMMAND_SET_PLAYER_GROUP, GAME_COMMAND_MODIFY_GROUPS, GAME_COMMAND_KICK_PLAYER, diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index e769d1ff9e..82149ea81c 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -28,6 +28,7 @@ #include "RideSetStatus.hpp" #include "SetParkEntranceFeeAction.hpp" #include "SignSetNameAction.hpp" +#include "SignSetStyleAction.hpp" #include "SmallSceneryRemoveAction.hpp" #include "StaffSetColourAction.hpp" #include "StaffSetNameAction.hpp" @@ -55,6 +56,7 @@ namespace GameActions Register(); Register(); Register(); + Register(); Register(); Register(); Register(); diff --git a/src/openrct2/actions/SignSetStyleAction.hpp b/src/openrct2/actions/SignSetStyleAction.hpp new file mode 100644 index 0000000000..971ba23560 --- /dev/null +++ b/src/openrct2/actions/SignSetStyleAction.hpp @@ -0,0 +1,136 @@ +/***************************************************************************** + * Copyright (c) 2014-2019 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 "../core/MemoryStream.h" +#include "../drawing/Drawing.h" +#include "../localisation/StringIds.h" +#include "../ui/UiContext.h" +#include "../windows/Intent.h" +#include "../world/Banner.h" +#include "../world/Scenery.h" +#include "../world/Sprite.h" +#include "GameAction.h" + +DEFINE_GAME_ACTION(SignSetStyleAction, GAME_COMMAND_SET_SIGN_STYLE, GameActionResult) +{ +private: + int32_t _bannerIndex; + uint8_t _mainColour; + uint8_t _textColour; + bool _isLarge; + +public: + SignSetStyleAction() = default; + SignSetStyleAction(int32_t bannerIndex, uint8_t mainColour, uint8_t textColour, bool isLarge) + : _bannerIndex(bannerIndex) + , _mainColour(mainColour) + , _textColour(textColour) + , _isLarge(isLarge) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + stream << DS_TAG(_bannerIndex) << DS_TAG(_mainColour) << DS_TAG(_textColour) << DS_TAG(_isLarge); + } + + GameActionResult::Ptr Query() const override + { + if ((BannerIndex)_bannerIndex >= MAX_BANNERS || _bannerIndex < 0) + { + log_warning("Invalid game command for setting sign style, banner id '%d' out of range", _bannerIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + rct_banner* banner = &gBanners[_bannerIndex]; + + CoordsXY coords{ banner->x * 32, banner->y * 32 }; + + if (_isLarge) + { + TileElement* tileElement = banner_get_tile_element((BannerIndex)_bannerIndex); + if (tileElement == nullptr) + { + log_warning("Invalid game command for setting sign style, banner id '%d' not found", _bannerIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + if (tileElement->GetType() != TILE_ELEMENT_TYPE_LARGE_SCENERY) + { + log_warning("Invalid game command for setting sign style, banner id '%d' is not large", _bannerIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + } + else + { + TileElement* tileElement = map_get_first_element_at(coords.x / 32, coords.y / 32); + bool wallFound = false; + do + { + if (tileElement->GetType() != TILE_ELEMENT_TYPE_WALL) + continue; + + rct_scenery_entry* scenery_entry = tileElement->AsWall()->GetEntry(); + if (scenery_entry->wall.scrolling_mode == 0xFF) + continue; + if (tileElement->AsWall()->GetBannerIndex() != (BannerIndex)_bannerIndex) + continue; + wallFound = true; + break; + } while (!(tileElement++)->IsLastForTile()); + + if (!wallFound == false) + { + log_warning("Invalid game command for setting sign style, banner id '%d' not found", _bannerIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + } + + return MakeResult(); + } + + GameActionResult::Ptr Execute() const override + { + rct_banner* banner = &gBanners[_bannerIndex]; + + CoordsXY coords{ banner->x * 32, banner->y * 32 }; + + if (_isLarge) + { + TileElement* tileElement = banner_get_tile_element((BannerIndex)_bannerIndex); + if (!sign_set_colour( + coords.x, coords.y, tileElement->base_height, tileElement->GetDirection(), + tileElement->AsLargeScenery()->GetSequenceIndex(), _mainColour, _textColour)) + { + return MakeResult(GA_ERROR::UNKNOWN, STR_NONE); + } + } + else + { + TileElement* tileElement = map_get_first_element_at(coords.x / 32, coords.y / 32); + tileElement->AsWall()->SetPrimaryColour(_mainColour); + tileElement->AsWall()->SetSecondaryColour(_textColour); + map_invalidate_tile(coords.x, coords.y, tileElement->base_height * 8, tileElement->clearance_height * 8); + } + + auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); + intent.putExtra(INTENT_EXTRA_BANNER_INDEX, (BannerIndex)_bannerIndex); + context_broadcast_intent(&intent); + + return MakeResult(); + } +}; diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index b7ba3c2840..062260914d 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -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 "26" +#define NETWORK_STREAM_VERSION "27" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static rct_peep* _pickup_peep = nullptr; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 5db97b861d..a0d1b5e49c 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -3985,90 +3985,6 @@ void map_clear_all_elements() } } -void game_command_set_sign_style( - [[maybe_unused]] int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, - int32_t* ebp) -{ - BannerIndex bannerId = *ecx & 0xFF; - if (bannerId > std::size(gBanners)) - { - log_warning("Invalid game command for setting sign style, banner id = %d", bannerId); - *ebx = MONEY32_UNDEFINED; - return; - } - rct_banner* banner = &gBanners[bannerId]; - int32_t x = banner->x << 5; - int32_t y = banner->y << 5; - - uint8_t mainColour = (uint8_t)*edx; - uint8_t textColour = (uint8_t)*edi; - - if (*ebp == 0) - { // small sign - TileElement* tileElement = map_get_first_element_at(x / 32, y / 32); - bool wall_found = false; - do - { - if (tileElement->GetType() != TILE_ELEMENT_TYPE_WALL) - continue; - - rct_scenery_entry* scenery_entry = tileElement->AsWall()->GetEntry(); - if (scenery_entry->wall.scrolling_mode == 0xFF) - continue; - if (tileElement->AsWall()->GetBannerIndex() != bannerId) - continue; - wall_found = true; - break; - } while (!(tileElement++)->IsLastForTile()); - - if (wall_found == false) - { - *ebx = MONEY32_UNDEFINED; - return; - } - - if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) - { - *ebx = 0; - return; - } - tileElement->AsWall()->SetPrimaryColour(mainColour); - tileElement->AsWall()->SetSecondaryColour(textColour); - - map_invalidate_tile(x, y, tileElement->base_height * 8, tileElement->clearance_height * 8); - } - else - { // large sign - TileElement* tileElement = banner_get_tile_element(bannerId); - if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_LARGE_SCENERY) - { - gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; - *ebx = MONEY32_UNDEFINED; - return; - } - - if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) - { - *ebx = 0; - return; - } - - if (!sign_set_colour( - banner->x * 32, banner->y * 32, tileElement->base_height, tileElement->GetDirection(), - tileElement->AsLargeScenery()->GetSequenceIndex(), mainColour, textColour)) - { - *ebx = MONEY32_UNDEFINED; - return; - } - } - - auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); - intent.putExtra(INTENT_EXTRA_BANNER_INDEX, *ecx); - context_broadcast_intent(&intent); - - *ebx = 0; -} - void game_command_modify_tile( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, int32_t* ebp) { diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 10107f4630..10f435ceaa 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -219,8 +219,6 @@ void game_command_set_banner_name( 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_banner_style( 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_sign_style( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); void game_command_modify_tile(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); struct tile_element_iterator