1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-16 03:23:15 +01:00

implement map smooth game command

This commit is contained in:
IntelOrca
2015-10-11 02:23:39 +01:00
parent 8ec4d61739
commit 969324032e

View File

@@ -2051,13 +2051,473 @@ 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)
{
int z = mapElement->base_height;
int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK;
switch (slopeMask) {
case 1:
if (slope & 1) {
z += 2;
if (slope == 27) {
z += 2;
}
}
break;
case 2:
if (slope & 2) {
z += 2;
if (slope == 23) {
z += 2;
}
}
break;
case 4:
if (slope & 4) {
z += 2;
if (slope == 30) {
z += 2;
}
}
break;
case 8:
if (slope & 8) {
z += 2;
if (slope == 29) {
z += 2;
}
}
break;
}
return z;
}
/**
*
* rct2: 0x0068C3B2
*/
static money32 sub_68C3B2(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, 1);
// 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[0][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[0][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: 0x0068C47A
*/
static money32 sub_68C47A(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, 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);
// 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 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;
// Play sound (only once)
if ((flags & GAME_COMMAND_FLAG_APPLY) && RCT2_GLOBAL(0x009A8C28, uint8) == 1) {
sound_play_panned(SOUND_PLACE_ITEM, 0x8001, centreX, centreY, centreZ);
}
money32 totalCost = 0;
// First raise / lower the centre tile
money32 result;
result = game_do_command(centreX, flags, centreY, mapLeftRight, subGameCommandType, 4, mapTopBottom);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
int x, y, z;
rct_map_element *mapElement;
x = mapLeft;
y = mapTop;
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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
x = mapLeft;
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;
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;
}
sint8 minZ = (byte_F1AD5C << 1) & 0xFF;
// 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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
y += 32;
// Side (West)
for (int i = 0; i < bx; 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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
minZ -= 2;
if (y >= mapTop) {
minZ += 2;
if (y > mapBottom) {
minZ += 2;
}
}
z = map_get_corner_height(mapElement, 8);
result = sub_68C3B2(flags, x, y, z, minZ);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
y += 32;
}
// 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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
x += 32;
// Side (South)
for (int i = 0; i < bx; 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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
minZ -= 2;
if (x >= mapLeft) {
minZ += 2;
if (x > mapRight) {
minZ += 2;
}
}
z = map_get_corner_height(mapElement, 1);
result = sub_68C47A(flags, x, y, z, minZ);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
x += 32;
}
// 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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
y -= 32;
// Side (East)
for (int i = 0; i < bx; 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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
minZ -= 2;
if (y <= mapBottom) {
minZ += 2;
if (y < mapTop) {
minZ += 2;
}
}
z = map_get_corner_height(mapElement, 2);
result = sub_68C222(flags, x, y, z, minZ);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
y -= 32;
}
// 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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
x -= 32;
// Side (North)
for (int i = 0; i < bx; 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);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
minZ -= 2;
if (x <= mapRight) {
minZ += 2;
if (x < mapLeft) {
minZ += 2;
}
}
z = map_get_corner_height(mapElement, 4);
result = sub_68C2EA(flags, x, y, z, minZ);
if (result != MONEY32_UNDEFINED) {
totalCost += result;
}
x -= 32;
}
}
*ebx = totalCost;
}
/**