mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #9264 from duncanspumpkin/tilemodify
Tile Modify GameAction
This commit is contained in:
commit
17cc6a862d
|
@ -14,6 +14,7 @@
|
||||||
#include <openrct2-ui/windows/Window.h>
|
#include <openrct2-ui/windows/Window.h>
|
||||||
#include <openrct2/Game.h>
|
#include <openrct2/Game.h>
|
||||||
#include <openrct2/Input.h>
|
#include <openrct2/Input.h>
|
||||||
|
#include <openrct2/actions/TileModifyAction.hpp>
|
||||||
#include <openrct2/common.h>
|
#include <openrct2/common.h>
|
||||||
#include <openrct2/core/Guard.hpp>
|
#include <openrct2/core/Guard.hpp>
|
||||||
#include <openrct2/localisation/Localisation.h>
|
#include <openrct2/localisation/Localisation.h>
|
||||||
|
@ -29,7 +30,6 @@
|
||||||
#include <openrct2/world/Scenery.h>
|
#include <openrct2/world/Scenery.h>
|
||||||
#include <openrct2/world/SmallScenery.h>
|
#include <openrct2/world/SmallScenery.h>
|
||||||
#include <openrct2/world/Surface.h>
|
#include <openrct2/world/Surface.h>
|
||||||
#include <openrct2/world/TileInspector.h>
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static constexpr const rct_string_id TerrainTypeStringIds[] = {
|
static constexpr const rct_string_id TerrainTypeStringIds[] = {
|
||||||
|
@ -619,25 +619,25 @@ static void window_tile_inspector_load_tile(rct_window* w, TileElement* elementT
|
||||||
static void window_tile_inspector_insert_corrupt_element(int32_t elementIndex)
|
static void window_tile_inspector_insert_corrupt_element(int32_t elementIndex)
|
||||||
{
|
{
|
||||||
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
|
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_ANY_INSERT_CORRUPT, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyInsertCorrupt, elementIndex);
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_remove_element(int32_t elementIndex)
|
static void window_tile_inspector_remove_element(int32_t elementIndex)
|
||||||
{
|
{
|
||||||
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
|
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_ANY_REMOVE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyRemove, elementIndex);
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_rotate_element(int32_t elementIndex)
|
static void window_tile_inspector_rotate_element(int32_t elementIndex)
|
||||||
{
|
{
|
||||||
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
|
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_ANY_ROTATE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyRotate, elementIndex);
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap element with its parent
|
// Swap element with its parent
|
||||||
|
@ -645,17 +645,16 @@ static void window_tile_inspector_swap_elements(int16_t first, int16_t second)
|
||||||
{
|
{
|
||||||
openrct2_assert(first >= 0 && first < windowTileInspectorElementCount, "first out of range");
|
openrct2_assert(first >= 0 && first < windowTileInspectorElementCount, "first out of range");
|
||||||
openrct2_assert(second >= 0 && second < windowTileInspectorElementCount, "second out of range");
|
openrct2_assert(second >= 0 && second < windowTileInspectorElementCount, "second out of range");
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_ANY_SWAP, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), first,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnySwap, first, second);
|
||||||
GAME_COMMAND_MODIFY_TILE, second, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_sort_elements()
|
static void window_tile_inspector_sort_elements()
|
||||||
{
|
{
|
||||||
openrct2_assert(windowTileInspectorTileSelected, "No tile selected");
|
openrct2_assert(windowTileInspectorTileSelected, "No tile selected");
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction({ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnySort);
|
||||||
TILE_INSPECTOR_ANY_SORT, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), 0,
|
GameActions::Execute(&modifyTile);
|
||||||
GAME_COMMAND_MODIFY_TILE, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_copy_element(rct_window* w)
|
static void window_tile_inspector_copy_element(rct_window* w)
|
||||||
|
@ -672,127 +671,130 @@ static void window_tile_inspector_paste_element(rct_window* w)
|
||||||
int32_t data[2];
|
int32_t data[2];
|
||||||
std::memcpy(&data[0], &tileInspectorCopiedElement, 8);
|
std::memcpy(&data[0], &tileInspectorCopiedElement, 8);
|
||||||
assert_struct_size(data, sizeof(tileInspectorCopiedElement));
|
assert_struct_size(data, sizeof(tileInspectorCopiedElement));
|
||||||
|
auto modifyTile = TileModifyAction(
|
||||||
game_do_command(
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyPaste, 0, 0,
|
||||||
TILE_INSPECTOR_ANY_PASTE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), data[0],
|
tileInspectorCopiedElement);
|
||||||
GAME_COMMAND_MODIFY_TILE, data[1], 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_base_height_offset(int16_t elementIndex, int8_t heightOffset)
|
static void window_tile_inspector_base_height_offset(int16_t elementIndex, int8_t heightOffset)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_ANY_BASE_HEIGHT_OFFSET, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyBaseHeightOffset, elementIndex,
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, heightOffset, 0);
|
heightOffset);
|
||||||
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_surface_show_park_fences(bool showFences)
|
static void window_tile_inspector_surface_show_park_fences(bool showFences)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_SURFACE_SHOW_PARK_FENCES, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::SurfaceShowParkFences, showFences);
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), showFences, GAME_COMMAND_MODIFY_TILE, 0, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_surface_toggle_corner(int32_t cornerIndex)
|
static void window_tile_inspector_surface_toggle_corner(int32_t cornerIndex)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_SURFACE_TOGGLE_CORNER, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::SurfaceToggleCorner, cornerIndex);
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), cornerIndex, GAME_COMMAND_MODIFY_TILE, 0, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_surface_toggle_diagonal()
|
static void window_tile_inspector_surface_toggle_diagonal()
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_SURFACE_TOGGLE_DIAGONAL, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::SurfaceToggleDiagonal);
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), 0, GAME_COMMAND_MODIFY_TILE, 0, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_path_set_sloped(int32_t elementIndex, bool sloped)
|
static void window_tile_inspector_path_set_sloped(int32_t elementIndex, bool sloped)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_PATH_SET_SLOPE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::PathSetSlope, elementIndex, sloped);
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, sloped, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_path_set_broken(int32_t elementIndex, bool broken)
|
static void window_tile_inspector_path_set_broken(int32_t elementIndex, bool broken)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_PATH_SET_BROKEN, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::PathSetBroken, elementIndex, broken);
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, broken, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_path_toggle_edge(int32_t elementIndex, int32_t cornerIndex)
|
static void window_tile_inspector_path_toggle_edge(int32_t elementIndex, int32_t cornerIndex)
|
||||||
{
|
{
|
||||||
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
|
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
|
||||||
openrct2_assert(cornerIndex >= 0 && cornerIndex < 8, "cornerIndex out of range");
|
openrct2_assert(cornerIndex >= 0 && cornerIndex < 8, "cornerIndex out of range");
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_PATH_TOGGLE_EDGE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::PathToggleEdge, elementIndex,
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, cornerIndex, 0);
|
cornerIndex);
|
||||||
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_entrance_make_usable(int32_t elementIndex)
|
static void window_tile_inspector_entrance_make_usable(int32_t elementIndex)
|
||||||
{
|
{
|
||||||
Guard::ArgumentInRange(elementIndex, 0, windowTileInspectorElementCount - 1);
|
Guard::ArgumentInRange(elementIndex, 0, windowTileInspectorElementCount - 1);
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_ENTRANCE_MAKE_USABLE, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::EntranceMakeUsable, elementIndex);
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_wall_set_slope(int32_t elementIndex, int32_t slopeValue)
|
static void window_tile_inspector_wall_set_slope(int32_t elementIndex, int32_t slopeValue)
|
||||||
{
|
{
|
||||||
// Make sure only the correct bits are set
|
// Make sure only the correct bits are set
|
||||||
openrct2_assert((slopeValue & 3) == slopeValue, "slopeValue doesn't match its mask");
|
openrct2_assert((slopeValue & 3) == slopeValue, "slopeValue doesn't match its mask");
|
||||||
|
auto modifyTile = TileModifyAction(
|
||||||
game_do_command(
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::WallSetSlope, elementIndex, slopeValue);
|
||||||
TILE_INSPECTOR_WALL_SET_SLOPE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
GameActions::Execute(&modifyTile);
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, slopeValue, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_track_block_height_offset(int32_t elementIndex, int8_t heightOffset)
|
static void window_tile_inspector_track_block_height_offset(int32_t elementIndex, int8_t heightOffset)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::TrackBaseHeightOffset, elementIndex,
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, heightOffset, 0);
|
heightOffset);
|
||||||
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_track_block_set_lift(int32_t elementIndex, bool entireTrackBlock, bool chain)
|
static void window_tile_inspector_track_block_set_lift(int32_t elementIndex, bool entireTrackBlock, bool chain)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_TRACK_SET_CHAIN, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY },
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, entireTrackBlock, chain);
|
entireTrackBlock ? TileModifyType::TrackSetChainBlock : TileModifyType::TrackSetChain, elementIndex, chain);
|
||||||
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_track_set_block_brake(int32_t elementIndex, bool blockBrake)
|
static void window_tile_inspector_track_set_block_brake(int32_t elementIndex, bool blockBrake)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_TRACK_SET_BLOCK_BRAKE, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::TrackSetBlockBrake, elementIndex,
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, blockBrake, 0);
|
blockBrake);
|
||||||
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_track_set_indestructible(int32_t elementIndex, bool isIndestructible)
|
static void window_tile_inspector_track_set_indestructible(int32_t elementIndex, bool isIndestructible)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_TRACK_SET_INDESTRUCTIBLE, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::TrackSetIndestructible, elementIndex,
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, isIndestructible,
|
isIndestructible);
|
||||||
0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_quarter_tile_set(int32_t elementIndex, const int32_t quarterIndex)
|
static void window_tile_inspector_quarter_tile_set(int32_t elementIndex, const int32_t quarterIndex)
|
||||||
{
|
{
|
||||||
// quarterIndex is widget index relative to WIDX_SCENERY_CHECK_QUARTER_N, so a value from 0-3
|
// quarterIndex is widget index relative to WIDX_SCENERY_CHECK_QUARTER_N, so a value from 0-3
|
||||||
openrct2_assert(quarterIndex >= 0 && quarterIndex < 4, "quarterIndex out of range");
|
openrct2_assert(quarterIndex >= 0 && quarterIndex < 4, "quarterIndex out of range");
|
||||||
|
auto modifyTile = TileModifyAction(
|
||||||
game_do_command(
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::ScenerySetQuarterLocation, elementIndex,
|
||||||
TILE_INSPECTOR_SCENERY_SET_QUARTER_LOCATION, GAME_COMMAND_FLAG_APPLY,
|
(quarterIndex - get_current_rotation()) & 3);
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE,
|
GameActions::Execute(&modifyTile);
|
||||||
(quarterIndex - get_current_rotation()) & 3, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_toggle_quadrant_collosion(int32_t elementIndex, const int32_t quadrantIndex)
|
static void window_tile_inspector_toggle_quadrant_collosion(int32_t elementIndex, const int32_t quadrantIndex)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_SCENERY_SET_QUARTER_COLLISION, GAME_COMMAND_FLAG_APPLY,
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::ScenerySetQuarterCollision, elementIndex,
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE,
|
(quadrantIndex + 2 - get_current_rotation()) & 3);
|
||||||
(quadrantIndex + 2 - get_current_rotation()) & 3, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_banner_toggle_block(int32_t elementIndex, int32_t edgeIndex)
|
static void window_tile_inspector_banner_toggle_block(int32_t elementIndex, int32_t edgeIndex)
|
||||||
|
@ -801,17 +803,17 @@ static void window_tile_inspector_banner_toggle_block(int32_t elementIndex, int3
|
||||||
|
|
||||||
// Make edgeIndex abstract
|
// Make edgeIndex abstract
|
||||||
edgeIndex = (edgeIndex - get_current_rotation()) & 3;
|
edgeIndex = (edgeIndex - get_current_rotation()) & 3;
|
||||||
|
auto modifyTile = TileModifyAction(
|
||||||
game_do_command(
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::BannerToggleBlockingEdge, elementIndex,
|
||||||
TILE_INSPECTOR_BANNER_TOGGLE_BLOCKING_EDGE, GAME_COMMAND_FLAG_APPLY,
|
edgeIndex);
|
||||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, edgeIndex, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_clamp_corrupt(int32_t elementIndex)
|
static void window_tile_inspector_clamp_corrupt(int32_t elementIndex)
|
||||||
{
|
{
|
||||||
game_do_command(
|
auto modifyTile = TileModifyAction(
|
||||||
TILE_INSPECTOR_CORRUPT_CLAMP, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
{ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::CorruptClamp, elementIndex);
|
||||||
elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0);
|
GameActions::Execute(&modifyTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_tile_inspector_mouseup(rct_window* w, rct_widgetindex widgetIndex)
|
static void window_tile_inspector_mouseup(rct_window* w, rct_widgetindex widgetIndex)
|
||||||
|
|
|
@ -1225,7 +1225,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = {
|
||||||
game_command_pickup_guest,
|
game_command_pickup_guest,
|
||||||
game_command_pickup_staff,
|
game_command_pickup_staff,
|
||||||
nullptr,
|
nullptr,
|
||||||
game_command_modify_tile,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
|
@ -88,7 +88,7 @@ enum GAME_COMMAND
|
||||||
GAME_COMMAND_PICKUP_GUEST,
|
GAME_COMMAND_PICKUP_GUEST,
|
||||||
GAME_COMMAND_PICKUP_STAFF,
|
GAME_COMMAND_PICKUP_STAFF,
|
||||||
GAME_COMMAND_BALLOON_PRESS, // GA
|
GAME_COMMAND_BALLOON_PRESS, // GA
|
||||||
GAME_COMMAND_MODIFY_TILE,
|
GAME_COMMAND_MODIFY_TILE, // GA
|
||||||
GAME_COMMAND_EDIT_SCENARIO_OPTIONS, // GA
|
GAME_COMMAND_EDIT_SCENARIO_OPTIONS, // GA
|
||||||
GAME_COMMAND_PLACE_PEEP_SPAWN, // GA, TODO: refactor to separate array for just game actions
|
GAME_COMMAND_PLACE_PEEP_SPAWN, // GA, TODO: refactor to separate array for just game actions
|
||||||
GAME_COMMAND_SET_CLIMATE, // GA
|
GAME_COMMAND_SET_CLIMATE, // GA
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "actions/RideEntranceExitPlaceAction.hpp"
|
#include "actions/RideEntranceExitPlaceAction.hpp"
|
||||||
#include "actions/RideSetSetting.hpp"
|
#include "actions/RideSetSetting.hpp"
|
||||||
#include "actions/SetCheatAction.hpp"
|
#include "actions/SetCheatAction.hpp"
|
||||||
|
#include "actions/TileModifyAction.hpp"
|
||||||
#include "actions/TrackPlaceAction.hpp"
|
#include "actions/TrackPlaceAction.hpp"
|
||||||
#include "config/Config.h"
|
#include "config/Config.h"
|
||||||
#include "core/DataSerialiser.h"
|
#include "core/DataSerialiser.h"
|
||||||
|
@ -537,6 +538,28 @@ namespace OpenRCT2
|
||||||
result.action->SetFlags(command.ebx & 0xFF);
|
result.action->SetFlags(command.ebx & 0xFF);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GAME_COMMAND_MODIFY_TILE:
|
||||||
|
{
|
||||||
|
int32_t param1 = command.edx;
|
||||||
|
int32_t param2 = command.edi;
|
||||||
|
CoordsXY loc = { static_cast<int16_t>((command.ecx & 0xFF) * 32),
|
||||||
|
static_cast<int16_t>(((command.ecx >> 8) & 0xFF) * 32) };
|
||||||
|
TileModifyType type = static_cast<TileModifyType>(command.eax & 0xFF);
|
||||||
|
|
||||||
|
if (type == TileModifyType::AnyPaste)
|
||||||
|
{
|
||||||
|
TileElement copiedElement{};
|
||||||
|
uint32_t data[2] = { command.edx, command.edi };
|
||||||
|
std::memcpy(&copiedElement, &data[0], 8);
|
||||||
|
result.action = std::make_unique<TileModifyAction>(loc, type, 0, 0, copiedElement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.action = std::make_unique<TileModifyAction>(loc, type, param1, param2);
|
||||||
|
}
|
||||||
|
result.action->SetFlags(command.ebx & 0xFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Deprecated game command requires replay translation.");
|
throw std::runtime_error("Deprecated game command requires replay translation.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
#include "StaffSetOrdersAction.hpp"
|
#include "StaffSetOrdersAction.hpp"
|
||||||
#include "StaffSetPatrolAreaAction.hpp"
|
#include "StaffSetPatrolAreaAction.hpp"
|
||||||
#include "SurfaceSetStyleAction.hpp"
|
#include "SurfaceSetStyleAction.hpp"
|
||||||
|
#include "TileModifyAction.hpp"
|
||||||
#include "TrackPlaceAction.hpp"
|
#include "TrackPlaceAction.hpp"
|
||||||
#include "TrackRemoveAction.hpp"
|
#include "TrackRemoveAction.hpp"
|
||||||
#include "TrackSetBrakeSpeedAction.hpp"
|
#include "TrackSetBrakeSpeedAction.hpp"
|
||||||
|
@ -151,6 +152,7 @@ namespace GameActions
|
||||||
Register<LandSetHeightAction>();
|
Register<LandSetHeightAction>();
|
||||||
Register<LandSetRightsAction>();
|
Register<LandSetRightsAction>();
|
||||||
Register<LandSmoothAction>();
|
Register<LandSmoothAction>();
|
||||||
|
Register<TileModifyAction>();
|
||||||
Register<TrackPlaceAction>();
|
Register<TrackPlaceAction>();
|
||||||
Register<TrackRemoveAction>();
|
Register<TrackRemoveAction>();
|
||||||
Register<TrackSetBrakeSpeedAction>();
|
Register<TrackSetBrakeSpeedAction>();
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* 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 "../world/TileInspector.h"
|
||||||
|
#include "GameAction.h"
|
||||||
|
|
||||||
|
enum class TileModifyType : uint8_t
|
||||||
|
{
|
||||||
|
AnyRemove,
|
||||||
|
AnySwap,
|
||||||
|
AnyInsertCorrupt,
|
||||||
|
AnyRotate,
|
||||||
|
AnyPaste,
|
||||||
|
AnySort,
|
||||||
|
AnyBaseHeightOffset,
|
||||||
|
SurfaceShowParkFences,
|
||||||
|
SurfaceToggleCorner,
|
||||||
|
SurfaceToggleDiagonal,
|
||||||
|
PathSetSlope,
|
||||||
|
PathSetBroken,
|
||||||
|
PathToggleEdge,
|
||||||
|
EntranceMakeUsable,
|
||||||
|
WallSetSlope,
|
||||||
|
TrackBaseHeightOffset,
|
||||||
|
TrackSetChain,
|
||||||
|
TrackSetChainBlock,
|
||||||
|
TrackSetBlockBrake,
|
||||||
|
TrackSetIndestructible,
|
||||||
|
ScenerySetQuarterLocation,
|
||||||
|
ScenerySetQuarterCollision,
|
||||||
|
BannerToggleBlockingEdge,
|
||||||
|
CorruptClamp,
|
||||||
|
Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_GAME_ACTION(TileModifyAction, GAME_COMMAND_MODIFY_TILE, GameActionResult)
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
CoordsXY _loc;
|
||||||
|
uint8_t _setting{ 0 };
|
||||||
|
uint32_t _value1{ 0 };
|
||||||
|
uint32_t _value2{ 0 };
|
||||||
|
TileElement _pasteElement{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
TileModifyAction()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
TileModifyAction(
|
||||||
|
CoordsXY loc, TileModifyType setting, uint32_t value1 = 0, uint32_t value2 = 0, TileElement pasteElement = {})
|
||||||
|
: _loc(loc)
|
||||||
|
, _setting(static_cast<uint8_t>(setting))
|
||||||
|
, _value1(value1)
|
||||||
|
, _value2(value2)
|
||||||
|
, _pasteElement(pasteElement)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t GetActionFlags() const override
|
||||||
|
{
|
||||||
|
return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialise(DataSerialiser & stream) override
|
||||||
|
{
|
||||||
|
GameAction::Serialise(stream);
|
||||||
|
|
||||||
|
stream << DS_TAG(_loc) << DS_TAG(_setting) << DS_TAG(_value1) << DS_TAG(_value2) << DS_TAG(_pasteElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
switch (static_cast<TileModifyType>(_setting))
|
||||||
|
{
|
||||||
|
case TileModifyType::AnyRemove:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
res = tile_inspector_remove_element_at(_loc, elementIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::AnySwap:
|
||||||
|
{
|
||||||
|
const auto firstIndex = _value1;
|
||||||
|
const auto secondIndex = _value2;
|
||||||
|
res = tile_inspector_swap_elements_at(_loc, firstIndex, secondIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::AnyInsertCorrupt:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
res = tile_inspector_insert_corrupt_at(_loc, elementIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::AnyRotate:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
res = tile_inspector_rotate_element_at(_loc, elementIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::AnyPaste:
|
||||||
|
{
|
||||||
|
res = tile_inspector_paste_element_at(_loc, _pasteElement, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::AnySort:
|
||||||
|
{
|
||||||
|
res = tile_inspector_sort_elements_at(_loc, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::AnyBaseHeightOffset:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const auto heightOffset = _value2;
|
||||||
|
res = tile_inspector_any_base_height_offset(_loc, elementIndex, heightOffset, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::SurfaceShowParkFences:
|
||||||
|
{
|
||||||
|
const bool showFences = _value1;
|
||||||
|
res = tile_inspector_surface_show_park_fences(_loc, showFences, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::SurfaceToggleCorner:
|
||||||
|
{
|
||||||
|
const auto cornerIndex = _value1;
|
||||||
|
res = tile_inspector_surface_toggle_corner(_loc, cornerIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::SurfaceToggleDiagonal:
|
||||||
|
{
|
||||||
|
res = tile_inspector_surface_toggle_diagonal(_loc, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::PathSetSlope:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const bool sloped = _value2;
|
||||||
|
res = tile_inspector_path_set_sloped(_loc, elementIndex, sloped, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::PathSetBroken:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const bool broken = _value2;
|
||||||
|
res = tile_inspector_path_set_broken(_loc, elementIndex, broken, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::PathToggleEdge:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const auto edgeIndex = _value2;
|
||||||
|
res = tile_inspector_path_toggle_edge(_loc, elementIndex, edgeIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::EntranceMakeUsable:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
res = tile_inspector_entrance_make_usable(_loc, elementIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::WallSetSlope:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const auto slopeValue = _value2;
|
||||||
|
res = tile_inspector_wall_set_slope(_loc, elementIndex, slopeValue, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::TrackBaseHeightOffset:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const auto heightOffset = _value2;
|
||||||
|
res = tile_inspector_track_base_height_offset(_loc, elementIndex, heightOffset, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::TrackSetChainBlock:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const bool setChain = _value2;
|
||||||
|
res = tile_inspector_track_set_chain(_loc, elementIndex, true, setChain, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::TrackSetChain:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const bool setChain = _value2;
|
||||||
|
res = tile_inspector_track_set_chain(_loc, elementIndex, false, setChain, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::TrackSetBlockBrake:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const bool blockBrake = _value2;
|
||||||
|
res = tile_inspector_track_set_block_brake(_loc, elementIndex, blockBrake, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::TrackSetIndestructible:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const bool isIndestructible = _value2;
|
||||||
|
res = tile_inspector_track_set_indestructible(_loc, elementIndex, isIndestructible, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::ScenerySetQuarterLocation:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const auto quarterIndex = _value2;
|
||||||
|
res = tile_inspector_scenery_set_quarter_location(_loc, elementIndex, quarterIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::ScenerySetQuarterCollision:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const auto quarterIndex = _value2;
|
||||||
|
res = tile_inspector_scenery_set_quarter_collision(_loc, elementIndex, quarterIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::BannerToggleBlockingEdge:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
const auto edgeIndex = _value2;
|
||||||
|
res = tile_inspector_banner_toggle_blocking_edge(_loc, elementIndex, edgeIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TileModifyType::CorruptClamp:
|
||||||
|
{
|
||||||
|
const auto elementIndex = _value1;
|
||||||
|
res = tile_inspector_corrupt_clamp(_loc, elementIndex, isExecuting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log_error("invalid instruction");
|
||||||
|
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
res->Position.x = _loc.x;
|
||||||
|
res->Position.y = _loc.y;
|
||||||
|
res->Position.z = tile_element_height(_loc.x, _loc.y);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
|
@ -16,6 +16,7 @@
|
||||||
#include "../network/network.h"
|
#include "../network/network.h"
|
||||||
#include "../ride/Ride.h"
|
#include "../ride/Ride.h"
|
||||||
#include "../world/Location.hpp"
|
#include "../world/Location.hpp"
|
||||||
|
#include "../world/TileElement.h"
|
||||||
#include "DataSerialiserTag.h"
|
#include "DataSerialiserTag.h"
|
||||||
#include "Endianness.h"
|
#include "Endianness.h"
|
||||||
#include "MemoryStream.h"
|
#include "MemoryStream.h"
|
||||||
|
@ -381,6 +382,40 @@ template<> struct DataSerializerTraits<MapRange>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<> struct DataSerializerTraits<TileElement>
|
||||||
|
{
|
||||||
|
static void encode(IStream* stream, const TileElement& tileElement)
|
||||||
|
{
|
||||||
|
stream->WriteValue(tileElement.type);
|
||||||
|
stream->WriteValue(tileElement.flags);
|
||||||
|
stream->WriteValue(tileElement.base_height);
|
||||||
|
stream->WriteValue(tileElement.clearance_height);
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
stream->WriteValue(tileElement.pad_04[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void decode(IStream* stream, TileElement& tileElement)
|
||||||
|
{
|
||||||
|
tileElement.type = stream->ReadValue<uint8_t>();
|
||||||
|
tileElement.flags = stream->ReadValue<uint8_t>();
|
||||||
|
tileElement.base_height = stream->ReadValue<uint8_t>();
|
||||||
|
tileElement.clearance_height = stream->ReadValue<uint8_t>();
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
tileElement.pad_04[i] = stream->ReadValue<uint8_t>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void log(IStream* stream, const TileElement& tileElement)
|
||||||
|
{
|
||||||
|
char msg[128] = {};
|
||||||
|
snprintf(
|
||||||
|
msg, sizeof(msg), "TileElement(type = %u, flags = %u, base_height = %u)", tileElement.type, tileElement.flags,
|
||||||
|
tileElement.base_height);
|
||||||
|
stream->Write(msg, strlen(msg));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<> struct DataSerializerTraits<CoordsXY>
|
template<> struct DataSerializerTraits<CoordsXY>
|
||||||
{
|
{
|
||||||
static void encode(IStream* stream, const CoordsXY& coords)
|
static void encode(IStream* stream, const CoordsXY& coords)
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
// This string specifies which version of network stream current build uses.
|
// This string specifies which version of network stream current build uses.
|
||||||
// It is used for making sure only compatible builds get connected, even within
|
// It is used for making sure only compatible builds get connected, even within
|
||||||
// single OpenRCT2 version.
|
// single OpenRCT2 version.
|
||||||
#define NETWORK_STREAM_VERSION "40"
|
#define NETWORK_STREAM_VERSION "41"
|
||||||
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
|
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
|
||||||
|
|
||||||
static Peep* _pickup_peep = nullptr;
|
static Peep* _pickup_peep = nullptr;
|
||||||
|
|
|
@ -2245,186 +2245,6 @@ void map_clear_all_elements()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
const int32_t flags = *ebx;
|
|
||||||
const int32_t x = *ecx & 0xFF;
|
|
||||||
const int32_t y = (*ecx >> 8) & 0xFF;
|
|
||||||
const TILE_INSPECTOR_INSTRUCTION_TYPE instruction = static_cast<TILE_INSPECTOR_INSTRUCTION_TYPE>(*eax);
|
|
||||||
|
|
||||||
switch (instruction)
|
|
||||||
{
|
|
||||||
case TILE_INSPECTOR_ANY_REMOVE:
|
|
||||||
{
|
|
||||||
const int16_t elementIndex = *edx;
|
|
||||||
*ebx = tile_inspector_remove_element_at(x, y, elementIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_ANY_SWAP:
|
|
||||||
{
|
|
||||||
const int32_t firstIndex = *edx;
|
|
||||||
const int32_t secondIndex = *edi;
|
|
||||||
*ebx = tile_inspector_swap_elements_at(x, y, firstIndex, secondIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_ANY_INSERT_CORRUPT:
|
|
||||||
{
|
|
||||||
const int16_t elementIndex = *edx;
|
|
||||||
*ebx = tile_inspector_insert_corrupt_at(x, y, elementIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_ANY_ROTATE:
|
|
||||||
{
|
|
||||||
const int16_t elementIndex = *edx;
|
|
||||||
*ebx = tile_inspector_rotate_element_at(x, y, elementIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_ANY_PASTE:
|
|
||||||
{
|
|
||||||
TileElement elementToPaste;
|
|
||||||
const int32_t data[] = { *edx, *edi };
|
|
||||||
assert_struct_size(data, sizeof(elementToPaste));
|
|
||||||
std::memcpy(&elementToPaste, data, 8);
|
|
||||||
*ebx = tile_inspector_paste_element_at(x, y, elementToPaste, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_ANY_SORT:
|
|
||||||
{
|
|
||||||
*ebx = tile_inspector_sort_elements_at(x, y, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_ANY_BASE_HEIGHT_OFFSET:
|
|
||||||
{
|
|
||||||
const int16_t elementIndex = *edx;
|
|
||||||
const int8_t heightOffset = *edi;
|
|
||||||
*ebx = tile_inspector_any_base_height_offset(x, y, elementIndex, heightOffset, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_SURFACE_SHOW_PARK_FENCES:
|
|
||||||
{
|
|
||||||
const bool showFences = *edx;
|
|
||||||
*ebx = tile_inspector_surface_show_park_fences(x, y, showFences, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_SURFACE_TOGGLE_CORNER:
|
|
||||||
{
|
|
||||||
const int32_t cornerIndex = *edx;
|
|
||||||
*ebx = tile_inspector_surface_toggle_corner(x, y, cornerIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_SURFACE_TOGGLE_DIAGONAL:
|
|
||||||
{
|
|
||||||
*ebx = tile_inspector_surface_toggle_diagonal(x, y, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_PATH_SET_SLOPE:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const bool sloped = *edi;
|
|
||||||
*ebx = tile_inspector_path_set_sloped(x, y, elementIndex, sloped, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_PATH_SET_BROKEN:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const bool broken = *edi;
|
|
||||||
*ebx = tile_inspector_path_set_broken(x, y, elementIndex, broken, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_PATH_TOGGLE_EDGE:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const int32_t edgeIndex = *edi;
|
|
||||||
*ebx = tile_inspector_path_toggle_edge(x, y, elementIndex, edgeIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_ENTRANCE_MAKE_USABLE:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
*ebx = tile_inspector_entrance_make_usable(x, y, elementIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_WALL_SET_SLOPE:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const int32_t slopeValue = *edi;
|
|
||||||
*ebx = tile_inspector_wall_set_slope(x, y, elementIndex, slopeValue, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const int8_t heightOffset = *edi;
|
|
||||||
*ebx = tile_inspector_track_base_height_offset(x, y, elementIndex, heightOffset, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_TRACK_SET_CHAIN:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const bool entireTrackBlock = *edi;
|
|
||||||
const bool setChain = *ebp;
|
|
||||||
*ebx = tile_inspector_track_set_chain(x, y, elementIndex, entireTrackBlock, setChain, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_TRACK_SET_BLOCK_BRAKE:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const bool blockBrake = *edi;
|
|
||||||
*ebx = tile_inspector_track_set_block_brake(x, y, elementIndex, blockBrake, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_TRACK_SET_INDESTRUCTIBLE:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const bool isIndestructible = *edi;
|
|
||||||
*ebx = tile_inspector_track_set_indestructible(x, y, elementIndex, isIndestructible, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_SCENERY_SET_QUARTER_LOCATION:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const int32_t quarterIndex = *edi;
|
|
||||||
*ebx = tile_inspector_scenery_set_quarter_location(x, y, elementIndex, quarterIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_SCENERY_SET_QUARTER_COLLISION:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const int32_t quarterIndex = *edi;
|
|
||||||
*ebx = tile_inspector_scenery_set_quarter_collision(x, y, elementIndex, quarterIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_BANNER_TOGGLE_BLOCKING_EDGE:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
const int32_t edgeIndex = *edi;
|
|
||||||
*ebx = tile_inspector_banner_toggle_blocking_edge(x, y, elementIndex, edgeIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_INSPECTOR_CORRUPT_CLAMP:
|
|
||||||
{
|
|
||||||
const int32_t elementIndex = *edx;
|
|
||||||
*ebx = tile_inspector_corrupt_clamp(x, y, elementIndex, flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
log_error("invalid instruction");
|
|
||||||
*ebx = MONEY32_UNDEFINED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY && gGameCommandNestLevel == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)
|
|
||||||
&& *ebx != MONEY32_UNDEFINED)
|
|
||||||
{
|
|
||||||
LocationXYZ16 coord;
|
|
||||||
coord.x = (x << 5) + 16;
|
|
||||||
coord.y = (y << 5) + 16;
|
|
||||||
coord.z = tile_element_height(coord.x, coord.y);
|
|
||||||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the track element at x, y, z.
|
* Gets the track element at x, y, z.
|
||||||
* @param x x units, not tiles.
|
* @param x x units, not tiles.
|
||||||
|
|
|
@ -187,8 +187,6 @@ int32_t map_can_construct_at(int32_t x, int32_t y, int32_t zLow, int32_t zHigh,
|
||||||
void rotate_map_coordinates(int16_t* x, int16_t* y, int32_t rotation);
|
void rotate_map_coordinates(int16_t* x, int16_t* y, int32_t rotation);
|
||||||
LocationXY16 coordinate_3d_to_2d(const LocationXYZ16* coordinate_3d, int32_t rotation);
|
LocationXY16 coordinate_3d_to_2d(const LocationXYZ16* coordinate_3d, int32_t rotation);
|
||||||
|
|
||||||
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
|
struct tile_element_iterator
|
||||||
{
|
{
|
||||||
int32_t x;
|
int32_t x;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "../Context.h"
|
#include "../Context.h"
|
||||||
#include "../Game.h"
|
#include "../Game.h"
|
||||||
|
#include "../actions/GameAction.h"
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../core/Guard.hpp"
|
#include "../core/Guard.hpp"
|
||||||
#include "../interface/Window.h"
|
#include "../interface/Window.h"
|
||||||
|
@ -34,10 +35,10 @@ uint32_t windowTileInspectorTileY;
|
||||||
int32_t windowTileInspectorElementCount = 0;
|
int32_t windowTileInspectorElementCount = 0;
|
||||||
int32_t windowTileInspectorSelectedIndex;
|
int32_t windowTileInspectorSelectedIndex;
|
||||||
|
|
||||||
static bool map_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t second)
|
static bool map_swap_elements_at(CoordsXY loc, int16_t first, int16_t second)
|
||||||
{
|
{
|
||||||
TileElement* const firstElement = map_get_nth_element_at(x, y, first);
|
TileElement* const firstElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, first);
|
||||||
TileElement* const secondElement = map_get_nth_element_at(x, y, second);
|
TileElement* const secondElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, second);
|
||||||
|
|
||||||
if (firstElement == nullptr)
|
if (firstElement == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -77,28 +78,29 @@ static bool map_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t se
|
||||||
* @param elementIndex The nth element on this tile
|
* @param elementIndex The nth element on this tile
|
||||||
* Returns 0 on success, MONEY_UNDEFINED otherwise.
|
* Returns 0 on success, MONEY_UNDEFINED otherwise.
|
||||||
*/
|
*/
|
||||||
int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIndex, int32_t flags)
|
GameActionResult::Ptr tile_inspector_insert_corrupt_at(CoordsXY loc, int16_t elementIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
// Make sure there is enough space for the new element
|
// Make sure there is enough space for the new element
|
||||||
if (!map_check_free_elements_and_reorganise(1))
|
if (!map_check_free_elements_and_reorganise(1))
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
// Create new corrupt element
|
// Create new corrupt element
|
||||||
TileElement* corruptElement = tile_element_insert(x, y, -1, 0); // Ugly hack: -1 guarantees this to be placed first
|
TileElement* corruptElement = tile_element_insert(
|
||||||
|
loc.x / 32, loc.y / 32, -1, 0); // Ugly hack: -1 guarantees this to be placed first
|
||||||
if (corruptElement == nullptr)
|
if (corruptElement == nullptr)
|
||||||
{
|
{
|
||||||
log_warning("Failed to insert corrupt element.");
|
log_warning("Failed to insert corrupt element.");
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
corruptElement->SetType(TILE_ELEMENT_TYPE_CORRUPT);
|
corruptElement->SetType(TILE_ELEMENT_TYPE_CORRUPT);
|
||||||
|
|
||||||
// Set the base height to be the same as the selected element
|
// Set the base height to be the same as the selected element
|
||||||
TileElement* const selectedElement = map_get_nth_element_at(x, y, elementIndex + 1);
|
TileElement* const selectedElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex + 1);
|
||||||
if (!selectedElement)
|
if (!selectedElement)
|
||||||
{
|
{
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
corruptElement->base_height = corruptElement->clearance_height = selectedElement->base_height;
|
corruptElement->base_height = corruptElement->clearance_height = selectedElement->base_height;
|
||||||
|
|
||||||
|
@ -106,7 +108,7 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn
|
||||||
// this way it's placed under the selected element, even when there are multiple elements with the same base height
|
// this way it's placed under the selected element, even when there are multiple elements with the same base height
|
||||||
for (int16_t i = 0; i < elementIndex; i++)
|
for (int16_t i = 0; i < elementIndex; i++)
|
||||||
{
|
{
|
||||||
if (!map_swap_elements_at(x, y, i, i + 1))
|
if (!map_swap_elements_at(loc, i, i + 1))
|
||||||
{
|
{
|
||||||
// don't return error here, we've already inserted an element
|
// don't return error here, we've already inserted an element
|
||||||
// and moved it as far as we could, the only sensible thing left
|
// and moved it as far as we could, the only sensible thing left
|
||||||
|
@ -115,12 +117,12 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
// Update the tile inspector's list for everyone who has the tile selected
|
// Update the tile inspector's list for everyone who has the tile selected
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
windowTileInspectorElementCount++;
|
windowTileInspectorElementCount++;
|
||||||
|
|
||||||
|
@ -135,7 +137,7 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing went wrong
|
// Nothing went wrong
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,23 +146,23 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn
|
||||||
* @param y The y coordinate of the tile
|
* @param y The y coordinate of the tile
|
||||||
* @param elementIndex The nth element on this tile
|
* @param elementIndex The nth element on this tile
|
||||||
*/
|
*/
|
||||||
int32_t tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIndex, int32_t flags)
|
GameActionResult::Ptr tile_inspector_remove_element_at(CoordsXY loc, int16_t elementIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
// Forcefully remove the element
|
// Forcefully remove the element
|
||||||
TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const tileElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
if (!tileElement)
|
if (!tileElement)
|
||||||
{
|
{
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
tile_element_remove(tileElement);
|
tile_element_remove(tileElement);
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
// Update the window
|
// Update the window
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
windowTileInspectorElementCount--;
|
windowTileInspectorElementCount--;
|
||||||
|
|
||||||
|
@ -177,23 +179,23 @@ int32_t tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t second, int32_t flags)
|
GameActionResult::Ptr tile_inspector_swap_elements_at(CoordsXY loc, int16_t first, int16_t second, bool isExecuting)
|
||||||
{
|
{
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
if (!map_swap_elements_at(x, y, first, second))
|
if (!map_swap_elements_at(loc, first, second))
|
||||||
{
|
{
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
// Update the window
|
// Update the window
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
// If one of them was selected, update selected list item
|
// If one of them was selected, update selected list item
|
||||||
if (windowTileInspectorSelectedIndex == first)
|
if (windowTileInspectorSelectedIndex == first)
|
||||||
|
@ -205,19 +207,19 @@ int32_t tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIndex, int32_t flags)
|
GameActionResult::Ptr tile_inspector_rotate_element_at(CoordsXY loc, int32_t elementIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
uint8_t newRotation, pathEdges, pathCorners;
|
uint8_t newRotation, pathEdges, pathCorners;
|
||||||
|
|
||||||
TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const tileElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
if (!tileElement)
|
if (!tileElement)
|
||||||
{
|
{
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
switch (tileElement->GetType())
|
switch (tileElement->GetType())
|
||||||
{
|
{
|
||||||
|
@ -247,11 +249,12 @@ int32_t tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIn
|
||||||
uint8_t z = tileElement->base_height;
|
uint8_t z = tileElement->base_height;
|
||||||
|
|
||||||
// Make sure this is the correct entrance or exit
|
// Make sure this is the correct entrance or exit
|
||||||
if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE && entrance.x == x && entrance.y == y && entrance.z == z)
|
if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE && entrance.x == loc.x / 32 && entrance.y == loc.y / 32
|
||||||
|
&& entrance.z == z)
|
||||||
{
|
{
|
||||||
ride_set_entrance_location(ride, stationIndex, { entrance.x, entrance.y, entrance.z, newRotation });
|
ride_set_entrance_location(ride, stationIndex, { entrance.x, entrance.y, entrance.z, newRotation });
|
||||||
}
|
}
|
||||||
else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == x && exit.y == y && exit.z == z)
|
else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == loc.x / 32 && exit.y == loc.y / 32 && exit.z == z)
|
||||||
{
|
{
|
||||||
ride_set_exit_location(ride, stationIndex, { exit.x, exit.y, exit.z, newRotation });
|
ride_set_exit_location(ride, stationIndex, { exit.x, exit.y, exit.z, newRotation });
|
||||||
}
|
}
|
||||||
|
@ -273,41 +276,41 @@ int32_t tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
if ((uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
if ((uint32_t)(loc.x / 32) == windowTileInspectorTileX && (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement element, int32_t flags)
|
GameActionResult::Ptr tile_inspector_paste_element_at(CoordsXY loc, TileElement element, bool isExecuting)
|
||||||
{
|
{
|
||||||
// Make sure there is enough space for the new element
|
// Make sure there is enough space for the new element
|
||||||
if (!map_check_free_elements_and_reorganise(1))
|
if (!map_check_free_elements_and_reorganise(1))
|
||||||
{
|
{
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
// Check if the element to be pasted refers to a banner index
|
// Check if the element to be pasted refers to a banner index
|
||||||
BannerIndex bannerIndex = tile_element_get_banner_index(&element);
|
BannerIndex bannerIndex = tile_element_get_banner_index(&element);
|
||||||
if (bannerIndex != BANNER_INDEX_NULL)
|
if (bannerIndex != BANNER_INDEX_NULL)
|
||||||
{
|
{
|
||||||
// The element to be pasted refers to a banner index - make a copy of it
|
// The element to be pasted refers to a banner index - make a copy of it
|
||||||
BannerIndex newBannerIndex = create_new_banner(flags);
|
BannerIndex newBannerIndex = create_new_banner(GAME_COMMAND_FLAG_APPLY);
|
||||||
if (newBannerIndex == BANNER_INDEX_NULL)
|
if (newBannerIndex == BANNER_INDEX_NULL)
|
||||||
{
|
{
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
rct_banner& newBanner = gBanners[newBannerIndex];
|
rct_banner& newBanner = gBanners[newBannerIndex];
|
||||||
newBanner = gBanners[bannerIndex];
|
newBanner = gBanners[bannerIndex];
|
||||||
newBanner.x = x;
|
newBanner.x = loc.x / 32;
|
||||||
newBanner.y = y;
|
newBanner.y = loc.y / 32;
|
||||||
|
|
||||||
// Use the new banner index
|
// Use the new banner index
|
||||||
tile_element_set_banner_index(&element, newBannerIndex);
|
tile_element_set_banner_index(&element, newBannerIndex);
|
||||||
|
@ -321,13 +324,13 @@ int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement elemen
|
||||||
rct_string_id newStringIdx = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
|
rct_string_id newStringIdx = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
|
||||||
if (newStringIdx == 0)
|
if (newStringIdx == 0)
|
||||||
{
|
{
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE);
|
||||||
}
|
}
|
||||||
gBanners[newBannerIndex].string_idx = newStringIdx;
|
gBanners[newBannerIndex].string_idx = newStringIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TileElement* const pastedElement = tile_element_insert(x, y, element.base_height, 0);
|
TileElement* const pastedElement = tile_element_insert(loc.x / 32, loc.y / 32, element.base_height, 0);
|
||||||
|
|
||||||
bool lastForTile = pastedElement->IsLastForTile();
|
bool lastForTile = pastedElement->IsLastForTile();
|
||||||
*pastedElement = element;
|
*pastedElement = element;
|
||||||
|
@ -337,16 +340,16 @@ int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement elemen
|
||||||
pastedElement->flags |= TILE_ELEMENT_FLAG_LAST_TILE;
|
pastedElement->flags |= TILE_ELEMENT_FLAG_LAST_TILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
windowTileInspectorElementCount++;
|
windowTileInspectorElementCount++;
|
||||||
|
|
||||||
// Select new element if there was none selected already
|
// Select new element if there was none selected already
|
||||||
int16_t newIndex = (int16_t)(pastedElement - map_get_first_element_at(x, y));
|
int16_t newIndex = (int16_t)(pastedElement - map_get_first_element_at(loc.x / 32, loc.y / 32));
|
||||||
if (windowTileInspectorSelectedIndex == -1)
|
if (windowTileInspectorSelectedIndex == -1)
|
||||||
windowTileInspectorSelectedIndex = newIndex;
|
windowTileInspectorSelectedIndex = newIndex;
|
||||||
else if (windowTileInspectorSelectedIndex >= newIndex)
|
else if (windowTileInspectorSelectedIndex >= newIndex)
|
||||||
|
@ -356,14 +359,14 @@ int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement elemen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags)
|
GameActionResult::Ptr tile_inspector_sort_elements_at(CoordsXY loc, bool isExecuting)
|
||||||
{
|
{
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
const TileElement* const firstElement = map_get_first_element_at(x, y);
|
const TileElement* const firstElement = map_get_first_element_at(loc.x / 32, loc.y / 32);
|
||||||
|
|
||||||
// Count elements on tile
|
// Count elements on tile
|
||||||
int32_t numElement = 0;
|
int32_t numElement = 0;
|
||||||
|
@ -387,7 +390,7 @@ int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags)
|
||||||
|| (otherElement->base_height == currentElement->base_height
|
|| (otherElement->base_height == currentElement->base_height
|
||||||
&& otherElement->clearance_height > currentElement->clearance_height)))
|
&& otherElement->clearance_height > currentElement->clearance_height)))
|
||||||
{
|
{
|
||||||
if (!map_swap_elements_at(x, y, currentId - 1, currentId))
|
if (!map_swap_elements_at(loc, currentId - 1, currentId))
|
||||||
{
|
{
|
||||||
// don't return error here, we've already ran some actions
|
// don't return error here, we've already ran some actions
|
||||||
// and moved things as far as we could, the only sensible
|
// and moved things as far as we could, the only sensible
|
||||||
|
@ -401,35 +404,36 @@ int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
// Deselect tile for clients who had it selected
|
// Deselect tile for clients who had it selected
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
windowTileInspectorSelectedIndex = -1;
|
windowTileInspectorSelectedIndex = -1;
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elementIndex, int8_t heightOffset, int32_t flags)
|
GameActionResult::Ptr tile_inspector_any_base_height_offset(
|
||||||
|
CoordsXY loc, int16_t elementIndex, int8_t heightOffset, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const tileElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
if (tileElement == nullptr)
|
if (tileElement == nullptr)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
int16_t newBaseHeight = (int16_t)tileElement->base_height + heightOffset;
|
int16_t newBaseHeight = (int16_t)tileElement->base_height + heightOffset;
|
||||||
int16_t newClearanceHeight = (int16_t)tileElement->clearance_height + heightOffset;
|
int16_t newClearanceHeight = (int16_t)tileElement->clearance_height + heightOffset;
|
||||||
if (newBaseHeight < 0 || newBaseHeight > 0xff || newClearanceHeight < 0 || newClearanceHeight > 0xff)
|
if (newBaseHeight < 0 || newBaseHeight > 0xff || newClearanceHeight < 0 || newClearanceHeight > 0xff)
|
||||||
{
|
{
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
if (tileElement->GetType() == TILE_ELEMENT_TYPE_ENTRANCE)
|
if (tileElement->GetType() == TILE_ELEMENT_TYPE_ENTRANCE)
|
||||||
{
|
{
|
||||||
|
@ -444,10 +448,11 @@ int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elem
|
||||||
uint8_t z = tileElement->base_height;
|
uint8_t z = tileElement->base_height;
|
||||||
|
|
||||||
// Make sure this is the correct entrance or exit
|
// Make sure this is the correct entrance or exit
|
||||||
if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE && entrance.x == x && entrance.y == y && entrance.z == z)
|
if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE && entrance.x == loc.x / 32 && entrance.y == loc.y / 32
|
||||||
|
&& entrance.z == z)
|
||||||
ride_set_entrance_location(
|
ride_set_entrance_location(
|
||||||
ride, entranceIndex, { entrance.x, entrance.y, z + heightOffset, entrance.direction });
|
ride, entranceIndex, { entrance.x, entrance.y, z + heightOffset, entrance.direction });
|
||||||
else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == x && exit.y == y && exit.z == z)
|
else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == loc.x / 32 && exit.y == loc.y / 32 && exit.z == z)
|
||||||
ride_set_exit_location(ride, entranceIndex, { exit.x, exit.y, z + heightOffset, exit.direction });
|
ride_set_exit_location(ride, entranceIndex, { exit.x, exit.y, z + heightOffset, exit.direction });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -455,56 +460,56 @@ int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elem
|
||||||
tileElement->base_height += heightOffset;
|
tileElement->base_height += heightOffset;
|
||||||
tileElement->clearance_height += heightOffset;
|
tileElement->clearance_height += heightOffset;
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool showFences, int32_t flags)
|
GameActionResult::Ptr tile_inspector_surface_show_park_fences(CoordsXY loc, bool showFences, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const surfaceelement = map_get_surface_element_at(x, y);
|
TileElement* const surfaceelement = map_get_surface_element_at(loc);
|
||||||
|
|
||||||
// No surface element on tile
|
// No surface element on tile
|
||||||
if (surfaceelement == nullptr)
|
if (surfaceelement == nullptr)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
if (!showFences)
|
if (!showFences)
|
||||||
surfaceelement->AsSurface()->SetParkFences(0);
|
surfaceelement->AsSurface()->SetParkFences(0);
|
||||||
else
|
else
|
||||||
update_park_fences({ x << 5, y << 5 });
|
update_park_fences(loc);
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t cornerIndex, int32_t flags)
|
GameActionResult::Ptr tile_inspector_surface_toggle_corner(CoordsXY loc, int32_t cornerIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const surfaceElement = map_get_surface_element_at(x, y);
|
TileElement* const surfaceElement = map_get_surface_element_at(loc);
|
||||||
|
|
||||||
// No surface element on tile
|
// No surface element on tile
|
||||||
if (surfaceElement == nullptr)
|
if (surfaceElement == nullptr)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
const uint8_t originalSlope = surfaceElement->AsSurface()->GetSlope();
|
const uint8_t originalSlope = surfaceElement->AsSurface()->GetSlope();
|
||||||
const bool diagonal = (originalSlope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT) >> 4;
|
const bool diagonal = (originalSlope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT) >> 4;
|
||||||
|
@ -550,28 +555,28 @@ int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t corne
|
||||||
surfaceElement->clearance_height = surfaceElement->base_height + (diagonal ? 2 : 0);
|
surfaceElement->clearance_height = surfaceElement->base_height + (diagonal ? 2 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t flags)
|
GameActionResult::Ptr tile_inspector_surface_toggle_diagonal(CoordsXY loc, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const surfaceElement = map_get_surface_element_at(x, y);
|
TileElement* const surfaceElement = map_get_surface_element_at(loc);
|
||||||
|
|
||||||
// No surface element on tile
|
// No surface element on tile
|
||||||
if (surfaceElement == nullptr)
|
if (surfaceElement == nullptr)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
uint8_t newSlope = surfaceElement->AsSurface()->GetSlope() ^ TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT;
|
uint8_t newSlope = surfaceElement->AsSurface()->GetSlope() ^ TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT;
|
||||||
surfaceElement->AsSurface()->SetSlope(newSlope);
|
surfaceElement->AsSurface()->SetSlope(newSlope);
|
||||||
|
@ -588,105 +593,105 @@ int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t fla
|
||||||
surfaceElement->clearance_height = surfaceElement->base_height;
|
surfaceElement->clearance_height = surfaceElement->base_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementIndex, bool sloped, int32_t flags)
|
GameActionResult::Ptr tile_inspector_path_set_sloped(CoordsXY loc, int32_t elementIndex, bool sloped, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const pathElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const pathElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
pathElement->AsPath()->SetSloped(sloped);
|
pathElement->AsPath()->SetSloped(sloped);
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_path_set_broken(int32_t x, int32_t y, int32_t elementIndex, bool broken, int32_t flags)
|
GameActionResult::Ptr tile_inspector_path_set_broken(CoordsXY loc, int32_t elementIndex, bool broken, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const pathElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const pathElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
pathElement->AsPath()->SetIsBroken(broken);
|
pathElement->AsPath()->SetIsBroken(broken);
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags)
|
GameActionResult::Ptr tile_inspector_path_toggle_edge(CoordsXY loc, int32_t elementIndex, int32_t edgeIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const pathElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const pathElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
uint8_t newEdges = pathElement->AsPath()->GetEdgesAndCorners() ^ (1 << edgeIndex);
|
uint8_t newEdges = pathElement->AsPath()->GetEdgesAndCorners() ^ (1 << edgeIndex);
|
||||||
pathElement->AsPath()->SetEdgesAndCorners(newEdges);
|
pathElement->AsPath()->SetEdgesAndCorners(newEdges);
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elementIndex, int32_t flags)
|
GameActionResult::Ptr tile_inspector_entrance_make_usable(CoordsXY loc, int32_t elementIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const entranceElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const entranceElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (entranceElement == nullptr || entranceElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
|
if (entranceElement == nullptr || entranceElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
Ride* ride = get_ride(entranceElement->AsEntrance()->GetRideIndex());
|
Ride* ride = get_ride(entranceElement->AsEntrance()->GetRideIndex());
|
||||||
|
|
||||||
if (ride == nullptr)
|
if (ride == nullptr)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
uint8_t stationIndex = entranceElement->AsEntrance()->GetStationIndex();
|
uint8_t stationIndex = entranceElement->AsEntrance()->GetStationIndex();
|
||||||
|
|
||||||
|
@ -694,67 +699,70 @@ int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elemen
|
||||||
{
|
{
|
||||||
case ENTRANCE_TYPE_RIDE_ENTRANCE:
|
case ENTRANCE_TYPE_RIDE_ENTRANCE:
|
||||||
ride_set_entrance_location(
|
ride_set_entrance_location(
|
||||||
ride, stationIndex, { x, y, entranceElement->base_height, (uint8_t)entranceElement->GetDirection() });
|
ride, stationIndex,
|
||||||
|
{ loc.x / 32, loc.y / 32, entranceElement->base_height, (uint8_t)entranceElement->GetDirection() });
|
||||||
break;
|
break;
|
||||||
case ENTRANCE_TYPE_RIDE_EXIT:
|
case ENTRANCE_TYPE_RIDE_EXIT:
|
||||||
ride_set_exit_location(
|
ride_set_exit_location(
|
||||||
ride, stationIndex, { x, y, entranceElement->base_height, (uint8_t)entranceElement->GetDirection() });
|
ride, stationIndex,
|
||||||
|
{ loc.x / 32, loc.y / 32, entranceElement->base_height, (uint8_t)entranceElement->GetDirection() });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex, int32_t slopeValue, int32_t flags)
|
GameActionResult::Ptr tile_inspector_wall_set_slope(CoordsXY loc, int32_t elementIndex, int32_t slopeValue, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const wallElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const wallElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (wallElement == nullptr || wallElement->GetType() != TILE_ELEMENT_TYPE_WALL)
|
if (wallElement == nullptr || wallElement->GetType() != TILE_ELEMENT_TYPE_WALL)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
// Set new slope value
|
// Set new slope value
|
||||||
wallElement->AsWall()->SetSlope(slopeValue);
|
wallElement->AsWall()->SetSlope(slopeValue);
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes the height of all track elements that belong to the same track piece
|
// Changes the height of all track elements that belong to the same track piece
|
||||||
// Broxzier: Copied from track_remove and stripped of unneeded code, but I think this should be smaller
|
// Broxzier: Copied from track_remove and stripped of unneeded code, but I think this should be smaller
|
||||||
int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t elementIndex, int8_t offset, int32_t flags)
|
GameActionResult::Ptr tile_inspector_track_base_height_offset(
|
||||||
|
CoordsXY loc, int32_t elementIndex, int8_t offset, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const trackElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const trackElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (offset == 0)
|
if (offset == 0)
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
|
|
||||||
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
uint8_t type = trackElement->AsTrack()->GetTrackType();
|
uint8_t type = trackElement->AsTrack()->GetTrackType();
|
||||||
int16_t originX = x << 5;
|
int16_t originX = loc.x;
|
||||||
int16_t originY = y << 5;
|
int16_t originY = loc.y;
|
||||||
int16_t originZ = trackElement->base_height * 8;
|
int16_t originZ = trackElement->base_height * 8;
|
||||||
uint8_t rotation = trackElement->GetDirection();
|
uint8_t rotation = trackElement->GetDirection();
|
||||||
ride_id_t rideIndex = trackElement->AsTrack()->GetRideIndex();
|
ride_id_t rideIndex = trackElement->AsTrack()->GetRideIndex();
|
||||||
|
@ -809,7 +817,7 @@ int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t el
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
log_error("Track map element part not found!");
|
log_error("Track map element part not found!");
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when
|
// track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when
|
||||||
|
@ -827,20 +835,20 @@ int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t el
|
||||||
// TODO: Only invalidate when one of the affected tiles is selected
|
// TODO: Only invalidate when one of the affected tiles is selected
|
||||||
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets chainlift, optionally for an entire track block
|
// Sets chainlift, optionally for an entire track block
|
||||||
// Broxzier: Basically a copy of the above function, with just two different lines... should probably be combined somehow
|
// Broxzier: Basically a copy of the above function, with just two different lines... should probably be combined somehow
|
||||||
int32_t tile_inspector_track_set_chain(
|
GameActionResult::Ptr tile_inspector_track_set_chain(
|
||||||
int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, int32_t flags)
|
CoordsXY loc, int32_t elementIndex, bool entireTrackBlock, bool setChain, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const trackElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const trackElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
if (!entireTrackBlock)
|
if (!entireTrackBlock)
|
||||||
{
|
{
|
||||||
|
@ -850,12 +858,12 @@ int32_t tile_inspector_track_set_chain(
|
||||||
trackElement->AsTrack()->SetHasChain(setChain);
|
trackElement->AsTrack()->SetHasChain(setChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t type = trackElement->AsTrack()->GetTrackType();
|
uint8_t type = trackElement->AsTrack()->GetTrackType();
|
||||||
int16_t originX = x << 5;
|
int16_t originX = loc.x;
|
||||||
int16_t originY = y << 5;
|
int16_t originY = loc.y;
|
||||||
int16_t originZ = trackElement->base_height * 8;
|
int16_t originZ = trackElement->base_height * 8;
|
||||||
uint8_t rotation = trackElement->GetDirection();
|
uint8_t rotation = trackElement->GetDirection();
|
||||||
ride_id_t rideIndex = trackElement->AsTrack()->GetRideIndex();
|
ride_id_t rideIndex = trackElement->AsTrack()->GetRideIndex();
|
||||||
|
@ -910,7 +918,7 @@ int32_t tile_inspector_track_set_chain(
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
log_error("Track map element part not found!");
|
log_error("Track map element part not found!");
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when
|
// track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when
|
||||||
|
@ -930,67 +938,68 @@ int32_t tile_inspector_track_set_chain(
|
||||||
// TODO: Only invalidate when one of the affected tiles is selected
|
// TODO: Only invalidate when one of the affected tiles is selected
|
||||||
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_track_set_block_brake(int32_t x, int32_t y, int32_t elementIndex, bool blockBrake, int32_t flags)
|
GameActionResult::Ptr tile_inspector_track_set_block_brake(
|
||||||
|
CoordsXY loc, int32_t elementIndex, bool blockBrake, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const trackElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const trackElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
trackElement->AsTrack()->SetBlockBrakeClosed(blockBrake);
|
trackElement->AsTrack()->SetBlockBrakeClosed(blockBrake);
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_track_set_indestructible(
|
GameActionResult::Ptr tile_inspector_track_set_indestructible(
|
||||||
int32_t x, int32_t y, int32_t elementIndex, bool isIndestructible, int32_t flags)
|
CoordsXY loc, int32_t elementIndex, bool isIndestructible, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const trackElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const trackElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
trackElement->AsTrack()->SetIsIndestructible(isIndestructible);
|
trackElement->AsTrack()->SetIsIndestructible(isIndestructible);
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
|
|
||||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
if (tileInspectorWindow != nullptr && (uint32_t)(loc.x / 32) == windowTileInspectorTileX
|
||||||
&& (uint32_t)y == windowTileInspectorTileY)
|
&& (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate(tileInspectorWindow);
|
window_invalidate(tileInspectorWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_scenery_set_quarter_location(
|
GameActionResult::Ptr tile_inspector_scenery_set_quarter_location(
|
||||||
int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags)
|
CoordsXY loc, int32_t elementIndex, int32_t quarterIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const tileElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
// Set quadrant index
|
// Set quadrant index
|
||||||
tileElement->AsSmallScenery()->SetSceneryQuadrant(quarterIndex);
|
tileElement->AsSmallScenery()->SetSceneryQuadrant(quarterIndex);
|
||||||
|
@ -999,80 +1008,81 @@ int32_t tile_inspector_scenery_set_quarter_location(
|
||||||
tileElement->flags &= 0xF0;
|
tileElement->flags &= 0xF0;
|
||||||
tileElement->flags |= 1 << ((quarterIndex + 2) & 3);
|
tileElement->flags |= 1 << ((quarterIndex + 2) & 3);
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
if ((uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
if ((uint32_t)(loc.x / 32) == windowTileInspectorTileX && (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_scenery_set_quarter_collision(
|
GameActionResult::Ptr tile_inspector_scenery_set_quarter_collision(
|
||||||
int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags)
|
CoordsXY loc, int32_t elementIndex, int32_t quarterIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const tileElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
tileElement->flags ^= 1 << quarterIndex;
|
tileElement->flags ^= 1 << quarterIndex;
|
||||||
|
|
||||||
map_invalidate_tile_full(x << 5, y << 5);
|
map_invalidate_tile_full(loc.x, loc.y);
|
||||||
if ((uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
if ((uint32_t)(loc.x / 32) == windowTileInspectorTileX && (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_banner_toggle_blocking_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags)
|
GameActionResult::Ptr tile_inspector_banner_toggle_blocking_edge(
|
||||||
|
CoordsXY loc, int32_t elementIndex, int32_t edgeIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const bannerElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const bannerElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (bannerElement == nullptr || bannerElement->GetType() != TILE_ELEMENT_TYPE_BANNER)
|
if (bannerElement == nullptr || bannerElement->GetType() != TILE_ELEMENT_TYPE_BANNER)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
uint8_t edges = bannerElement->AsBanner()->GetAllowedEdges();
|
uint8_t edges = bannerElement->AsBanner()->GetAllowedEdges();
|
||||||
edges ^= (1 << edgeIndex);
|
edges ^= (1 << edgeIndex);
|
||||||
bannerElement->AsBanner()->SetAllowedEdges(edges);
|
bannerElement->AsBanner()->SetAllowedEdges(edges);
|
||||||
|
|
||||||
if ((uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
if ((uint32_t)(loc.x / 32) == windowTileInspectorTileX && (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, int32_t flags)
|
GameActionResult::Ptr tile_inspector_corrupt_clamp(CoordsXY loc, int32_t elementIndex, bool isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const corruptElement = map_get_nth_element_at(x, y, elementIndex);
|
TileElement* const corruptElement = map_get_nth_element_at(loc.x / 32, loc.y / 32, elementIndex);
|
||||||
|
|
||||||
if (corruptElement == nullptr || corruptElement->GetType() != TILE_ELEMENT_TYPE_CORRUPT)
|
if (corruptElement == nullptr || corruptElement->GetType() != TILE_ELEMENT_TYPE_CORRUPT)
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (corruptElement->IsLastForTile())
|
if (corruptElement->IsLastForTile())
|
||||||
return MONEY32_UNDEFINED;
|
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
if (isExecuting)
|
||||||
{
|
{
|
||||||
TileElement* const nextElement = corruptElement + 1;
|
TileElement* const nextElement = corruptElement + 1;
|
||||||
corruptElement->base_height = corruptElement->clearance_height = nextElement->base_height;
|
corruptElement->base_height = corruptElement->clearance_height = nextElement->base_height;
|
||||||
|
|
||||||
if ((uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
if ((uint32_t)(loc.x / 32) == windowTileInspectorTileX && (uint32_t)(loc.y / 32) == windowTileInspectorTileY)
|
||||||
{
|
{
|
||||||
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
window_invalidate_by_class(WC_TILE_INSPECTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return std::make_unique<GameActionResult>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,58 +26,35 @@ enum TILE_INSPECTOR_ELEMENT_TYPE
|
||||||
TILE_INSPECTOR_ELEMENT_CORRUPT,
|
TILE_INSPECTOR_ELEMENT_CORRUPT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TILE_INSPECTOR_INSTRUCTION_TYPE
|
class GameActionResult;
|
||||||
{
|
using GameActionResultPtr = std::unique_ptr<GameActionResult>;
|
||||||
TILE_INSPECTOR_ANY_REMOVE,
|
GameActionResultPtr tile_inspector_insert_corrupt_at(CoordsXY loc, int16_t elementIndex, bool isExecuting);
|
||||||
TILE_INSPECTOR_ANY_SWAP,
|
GameActionResultPtr tile_inspector_remove_element_at(CoordsXY loc, int16_t elementIndex, bool isExecuting);
|
||||||
TILE_INSPECTOR_ANY_INSERT_CORRUPT,
|
GameActionResultPtr tile_inspector_swap_elements_at(CoordsXY loc, int16_t first, int16_t second, bool isExecuting);
|
||||||
TILE_INSPECTOR_ANY_ROTATE,
|
GameActionResultPtr tile_inspector_rotate_element_at(CoordsXY loc, int32_t elementIndex, bool isExecuting);
|
||||||
TILE_INSPECTOR_ANY_PASTE,
|
GameActionResultPtr tile_inspector_paste_element_at(CoordsXY loc, TileElement element, bool isExecuting);
|
||||||
TILE_INSPECTOR_ANY_SORT,
|
GameActionResultPtr tile_inspector_sort_elements_at(CoordsXY loc, bool isExecuting);
|
||||||
TILE_INSPECTOR_ANY_BASE_HEIGHT_OFFSET,
|
GameActionResultPtr tile_inspector_any_base_height_offset(
|
||||||
TILE_INSPECTOR_SURFACE_SHOW_PARK_FENCES,
|
CoordsXY loc, int16_t elementIndex, int8_t heightOffset, bool isExecuting);
|
||||||
TILE_INSPECTOR_SURFACE_TOGGLE_CORNER,
|
GameActionResultPtr tile_inspector_surface_show_park_fences(CoordsXY loc, bool enabled, bool isExecuting);
|
||||||
TILE_INSPECTOR_SURFACE_TOGGLE_DIAGONAL,
|
GameActionResultPtr tile_inspector_surface_toggle_corner(CoordsXY loc, int32_t cornerIndex, bool isExecuting);
|
||||||
TILE_INSPECTOR_PATH_SET_SLOPE,
|
GameActionResultPtr tile_inspector_surface_toggle_diagonal(CoordsXY loc, bool isExecuting);
|
||||||
TILE_INSPECTOR_PATH_SET_BROKEN,
|
GameActionResultPtr tile_inspector_path_set_sloped(CoordsXY loc, int32_t elementIndex, bool sloped, bool isExecuting);
|
||||||
TILE_INSPECTOR_PATH_TOGGLE_EDGE,
|
GameActionResultPtr tile_inspector_path_set_broken(CoordsXY loc, int32_t elementIndex, bool broken, bool isExecuting);
|
||||||
TILE_INSPECTOR_ENTRANCE_MAKE_USABLE,
|
GameActionResultPtr tile_inspector_path_toggle_edge(CoordsXY loc, int32_t elementIndex, int32_t cornerIndex, bool isExecuting);
|
||||||
TILE_INSPECTOR_WALL_SET_SLOPE,
|
GameActionResultPtr tile_inspector_entrance_make_usable(CoordsXY loc, int32_t elementIndex, bool isExecuting);
|
||||||
TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET,
|
GameActionResultPtr tile_inspector_wall_set_slope(CoordsXY loc, int32_t elementIndex, int32_t slopeValue, bool isExecuting);
|
||||||
TILE_INSPECTOR_TRACK_SET_CHAIN,
|
GameActionResultPtr tile_inspector_track_base_height_offset(
|
||||||
TILE_INSPECTOR_SCENERY_SET_QUARTER_LOCATION,
|
CoordsXY loc, int32_t elementIndex, int8_t offset, bool isExecuting);
|
||||||
TILE_INSPECTOR_SCENERY_SET_QUARTER_COLLISION,
|
GameActionResultPtr tile_inspector_track_set_block_brake(CoordsXY loc, int32_t elementIndex, bool blockBrake, bool isExecuting);
|
||||||
TILE_INSPECTOR_BANNER_TOGGLE_BLOCKING_EDGE,
|
GameActionResultPtr tile_inspector_track_set_indestructible(
|
||||||
TILE_INSPECTOR_CORRUPT_CLAMP,
|
CoordsXY loc, int32_t elementIndex, bool isIndestructible, bool isExecuting);
|
||||||
TILE_INSPECTOR_TRACK_SET_BLOCK_BRAKE,
|
GameActionResultPtr tile_inspector_track_set_chain(
|
||||||
TILE_INSPECTOR_TRACK_SET_INDESTRUCTIBLE,
|
CoordsXY loc, int32_t elementIndex, bool entireTrackBlock, bool setChain, bool isExecuting);
|
||||||
};
|
GameActionResultPtr tile_inspector_scenery_set_quarter_location(
|
||||||
|
CoordsXY loc, int32_t elementIndex, int32_t quarterIndex, bool isExecuting);
|
||||||
int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIndex, int32_t flags);
|
GameActionResultPtr tile_inspector_scenery_set_quarter_collision(
|
||||||
int32_t tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIndex, int32_t flags);
|
CoordsXY loc, int32_t elementIndex, int32_t quarterIndex, bool isExecuting);
|
||||||
int32_t tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t second, int32_t flags);
|
GameActionResultPtr tile_inspector_banner_toggle_blocking_edge(
|
||||||
int32_t tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIndex, int32_t flags);
|
CoordsXY loc, int32_t elementIndex, int32_t edgeIndex, bool isExecuting);
|
||||||
int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement element, int32_t flags);
|
GameActionResultPtr tile_inspector_corrupt_clamp(CoordsXY loc, int32_t elementIndex, bool isExecuting);
|
||||||
int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags);
|
|
||||||
int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elementIndex, int8_t heightOffset, int32_t flags);
|
|
||||||
int32_t tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool enabled, int32_t flags);
|
|
||||||
int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t cornerIndex, int32_t flags);
|
|
||||||
int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t flags);
|
|
||||||
int32_t tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementIndex, bool sloped, int32_t flags);
|
|
||||||
int32_t tile_inspector_path_set_broken(int32_t x, int32_t y, int32_t elementIndex, bool broken, int32_t flags);
|
|
||||||
int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t cornerIndex, int32_t flags);
|
|
||||||
int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elementIndex, int32_t flags);
|
|
||||||
int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex, int32_t slopeValue, int32_t flags);
|
|
||||||
int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t elementIndex, int8_t offset, int32_t flags);
|
|
||||||
int32_t tile_inspector_track_set_block_brake(int32_t x, int32_t y, int32_t elementIndex, bool blockBrake, int32_t flags);
|
|
||||||
int32_t tile_inspector_track_set_indestructible(
|
|
||||||
int32_t x, int32_t y, int32_t elementIndex, bool isIndestructible, int32_t flags);
|
|
||||||
int32_t tile_inspector_track_set_chain(
|
|
||||||
int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, int32_t flags);
|
|
||||||
int32_t tile_inspector_scenery_set_quarter_location(
|
|
||||||
int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags);
|
|
||||||
int32_t tile_inspector_scenery_set_quarter_collision(
|
|
||||||
int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags);
|
|
||||||
int32_t tile_inspector_banner_toggle_blocking_edge(
|
|
||||||
int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags);
|
|
||||||
int32_t tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, int32_t flags);
|
|
||||||
|
|
Loading…
Reference in New Issue