From 5ab42488a9897f7de63b552ed502061e2c736522 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sun, 7 Apr 2019 08:51:14 +0100 Subject: [PATCH] Implement large scenery set colour action --- src/openrct2-ui/windows/TopToolbar.cpp | 11 +- src/openrct2/Game.cpp | 6 +- src/openrct2/Game.h | 6 +- .../actions/GameActionRegistration.cpp | 2 + .../actions/LargeScenerySetColourAction.hpp | 145 ++++++++++++++++++ src/openrct2/world/Map.cpp | 83 ---------- src/openrct2/world/Map.h | 2 - 7 files changed, 158 insertions(+), 97 deletions(-) create mode 100644 src/openrct2/actions/LargeScenerySetColourAction.hpp diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 2dff172b21..240f3ca4db 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -1042,11 +1043,11 @@ static void repaint_scenery_tool_down(int16_t x, int16_t y, rct_widgetindex widg if (!(scenery_entry->large_scenery.flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR)) return; - gGameCommandErrorTitle = STR_CANT_REPAINT_THIS; - game_do_command( - grid_x, 1 | (tile_element->GetDirection() << 8), grid_y, - tile_element->base_height | (tile_element->AsLargeScenery()->GetSequenceIndex() << 8), - GAME_COMMAND_SET_LARGE_SCENERY_COLOUR, 0, gWindowSceneryPrimaryColour | (gWindowScenerySecondaryColour << 8)); + auto repaintScenery = LargeScenerySetColourAction( + { grid_x, grid_y, tile_element->base_height * 8, tile_element->GetDirection() }, + tile_element->AsLargeScenery()->GetSequenceIndex(), gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour); + + GameActions::Execute(&repaintScenery); break; } case VIEWPORT_INTERACTION_ITEM_BANNER: diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index ff27d0acda..066e1076f2 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -643,9 +643,7 @@ void game_log_multiplayer_command(int command, const int* eax, const int* ebx, c format_string(log_msg, 256, STR_LOG_REMOVE_SCENERY, args); network_append_server_log(log_msg); } - else if ( - command == GAME_COMMAND_SET_LARGE_SCENERY_COLOUR || command == GAME_COMMAND_SET_BANNER_COLOUR - || command == GAME_COMMAND_SET_BANNER_STYLE) + else if (command == GAME_COMMAND_SET_BANNER_COLOUR || command == GAME_COMMAND_SET_BANNER_STYLE) { // Log editing scenery char* args[1] = { @@ -1293,7 +1291,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = { game_command_remove_banner, nullptr, nullptr, - game_command_set_large_scenery_colour, + nullptr, game_command_set_banner_colour, game_command_set_land_ownership, nullptr, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index c64e65b6ab..4e48f867c3 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -71,9 +71,9 @@ enum GAME_COMMAND GAME_COMMAND_PLACE_MAZE_DESIGN, GAME_COMMAND_PLACE_BANNER, GAME_COMMAND_REMOVE_BANNER, - GAME_COMMAND_SET_SCENERY_COLOUR, // GA - GAME_COMMAND_SET_WALL_COLOUR, // GA - GAME_COMMAND_SET_LARGE_SCENERY_COLOUR, + GAME_COMMAND_SET_SCENERY_COLOUR, // GA + GAME_COMMAND_SET_WALL_COLOUR, // GA + GAME_COMMAND_SET_LARGE_SCENERY_COLOUR, // GA GAME_COMMAND_SET_BANNER_COLOUR, GAME_COMMAND_SET_LAND_OWNERSHIP, GAME_COMMAND_CLEAR_SCENERY, // GA diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index a3f8bb8b59..bf29777317 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -23,6 +23,7 @@ #include "LandSetHeightAction.hpp" #include "LandSmoothAction.hpp" #include "LargeSceneryRemoveAction.hpp" +#include "LargeScenerySetColourAction.hpp" #include "LoadOrQuitAction.hpp" #include "MazeSetTrackAction.hpp" #include "ParkEntranceRemoveAction.hpp" @@ -120,6 +121,7 @@ namespace GameActions Register(); Register(); Register(); + Register(); Register(); Register(); Register(); diff --git a/src/openrct2/actions/LargeScenerySetColourAction.hpp b/src/openrct2/actions/LargeScenerySetColourAction.hpp new file mode 100644 index 0000000000..b877c4857e --- /dev/null +++ b/src/openrct2/actions/LargeScenerySetColourAction.hpp @@ -0,0 +1,145 @@ +/***************************************************************************** + * 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 "../OpenRCT2.h" +#include "../management/Finance.h" +#include "../world/Scenery.h" +#include "GameAction.h" + +DEFINE_GAME_ACTION(LargeScenerySetColourAction, GAME_COMMAND_SET_LARGE_SCENERY_COLOUR, GameActionResult) +{ +private: + CoordsXYZD _loc; + uint8_t _tileIndex; + uint8_t _primaryColour; + uint8_t _secondaryColour; + +public: + LargeScenerySetColourAction() = default; + + LargeScenerySetColourAction(CoordsXYZD loc, uint8_t tileIndex, uint8_t primaryColour, uint8_t secondaryColour) + : _loc(loc) + , _tileIndex(tileIndex) + , _primaryColour(primaryColour) + , _secondaryColour(secondaryColour) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags() | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED; + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + + stream << DS_TAG(_loc) << DS_TAG(_tileIndex) << DS_TAG(_primaryColour) << DS_TAG(_secondaryColour); + } + + GameActionResult::Ptr Query() const override + { + return QueryExecute(false); + } + + GameActionResult::Ptr Execute() const override + { + return QueryExecute(true); + } + +private: + GameActionResult::Ptr QueryExecute(bool isExecuting) const + { + auto res = MakeResult(); + res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + res->Position.x = _loc.x + 16; + res->Position.y = _loc.y + 16; + res->Position.z = tile_element_height(_loc.x, _loc.y); + res->ErrorTitle = STR_CANT_REPAINT_THIS; + + if (_loc.x < 0 || _loc.y < 0 || _loc.x > gMapSizeMaxXY || _loc.y > gMapSizeMaxXY) + { + log_error("Invalid x / y coordinates: x = %d, y = %d", _loc.x, _loc.y); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REPAINT_THIS); + } + + if (_primaryColour > 31) + { + log_error("Invalid primary colour: colour = %u", _primaryColour); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REPAINT_THIS); + } + + if (_secondaryColour > 31) + { + log_error("Invalid primary colour: colour = %u", _secondaryColour); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REPAINT_THIS); + } + + auto largeElement = map_get_large_scenery_segment(_loc.x, _loc.y, _loc.z / 8, _loc.direction, _tileIndex); + + if (largeElement == nullptr) + { + log_error( + "Could not find large scenery at: x = %d, y = %d, z = %d, direction = %d, tileIndex = %u", _loc.x, _loc.y, + _loc.z, _loc.direction, _tileIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REPAINT_THIS); + } + + if ((GetFlags() & GAME_COMMAND_FLAG_GHOST) && !(largeElement->IsGhost())) + { + return res; + } + + rct_scenery_entry* sceneryEntry = largeElement->GetEntry(); + + if (sceneryEntry == nullptr) + { + log_error("Could not find scenery object. type = %u", largeElement->GetEntryIndex()); + return MakeResult(GA_ERROR::UNKNOWN, STR_CANT_REPAINT_THIS); + } + // Work out the base tile coordinates (Tile with index 0) + auto baseX = sceneryEntry->large_scenery.tiles[_tileIndex].x_offset; + auto baseY = sceneryEntry->large_scenery.tiles[_tileIndex].y_offset; + rotate_map_coordinates(&baseX, &baseY, _loc.direction); + + CoordsXYZ baseTile = { _loc.x - baseX, _loc.y - baseY, + _loc.z - sceneryEntry->large_scenery.tiles[_tileIndex].z_offset }; + + auto i = 0; + for (auto tile = sceneryEntry->large_scenery.tiles; tile->x_offset != -1; ++tile, ++i) + { + // Work out the current tile coordinates + auto tileX = tile->x_offset; + auto tileY = tile->y_offset; + rotate_map_coordinates(&tileX, &tileY, _loc.direction); + CoordsXYZ currentTile = { tileX + baseTile.x, tileY + baseTile.y, tile->z_offset + baseTile.z }; + + if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode) + { + if (!map_is_location_owned(currentTile.x, currentTile.y, currentTile.z)) + { + return MakeResult(GA_ERROR::NOT_OWNED, STR_CANT_REPAINT_THIS, STR_LAND_NOT_OWNED_BY_PARK); + } + } + + if (isExecuting) + { + auto tileElement = map_get_large_scenery_segment(currentTile.x, currentTile.y, _loc.z / 8, _loc.direction, i); + + tileElement->SetPrimaryColour(_primaryColour); + tileElement->SetSecondaryColour(_secondaryColour); + + map_invalidate_tile_full(currentTile.x, currentTile.y); + } + } + return res; + } +}; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 83762955bc..608b160195 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -795,89 +795,6 @@ bool map_is_location_owned_or_has_rights(int32_t x, int32_t y) return false; } -/** - * - * rct2: 0x006B909A - */ -void game_command_set_large_scenery_colour( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, [[maybe_unused]] int32_t* edi, - int32_t* ebp) -{ - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; - int32_t x = *eax; - int32_t y = *ecx; - uint8_t tile_element_direction = *ebx >> 8; - uint8_t flags = *ebx & 0xFF; - uint8_t base_height = *edx; - uint8_t tileIndex = *edx >> 8; - uint8_t colour1 = *ebp; - uint8_t colour2 = *ebp >> 8; - int32_t z = tile_element_height(x, y); - gCommandPosition.x = x + 16; - gCommandPosition.y = y + 16; - gCommandPosition.z = z; - - auto tile_element = map_get_large_scenery_segment(x, y, base_height, tile_element_direction, tileIndex); - - if (tile_element == nullptr) - { - *ebx = 0; - return; - } - - if ((flags & GAME_COMMAND_FLAG_GHOST) && !(tile_element->IsGhost())) - { - *ebx = 0; - return; - } - - rct_scenery_entry* scenery_entry = tile_element->GetEntry(); - - // Work out the base tile coordinates (Tile with index 0) - LocationXYZ16 baseTile = { - scenery_entry->large_scenery.tiles[tileIndex].x_offset, scenery_entry->large_scenery.tiles[tileIndex].y_offset, - static_cast((base_height * 8) - scenery_entry->large_scenery.tiles[tileIndex].z_offset) - }; - rotate_map_coordinates(&baseTile.x, &baseTile.y, tile_element_direction); - baseTile.x = x - baseTile.x; - baseTile.y = y - baseTile.y; - - for (int32_t i = 0; scenery_entry->large_scenery.tiles[i].x_offset != -1; ++i) - { - assert(i < MAXIMUM_MAP_SIZE_TECHNICAL); - - // Work out the current tile coordinates - LocationXYZ16 currentTile = { scenery_entry->large_scenery.tiles[i].x_offset, - scenery_entry->large_scenery.tiles[i].y_offset, - scenery_entry->large_scenery.tiles[i].z_offset }; - rotate_map_coordinates(¤tTile.x, ¤tTile.y, tile_element_direction); - currentTile.x += baseTile.x; - currentTile.y += baseTile.y; - currentTile.z += baseTile.z; - - if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode) - { - if (!map_is_location_owned(currentTile.x, currentTile.y, currentTile.z)) - { - *ebx = MONEY32_UNDEFINED; - return; - } - } - - if (flags & GAME_COMMAND_FLAG_APPLY) - { - auto tileElement = map_get_large_scenery_segment( - currentTile.x, currentTile.y, base_height, tile_element_direction, i); - - tileElement->SetPrimaryColour(colour1); - tileElement->SetSecondaryColour(colour2); - - map_invalidate_tile_full(currentTile.x, currentTile.y); - } - } - *ebx = 0; -} - // 0x00981A1E // Table of pre-calculated surface slopes (32) when raising the land tile for a given selection (5) // 0x1F = new slope diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index d009c5677b..323c081808 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -191,8 +191,6 @@ void game_command_set_land_ownership( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); void game_command_remove_banner( 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_large_scenery_colour( - 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_colour( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); void game_command_place_banner(