diff --git a/src/openrct2/windows/tile_inspector.c b/src/openrct2/windows/tile_inspector.c index 4fe6a50ba3..b9d8bd618d 100644 --- a/src/openrct2/windows/tile_inspector.c +++ b/src/openrct2/windows/tile_inspector.c @@ -469,8 +469,8 @@ static void window_tile_inspector_sort_elements(rct_window *w); static void window_tile_inspector_copy_element(rct_window *w); static void window_tile_inspector_paste_element(rct_window *w); static void window_tile_inspector_surface_toggle_corner(sint32 cornerIndex); -static void window_tile_inspector_track_block_height_offset(rct_map_element *mapElement, uint8 offset); -static void window_tile_inspector_track_block_set_lift(rct_map_element *mapElement, bool chain); +static void window_tile_inspector_track_block_height_offset(sint32 element_index, sint8 height_offset); +static void window_tile_inspector_track_block_set_lift(sint32 element_index, bool entire_track_block, bool chain); static void window_tile_inspector_quarter_tile_set(rct_map_element *const mapElement, const sint32 index); static void window_tile_inspector_mouseup(rct_window *w, sint32 widgetIndex); @@ -714,7 +714,7 @@ static void window_tile_inspector_paste_element(rct_window *w) ); } -static void window_tile_inspector_base_height_offset(sint16 element_index, sint8 offset) +static void window_tile_inspector_base_height_offset(sint16 element_index, sint8 height_offset) { game_do_command( TILE_INSPECTOR_ANY_BASE_HEIGHT_OFFSET, @@ -722,7 +722,7 @@ static void window_tile_inspector_base_height_offset(sint16 element_index, sint8 windowTileInspectorTileX | (windowTileInspectorTileY << 8), element_index, GAME_COMMAND_MODIFY_TILE, - offset, + height_offset, 0 ); } @@ -811,208 +811,30 @@ static void window_tile_inspector_fence_set_slope(sint32 element_index, sint32 s ); } -// Copied from track.c (track_remove), and modified for raising/lowering -// Not sure if this should be in this file, track.c, or maybe another one -static void window_tile_inspector_track_block_height_offset(rct_map_element *mapElement, uint8 offset) +static void window_tile_inspector_track_block_height_offset(sint32 element_index, sint8 height_offset) { - uint8 type = mapElement->properties.track.type; - sint16 originX = windowTileInspectorTileX << 5; - sint16 originY = windowTileInspectorTileY << 5; - sint16 originZ = mapElement->base_height * 8; - uint8 rotation = map_element_get_direction(mapElement); - uint8 rideIndex = mapElement->properties.track.ride_index; - - rct_ride* ride = get_ride(rideIndex); - const rct_preview_track* trackBlock = get_track_def_from_ride(ride, type); - trackBlock += mapElement->properties.track.sequence & 0x0F; - - uint8 originDirection = map_element_get_direction(mapElement); - switch (originDirection) { - case 0: - originX -= trackBlock->x; - originY -= trackBlock->y; - break; - case 1: - originX -= trackBlock->y; - originY += trackBlock->x; - break; - case 2: - originX += trackBlock->x; - originY += trackBlock->y; - break; - case 3: - originX += trackBlock->y; - originY -= trackBlock->x; - break; - } - - originZ -= trackBlock->z; - - trackBlock = get_track_def_from_ride(ride, type); - for (; trackBlock->index != 255; trackBlock++) { - sint16 x = originX, y = originY, z = originZ; - - switch (originDirection) { - case 0: - x += trackBlock->x; - y += trackBlock->y; - break; - case 1: - x += trackBlock->y; - y -= trackBlock->x; - break; - case 2: - x -= trackBlock->x; - y -= trackBlock->y; - break; - case 3: - x -= trackBlock->y; - y += trackBlock->x; - break; - } - - z += trackBlock->z; - - map_invalidate_tile_full(x, y); - - bool found = false; - mapElement = map_get_first_element_at(x >> 5, y >> 5); - do { - if (mapElement->base_height != z / 8) - continue; - - if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) - continue; - - if ((mapElement->type & MAP_ELEMENT_DIRECTION_MASK) != rotation) - continue; - - if ((mapElement->properties.track.sequence & 0x0F) != trackBlock->index) - continue; - - if (mapElement->properties.track.type != type) - continue; - - found = true; - break; - } while (!map_element_is_last_for_tile(mapElement++)); - - if (!found) { - log_error("Track map element part not found!"); - return; - } - - // track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when you decrease the map size. - openrct2_assert(map_get_surface_element_at(x >> 5, y >> 5) != NULL, "No surface at %d,%d", x >> 5, y >> 5); - - // Keep? - //invalidate_test_results(ride_index); - - mapElement->base_height += offset; - mapElement->clearance_height += offset; - } + game_do_command( + TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET, + GAME_COMMAND_FLAG_APPLY, + windowTileInspectorTileX | (windowTileInspectorTileY << 8), + element_index, + GAME_COMMAND_MODIFY_TILE, + height_offset, + 0 + ); } -// Sets chainlift for entire block -// Basically a copy of the above function, with just two different lines... should probably be combined somehow -static void window_tile_inspector_track_block_set_lift(rct_map_element *mapElement, bool chain) +static void window_tile_inspector_track_block_set_lift(sint32 element_index, bool entire_track_block, bool chain) { - uint8 type = mapElement->properties.track.type; - sint16 originX = windowTileInspectorTileX << 5; - sint16 originY = windowTileInspectorTileY << 5; - sint16 originZ = mapElement->base_height * 8; - uint8 rotation = map_element_get_direction(mapElement); - uint8 rideIndex = mapElement->properties.track.ride_index; - rct_ride* ride = get_ride(rideIndex); - const rct_preview_track* trackBlock = get_track_def_from_ride(ride, type); - trackBlock += mapElement->properties.track.sequence & 0x0F; - - uint8 originDirection = map_element_get_direction(mapElement); - switch (originDirection) { - case 0: - originX -= trackBlock->x; - originY -= trackBlock->y; - break; - case 1: - originX -= trackBlock->y; - originY += trackBlock->x; - break; - case 2: - originX += trackBlock->x; - originY += trackBlock->y; - break; - case 3: - originX += trackBlock->y; - originY -= trackBlock->x; - break; - } - - originZ -= trackBlock->z; - - trackBlock = get_track_def_from_ride(ride, type); - for (; trackBlock->index != 255; trackBlock++) { - sint16 x = originX, y = originY, z = originZ; - - switch (originDirection) { - case 0: - x += trackBlock->x; - y += trackBlock->y; - break; - case 1: - x += trackBlock->y; - y -= trackBlock->x; - break; - case 2: - x -= trackBlock->x; - y -= trackBlock->y; - break; - case 3: - x -= trackBlock->y; - y += trackBlock->x; - break; - } - - z += trackBlock->z; - - map_invalidate_tile_full(x, y); - - bool found = false; - mapElement = map_get_first_element_at(x >> 5, y >> 5); - do { - if (mapElement->base_height != z / 8) - continue; - - if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) - continue; - - if ((mapElement->type & MAP_ELEMENT_DIRECTION_MASK) != rotation) - continue; - - if ((mapElement->properties.track.sequence & 0x0F) != trackBlock->index) - continue; - - if (mapElement->properties.track.type != type) - continue; - - found = true; - break; - } while (!map_element_is_last_for_tile(mapElement++)); - - if (!found) { - log_error("Track map element part not found!"); - return; - } - - // track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when you decrease the map size. - openrct2_assert(map_get_surface_element_at(x >> 5, y >> 5) != NULL, "No surface at %d,%d", x >> 5, y >> 5); - - // Keep? - //invalidate_test_results(ride_index); - - if (track_element_is_lift_hill(mapElement) != chain) { - mapElement->type ^= TRACK_ELEMENT_FLAG_CHAIN_LIFT; - } - } + game_do_command( + TILE_INSPECTOR_TRACK_SET_CHAIN, + GAME_COMMAND_FLAG_APPLY, + windowTileInspectorTileX | (windowTileInspectorTileY << 8), + element_index, + GAME_COMMAND_MODIFY_TILE, + entire_track_block, + chain + ); } static void window_tile_inspector_quarter_tile_set(rct_map_element *const mapElement, const sint32 index) @@ -1170,33 +992,27 @@ static void window_tile_inspector_mouseup(rct_window *w, sint32 widgetIndex) break; case WIDX_TRACK_SPINNER_HEIGHT_INCREASE: if (widget_is_pressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL)) { - window_tile_inspector_track_block_height_offset(mapElement, 1); + window_tile_inspector_track_block_height_offset(w->selected_list_item, 1); } else { window_tile_inspector_base_height_offset(w->selected_list_item, 1); } - widget_invalidate(w, WIDX_TRACK_SPINNER_HEIGHT); break; case WIDX_TRACK_SPINNER_HEIGHT_DECREASE: if (widget_is_pressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL)) { - window_tile_inspector_track_block_height_offset(mapElement, -1); + window_tile_inspector_track_block_height_offset(w->selected_list_item, -1); } else { window_tile_inspector_base_height_offset(w->selected_list_item, -1); } - widget_invalidate(w, WIDX_TRACK_SPINNER_HEIGHT); break; case WIDX_TRACK_CHECK_CHAIN_LIFT: - if (widget_is_pressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL)) { - bool new_lift = !track_element_is_lift_hill(mapElement); - window_tile_inspector_track_block_set_lift(mapElement, new_lift); - } - else { - mapElement->type ^= TRACK_ELEMENT_FLAG_CHAIN_LIFT; - map_invalidate_tile_full(windowTileInspectorTileX << 5, windowTileInspectorTileY << 5); - } - widget_invalidate(w, widgetIndex); + { + bool entire_track_block = widget_is_pressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL); + bool new_lift = !track_element_is_lift_hill(mapElement); + window_tile_inspector_track_block_set_lift(w->selected_list_item, entire_track_block, new_lift); break; + } } // switch widget index break; diff --git a/src/openrct2/world/map.c b/src/openrct2/world/map.c index 385f77aa43..f1eda61a7b 100644 --- a/src/openrct2/world/map.c +++ b/src/openrct2/world/map.c @@ -5657,7 +5657,7 @@ void game_command_modify_tile(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx { const sint16 element_index = *edx; const sint8 height_offset = *edi; - *ebx = tile_inspector_change_base_height_at(x, y, element_index, height_offset, flags); + *ebx = tile_inspector_any_base_height_offset(x, y, element_index, height_offset, flags); return; } case TILE_INSPECTOR_SURFACE_SHOW_PARK_FENCES: @@ -5698,6 +5698,21 @@ void game_command_modify_tile(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx *ebx = tile_inspector_fence_set_slope(x, y, element_index, slope_value, flags); return; } + case TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET: + { + const sint32 element_index = *edx; + const sint8 height_offset = *edi; + *ebx = tile_inspector_track_base_height_offset(x, y, element_index, height_offset, flags); + return; + } + case TILE_INSPECTOR_TRACK_SET_CHAIN: + { + const sint32 element_index = *edx; + const bool entire_track_block = *edi; + const bool set_chain = *ebp; + *ebx = tile_inspector_track_set_chain(x, y, element_index, entire_track_block, set_chain, flags); + return; + } default: log_error("invalid instruction"); *ebx = MONEY32_UNDEFINED; diff --git a/src/openrct2/world/tile_inspector.c b/src/openrct2/world/tile_inspector.c index 148a6b6ade..59ff1674d2 100644 --- a/src/openrct2/world/tile_inspector.c +++ b/src/openrct2/world/tile_inspector.c @@ -18,6 +18,7 @@ #include "../core/Guard.hpp" #include "../game.h" #include "../interface/window.h" +#include "../ride/track.h" #include "../windows/tile_inspector.h" #include "footpath.h" #include "map.h" @@ -320,7 +321,7 @@ sint32 tile_inspector_sort_elements_at(sint32 x, sint32 y, sint32 flags) return 0; } -sint32 tile_inspector_change_base_height_at(sint32 x, sint32 y, sint16 element_index, sint8 height_offset, sint32 flags) +sint32 tile_inspector_any_base_height_offset(sint32 x, sint32 y, sint16 element_index, sint8 height_offset, sint32 flags) { rct_map_element *const map_element = map_get_first_element_at(x, y) + element_index; sint16 new_base_height = (sint16)map_element->base_height + height_offset; @@ -541,3 +542,263 @@ sint32 tile_inspector_fence_set_slope(sint32 x, sint32 y, sint32 element_index, return 0; } + +// Changes the height of all track elements that belong to the same track piece +// Broxzier: Copied from track_remove and stripped of unneeded code, but I think this should be smaller +sint32 tile_inspector_track_base_height_offset(sint32 x, sint32 y, sint32 element_index, sint8 offset, sint32 flags) +{ + rct_map_element *const track_element = map_get_first_element_at(x, y) + element_index; + + if (offset == 0) + { + return MONEY32_UNDEFINED; + } + + if (!track_element || map_element_get_type(track_element) != MAP_ELEMENT_TYPE_TRACK) + { + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) + { + uint8 type = track_element->properties.track.type; + sint16 originX = windowTileInspectorTileX << 5; + sint16 originY = windowTileInspectorTileY << 5; + sint16 originZ = track_element->base_height * 8; + uint8 rotation = map_element_get_direction(track_element); + uint8 rideIndex = track_element->properties.track.ride_index; + rct_ride* ride = get_ride(rideIndex); + const rct_preview_track* trackBlock = get_track_def_from_ride(ride, type); + trackBlock += track_element->properties.track.sequence & 0x0F; + + uint8 originDirection = map_element_get_direction(track_element); + switch (originDirection) + { + case 0: + originX -= trackBlock->x; + originY -= trackBlock->y; + break; + case 1: + originX -= trackBlock->y; + originY += trackBlock->x; + break; + case 2: + originX += trackBlock->x; + originY += trackBlock->y; + break; + case 3: + originX += trackBlock->y; + originY -= trackBlock->x; + break; + } + + originZ -= trackBlock->z; + + trackBlock = get_track_def_from_ride(ride, type); + for (; trackBlock->index != 255; trackBlock++) + { + sint16 elem_x = originX, elem_y = originY, elem_z = originZ; + + switch (originDirection) + { + case 0: + elem_x += trackBlock->x; + elem_y += trackBlock->y; + break; + case 1: + elem_x += trackBlock->y; + elem_y -= trackBlock->x; + break; + case 2: + elem_x -= trackBlock->x; + elem_y -= trackBlock->y; + break; + case 3: + elem_x -= trackBlock->y; + elem_y += trackBlock->x; + break; + } + + elem_z += trackBlock->z; + + map_invalidate_tile_full(elem_x, elem_y); + + bool found = false; + rct_map_element *map_element = map_get_first_element_at(elem_x >> 5, elem_y >> 5); + do + { + if (map_element->base_height != elem_z / 8) + continue; + + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_TRACK) + continue; + + if ((map_element->type & MAP_ELEMENT_DIRECTION_MASK) != rotation) + continue; + + if ((map_element->properties.track.sequence & 0x0F) != trackBlock->index) + continue; + + if (map_element->properties.track.type != type) + continue; + + found = true; + break; + } while (!map_element_is_last_for_tile(map_element++)); + + if (!found) + { + log_error("Track map element part not found!"); + return MONEY32_UNDEFINED; + } + + // track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when you decrease the map size. + openrct2_assert(map_get_surface_element_at(elem_x >> 5, elem_y >> 5) != NULL, "No surface at %d,%d", elem_x >> 5, elem_y >> 5); + + // Keep? + //invalidate_test_results(ride_index); + + map_element->base_height += offset; + map_element->clearance_height += offset; + } + } + + // TODO: Only invalidate when one of the affacted tiles is selected + window_invalidate_by_class(WC_TILE_INSPECTOR); + + return 0; +} + +// Sets chainlift, optionally for an entire track block +// Broxzier: Basically a copy of the above function, with just two different lines... should probably be combined somehow +sint32 tile_inspector_track_set_chain(sint32 xx, sint32 yy, sint32 element_index, bool entire_track_block, bool set_chain, sint32 flags) +{ + rct_map_element *const track_element = map_get_first_element_at(xx, yy) + element_index; + + if (!track_element || map_element_get_type(track_element) != MAP_ELEMENT_TYPE_TRACK) + { + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) + { + if (!entire_track_block) + { + // Set chain for only the selected piece + if (track_element_is_lift_hill(track_element) != set_chain) + { + track_element->type ^= TRACK_ELEMENT_FLAG_CHAIN_LIFT; + } + + return 0; + } + + uint8 type = track_element->properties.track.type; + sint16 originX = windowTileInspectorTileX << 5; + sint16 originY = windowTileInspectorTileY << 5; + sint16 originZ = track_element->base_height * 8; + uint8 rotation = map_element_get_direction(track_element); + uint8 rideIndex = track_element->properties.track.ride_index; + rct_ride* ride = get_ride(rideIndex); + const rct_preview_track* trackBlock = get_track_def_from_ride(ride, type); + trackBlock += track_element->properties.track.sequence & 0x0F; + + uint8 originDirection = map_element_get_direction(track_element); + switch (originDirection) + { + case 0: + originX -= trackBlock->x; + originY -= trackBlock->y; + break; + case 1: + originX -= trackBlock->y; + originY += trackBlock->x; + break; + case 2: + originX += trackBlock->x; + originY += trackBlock->y; + break; + case 3: + originX += trackBlock->y; + originY -= trackBlock->x; + break; + } + + originZ -= trackBlock->z; + + trackBlock = get_track_def_from_ride(ride, type); + for (; trackBlock->index != 255; trackBlock++) + { + sint16 elem_x = originX, elem_y = originY, elem_z = originZ; + + switch (originDirection) + { + case 0: + elem_x += trackBlock->x; + elem_y += trackBlock->y; + break; + case 1: + elem_x += trackBlock->y; + elem_y -= trackBlock->x; + break; + case 2: + elem_x -= trackBlock->x; + elem_y -= trackBlock->y; + break; + case 3: + elem_x -= trackBlock->y; + elem_y += trackBlock->x; + break; + } + + elem_z += trackBlock->z; + + map_invalidate_tile_full(elem_x, elem_y); + + bool found = false; + rct_map_element *map_element = map_get_first_element_at(elem_x >> 5, elem_y >> 5); + do + { + if (map_element->base_height != elem_z / 8) + continue; + + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_TRACK) + continue; + + if ((map_element->type & MAP_ELEMENT_DIRECTION_MASK) != rotation) + continue; + + if ((map_element->properties.track.sequence & 0x0F) != trackBlock->index) + continue; + + if (map_element->properties.track.type != type) + continue; + + found = true; + break; + } while (!map_element_is_last_for_tile(map_element++)); + + if (!found) + { + log_error("Track map element part not found!"); + return MONEY32_UNDEFINED; + } + + // track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when you decrease the map size. + openrct2_assert(map_get_surface_element_at(elem_x >> 5, elem_y >> 5) != NULL, "No surface at %d,%d", elem_x >> 5, elem_y >> 5); + + // Keep? + //invalidate_test_results(ride_index); + + if (track_element_is_lift_hill(map_element) != set_chain) + { + map_element->type ^= TRACK_ELEMENT_FLAG_CHAIN_LIFT; + } + } + } + + // TODO: Only invalidate when one of the affacted tiles is selected + window_invalidate_by_class(WC_TILE_INSPECTOR); + + return 0; +} diff --git a/src/openrct2/world/tile_inspector.h b/src/openrct2/world/tile_inspector.h index 2bfd26a3c3..7a03005a80 100644 --- a/src/openrct2/world/tile_inspector.h +++ b/src/openrct2/world/tile_inspector.h @@ -46,6 +46,8 @@ typedef enum { TILE_INSPECTOR_PATH_SET_SLOPE, TILE_INSPECTOR_PATH_TOGGLE_EDGE, TILE_INSPECTOR_FENCE_SET_SLOPE, + TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET, + TILE_INSPECTOR_TRACK_SET_CHAIN, } tile_inspector_instruction; sint32 tile_inspector_insert_corrupt_at(sint32 x, sint32 y, sint16 element_index, sint32 flags); @@ -54,10 +56,12 @@ sint32 tile_inspector_swap_elements_at(sint32 x, sint32 y, sint16 first, sint16 sint32 tile_inspector_rotate_element_at(sint32 x, sint32 y, sint32 element_index, sint32 flags); sint32 tile_inspector_paste_element_at(sint32 x, sint32 y, rct_map_element element, sint32 flags); sint32 tile_inspector_sort_elements_at(sint32 x, sint32 y, sint32 flags); -sint32 tile_inspector_change_base_height_at(sint32 x, sint32 y, sint16 element_index, sint8 height_offset, sint32 flags); +sint32 tile_inspector_any_base_height_offset(sint32 x, sint32 y, sint16 element_index, sint8 height_offset, sint32 flags); sint32 tile_inspector_surface_show_park_fences(sint32 x, sint32 y, bool enabled, sint32 flags); sint32 tile_inspector_surface_toggle_corner(sint32 x, sint32 y, sint32 corner_index, sint32 flags); sint32 tile_inspector_surface_toggle_diagonal(sint32 x, sint32 y, sint32 flags); sint32 tile_inspector_path_set_sloped(sint32 x, sint32 y, sint32 element_index, bool sloped, sint32 flags); sint32 tile_inspector_path_toggle_edge(sint32 x, sint32 y, sint32 element_index, sint32 corner_index, sint32 flags); sint32 tile_inspector_fence_set_slope(sint32 x, sint32 y, sint32 element_index, sint32 slope_value, sint32 flags); +sint32 tile_inspector_track_base_height_offset(sint32 x, sint32 y, sint32 element_index, sint8 offset, sint32 flags); +sint32 tile_inspector_track_set_chain(sint32 x, sint32 y, sint32 element_index, bool entire_track_block, bool set_chain, sint32 flags);