Remove game command

This commit is contained in:
duncanspumpkin 2019-03-16 22:16:56 +00:00
parent 81307f71df
commit 227786e05b
4 changed files with 11 additions and 577 deletions

View File

@ -1268,7 +1268,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = {
game_command_set_staff_name,
nullptr,
nullptr,
game_command_smooth_land,
nullptr,
nullptr,
nullptr,
nullptr,

View File

@ -44,16 +44,16 @@ enum GAME_COMMAND
GAME_COMMAND_SET_STAFF_NAME, // GA
GAME_COMMAND_RAISE_LAND, // GA
GAME_COMMAND_LOWER_LAND, // GA
GAME_COMMAND_EDIT_LAND_SMOOTH,
GAME_COMMAND_RAISE_WATER, // GA
GAME_COMMAND_LOWER_WATER, // GA
GAME_COMMAND_SET_BRAKES_SPEED, // GA
GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, // GA
GAME_COMMAND_SET_STAFF_PATROL, // GA
GAME_COMMAND_FIRE_STAFF_MEMBER, // GA
GAME_COMMAND_SET_STAFF_ORDERS, // GA
GAME_COMMAND_SET_PARK_NAME, // GA
GAME_COMMAND_SET_PARK_OPEN, // GA
GAME_COMMAND_EDIT_LAND_SMOOTH, // GA
GAME_COMMAND_RAISE_WATER, // GA
GAME_COMMAND_LOWER_WATER, // GA
GAME_COMMAND_SET_BRAKES_SPEED, // GA
GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, // GA
GAME_COMMAND_SET_STAFF_PATROL, // GA
GAME_COMMAND_FIRE_STAFF_MEMBER, // GA
GAME_COMMAND_SET_STAFF_ORDERS, // GA
GAME_COMMAND_SET_PARK_NAME, // GA
GAME_COMMAND_SET_PARK_OPEN, // GA
GAME_COMMAND_BUY_LAND_RIGHTS,
GAME_COMMAND_PLACE_PARK_ENTRANCE, // GA
GAME_COMMAND_REMOVE_PARK_ENTRANCE, // GA

View File

@ -1080,571 +1080,6 @@ uint8_t map_get_highest_land_height(int32_t xMin, int32_t xMax, int32_t yMin, in
return max_height;
}
static money32 smooth_land_tile(
int32_t direction, uint8_t flags, int32_t x, int32_t y, TileElement* tileElement, bool raiseLand)
{
int32_t targetBaseZ = tileElement->base_height;
int32_t slope = tileElement->AsSurface()->GetSlope();
if (raiseLand)
{
slope = tile_element_raise_styles[direction][slope];
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
{
targetBaseZ += 2;
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
}
}
else
{
slope = tile_element_lower_styles[direction][slope];
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
{
targetBaseZ -= 2;
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
}
}
auto landSetHeightAction = LandSetHeightAction({ x, y }, targetBaseZ, slope);
landSetHeightAction.SetFlags(flags);
auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? GameActions::ExecuteNested(&landSetHeightAction)
: GameActions::QueryNested(&landSetHeightAction);
if (res->Error == GA_ERROR::OK)
{
return res->Cost;
}
else
{
return MONEY32_UNDEFINED;
}
}
static money32 smooth_land_row_by_edge(
int32_t flags, int32_t x, int32_t y, int32_t expectedLandHeight1, int32_t expectedLandHeight2, int32_t stepX, int32_t stepY,
int32_t direction1, int32_t direction2, int32_t checkDirection1, int32_t checkDirection2, bool raiseLand)
{
uint8_t shouldContinue = 0xF;
int32_t landChangePerTile = raiseLand ? -2 : 2;
TileElement *tileElement, *nextTileElement;
money32 totalCost = 0;
// check if we need to start at all
if (!map_is_location_valid({ x, y }) || !map_is_location_valid({ x + stepX, y + stepY }))
{
return 0;
}
tileElement = map_get_surface_element_at({ x, y });
nextTileElement = map_get_surface_element_at({ x + stepX, y + stepY });
if (tileElement == nullptr || nextTileElement == nullptr)
{
return 0;
}
if (tile_element_get_corner_height(tileElement, checkDirection1) != expectedLandHeight1 + (raiseLand ? -2 : 2))
{
shouldContinue &= ~0x1;
}
if (tile_element_get_corner_height(tileElement, checkDirection2) != expectedLandHeight2 + (raiseLand ? -2 : 2))
{
shouldContinue &= ~0x2;
}
if (tile_element_get_corner_height(tileElement, checkDirection1)
!= tile_element_get_corner_height(nextTileElement, direction1))
{
shouldContinue &= ~0x1;
}
if (tile_element_get_corner_height(tileElement, checkDirection2)
!= tile_element_get_corner_height(nextTileElement, direction2))
{
shouldContinue &= ~0x2;
}
while ((shouldContinue & 0x3) != 0)
{
shouldContinue = ((shouldContinue << 2) | 0x3) & shouldContinue;
x += stepX;
y += stepY;
// check if we need to continue after raising the current tile
// this needs to be checked before the tile is changed
if (!map_is_location_valid({ x + stepX, y + stepY }))
{
shouldContinue &= ~0x3;
}
else
{
tileElement = nextTileElement;
nextTileElement = map_get_surface_element_at({ x + stepX, y + stepY });
if (nextTileElement == nullptr)
{
shouldContinue &= ~0x3;
}
if (tile_element_get_corner_height(tileElement, direction1) + landChangePerTile
!= tile_element_get_corner_height(tileElement, checkDirection1))
{
shouldContinue &= ~0x1;
}
if (tile_element_get_corner_height(tileElement, direction2) + landChangePerTile
!= tile_element_get_corner_height(tileElement, checkDirection2))
{
shouldContinue &= ~0x2;
}
if ((shouldContinue & 0x1)
&& tile_element_get_corner_height(tileElement, checkDirection1)
!= tile_element_get_corner_height(nextTileElement, direction1))
{
shouldContinue &= ~0x1;
}
if ((shouldContinue & 0x2)
&& tile_element_get_corner_height(tileElement, checkDirection2)
!= tile_element_get_corner_height(nextTileElement, direction2))
{
shouldContinue &= ~0x2;
}
}
expectedLandHeight1 += landChangePerTile;
// change land of current tile
int32_t targetBaseZ = tileElement->base_height;
int32_t slope = tileElement->AsSurface()->GetSlope();
int32_t oldSlope = slope;
if (raiseLand)
{
if (shouldContinue & 0x4)
{
slope = tile_element_raise_styles[direction1][slope];
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
{
targetBaseZ += 2;
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
}
}
if ((shouldContinue & 0x8)
&& map_get_corner_height(tileElement->base_height, oldSlope, direction2)
== map_get_corner_height(targetBaseZ, slope, direction2))
{
slope = tile_element_raise_styles[direction2][slope];
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
{
targetBaseZ += 2;
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
}
}
}
else
{
if (shouldContinue & 0x4)
{
slope = tile_element_lower_styles[direction1][slope];
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
{
targetBaseZ -= 2;
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
}
}
if ((shouldContinue & 0x8)
&& map_get_corner_height(tileElement->base_height, oldSlope, direction2)
== map_get_corner_height(targetBaseZ, slope, direction2))
{
slope = tile_element_lower_styles[direction2][slope];
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
{
targetBaseZ -= 2;
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
}
}
}
auto landSetHeightAction = LandSetHeightAction({ x, y }, targetBaseZ, slope);
landSetHeightAction.SetFlags(flags);
auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? GameActions::ExecuteNested(&landSetHeightAction)
: GameActions::QueryNested(&landSetHeightAction);
if (res->Error == GA_ERROR::OK)
{
totalCost += res->Cost;
}
}
return totalCost;
}
static money32 smooth_land_row_by_corner(
int32_t flags, int32_t x, int32_t y, int32_t expectedLandHeight, int32_t stepX, int32_t stepY, int32_t direction,
int32_t checkDirection, bool raiseLand)
{
bool shouldContinue = true;
TileElement *tileElement, *nextTileElement;
money32 totalCost = 0;
money32 result;
int32_t landChangePerTile;
if (stepX == 0 || stepY == 0)
{
landChangePerTile = raiseLand ? -2 : 2;
}
else
{
landChangePerTile = raiseLand ? -4 : 4;
}
// check if we need to start at all
if (!map_is_location_valid({ x, y }) || !map_is_location_valid({ x + stepX, y + stepY }))
{
return 0;
}
tileElement = map_get_surface_element_at({ x, y });
nextTileElement = map_get_surface_element_at((x + stepX) >> 5, (y + stepY) >> 5);
if (tileElement == nullptr || nextTileElement == nullptr)
{
return 0;
}
if (tile_element_get_corner_height(tileElement, checkDirection) != expectedLandHeight + (raiseLand ? -2 : 2))
{
return 0;
}
if (tile_element_get_corner_height(tileElement, checkDirection)
!= tile_element_get_corner_height(nextTileElement, direction))
{
return 0;
}
while (shouldContinue)
{
x += stepX;
y += stepY;
// check if we need to continue after raising the current tile
// this needs to be checked before the tile is changed
if (!map_is_location_valid({ x + stepX, y + stepY }))
{
shouldContinue = false;
}
else
{
tileElement = nextTileElement;
nextTileElement = map_get_surface_element_at((x + stepX) >> 5, (y + stepY) >> 5);
if (nextTileElement == nullptr)
{
shouldContinue = false;
}
if (tile_element_get_corner_height(tileElement, direction) + landChangePerTile
!= tile_element_get_corner_height(tileElement, checkDirection))
{
shouldContinue = false;
}
if (shouldContinue
&& tile_element_get_corner_height(tileElement, checkDirection)
!= tile_element_get_corner_height(nextTileElement, direction))
{
shouldContinue = false;
}
}
if (stepX * stepY != 0)
{
totalCost += smooth_land_row_by_corner(
flags, x, y, expectedLandHeight + (landChangePerTile / 2), 0, stepY, direction, checkDirection ^ 3, raiseLand);
totalCost += smooth_land_row_by_corner(
flags, x, y, expectedLandHeight + (landChangePerTile / 2), stepX, 0, direction, checkDirection ^ 1, raiseLand);
}
expectedLandHeight += landChangePerTile;
// change land of current tile
result = smooth_land_tile(direction, flags, x, y, tileElement, raiseLand);
if (result != MONEY32_UNDEFINED)
{
totalCost += result;
}
}
return totalCost;
}
static money32 smooth_land(
int32_t flags, int32_t centreX, int32_t centreY, int32_t mapLeft, int32_t mapTop, int32_t mapRight, int32_t mapBottom,
int32_t command)
{
// break up information in command
const bool raiseLand = command < 0x7FFF;
const int32_t selectionType = command & 0x7FFF;
const int32_t heightOffset = raiseLand ? 2 : -2;
// Cap bounds to map
mapLeft = std::max(mapLeft, 32);
mapTop = std::max(mapTop, 32);
mapRight = std::clamp(mapRight, 0, (MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32);
mapBottom = std::clamp(mapBottom, 0, (MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32);
// Play sound (only once)
int32_t centreZ = tile_element_height(centreX, centreY);
if ((flags & GAME_COMMAND_FLAG_APPLY) && gGameCommandNestLevel == 1)
{
audio_play_sound_at_location(SOUND_PLACE_ITEM, centreX, centreY, centreZ);
}
if (flags & GAME_COMMAND_FLAG_APPLY)
{
LocationXYZ16 coord;
coord.x = centreX + 16;
coord.y = centreY + 16;
coord.z = tile_element_height(coord.x, coord.y);
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
}
// Do the smoothing
money32 totalCost = 0;
switch (selectionType)
{
case MAP_SELECT_TYPE_FULL:
{
uint8_t minHeight = heightOffset + map_get_lowest_land_height(mapLeft, mapRight, mapTop, mapBottom);
uint8_t maxHeight = heightOffset + map_get_highest_land_height(mapLeft, mapRight, mapTop, mapBottom);
// Smooth the 4 corners
{ // top-left
TileElement* tileElement = map_get_surface_element_at({ mapLeft, mapTop });
int32_t z = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 2), minHeight, maxHeight);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, -32, 0, 2, raiseLand);
}
{ // bottom-left
TileElement* tileElement = map_get_surface_element_at(mapLeft >> 5, mapBottom >> 5);
int32_t z = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 3), minHeight, maxHeight);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapBottom, z, -32, 32, 1, 3, raiseLand);
}
{ // bottom-right
TileElement* tileElement = map_get_surface_element_at(mapRight >> 5, mapBottom >> 5);
int32_t z = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 0), minHeight, maxHeight);
totalCost += smooth_land_row_by_corner(flags, mapRight, mapBottom, z, 32, 32, 2, 0, raiseLand);
}
{ // top-right
TileElement* tileElement = map_get_surface_element_at(mapRight >> 5, mapTop >> 5);
int32_t z = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 1), minHeight, maxHeight);
totalCost += smooth_land_row_by_corner(flags, mapRight, mapTop, z, 32, -32, 3, 1, raiseLand);
}
// Smooth the edges
TileElement* tileElement = nullptr;
int32_t z1, z2;
for (int32_t y = mapTop; y <= mapBottom; y += 32)
{
tileElement = map_get_surface_element_at({ mapLeft, y });
z1 = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 3), minHeight, maxHeight);
z2 = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 2), minHeight, maxHeight);
totalCost += smooth_land_row_by_edge(flags, mapLeft, y, z1, z2, -32, 0, 0, 1, 3, 2, raiseLand);
tileElement = map_get_surface_element_at({ mapRight, y });
z1 = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 1), minHeight, maxHeight);
z2 = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 0), minHeight, maxHeight);
totalCost += smooth_land_row_by_edge(flags, mapRight, y, z1, z2, 32, 0, 2, 3, 1, 0, raiseLand);
}
for (int32_t x = mapLeft; x <= mapRight; x += 32)
{
tileElement = map_get_surface_element_at({ x, mapTop });
z1 = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 1), minHeight, maxHeight);
z2 = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 2), minHeight, maxHeight);
totalCost += smooth_land_row_by_edge(flags, x, mapTop, z1, z2, 0, -32, 0, 3, 1, 2, raiseLand);
tileElement = map_get_surface_element_at({ x, mapBottom });
z1 = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 0), minHeight, maxHeight);
z2 = std::clamp((uint8_t)tile_element_get_corner_height(tileElement, 3), minHeight, maxHeight);
totalCost += smooth_land_row_by_edge(flags, x, mapBottom, z1, z2, 0, 32, 1, 2, 0, 3, raiseLand);
}
break;
}
case MAP_SELECT_TYPE_CORNER_0:
case MAP_SELECT_TYPE_CORNER_1:
case MAP_SELECT_TYPE_CORNER_2:
case MAP_SELECT_TYPE_CORNER_3:
{
TileElement* tileElement = map_get_surface_element_at({ mapLeft, mapTop });
uint8_t newBaseZ = tileElement->base_height;
uint8_t newSlope = tileElement->AsSurface()->GetSlope();
if (raiseLand)
{
newSlope = tile_element_raise_styles[selectionType][newSlope];
}
else
{
newSlope = tile_element_lower_styles[selectionType][newSlope];
}
if (newSlope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
{
newBaseZ += heightOffset;
newSlope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
}
// Smooth the corners
int32_t z = map_get_corner_height(newBaseZ, newSlope, 2);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, -32, 0, 2, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 0);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 32, 2, 0, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 3);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 32, 1, 3, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 1);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, -32, 3, 1, raiseLand);
// Smooth the edges
switch (selectionType)
{
case MAP_SELECT_TYPE_CORNER_0:
z = map_get_corner_height(newBaseZ, newSlope, 0);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 0, 3, 0, raiseLand);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, 32, 1, 0, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 3);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 0, 0, 3, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 1);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, -32, 0, 1, raiseLand);
break;
case MAP_SELECT_TYPE_CORNER_1:
z = map_get_corner_height(newBaseZ, newSlope, 1);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 0, 2, 1, raiseLand);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, -32, 0, 1, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 2);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 0, 1, 2, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 0);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, 32, 1, 0, raiseLand);
break;
case MAP_SELECT_TYPE_CORNER_2:
z = map_get_corner_height(newBaseZ, newSlope, 2);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 0, 1, 2, raiseLand);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, -32, 3, 2, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 1);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 0, 2, 1, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 3);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, 32, 2, 3, raiseLand);
break;
case MAP_SELECT_TYPE_CORNER_3:
z = map_get_corner_height(newBaseZ, newSlope, 3);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 0, 0, 3, raiseLand);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, 32, 2, 3, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 0);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 0, 3, 0, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 2);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 0, -32, 3, 2, raiseLand);
break;
}
break;
}
case MAP_SELECT_TYPE_EDGE_0:
case MAP_SELECT_TYPE_EDGE_1:
case MAP_SELECT_TYPE_EDGE_2:
case MAP_SELECT_TYPE_EDGE_3:
{
// TODO: Handle smoothing by edge
// Get the two corners to raise
TileElement* surfaceElement = map_get_surface_element_at({ mapLeft, mapTop });
uint8_t newBaseZ = surfaceElement->base_height;
uint8_t oldSlope = surfaceElement->AsSurface()->GetSlope();
uint8_t newSlope = oldSlope;
int32_t rowIndex = selectionType - (MAP_SELECT_TYPE_EDGE_0 - MAP_SELECT_TYPE_FULL - 1);
if (raiseLand)
{
newSlope = tile_element_raise_styles[rowIndex][oldSlope];
}
else
{
newSlope = tile_element_lower_styles[rowIndex][oldSlope];
}
const bool changeBaseHeight = newSlope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
if (changeBaseHeight)
{
newBaseZ += heightOffset;
newSlope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
}
const uint8_t edge = selectionType - MAP_SELECT_TYPE_EDGE_0;
// Table with corners for each edge selection. The first two are the selected corners, the latter two are the
// opposites
static constexpr uint8_t cornerIndices[][4] = {
{ 2, 3, 1, 0 }, // MAP_SELECT_TYPE_EDGE_0
{ 3, 0, 2, 1 }, // MAP_SELECT_TYPE_EDGE_1
{ 0, 1, 3, 2 }, // MAP_SELECT_TYPE_EDGE_2
{ 1, 2, 0, 3 }, // MAP_SELECT_TYPE_EDGE_3
};
// Big coordinate offsets for the neigbouring tile for the given edge selection
static constexpr sLocationXY8 stepOffsets[] = {
{ -32, 0 },
{ 0, 32 },
{ 32, 0 },
{ 0, -32 },
};
// Smooth higher and lower edges
uint8_t c1 = cornerIndices[edge][0];
uint8_t c2 = cornerIndices[edge][1];
uint8_t c3 = cornerIndices[edge][2];
uint8_t c4 = cornerIndices[edge][3];
uint8_t z1 = map_get_corner_height(newBaseZ, newSlope, c1);
uint8_t z2 = map_get_corner_height(newBaseZ, newSlope, c2);
uint8_t z3 = map_get_corner_height(newBaseZ, newSlope, c3);
uint8_t z4 = map_get_corner_height(newBaseZ, newSlope, c4);
// Smooth the edge at the top of the new slope
totalCost += smooth_land_row_by_edge(
flags, mapLeft, mapTop, z1, z2, stepOffsets[edge].x, stepOffsets[edge].y, c3, c4, c1, c2, raiseLand);
// Smooth the edge at the bottom of the new slope
totalCost += smooth_land_row_by_edge(
flags, mapLeft, mapTop, z3, z4, -stepOffsets[edge].x, -stepOffsets[edge].y, c1, c2, c3, c4, raiseLand);
// Smooth corners
totalCost += smooth_land_row_by_corner(
flags, mapLeft, mapTop, z1, -stepOffsets[edge].y, stepOffsets[edge].x, c2, c1, raiseLand);
totalCost += smooth_land_row_by_corner(
flags, mapLeft, mapTop, z2, stepOffsets[edge].y, -stepOffsets[edge].x, c1, c2, raiseLand);
int32_t z = map_get_corner_height(newBaseZ, newSlope, 2);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, -32, 0, 2, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 0);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, 32, 2, 0, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 3);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, 32, 1, 3, raiseLand);
z = map_get_corner_height(newBaseZ, newSlope, 1);
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, -32, 3, 1, raiseLand);
break;
}
} // switch selectionType
// Raise / lower the land tool selection area
GameActionResult::Ptr res;
if (raiseLand)
{
auto raiseLandAction = LandRaiseAction({ centreX, centreY }, { mapLeft, mapTop, mapRight, mapBottom }, selectionType);
raiseLandAction.SetFlags(flags);
res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&raiseLandAction)
: GameActions::QueryNested(&raiseLandAction);
}
else
{
auto lowerLandAction = LandLowerAction({ centreX, centreY }, { mapLeft, mapTop, mapRight, mapBottom }, selectionType);
lowerLandAction.SetFlags(flags);
res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&lowerLandAction)
: GameActions::QueryNested(&lowerLandAction);
}
if (res->Error != GA_ERROR::OK)
{
return MONEY32_UNDEFINED;
}
totalCost += res->Cost;
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
gCommandPosition.x = centreX;
gCommandPosition.y = centreY;
gCommandPosition.z = centreZ;
return totalCost;
}
/**
*
* rct2: 0x0068BC01
*/
void game_command_smooth_land(
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, int32_t* ebp)
{
int32_t flags = *ebx & 0xFF;
int32_t centreX = *eax & 0xFFFF;
int32_t centreY = *ecx & 0xFFFF;
int32_t mapLeft = (int16_t)(*edx & 0xFFFF);
int32_t mapTop = (int16_t)(*ebp & 0xFFFF);
int32_t mapRight = (int16_t)(*edx >> 16);
int32_t mapBottom = (int16_t)(*ebp >> 16);
int32_t command = *edi;
*ebx = smooth_land(flags, centreX, centreY, mapLeft, mapTop, mapRight, mapBottom, command);
}
bool map_is_location_at_edge(int32_t x, int32_t y)
{
return x < 32 || y < 32 || x >= ((MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32) || y >= ((MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32);

View File

@ -202,7 +202,6 @@ void game_command_set_large_scenery_colour(
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
void game_command_set_banner_colour(
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
void game_command_smooth_land(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
void game_command_place_banner(
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
void game_command_place_wall(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);