From 44efbd95ac4f5546ed719100304673508314bc28 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Wed, 17 Dec 2014 20:45:27 +0000 Subject: [PATCH] implement more footpath construction and window --- src/addresses.h | 3 + src/interface/window.c | 5 +- src/windows/cheats.c | 4 +- src/windows/footpath.c | 350 +++++++++++++++++++++++++------- src/windows/guest.c | 4 +- src/windows/park.c | 4 +- src/windows/ride_construction.c | 4 +- src/windows/track_place.c | 6 +- src/world/footpath.c | 20 +- src/world/footpath.h | 5 + src/world/map.c | 49 +++++ src/world/map.h | 9 + 12 files changed, 371 insertions(+), 92 deletions(-) diff --git a/src/addresses.h b/src/addresses.h index 84315f2bb9..0479a24fb6 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -236,6 +236,9 @@ #define RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y 0x00F3EF8C #define RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z 0x00F3EF8E #define RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION 0x00F3EF90 +#define RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE 0x00F3EF91 + +#define RCT2_ADDRESS_CONSTRUCT_PATH_VALID_DIRECTIONS 0x00F3EF9E #define RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS 0x00F42B6C diff --git a/src/interface/window.c b/src/interface/window.c index c94ebff4e1..e798358e10 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -1534,9 +1534,8 @@ void tool_cancel() if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) { RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_TOOL_ACTIVE; - // - RCT2_CALLPROC_EBPSAFE(0x0068AAE1); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_selection_rect(); + map_invalidate_map_selection_tiles(); // Reset map selection RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) = 0; diff --git a/src/windows/cheats.c b/src/windows/cheats.c index 276b1c398c..f41e3682a5 100644 --- a/src/windows/cheats.c +++ b/src/windows/cheats.c @@ -646,7 +646,7 @@ void window_cheats_misc_tool_update(){ if (widgetIndex != WIDX_ZERO_CLEARANCE) return; - RCT2_CALLPROC_X(0x0068AAE1, x, y, 0, 0, (int)w, 0, 0); + map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); int temp_y = y + 16; @@ -660,7 +660,7 @@ void window_cheats_misc_tool_update(){ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = eax; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = temp_y; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = temp_y; - RCT2_CALLPROC_X(0x0068AAE1, eax, temp_y, 0, 0, (int)w, 0, 0); + map_invalidate_selection_rect(); } RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; diff --git a/src/windows/footpath.c b/src/windows/footpath.c index f044314b56..6cf762177a 100644 --- a/src/windows/footpath.c +++ b/src/windows/footpath.c @@ -33,8 +33,8 @@ enum { PATH_CONSTRUCTION_MODE_LAND, - PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL, - PATH_CONSTRUCTION_MODE_2 + PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL, + PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL }; enum { @@ -146,12 +146,16 @@ static void* window_footpath_events[] = { }; money32 _window_footpath_cost; +sint8 _window_footpath_provisional_path_arrow_timer; static void window_footpath_show_footpath_types_dialog(rct_window *w, rct_widget *widget, int showQueues); static void window_footpath_set_provisional_path_at_point(int x, int y); static void window_footpath_place_path_at_point(int x, int y); +static void window_footpath_start_bridge_at_point(int screenX, int screenY); static void window_footpath_construct(); static void window_footpath_remove(); +static void window_footpath_set_enabled_and_pressed_widgets(); +static void footpath_get_next_path_info(int *type, int *x, int *y, int *z, int *slope); /** * @@ -204,7 +208,7 @@ void window_footpath_open() tool_set(window, WIDX_CONSTRUCT_ON_LAND, 17); RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0; - RCT2_CALLPROC_EBPSAFE(0x006A855C); + window_footpath_set_enabled_and_pressed_widgets(); } /** @@ -219,7 +223,7 @@ static void window_footpath_close() sub_6A7831(); viewport_set_visibility(0); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_map_selection_tiles(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2; window_invalidate_by_class(WC_TOP_TOOLBAR); hide_gridlines(); @@ -253,28 +257,28 @@ static void window_footpath_mouseup() _window_footpath_cost = MONEY32_UNDEFINED; tool_cancel(); sub_6A7831(); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_map_selection_tiles(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2; RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_LAND; tool_set(w, WIDX_CONSTRUCT_ON_LAND, 17); RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0; - RCT2_CALLPROC_EBPSAFE(0x006A855C); + window_footpath_set_enabled_and_pressed_widgets(); break; case WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL: - if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL) + if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL) break; _window_footpath_cost = MONEY32_UNDEFINED; tool_cancel(); sub_6A7831(); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_map_selection_tiles(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2; - RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL; + RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL; tool_set(w, WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL, 12); RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0; - RCT2_CALLPROC_EBPSAFE(0x006A855C); + window_footpath_set_enabled_and_pressed_widgets(); break; } } @@ -399,11 +403,10 @@ static void window_footpath_tooldown() window_tool_get_registers(w, widgetIndex, x, y); - if (widgetIndex == WIDX_CONSTRUCT_ON_LAND) { + if (widgetIndex == WIDX_CONSTRUCT_ON_LAND) window_footpath_place_path_at_point(x, y); - } else if (widgetIndex == WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL) { - RCT2_CALLPROC_X(0x006A840F, x, y, 0, 0, (int)w, 0, 0); - } + else if (widgetIndex == WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL) + window_footpath_start_bridge_at_point(x, y); } /** @@ -440,16 +443,49 @@ static void window_footpath_toolup() } } +/** + * + * rct2: 0x006A7760 + */ +static void window_footpath_update_provisional_path_for_bridge_mode(rct_window *w) +{ + int type, x, y, z, slope; + + if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) != PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL) + return; + + // Update provisional bridge mode path + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) & (1 << 1))) { + footpath_get_next_path_info(&type, &x, &y, &z, &slope); + _window_footpath_cost = footpath_provisional_set(type, x, y, z, slope); + widget_invalidate(w, WIDX_CONSTRUCT); + } + + // Update little directional arrow on provisional bridge mode path + if (--_window_footpath_provisional_path_arrow_timer < 0) { + _window_footpath_provisional_path_arrow_timer = 5; + RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) ^= PROVISIONAL_PATH_FLAG_SHOW_ARROW; + footpath_get_next_path_info(&type, &x, &y, &z, &slope); + RCT2_GLOBAL(0x009DEA48, uint16) = x; + RCT2_GLOBAL(0x009DEA4A, uint16) = y; + RCT2_GLOBAL(0x009DEA4C, uint16) = z * 8; + RCT2_GLOBAL(0x009DEA4E, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8); + if (RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) & PROVISIONAL_PATH_FLAG_SHOW_ARROW) + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 2); + else + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 2); + map_invalidate_tile_full(x, y); + } +} + /** * * rct2: 0x006A84BB */ static void window_footpath_update(rct_window *w) { - // Invalidate construct button widget_invalidate(w, WIDX_CONSTRUCT); - - RCT2_CALLPROC_EBPSAFE(0x006A7760); + window_footpath_update_provisional_path_for_bridge_mode(w); // Check tool if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_LAND) { @@ -459,7 +495,7 @@ static void window_footpath_update(rct_window *w) window_close(w); else if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != WIDX_CONSTRUCT_ON_LAND) window_close(w); - } else if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL) { + } else if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL) { if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) window_close(w); else if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_FOOTPATH) @@ -489,7 +525,9 @@ static void window_footpath_invalidate() (1 << WIDX_QUEUELINE_TYPE); // Enable / disable construct button - window_footpath_widgets[WIDX_CONSTRUCT].type = RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_LAND ? WWT_EMPTY : WWT_IMGBTN; + window_footpath_widgets[WIDX_CONSTRUCT].type = + RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL ? + WWT_IMGBTN : WWT_EMPTY; // Set footpath and queue type button images selectedPath = RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, uint16); @@ -523,9 +561,9 @@ static void window_footpath_paint() if (!(w->disabled_widgets & (1 << WIDX_CONSTRUCT))) { // Get construction image image = (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) % 4; - if (RCT2_GLOBAL(0x00F3EF91, uint8) == 2) + if (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8) == 2) image += 4; - else if (RCT2_GLOBAL(0x00F3EF91, uint8) == 6) + else if (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8) == 6) image += 8; image = RCT2_ADDRESS(0x0098D7E0, uint8)[image]; @@ -604,21 +642,21 @@ static void window_footpath_set_provisional_path_at_point(int x, int y) int z, slope, pathType; rct_map_element *mapElement; - RCT2_CALLPROC_EBPSAFE(0x0068AAE1); - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~4; + map_invalidate_selection_rect(); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 2); get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement); if (z == 0) { - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~1; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); sub_6A7831(); } else { // Check for change - if ((RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) & 2) && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_X, uint16) == x && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_Y, uint16) == y && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_Z, uint8) == mapElement->base_height) + if ((RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) & (1 << 1)) && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_X, uint16) == x && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_Y, uint16) == y && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_Z, uint8) == mapElement->base_height) return; // Set map selection - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 1; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) = x; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = y; @@ -638,8 +676,6 @@ static void window_footpath_set_provisional_path_at_point(int x, int y) } } - - /** * * rct2: 0x006A82C5 @@ -679,6 +715,51 @@ static void window_footpath_place_path_at_point(int x, int y) } } +/** + * + * rct2: 0x006A840F + */ +static void window_footpath_start_bridge_at_point(int screenX, int screenY) +{ + int x, y, z, direction; + rct_map_element *mapElement; + + sub_68A0C9(screenX, screenY, &x, &y, &direction, &mapElement); + if (x == 0x8000) + return; + + if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SURFACE) { + // ? + uint8 dl = ((mapElement->properties.surface.slope & 0x0F) << direction) & 0xFF; + uint8 dh = dl; + dl = (dl >> 4) & 0x0F; + dh = (dh & 0x0F) | dl; + z = mapElement->base_height; + if ((dh & 0x0C) == 0x0C) + z += 2; + } else { + z = mapElement->base_height; + if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) { + if (mapElement->properties.path.type & 4) { + if (direction == (mapElement->properties.path.type & 3)) + z += 2; + } + } + } + + tool_cancel(); + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) = z * 8; + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8) = direction; + RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) = 0; + _window_footpath_provisional_path_arrow_timer = 0; + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL; + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_VALID_DIRECTIONS, uint8) = 255; + window_footpath_set_enabled_and_pressed_widgets(); +} + /** * * rct2: 0x006A79B7 @@ -690,56 +771,21 @@ static void window_footpath_construct() /** * - * rct2: 0x006A7863 + * rct2: 0x006A78EF */ -static void window_footpath_remove() +static rct_map_element *footpath_remove_map_element(rct_map_element *mapElement) { - int x, y, lastTile; - rct_map_element *mapElement; + int x, y, z; - // RCT2_CALLPROC_EBPSAFE(0x006A7863); - - _window_footpath_cost = MONEY32_UNDEFINED; - sub_6A7831(); - - x = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) / 32; - y = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) / 32; - int dl = (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) >> 3) & 0xFF; - int dh = dl - 2; - - if (x >= 256 || y >= 256) - goto loc_6A79B0; - - mapElement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[y * 256 + x]; - do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) { - if (mapElement->base_height == dl) { - if (mapElement->properties.path.type & 4) - if (((mapElement->properties.path.type & 3) ^ 2) != RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8)) - continue; - goto loc_6A78EF; - } else if (mapElement->base_height == dh) { - if (!(mapElement->properties.path.type & 4)) - if ((mapElement->properties.path.type & 3) == RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8)) - continue; - goto loc_6A78EF; - } - } - lastTile = (mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE) != 0; - mapElement++; - } while (!lastTile); - goto loc_6A79B0; - -loc_6A78EF: - dl = mapElement->base_height; + z = mapElement->base_height; int pathType = mapElement->properties.path.type; if (pathType & 4) { pathType &= 3; pathType ^= 2; if (pathType == RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8)) - dl += 2; + z += 2; } - + // Find a connected edge int edge = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8) ^ 2; if (!(mapElement->properties.path.edges & (1 << edge))) { @@ -753,7 +799,7 @@ loc_6A78EF: } } } - + // Remove path RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_CANT_REMOVE_FOOTPATH_FROM_HERE; footpath_remove( @@ -765,14 +811,166 @@ loc_6A78EF: // Move selection edge ^= 2; - x = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) - RCT2_GLOBAL(0x00993CCC + (edge * 4), sint16); - y = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) - RCT2_GLOBAL(0x00993CCE + (edge * 4), sint16); + x = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) - TileDirectionDelta[edge].x; + y = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) - TileDirectionDelta[edge].y; RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) = x; RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) = y; - RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) = dl << 3; + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) = z << 3; RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8) = edge; - RCT2_GLOBAL(0x00F3EF9E, uint8) = 255; + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_VALID_DIRECTIONS, uint8) = 255; +} -loc_6A79B0: - RCT2_CALLPROC_EBPSAFE(0x006A855C); +/** + * + * rct2: 0x006A7873 + */ +static rct_map_element *footpath_get_map_element_to_remove() +{ + rct_map_element *mapElement; + int x, y, z, zLow; + + x = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) / 32; + y = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) / 32; + if (x >= 256 || y >= 256) + return NULL; + + z = (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) >> 3) & 0xFF; + zLow = z - 2; + + mapElement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[y * 256 + x]; + do { + if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) { + if (mapElement->base_height == z) { + if (mapElement->properties.path.type & 4) + if (((mapElement->properties.path.type & 3) ^ 2) != RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8)) + continue; + + return mapElement; + } else if (mapElement->base_height == zLow) { + if (!(mapElement->properties.path.type & 4)) + if ((mapElement->properties.path.type & 3) == RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8)) + continue; + + return mapElement; + } + } + } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + + return NULL; +} + +/** + * + * rct2: 0x006A7863 + */ +static void window_footpath_remove() +{ + rct_map_element *mapElement; + + _window_footpath_cost = MONEY32_UNDEFINED; + sub_6A7831(); + + mapElement = footpath_get_map_element_to_remove(); + if (mapElement != NULL) + footpath_remove_map_element(mapElement); + + window_footpath_set_enabled_and_pressed_widgets(); +} + +/** + * + * rct2: 0x006A855C + */ +static void window_footpath_set_enabled_and_pressed_widgets() +{ + rct_window *w; + uint64 pressedWidgets, disabledWidgets; + int currentRotation, direction, slope; + + w = window_find_by_class(WC_FOOTPATH); + if (w == NULL) + return; + + if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL) { + map_invalidate_map_selection_tiles(); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 1) | (1 << 3); + + direction = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8); + gMapSelectionTiles[0].x = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) + TileDirectionDelta[direction].x; + gMapSelectionTiles[0].y = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) + TileDirectionDelta[direction].y; + gMapSelectionTiles[1].x = -1; + map_invalidate_map_selection_tiles(); + } + + pressedWidgets = w->pressed_widgets & 0xFFFF887F; + disabledWidgets = 0; + currentRotation = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8); + if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) >= PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL) { + // Set pressed directional widget + direction = (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8) + currentRotation) & 3; + pressedWidgets |= (1LL << (WIDX_DIRECTION_NW + direction)); + + // Set pressed slope widget + slope = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8); + if (slope == 6) + pressedWidgets |= (1 << WIDX_SLOPEDOWN); + else if (slope == 0) + pressedWidgets |= (1 << WIDX_LEVEL); + else + pressedWidgets |= (1 << WIDX_SLOPEUP); + + // Enable / disable directional widgets + direction = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_VALID_DIRECTIONS, uint8); + if (direction != 255) { + disabledWidgets |= + (1 << WIDX_DIRECTION_NW) | + (1 << WIDX_DIRECTION_NE) | + (1 << WIDX_DIRECTION_SW) | + (1 << WIDX_DIRECTION_SE); + + direction = (direction + currentRotation) & 3; + disabledWidgets &= ~(1 << (WIDX_DIRECTION_NW + direction)); + } + } else { + // Disable all bridge mode widgets + disabledWidgets |= + (1 << WIDX_DIRECTION_GROUP) | + (1 << WIDX_DIRECTION_NW) | + (1 << WIDX_DIRECTION_NE) | + (1 << WIDX_DIRECTION_SW) | + (1 << WIDX_DIRECTION_SE) | + (1 << WIDX_SLOPE_GROUP) | + (1 << WIDX_SLOPEDOWN) | + (1 << WIDX_LEVEL) | + (1 << WIDX_SLOPEUP) | + (1 << WIDX_CONSTRUCT) | + (1 << WIDX_REMOVE); + } + + w->pressed_widgets = pressedWidgets; + w->disabled_widgets = disabledWidgets; + window_invalidate(w); +} + +/** + * + * rct2: 0x006A7B20 + */ +static void footpath_get_next_path_info(int *type, int *x, int *y, int *z, int *slope) +{ + int direction; + + direction = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8); + *x = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) + TileDirectionDelta[direction].x; + *y = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) + TileDirectionDelta[direction].y; + *z = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) / 8; + *type = (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_TYPE, uint8) << 7) + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, uint8); + *slope = 0; + if (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8) != 0) { + *slope = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8) | 4; + if (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8) != 2) { + *z -= 2; + *slope ^= 2; + } + } } \ No newline at end of file diff --git a/src/windows/guest.c b/src/windows/guest.c index a267270916..42fcf4ea8c 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -1136,7 +1136,7 @@ void window_guest_overview_tool_update(){ if (widgetIndex != WIDX_PICKUP) return; - RCT2_CALLPROC_X(0x0068AAE1, x, y, 0, 0, (int)w, 0, 0); + map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); int temp_y = y + 16; @@ -1150,7 +1150,7 @@ void window_guest_overview_tool_update(){ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = eax; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = temp_y; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = temp_y; - RCT2_CALLPROC_X(0x0068AAE1, eax, temp_y, 0, 0, (int)w, 0, 0); + map_invalidate_selection_rect(); } RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; diff --git a/src/windows/park.c b/src/windows/park.c index 23087aa8de..3b980c2d01 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -793,7 +793,7 @@ static void window_park_entrance_toolupdate() window_tool_get_registers(w, widgetIndex, x, y); if (widgetIndex == WIDX_BUY_LAND_RIGHTS) { - RCT2_CALLPROC_X(0x0068AAE1, x, y, 0, 0, (int)w, 0, 0); + map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= 0xFFFE; screen_pos_to_map_pos(&x, &y); if (x != SPRITE_LOCATION_NULL) { @@ -803,7 +803,7 @@ static void window_park_entrance_toolupdate() RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = x; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = y; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = y; - RCT2_CALLPROC_X(0x0068AAE1, x, y, 0, 0, (int)w, 0, 0); + map_invalidate_selection_rect(); } } } diff --git a/src/windows/ride_construction.c b/src/windows/ride_construction.c index 2e9a31a637..6e2965da92 100644 --- a/src/windows/ride_construction.c +++ b/src/windows/ride_construction.c @@ -197,7 +197,7 @@ void window_construction_close(){ RCT2_CALLPROC_X(0x006C9627, 0, 0, 0, 0, 0, 0, 0); viewport_set_visibility(0); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_map_selection_tiles(); RCT2_GLOBAL(0x9DE58A, uint16) &= 0xFFFD; hide_gridlines(); @@ -228,7 +228,7 @@ void window_construction_maze_close(){ RCT2_CALLPROC_X(0x006C9627, 0, 0, 0, 0, 0, 0, 0); viewport_set_visibility(0); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_map_selection_tiles(); RCT2_GLOBAL(0x9DE58A, uint16) &= 0xFFFD; hide_gridlines(); diff --git a/src/windows/track_place.c b/src/windows/track_place.c index e5e586f2d1..362d3a147f 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -453,7 +453,7 @@ static void window_track_place_close() { window_track_place_clear_provisional(); viewport_set_visibility(0); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_map_selection_tiles(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~6; hide_gridlines(); free(_window_track_place_mini_preview); @@ -520,7 +520,7 @@ static void window_track_place_toolupdate() window_tool_get_registers(w, widgetIndex, x, y); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_map_selection_tiles(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~7; // Get the tool map position @@ -583,7 +583,7 @@ static void window_track_place_tooldown() window_tool_get_registers(w, widgetIndex, x, y); window_track_place_clear_provisional(); - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + map_invalidate_map_selection_tiles(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~7; sub_68A15E(x, y, &x, &y); diff --git a/src/world/footpath.c b/src/world/footpath.c index 39b71466b7..9d995daafc 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -80,8 +80,8 @@ void footpath_provisional_remove() */ void sub_6A7831() { - if (RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) & (1 << 0)) { - RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) &= ~(1 << 0); + if (RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) & PROVISIONAL_PATH_FLAG_SHOW_ARROW) { + RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) &= ~PROVISIONAL_PATH_FLAG_SHOW_ARROW; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint8) &= ~(1 << 2); map_invalidate_tile_full( @@ -90,4 +90,20 @@ void sub_6A7831() ); } footpath_provisional_remove(); +} + +/** + * + * rct2: 0x0068A0C9 + */ +void sub_68A0C9(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + eax = screenX; + ebx = screenY; + RCT2_CALLFUNC_X(0x0068A0C9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + if (x != NULL) *x = *((uint16*)&eax); + if (y != NULL) *y = *((uint16*)&ebx); + if (direction != NULL) *direction = *((uint8*)&ecx); + if (mapElement != NULL) *mapElement = (rct_map_element*)edx; } \ No newline at end of file diff --git a/src/world/footpath.h b/src/world/footpath.h index 6030004ef7..7eeea6d4c1 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -24,6 +24,10 @@ #include "../common.h" #include "../interface/viewport.h" +enum { + PROVISIONAL_PATH_FLAG_SHOW_ARROW = (1 << 0) +}; + typedef struct { uint16 pad_00; uint32 image; // 0x02 @@ -37,5 +41,6 @@ void footpath_remove(int x, int y, int z, int flags); money32 footpath_provisional_set(int type, int x, int y, int z, int slope); void footpath_provisional_remove(); void sub_6A7831(); +void sub_68A0C9(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement); #endif diff --git a/src/world/map.c b/src/world/map.c index 4c9f8b5f42..6ec218f93f 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -26,6 +26,19 @@ #include "park.h" #include "scenery.h" +const rct_xy16 TileDirectionDelta[] = { + { -32, 0 }, + { 0, +32 }, + { +32, 0 }, + { 0, -32 }, + { -32, +32 }, + { +32, +32 }, + { +32, -32 }, + { -32, -32 } +}; + +rct_xy16 *gMapSelectionTiles = (rct_xy16*)0x009DE596; + int _sub_6A876D_save_x; int _sub_6A876D_save_y; @@ -764,4 +777,40 @@ void map_remove_all_rides() } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); } } +} + +/** + * + * rct2: 0x0068AB1B + */ +void map_invalidate_map_selection_tiles() +{ + rct_xy16 *position; + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 1))) + return; + + for (position = gMapSelectionTiles; position->x != -1; position++) + map_invalidate_tile_full(position->x, position->y); +} + +/** + * + * rct2: 0x0068AAE1 + */ +void map_invalidate_selection_rect() +{ + int x, y, x0, y0, x1, y1; + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))) + return; + + x0 = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16); + y0 = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16); + x1 = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16); + y1 = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16); + + for (x = x0; x <= x1; x++) + for (y = y0; y <= y1; y++) + map_invalidate_tile_full(x, y); } \ No newline at end of file diff --git a/src/world/map.h b/src/world/map.h index 907d9e9828..044c8acd75 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -210,6 +210,13 @@ typedef struct { uint8 direction; } rct2_peep_spawn; +typedef struct { + sint16 x; + sint16 y; +} rct_xy16; + +extern const rct_xy16 TileDirectionDelta[]; +extern rct_xy16 *gMapSelectionTiles; void map_init(); void map_update_tile_pointers(); @@ -232,6 +239,8 @@ int map_get_station(rct_map_element *mapElement); void map_element_remove(rct_map_element *mapElement); void sub_6A6AA7(int x, int y, rct_map_element *mapElement); void map_remove_all_rides(); +void map_invalidate_map_selection_tiles(); +void map_invalidate_selection_rect(); void fountain_update_all();