From c4504323c8416f1b4b26728d5839eb1888b91818 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sun, 5 Jul 2015 16:47:22 +0100 Subject: [PATCH 1/2] implement-editor-callprocs, part 1 --- src/localisation/string_ids.h | 1 + src/windows/editor_bottom_toolbar.c | 142 ++++++++++++++++++++++++-- src/world/footpath.c | 153 ++++++++++++++++++++++++++++ src/world/footpath.h | 4 + 4 files changed, 289 insertions(+), 11 deletions(-) diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 0b0cc8eceb..73519e94d6 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -1625,6 +1625,7 @@ enum { STR_OBJECTIVE = 3322, + STR_PEEP_SPAWNS_NOT_SET = 3327, STR_CANT_ADVANCE_TO_NEXT_EDITOR_STAGE = 3328, STR_NO_PARK_ENTRANCES = 3329, STR_PARK_MUST_OWN_SOME_LAND = 3330, diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c index dfc63d52db..bd7528837f 100644 --- a/src/windows/editor_bottom_toolbar.c +++ b/src/windows/editor_bottom_toolbar.c @@ -25,15 +25,16 @@ #include "../scenario.h" #include "../sprites.h" #include "../localisation/localisation.h" +#include "../interface/themes.h" #include "../interface/viewport.h" #include "../interface/widget.h" #include "../interface/window.h" #include "../platform/platform.h" #include "../title.h" #include "../util/util.h" +#include "../world/footpath.h" #include "../world/scenery.h" #include "error.h" -#include "../interface/themes.h" enum { WIDX_PREVIOUS_IMAGE, // 1 @@ -153,13 +154,23 @@ void window_editor_bottom_toolbar_jump_back_to_object_selection() { gfx_invalidate_screen(); } +/** + * + * rct2: 0x006DFED0 + */ +static void sub_6DFED0() +{ + for (int i = 0; i < 56; i++) + RCT2_ADDRESS(0x01357BD0, sint32)[i] = -1; +} + /** * * rct2: 0x0066F62C */ void window_editor_bottom_toolbar_jump_back_to_landscape_editor() { window_close_all(); - RCT2_CALLPROC_EBPSAFE(0x006DFED0); + sub_6DFED0(); scenery_set_default_placement_configuration(); g_editor_step = EDITOR_STEP_LANDSCAPE_EDITOR; window_map_open(); @@ -199,13 +210,60 @@ void window_editor_bottom_toolbar_jump_back_to_options_selection() { gfx_invalidate_screen(); } +/** + * + * rct2: 0x006AB9B8 + */ +static bool editor_check_object_selection() +{ + return !(RCT2_CALLPROC_EBPSAFE(0x006AB9B8) & 0x100); +} + /** * * rct2: 0x006AB1CE */ -int window_editor_bottom_toolbar_check_object_selection() +bool window_editor_bottom_toolbar_check_object_selection() { - return RCT2_CALLPROC_EBPSAFE(0x006AB1CE) & 0x100; + rct_window *w; + + if (editor_check_object_selection()) { + window_close_by_class(WC_EDITOR_OBJECT_SELECTION); + return true; + } + + window_error_open(STR_INVALID_SELECTION_OF_OBJECTS, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id)); + w = window_find_by_class(WC_EDITOR_OBJECT_SELECTION); + if (w != NULL) { + // Click first tab (rides) + window_event_mouse_up_call(w, 4); + } + return false; +} + +/** + * + * rct2: 0x0066F6E3 + */ +static void sub_66F6E3() +{ + RCT2_GLOBAL(0x01357404, uint32) = 0xFFFFFFFF; + RCT2_GLOBAL(0x01357408, uint32) = 0xFFFFFFFF; + RCT2_GLOBAL(0x0135740C, uint32) = 0xFFFFFFFF; + RCT2_GLOBAL(0x01357410, uint32) = 0xFFFFFFFF; + + for (int i = 0; i < 128; i++) { + RCT2_ADDRESS(0x01357444, uint32)[i] = RCT2_ADDRESS(0x0097C468, uint32)[i]; + RCT2_ADDRESS(0x01357644, uint32)[i] = RCT2_ADDRESS(0x0097C5D4, uint32)[i]; + } + + for (int i = 0; i < 8; i++) { + RCT2_ADDRESS(0x01357424, uint32)[i] = 0xFFFFFFFF; + } + + window_new_ride_open(); + RCT2_GLOBAL(0x0141F570, uint8) = 6; + gfx_invalidate_screen(); } /** @@ -214,13 +272,13 @@ int window_editor_bottom_toolbar_check_object_selection() */ void window_editor_bottom_toolbar_jump_forward_from_object_selection() { - if (window_editor_bottom_toolbar_check_object_selection()) + if (!window_editor_bottom_toolbar_check_object_selection()) return; if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) { - RCT2_CALLPROC_EBPSAFE(0x0066F6E3); + sub_66F6E3(); } else { - RCT2_CALLPROC_EBPSAFE(0x006DFED0); + sub_6DFED0(); scenery_set_default_placement_configuration(); RCT2_GLOBAL(0x00141F570, uint8) = 1; window_map_open(); @@ -228,14 +286,76 @@ void window_editor_bottom_toolbar_jump_forward_from_object_selection() } } +/** + * + * rct2: 0x0066FEAC + */ +bool editor_check_park() +{ + // return !(RCT2_CALLPROC_EBPSAFE(0x0066FEAC) & 0x100); + + int parkSize = park_calculate_size(); + if (parkSize == 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_MUST_OWN_SOME_LAND; + return false; + } + + for (int i = 0; i < 4; i++) { + if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] != 0x8000) + break; + + if (i == 3) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NO_PARK_ENTRANCES; + return false; + } + } + + for (int i = 0; i < 4; i++) { + if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] == 0x8000) + continue; + + int x = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i]; + int y = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, uint16)[i]; + int z = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, uint16)[i] / 8; + int direction = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_DIRECTION, uint8)[i] ^ 2; + + // dh = 0; + // di = 0xFFFF; + RCT2_GLOBAL(0x00F1AEDC, uint8) = 16; + RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; + RCT2_GLOBAL(0x00F1AEDE, uint16) = 0; + RCT2_GLOBAL(0x00F1AEDD, uint8) = 0; + if (!footpath_is_connected_to_map_edge(x, y, z, direction, 0)) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_ENTRANCE_WRONG_DIRECTION_OR_NO_PATH; + if (RCT2_GLOBAL(0x00F1AEDD, uint8) & (1 << 6)) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_ENTRANCE_PATH_INCOMPLETE_OR_COMPLEX; + } + return false; + } + + // dh = 0; + // di = 0xFFFF; + RCT2_GLOBAL(0x00F1AEDC, uint8) = 16; + RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; + RCT2_GLOBAL(0x00F1AEDE, uint16) = 0; + RCT2_GLOBAL(0x00F1AEDD, uint8) = 0x20; + footpath_is_connected_to_map_edge(x, y, z, direction, 0x20); + } + + if (gPeepSpawns[0].x == 0xFFFF && gPeepSpawns[1].x == 0xFFFF) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PEEP_SPAWNS_NOT_SET; + return false; + } + + return true; +} + /** * -* rct2: 0x0066f758 +* rct2: 0x0066F758 */ void window_editor_bottom_toolbar_jump_forward_to_invention_list_set_up() { - uint32 flags = RCT2_CALLPROC_X(0x0066FEAC, 0, 0, 0, 0, 0, 0, 0); - - if (!(flags & 0x100)) { + if (editor_check_park()) { window_close_all(); window_editor_inventions_list_open(); g_editor_step = EDITOR_STEP_INVENTIONS_LIST_SET_UP; diff --git a/src/world/footpath.c b/src/world/footpath.c index 3e5f38a2ef..75e2228707 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -731,3 +731,156 @@ void sub_6A759F() } } } + +static void loc_69ADBD(int x, int y, rct_map_element *pathElement) +{ + int ownershipUnk = 0; + int z = pathElement->base_height; + rct_map_element *surfaceElement = map_get_surface_element_at(x >> 5, y >> 5); + if (surfaceElement->base_height |= z) { + z -= 2; + if (surfaceElement->base_height |= z) { + ownershipUnk = (surfaceElement->properties.surface.ownership & 0xCF) >> 4; + } + } + map_buy_land_rights(x, y, x, y, 6, 1); +} + +bool get_next_direction(int edges, int *direction) +{ + int index = bitscanforward(edges); + if (index == -1) + return false; + + *direction = index; + return true; +} + +/** + * + * rct2: 0x0069AC1A + */ +bool footpath_is_connected_to_map_edge_recurse( + int x, int y, int z, int direction, int flags, + int level, int distanceFromJunction, int junctionTolerance +) { + // int eax, ebx, ecx, edx, esi, edi, ebp; + // RCT2_GLOBAL(0x00F1AEDC, uint8) = 16; + // RCT2_GLOBAL(0x00F1AEDD, uint8) = 0; + // RCT2_GLOBAL(0x00F1AEDE, uint16) = 0; + // RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; + // dh + // di + // edx = 0; + // edi = 0xFFFF; + // RCT2_CALLFUNC_X(0x0069AC1A, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + // return edi & 0xFFFF; + + rct_map_element *mapElement; + int edges, slopeDirection; + + x += TileDirectionDelta[direction].x; + y += TileDirectionDelta[direction].y; + if (++level > 250) + return false; + + // Check if we are at edge of map + if (x < 32 || y < 32) + return true; + if (x >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16)) + return true; + + mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_PATH) + continue; + + if (footpath_element_is_sloped(mapElement)) { + // loc_69AD78 + slopeDirection = footpath_element_get_slope_direction(mapElement); + if (slopeDirection != direction) { + if ((slopeDirection ^ 2) != direction) continue; + if (mapElement->base_height + 2 != z) continue; + + goto loc_69AD9F; + } + } + + if (mapElement->base_height != z) + continue; + + loc_69AD9F: + if (mapElement->type & RCT2_GLOBAL(0x00F1AEE0, uint8)) continue; + + flags |= 0x40; + if (flags & 0x20) { + loc_69ADBD(x, y, mapElement); + } + edges = mapElement->properties.path.edges & 0x0F; + direction ^= 2; + if ((mapElement + 1)->type == 28) { + // goto loc_69AC9C; + } + if ((mapElement + 1)->base_height == 28) { + // goto loc_69AD00; + } + goto loc_69AE22; + } while (!map_element_is_last_for_tile(mapElement++)); + return false; + +loc_69AE22: + // Exclude direction we came from + z = mapElement->base_height; + edges &= ~(1 << direction); + + // Find next direction to go + if (!get_next_direction(edges, &direction)) + return false; + + edges &= ~(1 << direction); + if (edges == 0) { + // Only possible direction to go + if (footpath_element_is_sloped(mapElement) && footpath_element_get_slope_direction(mapElement) == direction) { + z += 2; + } + return footpath_is_connected_to_map_edge_recurse( + x, y, z, direction, flags, + level, distanceFromJunction + 1, junctionTolerance + ); + } else { + // We have reached a junction + if (distanceFromJunction != 0) { + junctionTolerance--; + } + junctionTolerance--; + if (junctionTolerance < 0) + return false; + + do { + edges &= ~(1 << direction); + if (footpath_element_is_sloped(mapElement) && footpath_element_get_slope_direction(mapElement) == direction) { + z += 2; + } + if (footpath_is_connected_to_map_edge_recurse(x, y, z, direction, flags, level, 0, junctionTolerance)) { + return true; + } + } while (get_next_direction(edges, &direction)); + + return false; + } +} + +bool footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags) +{ + footpath_is_connected_to_map_edge_recurse(x, y, z, direction, flags, 0, 0, 12); +} + +bool footpath_element_is_sloped(rct_map_element *mapElement) +{ + return mapElement->properties.path.type & 4; +} + +int footpath_element_get_slope_direction(rct_map_element *mapElement) +{ + return mapElement->properties.path.type & 3; +} diff --git a/src/world/footpath.h b/src/world/footpath.h index 5d4ce3d22f..59b25b25e3 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -57,4 +57,8 @@ void sub_6A742F(int rideIndex, int entranceIndex, int x, int y, rct_map_element void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement); +bool footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags); +bool footpath_element_is_sloped(rct_map_element *mapElement); +int footpath_element_get_slope_direction(rct_map_element *mapElement); + #endif From 791c2391f55eacfbd8281777278a70016bb23803 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 6 Jul 2015 14:40:37 +0100 Subject: [PATCH 2/2] implement-editor-callprocs, part 2 --- src/editor.c | 66 ++++++++++++++++- src/editor.h | 3 + src/windows/editor_bottom_toolbar.c | 73 ------------------- src/world/footpath.c | 106 ++++++++++++++-------------- src/world/footpath.h | 9 ++- 5 files changed, 129 insertions(+), 128 deletions(-) diff --git a/src/editor.c b/src/editor.c index 8209478e56..4d92429e2c 100644 --- a/src/editor.c +++ b/src/editor.c @@ -39,6 +39,7 @@ #include "util/util.h" #include "world/banner.h" #include "world/climate.h" +#include "world/footpath.h" #include "world/map.h" #include "world/park.h" #include "world/scenery.h" @@ -599,4 +600,67 @@ static void editor_finalise_main_view() RCT2_GLOBAL(0x009DEB7C, uint16) = 0; load_palette(); gfx_invalidate_screen(); -} \ No newline at end of file +} + +/** + * + * rct2: 0x006AB9B8 + */ +bool editor_check_object_selection() +{ + return !(RCT2_CALLPROC_EBPSAFE(0x006AB9B8) & 0x100); +} + +/** + * + * rct2: 0x0066FEAC + */ +bool editor_check_park() +{ + int parkSize = park_calculate_size(); + if (parkSize == 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_MUST_OWN_SOME_LAND; + return false; + } + + for (int i = 0; i < 4; i++) { + if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] != 0x8000) + break; + + if (i == 3) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NO_PARK_ENTRANCES; + return false; + } + } + + for (int i = 0; i < 4; i++) { + if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] == 0x8000) + continue; + + int x = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i]; + int y = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, uint16)[i]; + int z = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, uint16)[i] / 8; + int direction = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_DIRECTION, uint8)[i] ^ 2; + + switch (footpath_is_connected_to_map_edge(x, y, z, direction, 0)) { + case FOOTPATH_SEARCH_NOT_FOUND: + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_ENTRANCE_WRONG_DIRECTION_OR_NO_PATH; + return false; + case FOOTPATH_SEARCH_INCOMPLETE: + case FOOTPATH_SEARCH_TOO_COMPLEX: + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_ENTRANCE_PATH_INCOMPLETE_OR_COMPLEX; + return false; + case FOOTPATH_SEARCH_SUCCESS: + // Run the search again and unown the path + footpath_is_connected_to_map_edge(x, y, z, direction, 0x20); + break; + } + } + + if (gPeepSpawns[0].x == 0xFFFF && gPeepSpawns[1].x == 0xFFFF) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PEEP_SPAWNS_NOT_SET; + return false; + } + + return true; +} diff --git a/src/editor.h b/src/editor.h index 9232dd7c59..8c0fd56699 100644 --- a/src/editor.h +++ b/src/editor.h @@ -47,4 +47,7 @@ void sub_6BD3A4(); void editor_open_windows_for_current_step(); +bool editor_check_park(); +bool editor_check_object_selection(); + #endif diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c index bd7528837f..b5c15ce0cf 100644 --- a/src/windows/editor_bottom_toolbar.c +++ b/src/windows/editor_bottom_toolbar.c @@ -210,15 +210,6 @@ void window_editor_bottom_toolbar_jump_back_to_options_selection() { gfx_invalidate_screen(); } -/** - * - * rct2: 0x006AB9B8 - */ -static bool editor_check_object_selection() -{ - return !(RCT2_CALLPROC_EBPSAFE(0x006AB9B8) & 0x100); -} - /** * * rct2: 0x006AB1CE @@ -286,70 +277,6 @@ void window_editor_bottom_toolbar_jump_forward_from_object_selection() } } -/** - * - * rct2: 0x0066FEAC - */ -bool editor_check_park() -{ - // return !(RCT2_CALLPROC_EBPSAFE(0x0066FEAC) & 0x100); - - int parkSize = park_calculate_size(); - if (parkSize == 0) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_MUST_OWN_SOME_LAND; - return false; - } - - for (int i = 0; i < 4; i++) { - if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] != 0x8000) - break; - - if (i == 3) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NO_PARK_ENTRANCES; - return false; - } - } - - for (int i = 0; i < 4; i++) { - if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] == 0x8000) - continue; - - int x = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i]; - int y = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, uint16)[i]; - int z = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, uint16)[i] / 8; - int direction = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_DIRECTION, uint8)[i] ^ 2; - - // dh = 0; - // di = 0xFFFF; - RCT2_GLOBAL(0x00F1AEDC, uint8) = 16; - RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; - RCT2_GLOBAL(0x00F1AEDE, uint16) = 0; - RCT2_GLOBAL(0x00F1AEDD, uint8) = 0; - if (!footpath_is_connected_to_map_edge(x, y, z, direction, 0)) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_ENTRANCE_WRONG_DIRECTION_OR_NO_PATH; - if (RCT2_GLOBAL(0x00F1AEDD, uint8) & (1 << 6)) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_ENTRANCE_PATH_INCOMPLETE_OR_COMPLEX; - } - return false; - } - - // dh = 0; - // di = 0xFFFF; - RCT2_GLOBAL(0x00F1AEDC, uint8) = 16; - RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; - RCT2_GLOBAL(0x00F1AEDE, uint16) = 0; - RCT2_GLOBAL(0x00F1AEDD, uint8) = 0x20; - footpath_is_connected_to_map_edge(x, y, z, direction, 0x20); - } - - if (gPeepSpawns[0].x == 0xFFFF && gPeepSpawns[1].x == 0xFFFF) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PEEP_SPAWNS_NOT_SET; - return false; - } - - return true; -} - /** * * rct2: 0x0066F758 diff --git a/src/world/footpath.c b/src/world/footpath.c index 75e2228707..a57491cfe2 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -732,7 +732,11 @@ void sub_6A759F() } } -static void loc_69ADBD(int x, int y, rct_map_element *pathElement) +/** + * + * rct2: 0x0069ADBD + */ +static void footpath_unown(int x, int y, rct_map_element *pathElement) { int ownershipUnk = 0; int z = pathElement->base_height; @@ -760,82 +764,75 @@ bool get_next_direction(int edges, int *direction) * * rct2: 0x0069AC1A */ -bool footpath_is_connected_to_map_edge_recurse( +int footpath_is_connected_to_map_edge_recurse( int x, int y, int z, int direction, int flags, int level, int distanceFromJunction, int junctionTolerance ) { - // int eax, ebx, ecx, edx, esi, edi, ebp; - // RCT2_GLOBAL(0x00F1AEDC, uint8) = 16; - // RCT2_GLOBAL(0x00F1AEDD, uint8) = 0; - // RCT2_GLOBAL(0x00F1AEDE, uint16) = 0; - // RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; - // dh - // di - // edx = 0; - // edi = 0xFFFF; - // RCT2_CALLFUNC_X(0x0069AC1A, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - // return edi & 0xFFFF; - rct_map_element *mapElement; int edges, slopeDirection; x += TileDirectionDelta[direction].x; y += TileDirectionDelta[direction].y; if (++level > 250) - return false; + return FOOTPATH_SEARCH_TOO_COMPLEX; // Check if we are at edge of map if (x < 32 || y < 32) - return true; + return FOOTPATH_SEARCH_SUCCESS; if (x >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16)) - return true; + return FOOTPATH_SEARCH_SUCCESS; mapElement = map_get_first_element_at(x >> 5, y >> 5); do { if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_PATH) continue; - if (footpath_element_is_sloped(mapElement)) { - // loc_69AD78 - slopeDirection = footpath_element_get_slope_direction(mapElement); - if (slopeDirection != direction) { - if ((slopeDirection ^ 2) != direction) continue; - if (mapElement->base_height + 2 != z) continue; - - goto loc_69AD9F; - } + if ( + footpath_element_is_sloped(mapElement) && + (slopeDirection = footpath_element_get_slope_direction(mapElement)) != direction + ) { + if ((slopeDirection ^ 2) != direction) continue; + if (mapElement->base_height + 2 != z) continue; + } else if (mapElement->base_height != z) { + continue; } - if (mapElement->base_height != z) - continue; + if (mapElement->type & RCT2_GLOBAL(0x00F1AEE0, uint8)) continue; - loc_69AD9F: - if (mapElement->type & RCT2_GLOBAL(0x00F1AEE0, uint8)) continue; - - flags |= 0x40; - if (flags & 0x20) { - loc_69ADBD(x, y, mapElement); + if (flags & 0x20) { + footpath_unown(x, y, mapElement); + } + edges = mapElement->properties.path.edges & 0x0F; + direction ^= 2; + if (!(flags & 0x80)) { + if (mapElement[1].type == MAP_ELEMENT_TYPE_BANNER) { + for (int i = 1; i < 4; i++) { + if (map_element_is_last_for_tile(&mapElement[i - 1])) break; + if (mapElement[i].type != MAP_ELEMENT_TYPE_BANNER) break; + edges &= mapElement[i].properties.banner.flags; + } } - edges = mapElement->properties.path.edges & 0x0F; - direction ^= 2; - if ((mapElement + 1)->type == 28) { - // goto loc_69AC9C; + if (mapElement[2].type == MAP_ELEMENT_TYPE_BANNER && mapElement[1].type != MAP_ELEMENT_TYPE_PATH) { + for (int i = 1; i < 6; i++) { + if (map_element_is_last_for_tile(&mapElement[i - 1])) break; + if (mapElement[i].type != MAP_ELEMENT_TYPE_BANNER) break; + edges &= mapElement[i].properties.banner.flags; + } } - if ((mapElement + 1)->base_height == 28) { - // goto loc_69AD00; - } - goto loc_69AE22; + } + goto searchFromFootpath; } while (!map_element_is_last_for_tile(mapElement++)); - return false; + return level == 1 ? FOOTPATH_SEARCH_NOT_FOUND : FOOTPATH_SEARCH_INCOMPLETE; -loc_69AE22: +searchFromFootpath: // Exclude direction we came from z = mapElement->base_height; edges &= ~(1 << direction); // Find next direction to go - if (!get_next_direction(edges, &direction)) - return false; + if (!get_next_direction(edges, &direction)) { + return FOOTPATH_SEARCH_INCOMPLETE; + } edges &= ~(1 << direction); if (edges == 0) { @@ -853,26 +850,29 @@ loc_69AE22: junctionTolerance--; } junctionTolerance--; - if (junctionTolerance < 0) - return false; + if (junctionTolerance < 0) { + return FOOTPATH_SEARCH_TOO_COMPLEX; + } do { edges &= ~(1 << direction); if (footpath_element_is_sloped(mapElement) && footpath_element_get_slope_direction(mapElement) == direction) { z += 2; } - if (footpath_is_connected_to_map_edge_recurse(x, y, z, direction, flags, level, 0, junctionTolerance)) { - return true; + int result = footpath_is_connected_to_map_edge_recurse(x, y, z, direction, flags, level, 0, junctionTolerance); + if (result == FOOTPATH_SEARCH_SUCCESS) { + return result; } } while (get_next_direction(edges, &direction)); - return false; + return FOOTPATH_SEARCH_INCOMPLETE; } } -bool footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags) +int footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags) { - footpath_is_connected_to_map_edge_recurse(x, y, z, direction, flags, 0, 0, 12); + RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; + return footpath_is_connected_to_map_edge_recurse(x, y, z, direction, flags, 0, 0, 16); } bool footpath_element_is_sloped(rct_map_element *mapElement) diff --git a/src/world/footpath.h b/src/world/footpath.h index 59b25b25e3..a44538db1b 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -37,6 +37,13 @@ typedef struct { uint8 flags; // 0x0B } rct_path_type; +enum { + FOOTPATH_SEARCH_SUCCESS, + FOOTPATH_SEARCH_NOT_FOUND, + FOOTPATH_SEARCH_INCOMPLETE, + FOOTPATH_SEARCH_TOO_COMPLEX +}; + #define g_pathTypeEntries ((rct_path_type**)object_entry_groups[OBJECT_TYPE_PATHS].chunks) extern const rct_xy16 word_981D6C[4]; @@ -57,7 +64,7 @@ void sub_6A742F(int rideIndex, int entranceIndex, int x, int y, rct_map_element void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement); -bool footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags); +int footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags); bool footpath_element_is_sloped(rct_map_element *mapElement); int footpath_element_get_slope_direction(rct_map_element *mapElement);