diff --git a/src/world/map.c b/src/world/map.c index 0194509789..0926e655c0 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -2051,12 +2051,12 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i ); } -static int map_get_corner_height(rct_map_element *mapElement, int slopeMask) +static int map_get_corner_height(rct_map_element *mapElement, int direction) { int z = mapElement->base_height; int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - switch (slopeMask) { - case 1: + switch (direction) { + case 0: if (slope & 1) { z += 2; if (slope == 27) { @@ -2064,7 +2064,7 @@ static int map_get_corner_height(rct_map_element *mapElement, int slopeMask) } } break; - case 2: + case 1: if (slope & 2) { z += 2; if (slope == 23) { @@ -2072,7 +2072,7 @@ static int map_get_corner_height(rct_map_element *mapElement, int slopeMask) } } break; - case 4: + case 2: if (slope & 4) { z += 2; if (slope == 30) { @@ -2080,7 +2080,7 @@ static int map_get_corner_height(rct_map_element *mapElement, int slopeMask) } } break; - case 8: + case 3: if (slope & 8) { z += 2; if (slope == 29) { @@ -2094,9 +2094,12 @@ static int map_get_corner_height(rct_map_element *mapElement, int slopeMask) /** * - * rct2: 0x0068C3B2 + * rct2: 0x0068C3B2 slope 1, style 0 + * rct2: 0x0068C47A slope 2, style 1 + * rct2: 0x0068C222 slope 4, style 2 + * rct2: 0x0068C2EA slope 8, style 3 */ -static money32 sub_68C3B2(uint8 flags, int x, int y, uint8 targetBaseZ, uint8 minBaseZ) +static money32 smooth_land_tile(int direction, uint8 flags, int x, int y, uint8 targetBaseZ, uint8 minBaseZ) { // Check if inside map bounds if (x < 0 || y < 0 || x >= (256 * 32) || y >= (256 * 32)) { @@ -2105,7 +2108,7 @@ static money32 sub_68C3B2(uint8 flags, int x, int y, uint8 targetBaseZ, uint8 mi // Get height of tile rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); - uint8 baseZ = map_get_corner_height(mapElement, 1); + uint8 baseZ = map_get_corner_height(mapElement, direction); // Check if tile is same height as target tile if (baseZ == targetBaseZ) { @@ -2121,7 +2124,7 @@ static money32 sub_68C3B2(uint8 flags, int x, int y, uint8 targetBaseZ, uint8 mi } targetBaseZ = mapElement->base_height; int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_lower_styles[0][slope]; + style = map_element_lower_styles[direction][slope]; if (style & 0x20) { targetBaseZ -= 2; style &= ~0x20; @@ -2133,7 +2136,7 @@ static money32 sub_68C3B2(uint8 flags, int x, int y, uint8 targetBaseZ, uint8 mi } targetBaseZ = mapElement->base_height; int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_raise_styles[0][slope]; + style = map_element_raise_styles[direction][slope]; if ((style & 0x20) != 0) { targetBaseZ += 2; style &= ~0x20; @@ -2143,180 +2146,12 @@ static money32 sub_68C3B2(uint8 flags, int x, int y, uint8 targetBaseZ, uint8 mi return game_do_command(x, flags, y, targetBaseZ | (style << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); } -/** - * - * rct2: 0x0068C47A - */ -static money32 sub_68C47A(uint8 flags, int x, int y, uint8 targetBaseZ, uint8 minBaseZ) +money32 smooth_land(int flags, int centreX, int centreY, int mapLeft, int mapTop, int mapRight, int mapBottom, int command) { - // Check if inside map bounds - if (x < 0 || y < 0 || x >= (256 * 32) || y >= (256 * 32)) { - return MONEY32_UNDEFINED; - } - - // Get height of tile - rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); - uint8 baseZ = map_get_corner_height(mapElement, 2); - - // Check if tile is same height as target tile - if (baseZ == targetBaseZ) { - // No need to raise or lower - return MONEY32_UNDEFINED; - } - - uint8 style; - if (targetBaseZ <= baseZ) { - baseZ = baseZ - targetBaseZ; - if (baseZ <= minBaseZ) { - return MONEY32_UNDEFINED; - } - targetBaseZ = mapElement->base_height; - int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_lower_styles[1][slope]; - if (style & 0x20) { - targetBaseZ -= 2; - style &= ~0x20; - } - } else { - baseZ = targetBaseZ - baseZ; - if (baseZ <= minBaseZ) { - return MONEY32_UNDEFINED; - } - targetBaseZ = mapElement->base_height; - int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_raise_styles[1][slope]; - if ((style & 0x20) != 0) { - targetBaseZ += 2; - style &= ~0x20; - } - } - - return game_do_command(x, flags, y, targetBaseZ | (style << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); -} - -/** - * - * rct2: 0x0068C222 - */ -static money32 sub_68C222(uint8 flags, int x, int y, uint8 targetBaseZ, uint8 minBaseZ) -{ - // Check if inside map bounds - if (x < 0 || y < 0 || x >= (256 * 32) || y >= (256 * 32)) { - return MONEY32_UNDEFINED; - } - - // Get height of tile - rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); - uint8 baseZ = map_get_corner_height(mapElement, 4); - - // Check if tile is same height as target tile - if (baseZ == targetBaseZ) { - // No need to raise or lower - return MONEY32_UNDEFINED; - } - - uint8 style; - if (targetBaseZ <= baseZ) { - baseZ = baseZ - targetBaseZ; - if (baseZ <= minBaseZ) { - return MONEY32_UNDEFINED; - } - targetBaseZ = mapElement->base_height; - int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_lower_styles[2][slope]; - if (style & 0x20) { - targetBaseZ -= 2; - style &= ~0x20; - } - } else { - baseZ = targetBaseZ - baseZ; - if (baseZ <= minBaseZ) { - return MONEY32_UNDEFINED; - } - targetBaseZ = mapElement->base_height; - int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_raise_styles[2][slope]; - if ((style & 0x20) != 0) { - targetBaseZ += 2; - style &= ~0x20; - } - } - - return game_do_command(x, flags, y, targetBaseZ | (style << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); -} - -/** - * - * rct2: 0x0068C2EA - */ -static money32 sub_68C2EA(uint8 flags, int x, int y, uint8 targetBaseZ, uint8 minBaseZ) -{ - // Check if inside map bounds - if (x < 0 || y < 0 || x >= (256 * 32) || y >= (256 * 32)) { - return MONEY32_UNDEFINED; - } - - // Get height of tile - rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); - uint8 baseZ = map_get_corner_height(mapElement, 8); - - // Check if tile is same height as target tile - if (baseZ == targetBaseZ) { - // No need to raise or lower - return MONEY32_UNDEFINED; - } - - uint8 style; - if (targetBaseZ <= baseZ) { - baseZ = baseZ - targetBaseZ; - if (baseZ <= minBaseZ) { - return MONEY32_UNDEFINED; - } - targetBaseZ = mapElement->base_height; - int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_lower_styles[3][slope]; - if (style & 0x20) { - targetBaseZ -= 2; - style &= ~0x20; - } - } else { - baseZ = targetBaseZ - baseZ; - if (baseZ <= minBaseZ) { - return MONEY32_UNDEFINED; - } - targetBaseZ = mapElement->base_height; - int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - style = map_element_raise_styles[3][slope]; - if ((style & 0x20) != 0) { - targetBaseZ += 2; - style &= ~0x20; - } - } - - return game_do_command(x, flags, y, targetBaseZ | (style << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); -} - -/** - * - * rct2: 0x0068BC01 - */ -void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) -{ - // RCT2_CALLFUNC_X(0x0068BC01, eax, ebx, ecx, edx, esi, edi, ebp); return; - - int flags = *ebx & 0xFF; - int centreX = *eax & 0xFFFF; - int centreY = *ecx & 0xFFFF; + int commandType; int centreZ = map_element_height(centreX, centreY); - int mapLeftRight = *edx; - int mapTopBottom = *ebp; - int mapLeft = mapLeftRight & 0xFFFF; - int mapTop = mapTopBottom & 0xFFFF; - int mapRight = mapLeftRight >> 16; - int mapBottom = mapTopBottom >> 16; - - int subCommand = *edi; - int subGameCommandType = *edi == 1 ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND; + int mapLeftRight = mapLeft | (mapRight << 16); + int mapTopBottom = mapTop | (mapBottom << 16); // Play sound (only once) if ((flags & GAME_COMMAND_FLAG_APPLY) && RCT2_GLOBAL(0x009A8C28, uint8) == 1) { @@ -2327,7 +2162,8 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, // First raise / lower the centre tile money32 result; - result = game_do_command(centreX, flags, centreY, mapLeftRight, subGameCommandType, 4, mapTopBottom); + commandType = command == 1 ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND; + result = game_do_command(centreX, flags, centreY, mapLeftRight, commandType, 4, mapTopBottom); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2340,8 +2176,8 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, mapElement = map_get_surface_element_at(x >> 5, y >> 5); int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; if (slope != 0) { - int command = subCommand == 0xFFFF ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND; - result = game_do_command(centreX, flags, centreY, mapLeftRight, command, 4, mapTopBottom); + commandType = command == 0xFFFF ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND; + result = game_do_command(centreX, flags, centreY, mapLeftRight, commandType, 4, mapTopBottom); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2350,51 +2186,41 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, y = mapTop; mapElement = map_get_surface_element_at(x >> 5, y >> 5); slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; - - *ebx = totalCost * 4; - RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = centreX; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = centreY; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = centreZ; - return; - } - - x = mapLeft; - y = mapTop; - int bx = ((mapRight - mapLeft) >> 5) - 1; - sint8 byte_F1AD5C = -2; - - for (;;) { - byte_F1AD5C += 2; - bx += 2; - x -= 32; - y -= 32; - if (bx > 64) { - *ebx = totalCost * 4; + if (slope != 0) { RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = centreX; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = centreY; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = centreZ; - return; + return totalCost * 4; } + } - sint8 minZ = (byte_F1AD5C << 1) & 0xFF; + x = mapLeft; + y = mapTop; + int size = ((mapRight - mapLeft) >> 5) + 1; + sint8 initialMinZ = -2; + + for (; size <= 64; size += 2) { + initialMinZ += 2; + sint8 minZ = (initialMinZ << 1) & 0xFF; + x -= 32; + y -= 32; // Corner (North-West) mapElement = map_get_surface_element_at(mapLeft >> 5, mapTop >> 5); - z = map_get_corner_height(mapElement, 4); - result = sub_68C3B2(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 2); + result = smooth_land_tile(0, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } y += 32; // Side (West) - for (int i = 0; i < bx; i++) { + for (int i = 0; i < size; i++) { int y2 = clamp(mapTop, y, mapBottom); mapElement = map_get_surface_element_at(mapLeft >> 5, y2 >> 5); - z = map_get_corner_height(mapElement, 4); - result = sub_68C47A(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 2); + result = smooth_land_tile(1, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2405,8 +2231,8 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, minZ += 2; } } - z = map_get_corner_height(mapElement, 8); - result = sub_68C3B2(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 3); + result = smooth_land_tile(0, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2416,19 +2242,19 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, // Corner (South-West) mapElement = map_get_surface_element_at(mapLeft >> 5, mapBottom >> 5); - z = map_get_corner_height(mapElement, 8); - result = sub_68C47A(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 3); + result = smooth_land_tile(1, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } x += 32; // Side (South) - for (int i = 0; i < bx; i++) { + for (int i = 0; i < size; i++) { int x2 = clamp(mapLeft, x, mapRight); mapElement = map_get_surface_element_at(x2 >> 5, mapBottom >> 5); - z = map_get_corner_height(mapElement, 8); - result = sub_68C222(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 3); + result = smooth_land_tile(2, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2439,8 +2265,8 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, minZ += 2; } } - z = map_get_corner_height(mapElement, 1); - result = sub_68C47A(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 0); + result = smooth_land_tile(1, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2450,19 +2276,19 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, // Corner (South-East) mapElement = map_get_surface_element_at(mapRight >> 5, mapBottom >> 5); - z = map_get_corner_height(mapElement, 1); - result = sub_68C222(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 0); + result = smooth_land_tile(2, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } y -= 32; // Side (East) - for (int i = 0; i < bx; i++) { + for (int i = 0; i < size; i++) { int y2 = clamp(mapTop, y, mapBottom); mapElement = map_get_surface_element_at(mapRight >> 5, y2 >> 5); - z = map_get_corner_height(mapElement, 1); - result = sub_68C2EA(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 0); + result = smooth_land_tile(3, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2473,8 +2299,8 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, minZ += 2; } } - z = map_get_corner_height(mapElement, 2); - result = sub_68C222(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 1); + result = smooth_land_tile(2, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2484,19 +2310,19 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, // Corner (North-East) mapElement = map_get_surface_element_at(mapRight >> 5, mapTop >> 5); - z = map_get_corner_height(mapElement, 2); - result = sub_68C2EA(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 1); + result = smooth_land_tile(3, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } x -= 32; // Side (North) - for (int i = 0; i < bx; i++) { + for (int i = 0; i < size; i++) { int x2 = clamp(mapLeft, x, mapRight); mapElement = map_get_surface_element_at(x2 >> 5, mapTop >> 5); - z = map_get_corner_height(mapElement, 2); - result = sub_68C3B2(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 1); + result = smooth_land_tile(0, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2507,8 +2333,8 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, minZ += 2; } } - z = map_get_corner_height(mapElement, 4); - result = sub_68C2EA(flags, x, y, z, minZ); + z = map_get_corner_height(mapElement, 2); + result = smooth_land_tile(3, flags, x, y, z, minZ); if (result != MONEY32_UNDEFINED) { totalCost += result; } @@ -2517,7 +2343,28 @@ void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, } } - *ebx = totalCost; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = centreX; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = centreY; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = centreZ; + return totalCost * 4; +} + +/** + * + * rct2: 0x0068BC01 + */ +void game_command_smooth_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int flags = *ebx & 0xFF; + int centreX = *eax & 0xFFFF; + int centreY = *ecx & 0xFFFF; + int mapLeft = *edx & 0xFFFF; + int mapTop = *ebp & 0xFFFF; + int mapRight = *edx >> 16; + int mapBottom = *ebp >> 16; + int command = *edi; + *ebx = smooth_land(flags, centreX, centreY, mapLeft, mapTop, mapRight, mapBottom, command); } /**