mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
Land Line Tools (select land edges/row of tiles)
(This commit is multiple commits squashed together, to make rebasing and merging easier. Many of the commits undid or slightly altered previous changes.) This Extends the land-tool by allowing the player to select an edge of a surface tile, and to select a row of tiles. Both work by holding down the Ctrl key (same key for keeping the same base-height for other tools). When using a single-sized tool, the selection will become the edge, and when using a selection area of 2x2 or higher, the selection becomes a row of tiles. The tables `tile_element_raise_styles` and `tile_element_lower_styles` hold the data for how slopes should change when a tile gets raised or lowered with the land tool. Each row represents a selection, and each column the slope type. Co-authored-by: Adam T <32143337+Despotico@users.noreply.github.com>
This commit is contained in:
@@ -1857,15 +1857,18 @@ static void top_toolbar_tool_update_scenery_clear(sint16 x, sint16 y){
|
||||
}
|
||||
}
|
||||
|
||||
static void top_toolbar_tool_update_land_paint(sint16 x, sint16 y){
|
||||
static void top_toolbar_tool_update_land_paint(sint16 x, sint16 y)
|
||||
{
|
||||
map_invalidate_selection_rect();
|
||||
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
|
||||
|
||||
LocationXY16 mapTile = { 0 };
|
||||
screen_get_map_xy(x, y, &mapTile.x, &mapTile.y, nullptr);
|
||||
|
||||
if (mapTile.x == LOCATION_NULL) {
|
||||
if (gClearSceneryCost != MONEY32_UNDEFINED) {
|
||||
if (mapTile.x == LOCATION_NULL)
|
||||
{
|
||||
if (gClearSceneryCost != MONEY32_UNDEFINED)
|
||||
{
|
||||
gClearSceneryCost = MONEY32_UNDEFINED;
|
||||
window_invalidate_by_class(WC_CLEAR_SCENERY);
|
||||
}
|
||||
@@ -1874,12 +1877,14 @@ static void top_toolbar_tool_update_land_paint(sint16 x, sint16 y){
|
||||
|
||||
uint8 state_changed = 0;
|
||||
|
||||
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)) {
|
||||
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
|
||||
{
|
||||
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectType != MAP_SELECT_TYPE_FULL) {
|
||||
if (gMapSelectType != MAP_SELECT_TYPE_FULL)
|
||||
{
|
||||
gMapSelectType = MAP_SELECT_TYPE_FULL;
|
||||
state_changed++;
|
||||
}
|
||||
@@ -1893,12 +1898,14 @@ static void top_toolbar_tool_update_land_paint(sint16 x, sint16 y){
|
||||
mapTile.x &= 0xFFE0;
|
||||
mapTile.y &= 0xFFE0;
|
||||
|
||||
if (gMapSelectPositionA.x != mapTile.x){
|
||||
if (gMapSelectPositionA.x != mapTile.x)
|
||||
{
|
||||
gMapSelectPositionA.x = mapTile.x;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectPositionA.y != mapTile.y){
|
||||
if (gMapSelectPositionA.y != mapTile.y)
|
||||
{
|
||||
gMapSelectPositionA.y = mapTile.y;
|
||||
state_changed++;
|
||||
}
|
||||
@@ -1906,12 +1913,14 @@ static void top_toolbar_tool_update_land_paint(sint16 x, sint16 y){
|
||||
mapTile.x += tool_length;
|
||||
mapTile.y += tool_length;
|
||||
|
||||
if (gMapSelectPositionB.x != mapTile.x){
|
||||
if (gMapSelectPositionB.x != mapTile.x)
|
||||
{
|
||||
gMapSelectPositionB.x = mapTile.x;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectPositionB.y != mapTile.y){
|
||||
if (gMapSelectPositionB.y != mapTile.y)
|
||||
{
|
||||
gMapSelectPositionB.y = mapTile.y;
|
||||
state_changed++;
|
||||
}
|
||||
@@ -1925,18 +1934,22 @@ static void top_toolbar_tool_update_land_paint(sint16 x, sint16 y){
|
||||
*
|
||||
* rct2: 0x00664280
|
||||
*/
|
||||
static void top_toolbar_tool_update_land(sint16 x, sint16 y){
|
||||
static void top_toolbar_tool_update_land(sint16 x, sint16 y)
|
||||
{
|
||||
const bool mapCtrlPressed = input_test_place_object_modifier(PLACE_OBJECT_MODIFIER_COPY_Z);
|
||||
|
||||
map_invalidate_selection_rect();
|
||||
|
||||
if (gCurrentToolId == TOOL_UP_DOWN_ARROW){
|
||||
if (gCurrentToolId == TOOL_UP_DOWN_ARROW)
|
||||
{
|
||||
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
|
||||
return;
|
||||
|
||||
money32 lower_cost = selection_lower_land(0);
|
||||
money32 raise_cost = selection_raise_land(0);
|
||||
|
||||
if (gLandToolRaiseCost != raise_cost ||
|
||||
gLandToolLowerCost != lower_cost){
|
||||
if (gLandToolRaiseCost != raise_cost || gLandToolLowerCost != lower_cost)
|
||||
{
|
||||
gLandToolRaiseCost = raise_cost;
|
||||
gLandToolLowerCost = lower_cost;
|
||||
window_invalidate_by_class(WC_LAND);
|
||||
@@ -1944,20 +1957,26 @@ static void top_toolbar_tool_update_land(sint16 x, sint16 y){
|
||||
return;
|
||||
}
|
||||
|
||||
sint16 tool_size = gLandToolSize;
|
||||
LocationXY16 mapTile = { x, y };
|
||||
sint16 tool_size = gLandToolSize;
|
||||
LocationXY16 mapTile;
|
||||
uint8 side;
|
||||
|
||||
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
|
||||
if (tool_size == 1){
|
||||
sint32 direction;
|
||||
screen_pos_to_map_pos(&mapTile.x, &mapTile.y, &direction);
|
||||
if (tool_size == 1)
|
||||
{
|
||||
sint32 selectionType;
|
||||
// Get selection type and map coordinates from mouse x,y position
|
||||
mapTile = { x, y };
|
||||
screen_pos_to_map_pos(&mapTile.x, &mapTile.y, &selectionType);
|
||||
screen_get_map_xy_side(x, y, &mapTile.x, &mapTile.y, &side);
|
||||
|
||||
if (mapTile.x == LOCATION_NULL) {
|
||||
if (mapTile.x == LOCATION_NULL)
|
||||
{
|
||||
money32 lower_cost = MONEY32_UNDEFINED;
|
||||
money32 raise_cost = MONEY32_UNDEFINED;
|
||||
|
||||
if (gLandToolRaiseCost != raise_cost ||
|
||||
gLandToolLowerCost != lower_cost){
|
||||
if (gLandToolRaiseCost != raise_cost || gLandToolLowerCost != lower_cost)
|
||||
{
|
||||
gLandToolRaiseCost = raise_cost;
|
||||
gLandToolLowerCost = lower_cost;
|
||||
window_invalidate_by_class(WC_LAND);
|
||||
@@ -1967,33 +1986,44 @@ static void top_toolbar_tool_update_land(sint16 x, sint16 y){
|
||||
|
||||
uint8 state_changed = 0;
|
||||
|
||||
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)) {
|
||||
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
|
||||
{
|
||||
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectType != direction) {
|
||||
gMapSelectType = direction;
|
||||
if (gMapSelectType != selectionType)
|
||||
{
|
||||
gMapSelectType = selectionType;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if ((gMapSelectType != MAP_SELECT_TYPE_EDGE_0 + (side & 0xFF)) && mapCtrlPressed)
|
||||
{
|
||||
gMapSelectType = MAP_SELECT_TYPE_EDGE_0 + (side & 0xFF);
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectPositionA.x != mapTile.x){
|
||||
if (gMapSelectPositionA.x != mapTile.x)
|
||||
{
|
||||
gMapSelectPositionA.x = mapTile.x;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectPositionA.y != mapTile.y){
|
||||
if (gMapSelectPositionA.y != mapTile.y)
|
||||
{
|
||||
gMapSelectPositionA.y = mapTile.y;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectPositionB.x != mapTile.x){
|
||||
if (gMapSelectPositionB.x != mapTile.x)
|
||||
{
|
||||
gMapSelectPositionB.x = mapTile.x;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectPositionB.y != mapTile.y){
|
||||
if (gMapSelectPositionB.y != mapTile.y)
|
||||
{
|
||||
gMapSelectPositionB.y = mapTile.y;
|
||||
state_changed++;
|
||||
}
|
||||
@@ -2014,7 +2044,8 @@ static void top_toolbar_tool_update_land(sint16 x, sint16 y){
|
||||
return;
|
||||
}
|
||||
|
||||
screen_get_map_xy(x, y, &mapTile.x, &mapTile.y, nullptr);
|
||||
// Get map coordinates and the side of the tile that is being hovered over
|
||||
screen_get_map_xy_side(x, y, &mapTile.x, &mapTile.y, &side);
|
||||
|
||||
if (mapTile.x == LOCATION_NULL) {
|
||||
money32 lower_cost = MONEY32_UNDEFINED;
|
||||
@@ -2041,30 +2072,74 @@ static void top_toolbar_tool_update_land(sint16 x, sint16 y){
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if ((gMapSelectType != MAP_SELECT_TYPE_EDGE_0 + (side & 0xFF)) && mapCtrlPressed)
|
||||
{
|
||||
gMapSelectType = MAP_SELECT_TYPE_EDGE_0 + (side & 0xFF);
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (tool_size == 0)
|
||||
tool_size = 1;
|
||||
|
||||
sint16 tool_length = (tool_size - 1) * 32;
|
||||
|
||||
// Move to tool bottom left
|
||||
mapTile.x -= (tool_size - 1) * 16;
|
||||
mapTile.y -= (tool_size - 1) * 16;
|
||||
mapTile.x &= 0xFFE0;
|
||||
mapTile.y &= 0xFFE0;
|
||||
// Decide on shape of the brush for bigger selection size
|
||||
switch (gMapSelectType)
|
||||
{
|
||||
case MAP_SELECT_TYPE_EDGE_0:
|
||||
case MAP_SELECT_TYPE_EDGE_2:
|
||||
// Line
|
||||
mapTile.y -= (tool_size - 1) * 16;
|
||||
mapTile.y &= 0xFFE0;
|
||||
break;
|
||||
case MAP_SELECT_TYPE_EDGE_1:
|
||||
case MAP_SELECT_TYPE_EDGE_3:
|
||||
// Line
|
||||
mapTile.x -= (tool_size - 1) * 16;
|
||||
mapTile.x &= 0xFFE0;
|
||||
break;
|
||||
default:
|
||||
// Move to tool bottom left
|
||||
mapTile.x -= (tool_size - 1) * 16;
|
||||
mapTile.y -= (tool_size - 1) * 16;
|
||||
mapTile.x &= 0xFFE0;
|
||||
mapTile.y &= 0xFFE0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gMapSelectPositionA.x != mapTile.x){
|
||||
if (gMapSelectPositionA.x != mapTile.x)
|
||||
{
|
||||
gMapSelectPositionA.x = mapTile.x;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
if (gMapSelectPositionA.y != mapTile.y){
|
||||
if (gMapSelectPositionA.y != mapTile.y)
|
||||
{
|
||||
gMapSelectPositionA.y = mapTile.y;
|
||||
state_changed++;
|
||||
}
|
||||
|
||||
mapTile.x += tool_length;
|
||||
mapTile.y += tool_length;
|
||||
// Go to other side
|
||||
switch (gMapSelectType)
|
||||
{
|
||||
case MAP_SELECT_TYPE_EDGE_0:
|
||||
case MAP_SELECT_TYPE_EDGE_2:
|
||||
// Line
|
||||
mapTile.y += tool_length;
|
||||
gMapSelectType = MAP_SELECT_TYPE_FULL;
|
||||
break;
|
||||
case MAP_SELECT_TYPE_EDGE_1:
|
||||
case MAP_SELECT_TYPE_EDGE_3:
|
||||
// Line
|
||||
mapTile.x += tool_length;
|
||||
gMapSelectType = MAP_SELECT_TYPE_FULL;
|
||||
break;
|
||||
default:
|
||||
mapTile.x += tool_length;
|
||||
mapTile.y += tool_length;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (gMapSelectPositionB.x != mapTile.x){
|
||||
gMapSelectPositionB.x = mapTile.x;
|
||||
@@ -2425,7 +2500,7 @@ static void top_toolbar_tool_update_scenery(sint16 x, sint16 y){
|
||||
money32 cost = 0;
|
||||
|
||||
switch (scenery_type){
|
||||
case 0:
|
||||
case SCENERY_TYPE_SMALL:
|
||||
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
||||
if (gWindowSceneryClusterEnabled) {
|
||||
gMapSelectPositionA.x = mapTile.x - (8 << 5);
|
||||
@@ -2487,7 +2562,7 @@ static void top_toolbar_tool_update_scenery(sint16 x, sint16 y){
|
||||
|
||||
gSceneryPlaceCost = cost;
|
||||
break;
|
||||
case 1:
|
||||
case SCENERY_TYPE_PATH_ITEM:
|
||||
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
||||
gMapSelectPositionA.x = mapTile.x;
|
||||
gMapSelectPositionA.y = mapTile.y;
|
||||
@@ -2516,7 +2591,7 @@ static void top_toolbar_tool_update_scenery(sint16 x, sint16 y){
|
||||
|
||||
gSceneryPlaceCost = cost;
|
||||
break;
|
||||
case 2:
|
||||
case SCENERY_TYPE_WALL:
|
||||
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
||||
gMapSelectPositionA.x = mapTile.x;
|
||||
gMapSelectPositionA.y = mapTile.y;
|
||||
@@ -2564,7 +2639,7 @@ static void top_toolbar_tool_update_scenery(sint16 x, sint16 y){
|
||||
|
||||
gSceneryPlaceCost = cost;
|
||||
break;
|
||||
case 3:
|
||||
case SCENERY_TYPE_LARGE:
|
||||
{
|
||||
scenery = get_large_scenery_entry(selected_scenery);
|
||||
LocationXY16* selectedTile = gMapSelectionTiles;
|
||||
@@ -2623,7 +2698,7 @@ static void top_toolbar_tool_update_scenery(sint16 x, sint16 y){
|
||||
gSceneryPlaceCost = cost;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case SCENERY_TYPE_BANNER:
|
||||
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
||||
gMapSelectPositionA.x = mapTile.x;
|
||||
gMapSelectPositionA.y = mapTile.y;
|
||||
@@ -2798,6 +2873,7 @@ static void window_top_toolbar_land_tool_drag(sint16 x, sint16 y)
|
||||
sint16 tile_height = -16 / (1 << viewport->zoom);
|
||||
|
||||
sint32 y_diff = y - gInputDragLastY;
|
||||
|
||||
if (y_diff <= tile_height) {
|
||||
gInputDragLastY += tile_height;
|
||||
|
||||
|
||||
@@ -1385,21 +1385,36 @@ void game_command_change_surface_style(
|
||||
}
|
||||
|
||||
//0x00981A1E
|
||||
static constexpr const uint8 tile_element_raise_styles[5][32] = {
|
||||
{ 0x01, 0x1B, 0x03, 0x1B, 0x05, 0x21, 0x07, 0x21, 0x09, 0x1B, 0x0B, 0x1B, 0x0D, 0x21, 0x20, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x23, 0x18, 0x19, 0x1A, 0x3B, 0x1C, 0x29, 0x24, 0x1F },
|
||||
{ 0x02, 0x03, 0x17, 0x17, 0x06, 0x07, 0x17, 0x17, 0x0A, 0x0B, 0x22, 0x22, 0x0E, 0x20, 0x22, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x37, 0x18, 0x19, 0x1A, 0x23, 0x1C, 0x28, 0x26, 0x1F },
|
||||
{ 0x04, 0x05, 0x06, 0x07, 0x1E, 0x24, 0x1E, 0x24, 0x0C, 0x0D, 0x0E, 0x20, 0x1E, 0x24, 0x1E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x26, 0x18, 0x19, 0x1A, 0x21, 0x1C, 0x2C, 0x3E, 0x1F },
|
||||
{ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x20, 0x1D, 0x1D, 0x28, 0x28, 0x1D, 0x1D, 0x28, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x22, 0x18, 0x19, 0x1A, 0x29, 0x1C, 0x3D, 0x2C, 0x1F },
|
||||
{ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x20, 0x20, 0x20, 0x21, 0x20, 0x28, 0x24, 0x20 },
|
||||
#define SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT 0x20
|
||||
// Table of pre-calculated surface slopes (32) when raising the land tile for a given selection (5)
|
||||
// 0x1F = new slope
|
||||
// 0x20 = base height increases
|
||||
static constexpr const uint8 tile_element_raise_styles[9][32] = {
|
||||
{ 0x01, 0x1B, 0x03, 0x1B, 0x05, 0x21, 0x07, 0x21, 0x09, 0x1B, 0x0B, 0x1B, 0x0D, 0x21, 0x20, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x23, 0x18, 0x19, 0x1A, 0x3B, 0x1C, 0x29, 0x24, 0x1F }, // MAP_SELECT_TYPE_CORNER_0 (absolute rotation)
|
||||
{ 0x02, 0x03, 0x17, 0x17, 0x06, 0x07, 0x17, 0x17, 0x0A, 0x0B, 0x22, 0x22, 0x0E, 0x20, 0x22, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x37, 0x18, 0x19, 0x1A, 0x23, 0x1C, 0x28, 0x26, 0x1F }, // MAP_SELECT_TYPE_CORNER_1
|
||||
{ 0x04, 0x05, 0x06, 0x07, 0x1E, 0x24, 0x1E, 0x24, 0x0C, 0x0D, 0x0E, 0x20, 0x1E, 0x24, 0x1E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x26, 0x18, 0x19, 0x1A, 0x21, 0x1C, 0x2C, 0x3E, 0x1F }, // MAP_SELECT_TYPE_CORNER_2
|
||||
{ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x20, 0x1D, 0x1D, 0x28, 0x28, 0x1D, 0x1D, 0x28, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x22, 0x18, 0x19, 0x1A, 0x29, 0x1C, 0x3D, 0x2C, 0x1F }, // MAP_SELECT_TYPE_CORNER_3
|
||||
{ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x20, 0x20, 0x20, 0x21, 0x20, 0x28, 0x24, 0x20 }, // MAP_SELECT_TYPE_FULL
|
||||
{ 0x0C, 0x0D, 0x0E, 0x20, 0x0C, 0x0D, 0x0E, 0x20, 0x0C, 0x0D, 0x0E, 0x20, 0x2C, 0x2C, 0x2C, 0x2C, 0x0C, 0x0D, 0x0E, 0x20, 0x0C, 0x0C, 0x0E, 0x22, 0x0C, 0x0D, 0x0E, 0x21, 0x2C, 0x2C, 0x2C, 0x2C }, // MAP_SELECT_TYPE_EDGE_0
|
||||
{ 0x09, 0x09, 0x0B, 0x0B, 0x0D, 0x0D, 0x20, 0x20, 0x09, 0x29, 0x0B, 0x29, 0x0D, 0x29, 0x20, 0x29, 0x09, 0x09, 0x0B, 0x0B, 0x0D, 0x0D, 0x24, 0x22, 0x09, 0x29, 0x0B, 0x29, 0x0D, 0x29, 0x24, 0x29 }, // MAP_SELECT_TYPE_EDGE_1
|
||||
{ 0x03, 0x03, 0x03, 0x23, 0x07, 0x07, 0x07, 0x23, 0x0B, 0x0B, 0x0B, 0x23, 0x20, 0x20, 0x20, 0x23, 0x03, 0x03, 0x03, 0x23, 0x07, 0x07, 0x07, 0x23, 0x0B, 0x0B, 0x0B, 0x23, 0x20, 0x28, 0x24, 0x23 }, // MAP_SELECT_TYPE_EDGE_2
|
||||
{ 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x26, 0x26, 0x0E, 0x20, 0x0E, 0x20, 0x0E, 0x20, 0x26, 0x26, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x26, 0x26, 0x0E, 0x20, 0x0E, 0x21, 0x0E, 0x28, 0x26, 0x26 }, // MAP_SELECT_TYPE_EDGE_3
|
||||
};
|
||||
|
||||
//0x00981ABE
|
||||
static constexpr const uint8 tile_element_lower_styles[5][32] = {
|
||||
{ 0x2E, 0x00, 0x2E, 0x02, 0x3E, 0x04, 0x3E, 0x06, 0x2E, 0x08, 0x2E, 0x0A, 0x3E, 0x0C, 0x3E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x06, 0x18, 0x19, 0x1A, 0x0B, 0x1C, 0x0C, 0x3E, 0x1F },
|
||||
{ 0x2D, 0x2D, 0x00, 0x01, 0x2D, 0x2D, 0x04, 0x05, 0x3D, 0x3D, 0x08, 0x09, 0x3D, 0x3D, 0x0C, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07, 0x18, 0x19, 0x1A, 0x09, 0x1C, 0x3D, 0x0C, 0x1F },
|
||||
{ 0x2B, 0x3B, 0x2B, 0x3B, 0x00, 0x01, 0x02, 0x03, 0x2B, 0x3B, 0x2B, 0x3B, 0x08, 0x09, 0x0A, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x03, 0x18, 0x19, 0x1A, 0x3B, 0x1C, 0x09, 0x0E, 0x1F },
|
||||
{ 0x27, 0x27, 0x37, 0x37, 0x27, 0x27, 0x37, 0x37, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x37, 0x18, 0x19, 0x1A, 0x03, 0x1C, 0x0D, 0x06, 0x1F },
|
||||
{ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x0D, 0x0E, 0x00 },
|
||||
// Basically the inverse of the table above.
|
||||
// 0x1F = new slope
|
||||
// 0x20 = base height increases
|
||||
static constexpr const uint8 tile_element_lower_styles[9][32] = {
|
||||
{ 0x2E, 0x00, 0x2E, 0x02, 0x3E, 0x04, 0x3E, 0x06, 0x2E, 0x08, 0x2E, 0x0A, 0x3E, 0x0C, 0x3E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x06, 0x18, 0x19, 0x1A, 0x0B, 0x1C, 0x0C, 0x3E, 0x1F }, // MAP_SELECT_TYPE_CORNER_0
|
||||
{ 0x2D, 0x2D, 0x00, 0x01, 0x2D, 0x2D, 0x04, 0x05, 0x3D, 0x3D, 0x08, 0x09, 0x3D, 0x3D, 0x0C, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07, 0x18, 0x19, 0x1A, 0x09, 0x1C, 0x3D, 0x0C, 0x1F }, // MAP_SELECT_TYPE_CORNER_1
|
||||
{ 0x2B, 0x3B, 0x2B, 0x3B, 0x00, 0x01, 0x02, 0x03, 0x2B, 0x3B, 0x2B, 0x3B, 0x08, 0x09, 0x0A, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x03, 0x18, 0x19, 0x1A, 0x3B, 0x1C, 0x09, 0x0E, 0x1F }, // MAP_SELECT_TYPE_CORNER_2
|
||||
{ 0x27, 0x27, 0x37, 0x37, 0x27, 0x27, 0x37, 0x37, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x37, 0x18, 0x19, 0x1A, 0x03, 0x1C, 0x0D, 0x06, 0x1F }, // MAP_SELECT_TYPE_CORNER_3
|
||||
{ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x0D, 0x0E, 0x00 }, // MAP_SELECT_TYPE_FULL
|
||||
{ 0x23, 0x23, 0x23, 0x23, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x23, 0x23, 0x23, 0x23, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x00, 0x0D, 0x0E, 0x03 }, // MAP_SELECT_TYPE_EDGE_0
|
||||
{ 0x26, 0x00, 0x26, 0x02, 0x26, 0x04, 0x26, 0x06, 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x06, 0x26, 0x00, 0x26, 0x02, 0x26, 0x04, 0x26, 0x06, 0x00, 0x00, 0x02, 0x0B, 0x04, 0x0D, 0x06, 0x06 }, // MAP_SELECT_TYPE_EDGE_1
|
||||
{ 0x2C, 0x00, 0x00, 0x00, 0x2C, 0x04, 0x04, 0x04, 0x2C, 0x08, 0x08, 0x08, 0x2C, 0x0C, 0x0C, 0x0C, 0x2C, 0x00, 0x00, 0x00, 0x2C, 0x04, 0x04, 0x07, 0x2C, 0x08, 0x08, 0x0B, 0x2C, 0x0C, 0x0C, 0x0C }, // MAP_SELECT_TYPE_EDGE_2
|
||||
{ 0x29, 0x29, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x29, 0x29, 0x08, 0x09, 0x08, 0x09, 0x08, 0x09, 0x29, 0x29, 0x00, 0x01, 0x00, 0x01, 0x00, 0x07, 0x29, 0x29, 0x08, 0x09, 0x08, 0x09, 0x0E, 0x09 }, // MAP_SELECT_TYPE_EDGE_3
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1461,7 +1476,7 @@ static sint32 map_get_corner_height(sint32 z, sint32 slope, sint32 direction)
|
||||
return z;
|
||||
}
|
||||
|
||||
static sint32 tile_element_get_corner_height(rct_tile_element *tileElement, sint32 direction)
|
||||
static sint32 tile_element_get_corner_height(const rct_tile_element *tileElement, sint32 direction)
|
||||
{
|
||||
sint32 z = tileElement->base_height;
|
||||
sint32 slope = tileElement->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
@@ -1791,43 +1806,50 @@ static uint8 map_get_highest_land_height(sint32 xMin, sint32 xMax, sint32 yMin,
|
||||
return max_height;
|
||||
}
|
||||
|
||||
static money32 raise_land(sint32 flags, sint32 x, sint32 y, sint32 z, sint32 ax, sint32 ay, sint32 bx, sint32 by, sint32 selectionType)
|
||||
static money32 raise_land(sint32 flags, sint32 x, sint32 y, sint32 z, sint32 point_a_x, sint32 point_a_y, sint32 point_b_x, sint32 point_b_y, sint32 selectionType)
|
||||
{
|
||||
money32 cost = 0;
|
||||
size_t tableRow = selectionType;
|
||||
|
||||
if (selectionType < 0 || selectionType >= (sint32)Util::CountOf(tile_element_raise_styles))
|
||||
// The selections between MAP_SELECT_TYPE_FULL and MAP_SELECT_TYPE_EDGE_0 are not included in the tables
|
||||
if (selectionType >= MAP_SELECT_TYPE_EDGE_0 && selectionType <= MAP_SELECT_TYPE_EDGE_3)
|
||||
tableRow -= MAP_SELECT_TYPE_EDGE_0 - MAP_SELECT_TYPE_FULL - 1;
|
||||
|
||||
if ((flags & GAME_COMMAND_FLAG_APPLY) && gGameCommandNestLevel == 1)
|
||||
{
|
||||
log_warning("Invalid selection type %d for raising land", selectionType);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if ((flags & GAME_COMMAND_FLAG_APPLY) && gGameCommandNestLevel == 1) {
|
||||
audio_play_sound_at_location(SOUND_PLACE_ITEM, x, y, z);
|
||||
}
|
||||
|
||||
// Keep big coordinates within map boundaries
|
||||
ax = std::max<decltype(ax)>(32, ax);
|
||||
bx = std::min<decltype(bx)>(gMapSizeMaxXY, bx);
|
||||
ay = std::max<decltype(bx)>(32, ay);
|
||||
by = std::min<decltype(by)>(gMapSizeMaxXY, by);
|
||||
point_a_x = std::max<decltype(point_a_x)>(32, point_a_x);
|
||||
point_b_x = std::min<decltype(point_b_x)>(gMapSizeMaxXY, point_b_x);
|
||||
point_a_y = std::max<decltype(point_a_y)>(32, point_a_y);
|
||||
point_b_y = std::min<decltype(point_b_y)>(gMapSizeMaxXY, point_b_y);
|
||||
|
||||
uint8 min_height = map_get_lowest_land_height(ax, bx, ay, by);
|
||||
uint8 min_height = map_get_lowest_land_height(point_a_x, point_b_x, point_a_y, point_b_y);
|
||||
|
||||
for (sint32 yi = ay; yi <= by; yi += 32) {
|
||||
for (sint32 xi = ax; xi <= bx; xi += 32) {
|
||||
rct_tile_element *tile_element = map_get_surface_element_at({xi, yi});
|
||||
if (tile_element != nullptr) {
|
||||
for (sint32 y_coord = point_a_y; y_coord <= point_b_y; y_coord += 32)
|
||||
{
|
||||
for (sint32 x_coord = point_a_x; x_coord <= point_b_x; x_coord += 32)
|
||||
{
|
||||
rct_tile_element * tile_element = map_get_surface_element_at(x_coord / 32, y_coord / 32);
|
||||
if (tile_element != nullptr)
|
||||
{
|
||||
uint8 height = tile_element->base_height;
|
||||
if (height <= min_height){
|
||||
uint8 newStyle = tile_element_raise_styles[selectionType][tile_element->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK];
|
||||
if (newStyle & 0x20) { // needs to be raised
|
||||
height += 2;
|
||||
newStyle &= ~0x20;
|
||||
}
|
||||
money32 tileCost = map_set_land_height(flags, xi, yi, height, newStyle);
|
||||
if (tileCost == MONEY32_UNDEFINED)
|
||||
return MONEY32_UNDEFINED;
|
||||
if (height <= min_height)
|
||||
{
|
||||
uint8 raisedCorners = tile_element->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
uint8 slope = tile_element_raise_styles[tableRow][raisedCorners];
|
||||
|
||||
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
|
||||
height += 2;
|
||||
|
||||
slope &= TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
money32 tileCost = map_set_land_height(flags, x_coord, y_coord, height, slope);
|
||||
if (tileCost == MONEY32_UNDEFINED)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
cost += tileCost;
|
||||
}
|
||||
}
|
||||
@@ -1844,48 +1866,55 @@ static money32 raise_land(sint32 flags, sint32 x, sint32 y, sint32 z, sint32 ax,
|
||||
return cost;
|
||||
}
|
||||
|
||||
static money32 lower_land(sint32 flags, sint32 x, sint32 y, sint32 z, sint32 ax, sint32 ay, sint32 bx, sint32 by, sint32 selectionType)
|
||||
static money32 lower_land(sint32 flags, sint32 x, sint32 y, sint32 z, sint32 point_a_x, sint32 point_a_y, sint32 point_b_x, sint32 point_b_y, sint32 selectionType)
|
||||
{
|
||||
money32 cost = 0;
|
||||
size_t tableRow = selectionType;
|
||||
|
||||
if ((flags & GAME_COMMAND_FLAG_APPLY) && gGameCommandNestLevel == 1) {
|
||||
// The selections between MAP_SELECT_TYPE_FULL and MAP_SELECT_TYPE_EDGE_0 are not included in the tables
|
||||
if (selectionType >= MAP_SELECT_TYPE_EDGE_0 && selectionType <= MAP_SELECT_TYPE_EDGE_3)
|
||||
tableRow -= MAP_SELECT_TYPE_EDGE_0 - MAP_SELECT_TYPE_FULL - 1;
|
||||
|
||||
// Keep big coordinates within map boundaries
|
||||
point_a_x = std::max<decltype(point_a_x)>(32, point_a_x);
|
||||
point_b_x = std::min<decltype(point_b_x)>(gMapSizeMaxXY, point_b_x);
|
||||
point_a_y = std::max<decltype(point_a_y)>(32, point_a_y);
|
||||
point_b_y = std::min<decltype(point_b_y)>(gMapSizeMaxXY, point_b_y);
|
||||
|
||||
if ((flags & GAME_COMMAND_FLAG_APPLY) && gGameCommandNestLevel == 1)
|
||||
{
|
||||
audio_play_sound_at_location(SOUND_PLACE_ITEM, x, y, z);
|
||||
}
|
||||
|
||||
if (selectionType < 0 || selectionType >= 5)
|
||||
uint8 max_height = map_get_highest_land_height(point_a_x, point_b_x, point_a_y, point_b_y);
|
||||
|
||||
for (sint32 y_coord = point_a_y; y_coord <= point_b_y; y_coord += 32)
|
||||
{
|
||||
log_warning("Improper selection type %d", selectionType);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
// Keep big coordinates within map boundaries
|
||||
ax = std::max<decltype(ax)>(32, ax);
|
||||
bx = std::min<decltype(bx)>(gMapSizeMaxXY, bx);
|
||||
ay = std::max<decltype(bx)>(32, ay);
|
||||
by = std::min<decltype(by)>(gMapSizeMaxXY, by);
|
||||
|
||||
uint8 max_height = map_get_highest_land_height(ax, bx, ay, by);
|
||||
|
||||
for (sint32 yi = ay; yi <= by; yi += 32) {
|
||||
for (sint32 xi = ax; xi <= bx; xi += 32) {
|
||||
rct_tile_element *tile_element = map_get_surface_element_at({xi, yi});
|
||||
if (tile_element != nullptr) {
|
||||
for (sint32 x_coord = point_a_x; x_coord <= point_b_x; x_coord += 32)
|
||||
{
|
||||
rct_tile_element * tile_element = map_get_surface_element_at(x_coord / 32, y_coord / 32);
|
||||
if (tile_element != nullptr)
|
||||
{
|
||||
uint8 height = tile_element->base_height;
|
||||
if (tile_element->properties.surface.slope & TILE_ELEMENT_SLOPE_ALL_CORNERS_UP)
|
||||
if (tile_element->properties.surface.slope & TILE_ELEMENT_SURFACE_RAISED_CORNERS_MASK)
|
||||
height += 2;
|
||||
if (tile_element->properties.surface.slope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT)
|
||||
if (tile_element->properties.surface.slope & TILE_ELEMENT_SURFACE_DIAGONAL_FLAG)
|
||||
height += 2;
|
||||
if (height >= max_height) {
|
||||
height = tile_element->base_height;
|
||||
uint8 newStyle = tile_element_lower_styles[selectionType][tile_element->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK];
|
||||
if (newStyle & 0x20) { // needs to be lowered
|
||||
height -= 2;
|
||||
newStyle &= ~0x20;
|
||||
}
|
||||
money32 tileCost = map_set_land_height(flags, xi, yi, height, newStyle);
|
||||
if (tileCost == MONEY32_UNDEFINED)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
||||
if (height >= max_height)
|
||||
{
|
||||
height = tile_element->base_height;
|
||||
uint8 currentSlope = tile_element->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
uint8 newSlope = tile_element_lower_styles[tableRow][currentSlope];
|
||||
if (newSlope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT)
|
||||
height -= 2;
|
||||
|
||||
newSlope &= TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
money32 tileCost = map_set_land_height(flags, x_coord, y_coord, height, newSlope);
|
||||
if (tileCost == MONEY32_UNDEFINED)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
cost += tileCost;
|
||||
}
|
||||
}
|
||||
@@ -2105,16 +2134,17 @@ static money32 smooth_land_tile(sint32 direction, uint8 flags, sint32 x, sint32
|
||||
sint32 slope = tileElement->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
if (raiseLand) {
|
||||
slope = tile_element_raise_styles[direction][slope];
|
||||
if (slope & 0x20) {
|
||||
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT) {
|
||||
targetBaseZ += 2;
|
||||
slope &= ~0x20;
|
||||
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
slope = tile_element_lower_styles[direction][slope];
|
||||
if (slope & 0x20) {
|
||||
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT) {
|
||||
targetBaseZ -= 2;
|
||||
slope &= ~0x20;
|
||||
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
|
||||
}
|
||||
}
|
||||
return game_do_command(x, flags, y, targetBaseZ | (slope << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0);
|
||||
@@ -2188,9 +2218,9 @@ static money32 smooth_land_row_by_edge(sint32 flags, sint32 x, sint32 y, sint32
|
||||
if (raiseLand) {
|
||||
if (shouldContinue & 0x4) {
|
||||
slope = tile_element_raise_styles[direction1][slope];
|
||||
if (slope & 0x20) {
|
||||
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT) {
|
||||
targetBaseZ += 2;
|
||||
slope &= ~0x20;
|
||||
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
|
||||
}
|
||||
}
|
||||
if ((shouldContinue & 0x8) &&
|
||||
@@ -2198,9 +2228,9 @@ static money32 smooth_land_row_by_edge(sint32 flags, sint32 x, sint32 y, sint32
|
||||
map_get_corner_height(targetBaseZ, slope, direction2))
|
||||
{
|
||||
slope = tile_element_raise_styles[direction2][slope];
|
||||
if (slope & 0x20) {
|
||||
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT) {
|
||||
targetBaseZ += 2;
|
||||
slope &= ~0x20;
|
||||
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2208,9 +2238,9 @@ static money32 smooth_land_row_by_edge(sint32 flags, sint32 x, sint32 y, sint32
|
||||
{
|
||||
if (shouldContinue & 0x4) {
|
||||
slope = tile_element_lower_styles[direction1][slope];
|
||||
if (slope & 0x20) {
|
||||
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT) {
|
||||
targetBaseZ -= 2;
|
||||
slope &= ~0x20;
|
||||
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
|
||||
}
|
||||
}
|
||||
if ((shouldContinue & 0x8) &&
|
||||
@@ -2218,9 +2248,9 @@ static money32 smooth_land_row_by_edge(sint32 flags, sint32 x, sint32 y, sint32
|
||||
map_get_corner_height(targetBaseZ, slope, direction2))
|
||||
{
|
||||
slope = tile_element_lower_styles[direction2][slope];
|
||||
if (slope & 0x20) {
|
||||
if (slope & SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT) {
|
||||
targetBaseZ -= 2;
|
||||
slope &= ~0x20;
|
||||
slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2303,32 +2333,22 @@ static money32 smooth_land_row_by_corner(sint32 flags, sint32 x, sint32 y, sint3
|
||||
|
||||
static money32 smooth_land(sint32 flags, sint32 centreX, sint32 centreY, sint32 mapLeft, sint32 mapTop, sint32 mapRight, sint32 mapBottom, sint32 command)
|
||||
{
|
||||
// break up information in command
|
||||
const bool raiseLand = command < 0x7FFF;
|
||||
const sint32 selectionType = command & 0x7FFF;
|
||||
const sint32 heightOffset = raiseLand ? 2 : -2;
|
||||
|
||||
// Cap bounds to map
|
||||
mapLeft = std::max(mapLeft, 32);
|
||||
mapTop = std::max(mapTop, 32);
|
||||
mapRight = Math::Clamp(0, mapRight, (MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32);
|
||||
mapBottom = Math::Clamp(0, mapBottom, (MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32);
|
||||
|
||||
bool raiseLand = command < 0x7FFF;
|
||||
sint32 commandType = raiseLand ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND;
|
||||
sint32 centreZ = tile_element_height(centreX, centreY);
|
||||
sint32 mapLeftRight = mapLeft | (mapRight << 16);
|
||||
sint32 mapTopBottom = mapTop | (mapBottom << 16);
|
||||
bool fullTile = ((command & 0x7FFF) == MAP_SELECT_TYPE_FULL);
|
||||
|
||||
// Play sound (only once)
|
||||
if ((flags & GAME_COMMAND_FLAG_APPLY) && gGameCommandNestLevel == 1) {
|
||||
audio_play_sound_at_location(SOUND_PLACE_ITEM, centreX, centreY, centreZ);
|
||||
}
|
||||
|
||||
money32 totalCost = 0;
|
||||
money32 result;
|
||||
|
||||
rct_tile_element *tileElement = map_get_surface_element_at({mapLeft, mapTop});
|
||||
if (tileElement == nullptr)
|
||||
sint32 centreZ = tile_element_height(centreX, centreY);
|
||||
if ((flags & GAME_COMMAND_FLAG_APPLY) && gGameCommandNestLevel == 1)
|
||||
{
|
||||
log_warning("Invalid coordinates for land smoothing, x = %d, y = %d", mapLeft, mapTop);
|
||||
return MONEY32_UNDEFINED;
|
||||
audio_play_sound_at_location(SOUND_PLACE_ITEM, centreX, centreY, centreZ);
|
||||
}
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
@@ -2339,100 +2359,91 @@ static money32 smooth_land(sint32 flags, sint32 centreX, sint32 centreY, sint32
|
||||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
||||
}
|
||||
|
||||
uint8 maxHeight = 0;
|
||||
uint8 minHeight = 0xFF;
|
||||
uint32 newBaseZ = 0;
|
||||
uint32 newSlope = 0;
|
||||
|
||||
// Predict the land height for future use
|
||||
if (fullTile)
|
||||
// Do the smoothing
|
||||
money32 totalCost = 0;
|
||||
switch (selectionType)
|
||||
{
|
||||
minHeight = map_get_lowest_land_height(mapLeft, mapRight, mapTop, mapBottom);
|
||||
maxHeight = map_get_highest_land_height(mapLeft, mapRight, mapTop, mapBottom);
|
||||
|
||||
if (commandType == GAME_COMMAND_RAISE_LAND) {
|
||||
minHeight += 2;
|
||||
maxHeight += 2;
|
||||
}
|
||||
else {
|
||||
maxHeight -= 2;
|
||||
minHeight -= 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
case MAP_SELECT_TYPE_FULL:
|
||||
{
|
||||
// One corner tile selected
|
||||
newBaseZ = tileElement->base_height;
|
||||
newSlope = tileElement->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
if (commandType == GAME_COMMAND_RAISE_LAND) {
|
||||
newSlope = tile_element_raise_styles[command & 0xFF][newSlope];
|
||||
if (newSlope & 0x20) {
|
||||
newBaseZ += 2;
|
||||
newSlope &= ~0x20;
|
||||
}
|
||||
}
|
||||
else {
|
||||
newSlope = tile_element_lower_styles[command & 0xFF][newSlope];
|
||||
if (newSlope & 0x20) {
|
||||
newBaseZ -= 2;
|
||||
newSlope &= ~0x20;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8 minHeight = heightOffset + map_get_lowest_land_height(mapLeft, mapRight, mapTop, mapBottom);
|
||||
uint8 maxHeight = heightOffset + map_get_highest_land_height(mapLeft, mapRight, mapTop, mapBottom);
|
||||
|
||||
// Then do the smoothing
|
||||
if (fullTile) {
|
||||
// Smooth the corners
|
||||
sint32 z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 2), maxHeight);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, -32, 0, 2, raiseLand);
|
||||
tileElement = map_get_surface_element_at(mapLeft >> 5, mapBottom >> 5);
|
||||
z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 3), maxHeight);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapBottom, z, -32, 32, 1, 3, raiseLand);
|
||||
tileElement = map_get_surface_element_at(mapRight >> 5, mapBottom >> 5);
|
||||
z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 0), maxHeight);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapRight, mapBottom, z, 32, 32, 2, 0, raiseLand);
|
||||
tileElement = map_get_surface_element_at(mapRight >> 5, mapTop >> 5);
|
||||
z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 1), maxHeight);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapRight, mapTop, z, 32, -32, 3, 1, raiseLand);
|
||||
// Smooth the 4 corners
|
||||
{ // top-left
|
||||
rct_tile_element * tileElement = map_get_surface_element_at({ mapLeft, mapTop });
|
||||
sint32 z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 2), maxHeight);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, -32, 0, 2, raiseLand);
|
||||
}
|
||||
{ // bottom-left
|
||||
rct_tile_element * tileElement = map_get_surface_element_at(mapLeft >> 5, mapBottom >> 5);
|
||||
sint32 z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 3), maxHeight);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapBottom, z, -32, 32, 1, 3, raiseLand);
|
||||
}
|
||||
{ // bottom-right
|
||||
rct_tile_element * tileElement = map_get_surface_element_at(mapRight >> 5, mapBottom >> 5);
|
||||
sint32 z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 0), maxHeight);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapRight, mapBottom, z, 32, 32, 2, 0, raiseLand);
|
||||
}
|
||||
{ // top-right
|
||||
rct_tile_element * tileElement = map_get_surface_element_at(mapRight >> 5, mapTop >> 5);
|
||||
sint32 z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 1), maxHeight);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapRight, mapTop, z, 32, -32, 3, 1, raiseLand);
|
||||
}
|
||||
|
||||
// Smooth the edges
|
||||
sint32 x = mapLeft;
|
||||
sint32 y, z2;
|
||||
for (y = mapTop; y <= mapBottom; y += 32)
|
||||
rct_tile_element * tileElement = nullptr;
|
||||
sint32 z1, z2;
|
||||
for (sint32 y = mapTop; y <= mapBottom; y += 32)
|
||||
{
|
||||
tileElement = map_get_surface_element_at({x, y});
|
||||
z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 3), maxHeight);
|
||||
z2 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 2), maxHeight);
|
||||
totalCost += smooth_land_row_by_edge(flags, x, y, z, z2, -32, 0, 0, 1, 3, 2, raiseLand);
|
||||
tileElement = map_get_surface_element_at({ mapLeft, y });
|
||||
z1 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 3), maxHeight);
|
||||
z2 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 2), 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 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 1), maxHeight);
|
||||
z2 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 0), maxHeight);
|
||||
totalCost += smooth_land_row_by_edge(flags, mapRight, y, z1, z2, 32, 0, 2, 3, 1, 0, raiseLand);
|
||||
}
|
||||
x = mapRight;
|
||||
for (y = mapTop; y <= mapBottom; y += 32)
|
||||
|
||||
for (sint32 x = mapLeft; x <= mapRight; x += 32)
|
||||
{
|
||||
tileElement = map_get_surface_element_at({x, y});
|
||||
z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 1), maxHeight);
|
||||
z2 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 0), maxHeight);
|
||||
totalCost += smooth_land_row_by_edge(flags, x, y, z, z2, 32, 0, 2, 3, 1, 0, raiseLand);
|
||||
}
|
||||
y = mapTop;
|
||||
for (x = mapLeft; x <= mapRight; x += 32)
|
||||
{
|
||||
tileElement = map_get_surface_element_at({x, y});
|
||||
z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 1), maxHeight);
|
||||
z2 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 2), maxHeight);
|
||||
totalCost += smooth_land_row_by_edge(flags, x, y, z, z2, 0, -32, 0, 3, 1, 2, raiseLand);
|
||||
}
|
||||
y = mapBottom;
|
||||
for (x = mapLeft; x <= mapRight; x += 32)
|
||||
{
|
||||
tileElement = map_get_surface_element_at({x, y});
|
||||
z = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 0), maxHeight);
|
||||
z2 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 3), maxHeight);
|
||||
totalCost += smooth_land_row_by_edge(flags, x, y, z, z2, 0, 32, 1, 2, 0, 3, raiseLand);
|
||||
tileElement = map_get_surface_element_at({ x, mapTop });
|
||||
z1 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 1), maxHeight);
|
||||
z2 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 2), 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 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 0), maxHeight);
|
||||
z2 = Math::Clamp(minHeight, (uint8)tile_element_get_corner_height(tileElement, 3), maxHeight);
|
||||
totalCost += smooth_land_row_by_edge(flags, x, mapBottom, z1, z2, 0, 32, 1, 2, 0, 3, raiseLand);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
case MAP_SELECT_TYPE_CORNER_0:
|
||||
case MAP_SELECT_TYPE_CORNER_1:
|
||||
case MAP_SELECT_TYPE_CORNER_2:
|
||||
case MAP_SELECT_TYPE_CORNER_3:
|
||||
{
|
||||
// One corner tile selected
|
||||
rct_tile_element * tileElement = map_get_surface_element_at({ mapLeft, mapTop });
|
||||
uint8 newBaseZ = tileElement->base_height;
|
||||
uint8 newSlope = tileElement->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
|
||||
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
|
||||
sint32 z = map_get_corner_height(newBaseZ, newSlope, 2);
|
||||
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, -32, -32, 0, 2, raiseLand);
|
||||
@@ -2444,7 +2455,8 @@ static money32 smooth_land(sint32 flags, sint32 centreX, sint32 centreY, sint32
|
||||
totalCost += smooth_land_row_by_corner(flags, mapLeft, mapTop, z, 32, -32, 3, 1, raiseLand);
|
||||
|
||||
// Smooth the edges
|
||||
switch (command & 0x7FFF) {
|
||||
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);
|
||||
@@ -2482,20 +2494,99 @@ static money32 smooth_land(sint32 flags, sint32 centreX, sint32 centreY, sint32
|
||||
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
|
||||
rct_tile_element * surfaceElement = map_get_surface_element_at({ mapLeft, mapTop });
|
||||
uint8 newBaseZ = surfaceElement->base_height;
|
||||
uint8 oldSlope = surfaceElement->properties.surface.slope;
|
||||
uint8 newSlope = oldSlope;
|
||||
sint32 rowIndex = selectionType - (MAP_SELECT_TYPE_EDGE_0 - MAP_SELECT_TYPE_FULL - 1);
|
||||
|
||||
// Finally raise / lower the centre tile
|
||||
result = game_do_command(centreX, flags, centreY, mapLeftRight, commandType, command & 0x7FFF, mapTopBottom);
|
||||
if (result != MONEY32_UNDEFINED) {
|
||||
totalCost += result;
|
||||
} else {
|
||||
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 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 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 c1 = cornerIndices[edge][0];
|
||||
uint8 c2 = cornerIndices[edge][1];
|
||||
uint8 c3 = cornerIndices[edge][2];
|
||||
uint8 c4 = cornerIndices[edge][3];
|
||||
uint8 z1 = map_get_corner_height(newBaseZ, newSlope, c1);
|
||||
uint8 z2 = map_get_corner_height(newBaseZ, newSlope, c2);
|
||||
uint8 z3 = map_get_corner_height(newBaseZ, newSlope, c3);
|
||||
uint8 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);
|
||||
sint32 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
|
||||
sint32 commandType = raiseLand ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND;
|
||||
sint32 mapLeftRight = mapLeft | (mapRight << 16);
|
||||
sint32 mapTopBottom = mapTop | (mapBottom << 16);
|
||||
money32 cost = game_do_command(centreX, flags, centreY, mapLeftRight, commandType, command & 0x7FFF, mapTopBottom);
|
||||
if (cost == MONEY32_UNDEFINED)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
totalCost += cost;
|
||||
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
gCommandPosition.x = centreX;
|
||||
gCommandPosition.y = centreY;
|
||||
gCommandPosition.z = centreZ;
|
||||
gCommandPosition.x = centreX;
|
||||
gCommandPosition.y = centreY;
|
||||
gCommandPosition.z = centreZ;
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user