Merge pull request #8799 from duncanspumpkin/set_water_height_ga

Set Water Height Action
This commit is contained in:
Duncan 2019-03-02 17:42:04 +00:00 committed by GitHub
commit f198ef5919
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 196 additions and 123 deletions

View File

@ -33,6 +33,7 @@
2A5354E922099C4F00A5440F /* Network.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A5354E822099C4F00A5440F /* Network.cpp */; };
2A5C1368221E9F9000F8C245 /* TrackRemoveAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A5C1367221E9F9000F8C245 /* TrackRemoveAction.hpp */; };
2A61CAFB2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A61CAFA2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp */; };
2A61CAF92229E59F0095AD67 /* WaterSetHeightAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2A61CAF82229E59F0095AD67 /* WaterSetHeightAction.hpp */; };
2AA050322209A8E300D3A922 /* StaffSetCostumeAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2AA050302209A8E300D3A922 /* StaffSetCostumeAction.hpp */; };
2AA050332209A8E300D3A922 /* StaffSetOrdersAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2AA050312209A8E300D3A922 /* StaffSetOrdersAction.hpp */; };
2AAFD7FA220DD2DC002461A4 /* TrackPlaceAction.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2AAFD7F9220DD2DC002461A4 /* TrackPlaceAction.hpp */; };
@ -640,6 +641,7 @@
2A5354EB22099D7700A5440F /* SignSetStyleAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SignSetStyleAction.hpp; sourceTree = "<group>"; };
2A5C1367221E9F9000F8C245 /* TrackRemoveAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrackRemoveAction.hpp; sourceTree = "<group>"; };
2A61CAFA2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RideEntranceExitPlaceAction.hpp; sourceTree = "<group>"; };
2A61CAF82229E59F0095AD67 /* WaterSetHeightAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = WaterSetHeightAction.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>"; };
2AAFD7F9220DD2DC002461A4 /* TrackPlaceAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrackPlaceAction.hpp; sourceTree = "<group>"; };
@ -2027,6 +2029,7 @@
isa = PBXGroup;
children = (
2A61CAFA2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp */,
2A61CAF82229E59F0095AD67 /* WaterSetHeightAction.hpp */,
2ACBAB162226850A0034FB91 /* RideSetSetting.hpp */,
2A43D2B92225B8D900E8F73B /* LoadOrQuitAction.hpp */,
2A43D2B72225B8D900E8F73B /* RideSetVehiclesAction.hpp */,
@ -3347,6 +3350,7 @@
C6352B971F477032006CCEE3 /* SetParkEntranceFeeAction.hpp in Headers */,
2AA050332209A8E300D3A922 /* StaffSetOrdersAction.hpp in Headers */,
2AAFD7FA220DD2DC002461A4 /* TrackPlaceAction.hpp in Headers */,
2A61CAF92229E59F0095AD67 /* WaterSetHeightAction.hpp in Headers */,
933F2CBB20935668001B33FD /* LocalisationService.h in Headers */,
2A5C1368221E9F9000F8C245 /* TrackRemoveAction.hpp in Headers */,
2A61CAFB2229E5C50095AD67 /* RideEntranceExitPlaceAction.hpp in Headers */,

View File

@ -1276,7 +1276,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = {
nullptr,
nullptr,
nullptr,
game_command_set_water_height,
nullptr,
game_command_place_footpath,
game_command_place_footpath_from_track,
nullptr,

View File

@ -34,7 +34,7 @@ enum GAME_COMMAND
GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT, // GA
GAME_COMMAND_REMOVE_SCENERY, // GA
GAME_COMMAND_PLACE_SCENERY, // GA
GAME_COMMAND_SET_WATER_HEIGHT,
GAME_COMMAND_SET_WATER_HEIGHT, // GA
GAME_COMMAND_PLACE_PATH,
GAME_COMMAND_PLACE_PATH_FROM_TRACK,
GAME_COMMAND_REMOVE_PATH,

View File

@ -47,6 +47,7 @@
#include "TrackPlaceAction.hpp"
#include "TrackRemoveAction.hpp"
#include "WallRemoveAction.hpp"
#include "WaterSetHeightAction.hpp"
namespace GameActions
{
@ -91,5 +92,6 @@ namespace GameActions
Register<ClearAction>();
Register<PauseToggleAction>();
Register<LoadOrQuitAction>();
Register<WaterSetHeightAction>();
}
} // namespace GameActions

View File

@ -0,0 +1,163 @@
/*****************************************************************************
* 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/Park.h"
#include "../world/Surface.h"
#include "GameAction.h"
DEFINE_GAME_ACTION(WaterSetHeightAction, GAME_COMMAND_SET_WATER_HEIGHT, GameActionResult)
{
private:
CoordsXY _coords;
uint8_t _height;
public:
WaterSetHeightAction()
{
}
WaterSetHeightAction(CoordsXY coords, uint8_t height)
: _coords(coords)
, _height(height)
{
}
uint16_t GetActionFlags() const override
{
return GameAction::GetActionFlags();
}
void Serialise(DataSerialiser & stream) override
{
GameAction::Serialise(stream);
stream << DS_TAG(_coords) << DS_TAG(_height);
}
GameActionResult::Ptr Query() const override
{
auto res = MakeResult();
res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
res->Position.x = _coords.x + 16;
res->Position.y = _coords.y + 16;
res->Position.z = _height * 8;
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode
&& gParkFlags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES)
{
return MakeResult(GA_ERROR::DISALLOWED, STR_NONE, STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY);
}
rct_string_id errorMsg = CheckParameters();
if (errorMsg != STR_NONE)
{
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE, errorMsg);
}
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode)
{
if (!map_is_location_in_park(_coords))
{
return MakeResult(GA_ERROR::DISALLOWED, STR_NONE, STR_LAND_NOT_OWNED_BY_PARK);
}
}
SurfaceElement* surfaceElement = map_get_surface_element_at(_coords)->AsSurface();
if (surfaceElement == nullptr)
{
log_error("Could not find surface element at: x %u, y %u", _coords.x, _coords.y);
return MakeResult(GA_ERROR::UNKNOWN, STR_NONE);
}
int32_t zHigh = surfaceElement->base_height;
int32_t zLow = _height;
if (surfaceElement->GetWaterHeight() > 0)
{
zHigh = surfaceElement->GetWaterHeight() * 2;
}
if (zLow > zHigh)
{
int32_t temp = zHigh;
zHigh = zLow;
zLow = temp;
}
if (!map_can_construct_at(_coords.x, _coords.y, zLow, zHigh, { 0b1111, 0b1111 }))
{
return MakeResult(GA_ERROR::NO_CLEARANCE, STR_NONE, gGameCommandErrorText, gCommonFormatArgs);
}
if (surfaceElement->HasTrackThatNeedsWater())
{
return MakeResult(GA_ERROR::DISALLOWED, STR_NONE);
}
res->Cost = 250;
return res;
}
GameActionResult::Ptr Execute() const override
{
auto res = MakeResult();
res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
res->Position.x = _coords.x + 16;
res->Position.y = _coords.y + 16;
res->Position.z = _height * 8;
int32_t surfaceHeight = tile_element_height(_coords.x, _coords.y) & 0xFFFF;
footpath_remove_litter(_coords.x, _coords.y, surfaceHeight);
if (!gCheatsDisableClearanceChecks)
wall_remove_at_z(_coords.x, _coords.y, surfaceHeight);
SurfaceElement* surfaceElement = map_get_surface_element_at(_coords)->AsSurface();
if (surfaceElement == nullptr)
{
log_error("Could not find surface element at: x %u, y %u", _coords.x, _coords.y);
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
}
if (_height > surfaceElement->base_height)
{
surfaceElement->SetWaterHeight(_height / 2);
}
else
{
surfaceElement->SetWaterHeight(0);
}
map_invalidate_tile_full(_coords.x, _coords.y);
res->Cost = 250;
return res;
}
private:
rct_string_id CheckParameters() const
{
if (_coords.x > gMapSizeMaxXY || _coords.y > gMapSizeMaxXY)
{
return STR_OFF_EDGE_OF_MAP;
}
if (_height < MINIMUM_WATER_HEIGHT)
{
return STR_TOO_LOW;
}
if (_height > MAXIMUM_WATER_HEIGHT)
{
return STR_TOO_HIGH;
}
return STR_NONE;
}
};

View File

@ -31,7 +31,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 "51"
#define NETWORK_STREAM_VERSION "52"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
static Peep* _pickup_peep = nullptr;

View File

@ -19,6 +19,7 @@
#include "../actions/LargeSceneryRemoveAction.hpp"
#include "../actions/SmallSceneryRemoveAction.hpp"
#include "../actions/WallRemoveAction.hpp"
#include "../actions/WaterSetHeightAction.hpp"
#include "../audio/audio.h"
#include "../config/Config.h"
#include "../core/Guard.hpp"
@ -1402,12 +1403,18 @@ money32 raise_water(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t flag
height = tile_element->base_height + 2;
}
money32 tileCost = game_do_command(
xi, flags, yi, (max_height << 8) + height, GAME_COMMAND_SET_WATER_HEIGHT, 0, 0);
if (tileCost == MONEY32_UNDEFINED)
auto waterSetHeightAction = WaterSetHeightAction({ xi, yi }, height);
waterSetHeightAction.SetFlags(flags);
auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&waterSetHeightAction)
: GameActions::QueryNested(&waterSetHeightAction);
if (res->Error != GA_ERROR::OK)
{
gGameCommandErrorText = res->ErrorMessage;
// set gCommonFormatArguments to res->ErrorArgs
return MONEY32_UNDEFINED;
}
cost += tileCost;
cost += res->Cost;
waterHeightChanged = true;
}
}
@ -1490,11 +1497,18 @@ money32 lower_water(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t flag
if (height < min_height)
continue;
height -= 2;
int32_t tileCost = game_do_command(
xi, flags, yi, (min_height << 8) + height, GAME_COMMAND_SET_WATER_HEIGHT, 0, 0);
if (tileCost == MONEY32_UNDEFINED)
auto waterSetHeightAction = WaterSetHeightAction({ xi, yi }, height);
waterSetHeightAction.SetFlags(flags);
auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&waterSetHeightAction)
: GameActions::QueryNested(&waterSetHeightAction);
if (res->Error != GA_ERROR::OK)
{
gGameCommandErrorText = res->ErrorMessage;
// set gCommonFormatArguments to res->ErrorArgs
return MONEY32_UNDEFINED;
cost += tileCost;
}
cost += res->Cost;
waterHeightChanged = true;
}
}
@ -2135,116 +2149,6 @@ void game_command_lower_water(
(int16_t)(*eax & 0xFFFF), (int16_t)(*ecx & 0xFFFF), (int16_t)(*edi & 0xFFFF), (int16_t)(*ebp & 0xFFFF), (uint8_t)*ebx);
}
/**
*
* rct2: 0x006E650F
*/
void game_command_set_water_height(
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, [[maybe_unused]] int32_t* edi,
[[maybe_unused]] int32_t* ebp)
{
int32_t x = *eax;
int32_t y = *ecx;
uint8_t base_height = *edx;
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
gCommandPosition.x = x + 16;
gCommandPosition.y = y + 16;
gCommandPosition.z = base_height * 8;
if (game_is_paused() && !gCheatsBuildInPauseMode)
{
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
*ebx = MONEY32_UNDEFINED;
return;
}
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode
&& gParkFlags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES)
{
gGameCommandErrorText = STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY;
*ebx = MONEY32_UNDEFINED;
return;
}
if (base_height < 2)
{
gGameCommandErrorText = STR_TOO_LOW;
*ebx = MONEY32_UNDEFINED;
return;
}
if (base_height >= 58)
{
gGameCommandErrorText = STR_TOO_HIGH;
*ebx = MONEY32_UNDEFINED;
return;
}
if (x >= gMapSizeUnits || y >= gMapSizeUnits)
{
gGameCommandErrorText = STR_OFF_EDGE_OF_MAP;
*ebx = MONEY32_UNDEFINED;
return;
}
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !map_is_location_in_park({ x, y }))
{
*ebx = MONEY32_UNDEFINED;
return;
}
if (*ebx & GAME_COMMAND_FLAG_APPLY)
{
int32_t element_height = tile_element_height(x, y);
footpath_remove_litter(x, y, element_height);
if (!gCheatsDisableClearanceChecks)
wall_remove_at_z(x, y, element_height);
}
TileElement* tile_element = map_get_surface_element_at({ x, y });
int32_t zHigh = tile_element->base_height;
int32_t zLow = base_height;
if (tile_element->AsSurface()->GetWaterHeight() > 0)
{
zHigh = tile_element->AsSurface()->GetWaterHeight() * 2;
}
if (zLow > zHigh)
{
int32_t temp = zHigh;
zHigh = zLow;
zLow = temp;
}
if (map_can_construct_at(x, y, zLow, zHigh, { 0b1111, 0b1111 }))
{
if (tile_element->AsSurface()->HasTrackThatNeedsWater())
{
gGameCommandErrorText = 0;
*ebx = MONEY32_UNDEFINED;
return;
}
if (*ebx & GAME_COMMAND_FLAG_APPLY)
{
if (base_height > tile_element->base_height)
{
tile_element->AsSurface()->SetWaterHeight(base_height / 2);
}
else
{
tile_element->AsSurface()->SetWaterHeight(0);
}
map_invalidate_tile_full(x, y);
}
*ebx = 250;
if (gParkFlags & PARK_FLAGS_NO_MONEY)
{
*ebx = 0;
}
}
else
{
*ebx = MONEY32_UNDEFINED;
}
}
bool map_is_location_at_edge(int32_t x, int32_t y)
{
return x < 32 || y < 32 || x >= ((MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32) || y >= ((MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32);

View File

@ -19,6 +19,8 @@
#define MINIMUM_LAND_HEIGHT 2
#define MAXIMUM_LAND_HEIGHT 142
#define MINIMUM_WATER_HEIGHT 2
#define MAXIMUM_WATER_HEIGHT 58
#define MINIMUM_MAP_SIZE_TECHNICAL 15
#define MAXIMUM_MAP_SIZE_TECHNICAL 256
@ -202,8 +204,6 @@ void game_command_lower_land(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t*
void game_command_smooth_land(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
void game_command_raise_water(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
void game_command_lower_water(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_water_height(
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(
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_wall(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);