diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 35d60909ee..41cb43ed47 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -1955,7 +1955,7 @@ void sub_68862C() * mapElement: edx * viewport: edi */ -void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *interactionType, rct_map_element **mapElement, rct_viewport **viewport) +void get_map_coordinates_from_pos(int screenX, int screenY, int flags, sint16 *x, sint16 *y, int *interactionType, rct_map_element **mapElement, rct_viewport **viewport) { RCT2_GLOBAL(0x9AC154, uint16_t) = flags & 0xFFFF; RCT2_GLOBAL(0x9AC148, uint8_t) = 0; @@ -1994,7 +1994,7 @@ void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, i if (viewport != NULL) *viewport = myviewport; } if (interactionType != NULL) *interactionType = RCT2_GLOBAL(0x9AC148, uint8_t); - if (x != NULL) *x = (int)RCT2_GLOBAL(0x9AC14C, int16_t); - if (y != NULL) *y = (int)RCT2_GLOBAL(0x9AC14E, int16_t); + if (x != NULL) *x = RCT2_GLOBAL(0x9AC14C, int16_t); + if (y != NULL) *y = RCT2_GLOBAL(0x9AC14E, int16_t); if (mapElement != NULL) *mapElement = RCT2_GLOBAL(0x9AC150, rct_map_element*); } \ No newline at end of file diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index 5167793671..490c6c6eca 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -1792,6 +1792,140 @@ void top_toolbar_tool_update_land(sint16 x, sint16 y){ } } +/** +* +* rct2: 0x006E6BDC +*/ +void top_toolbar_tool_update_water(sint16 x, sint16 y){ + map_invalidate_selection_rect(); + + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) == 3){ + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))) + return; + + money32 lower_cost = lower_water( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16), + 0); + + money32 raise_cost = raise_water( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16), + 0); + + if (RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_WATER); + } + return; + } + + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); + + rct_xy16 mapTile = { 0 }; + int interaction_type = 0; + get_map_coordinates_from_pos( + x, + y, + VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER, + &mapTile.x, + &mapTile.y, + &interaction_type, + NULL, + NULL); + + if (interaction_type == VIEWPORT_INTERACTION_ITEM_NONE){ + if (RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) != MONEY32_UNDEFINED || + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) != MONEY32_UNDEFINED){ + RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) = MONEY32_UNDEFINED; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) = MONEY32_UNDEFINED; + window_invalidate_by_class(WC_WATER); + } + return; + } + + mapTile.x += 16; + mapTile.y += 16; + + uint8 state_changed = 0; + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) != 4){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; + state_changed++; + } + + sint16 tool_size = RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16); + 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; + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + state_changed++; + } + + mapTile.x += tool_length; + mapTile.y += tool_length; + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + state_changed++; + } + + map_invalidate_selection_rect(); + if (!state_changed) + return; + + money32 lower_cost = lower_water( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16), + 0); + + money32 raise_cost = raise_water( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16), + 0); + + if (RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_WATER); + } +} + /** * * rct2: 0x0066CB25 diff --git a/src/world/map.c b/src/world/map.c index c84d6248a0..7086d14a7f 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1560,68 +1560,59 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i *ebx = cost; } -/** - * - * rct2: 0x006E66A0 - */ -void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) -{ - int ax = (uint16)*eax; - int ay = (uint16)*ecx; - int bx = (uint16)*edi; - int by = (uint16)*ebp; - - int cost = 0; +money32 raise_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags){ + money32 cost = 0; uint8 max_height = 0xFF; - for(int yi = ay; yi <= by; yi += 32){ - for(int xi = ax; xi <= bx; xi += 32){ + for (int yi = y0; yi <= y1; yi += 32){ + for (int xi = x0; xi <= x1; xi += 32){ rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); uint8 height = map_element->base_height; - if(map_element->properties.surface.terrain & 0x1F){ + if (map_element->properties.surface.terrain & 0x1F){ height = (map_element->properties.surface.terrain & 0x1F) * 2; } - if(max_height > height){ + if (max_height > height){ max_height = height; } } } - for(int yi = ay; yi <= by; yi += 32){ - for(int xi = ax; xi <= bx; xi += 32){ + for (int yi = y0; yi <= y1; yi += 32){ + for (int xi = x0; xi <= x1; xi += 32){ rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); - - if(map_element->base_height <= max_height){ + + if (map_element->base_height <= max_height){ uint8 height = (map_element->properties.surface.terrain & 0x1F); - if(height){ + if (height){ height *= 2; - if(height > max_height){ + if (height > max_height){ continue; } height += 2; - }else{ + } + else{ height = map_element->base_height + 2; } - int eax2 = xi, ebx2 = *ebx, ecx2 = yi, edx2 = (max_height << 8) + height, esi2, edi2, ebp2; - ebx2 = game_do_command_p(GAME_COMMAND_16, &eax2, &ebx2, &ecx2, &edx2, &esi2, &edi2, &ebp2); - if(ebx2 == MONEY32_UNDEFINED){ - *ebx = MONEY32_UNDEFINED; - return; - }else{ - cost += ebx2; + + money32 cost2 = game_do_command(GAME_COMMAND_16, xi, flags, yi, (max_height << 8) + height, 0, 0, 0); + if (cost2 == MONEY32_UNDEFINED){ + return MONEY32_UNDEFINED; + } + else{ + cost += cost2; } } } } - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - int x = ((ax + bx) / 2) + 16; - int y = ((ay + by) / 2) + 16; + if (flags & GAME_COMMAND_FLAG_APPLY){ + int x = ((x0 + x1) / 2) + 16; + int y = ((y0 + y1) / 2) + 16; int z = map_element_height(x, y); sint16 water_height_z = z >> 16; sint16 base_height_z = z; z = water_height_z; - if(!z){ + if (!z){ z = base_height_z; } RCT2_GLOBAL(0x009DEA5E, uint32) = x; @@ -1629,7 +1620,79 @@ void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, RCT2_GLOBAL(0x009DEA62, uint32) = z; sound_play_panned(SOUND_LAYING_OUT_WATER, 0x8001, x, y, z); } - *ebx = cost; + return cost; +} + +/** + * + * rct2: 0x006E66A0 + */ +void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + *ebx = raise_water( + (sint16)*eax, + (sint16)*ecx, + (sint16)*edi, + (sint16)*ebp, + (uint8)*ebx); +} + +money32 lower_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags){ + money32 cost = 0; + + uint8 min_height = 0; + + for (int yi = y0; yi <= y1; yi += 32){ + for (int xi = x0; xi <= x1; xi += 32){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + + uint8 height = map_element->properties.surface.terrain & 0x1F; + if (height){ + height *= 2; + if (height > min_height){ + min_height = height; + } + } + } + } + + for (int yi = y0; yi <= y1; yi += 32){ + for (int xi = x0; xi <= x1; xi += 32){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + + uint8 height = (map_element->properties.surface.terrain & 0x1F); + if (height){ + height *= 2; + if (height < min_height){ + continue; + } + height -= 2; + int cost2 = game_do_command(xi, flags, yi, (min_height << 8) + height, GAME_COMMAND_16, 0, 0); + if (cost2 == MONEY32_UNDEFINED){ + return MONEY32_UNDEFINED; + } + else{ + cost += cost2; + } + } + } + } + if (flags & GAME_COMMAND_FLAG_APPLY){ + int x = ((x0 + x1) / 2) + 16; + int y = ((y0 + y1) / 2) + 16; + int z = map_element_height(x, y); + sint16 water_height_z = z >> 16; + sint16 base_height_z = z; + z = water_height_z; + if (!z){ + z = base_height_z; + } + RCT2_GLOBAL(0x009DEA5E, uint32) = x; + RCT2_GLOBAL(0x009DEA60, uint32) = y; + RCT2_GLOBAL(0x009DEA62, uint32) = z; + sound_play_panned(SOUND_LAYING_OUT_WATER, 0x8001, x, y, z); + } + return cost; } /** @@ -1638,66 +1701,12 @@ void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, */ void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { - int ax = (uint16)*eax; - int ay = (uint16)*ecx; - int bx = (uint16)*edi; - int by = (uint16)*ebp; - - int cost = 0; - - uint8 min_height = 0; - - for(int yi = ay; yi <= by; yi += 32){ - for(int xi = ax; xi <= bx; xi += 32){ - rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); - - uint8 height = map_element->properties.surface.terrain & 0x1F; - if(height){ - height *= 2; - if(height > min_height){ - min_height = height; - } - } - } - } - - for(int yi = ay; yi <= by; yi += 32){ - for(int xi = ax; xi <= bx; xi += 32){ - rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); - - uint8 height = (map_element->properties.surface.terrain & 0x1F); - if(height){ - height *= 2; - if(height < min_height){ - continue; - } - height -= 2; - int ebx2 = game_do_command(xi, *ebx, yi, (min_height << 8) + height, GAME_COMMAND_16, 0, 0); - if(ebx2 == MONEY32_UNDEFINED){ - *ebx = MONEY32_UNDEFINED; - return; - }else{ - cost += ebx2; - } - } - } - } - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - int x = ((ax + bx) / 2) + 16; - int y = ((ay + by) / 2) + 16; - int z = map_element_height(x, y); - sint16 water_height_z = z >> 16; - sint16 base_height_z = z; - z = water_height_z; - if(!z){ - z = base_height_z; - } - RCT2_GLOBAL(0x009DEA5E, uint32) = x; - RCT2_GLOBAL(0x009DEA60, uint32) = y; - RCT2_GLOBAL(0x009DEA62, uint32) = z; - sound_play_panned(SOUND_LAYING_OUT_WATER, 0x8001, x, y, z); - } - *ebx = cost; + *ebx = lower_water( + (sint16)*eax, + (sint16)*ecx, + (sint16)*edi, + (sint16)*ebp, + (uint8)*ebx); } /** diff --git a/src/world/map.h b/src/world/map.h index 89d65937df..f978ed971b 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -280,6 +280,8 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); int sub_6BA278(int ebx); money32 map_clear_scenery(int x0, int y0, int x1, int y1, int flags); +money32 lower_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags); +money32 raise_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);