diff --git a/src/peep/peep.c b/src/peep/peep.c index 001e328035..f7347f55c2 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -67,6 +67,7 @@ static void peep_pick_ride_to_go_on(rct_peep *peep); static void peep_head_for_nearest_ride_type(rct_peep *peep, int rideType); static void peep_head_for_nearest_ride_with_flags(rct_peep *peep, int rideTypeFlags); static void peep_give_real_name(rct_peep *peep); +static int guest_surface_path_finding(rct_peep* peep); const char *gPeepEasterEggNames[] = { "MICHAEL SCHUMACHER", @@ -6555,6 +6556,100 @@ static int peep_interact_with_shop(rct_peep* peep, sint16 x, sint16 y, rct_map_e } } +/* rct2: 0x0069524E */ +static int peep_move_one_tile(uint8 direction, rct_peep* peep){ + sint16 x = peep->next_x; + sint16 y = peep->next_y; + x += RCT2_ADDRESS(0x00993CC, sint16)[direction * 2]; + y += RCT2_ADDRESS(0x00993CE, sint16)[direction * 2]; + + if (x >= 8192 || y >= 8192){ + // This could loop! + return guest_surface_path_finding(peep); + } + + peep->var_78 = direction; + peep->destination_x = x + 16; + peep->destination_y = y + 16; + peep->destination_tolerence = 2; + if (peep->state == PEEP_STATE_QUEUING){ + peep->destination_tolerence = (scenario_rand() & 7) + 2; + } + return 0; +} + +/* rct2: 0x00694C41 */ +static int guest_surface_path_finding(rct_peep* peep){ + sint16 x = peep->next_x; + sint16 y = peep->next_y; + sint16 z = peep->next_z; + uint8 randDirection = scenario_rand() & 3; + + if (!fence_in_the_way(x, y, z, z + 4, randDirection)){ + x += RCT2_ADDRESS(0x00993CC, sint16)[randDirection * 2]; + y += RCT2_ADDRESS(0x00993CE, sint16)[randDirection * 2]; + randDirection ^= (1 << 1); + + if (!fence_in_the_way(x, y, z, z + 4, randDirection)){ + randDirection ^= (1 << 1); + if (!map_surface_is_blocked(x, y)){ + return peep_move_one_tile(randDirection, peep); + } + } + } + + randDirection++; + uint8 rand_backwards = scenario_rand() & 1; + if (rand_backwards){ + randDirection -= 2; + } + randDirection &= 3; + + if (!fence_in_the_way(x, y, z, z + 4, randDirection)){ + x += RCT2_ADDRESS(0x00993CC, sint16)[randDirection * 2]; + y += RCT2_ADDRESS(0x00993CE, sint16)[randDirection * 2]; + randDirection ^= (1 << 1); + + if (!fence_in_the_way(x, y, z, z + 4, randDirection)){ + randDirection ^= (1 << 1); + if (!map_surface_is_blocked(x, y)){ + return peep_move_one_tile(randDirection, peep); + } + } + } + + randDirection -= 2; + randDirection &= 3; + + if (!fence_in_the_way(x, y, z, z + 4, randDirection)){ + x += RCT2_ADDRESS(0x00993CC, sint16)[randDirection * 2]; + y += RCT2_ADDRESS(0x00993CE, sint16)[randDirection * 2]; + randDirection ^= (1 << 1); + + if (!fence_in_the_way(x, y, z, z + 4, randDirection)){ + randDirection ^= (1 << 1); + if (!map_surface_is_blocked(x, y)){ + return peep_move_one_tile(randDirection, peep); + } + } + } + + randDirection--; + if (rand_backwards){ + randDirection += 2; + } + return peep_move_one_tile(randDirection, peep); +} + +/* rct2: 0x00694C35 */ +static int guest_path_finding(rct_peep* peep){ + sint16 x, y, z; + if (peep->next_var_29 & 0x18){ + return guest_surface_path_finding(peep); + } + //694DA8 +} + /** * * rct2: 0x00693C9E diff --git a/src/world/footpath.c b/src/world/footpath.c index a212baf0e4..997c80b1e9 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -698,7 +698,8 @@ void footpath_interrupt_peeps(int x, int y, int z) } } -bool sub_6E59DC(int x, int y, int z0, int z1, int direction) +/* rct2: 0x006E59DC */ +bool fence_in_the_way(int x, int y, int z0, int z1, int direction) { rct_map_element *mapElement; @@ -899,7 +900,7 @@ static rct_map_element *footpath_get_element(int x, int y, int z0, int z1, int d static bool sub_footpath_disconnect_queue_from_path(int x, int y, rct_map_element *mapElement, int action, int direction) { if (((mapElement->properties.path.edges & (1 << direction)) == 0) ^ (action < 0)) return false; - if ((action < 0) && sub_6E59DC(x, y, mapElement->base_height, mapElement->clearance_height, direction)) + if ((action < 0) && fence_in_the_way(x, y, mapElement->base_height, mapElement->clearance_height, direction)) return false; int x1 = x + TileDirectionDelta[direction].x; @@ -1018,7 +1019,7 @@ static void loc_6A6D7E( loc_6A6F1F: if (query) { - if (sub_6E59DC(x, y, mapElement->base_height, mapElement->clearance_height, direction ^ 2)) { + if (fence_in_the_way(x, y, mapElement->base_height, mapElement->clearance_height, direction ^ 2)) { return; } if (footpath_element_is_queue(mapElement)) { @@ -1061,7 +1062,7 @@ static void loc_6A6C85( int x, int y, int direction, rct_map_element *mapElement, int flags, bool query, rct_neighbour_list *neighbourList ) { - if (query && sub_6E59DC(x, y, mapElement->base_height, mapElement->clearance_height, direction)) + if (query && fence_in_the_way(x, y, mapElement->base_height, mapElement->clearance_height, direction)) return; if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) { diff --git a/src/world/footpath.h b/src/world/footpath.h index 4cf703b54d..fbd00b2d0c 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -61,6 +61,7 @@ void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, void footpath_remove_litter(int x, int y, int z); void footpath_connect_edges(int x, int y, rct_map_element *mapElement, int flags); void sub_6A759F(); +bool fence_in_the_way(int x, int y, int z0, int z1, int direction); void footpath_chain_ride_queue(int rideIndex, int entranceIndex, int x, int y, rct_map_element *mapElement, int direction); void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement); diff --git a/src/world/map.c b/src/world/map.c index a3434ca198..9f719e4177 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -3612,3 +3612,42 @@ int map_get_tile_quadrant(int mapX, int mapY) (subMapY < 16 ? 2 : 3); } +/* rct2: 0x00693BFF */ +bool map_surface_is_blocked(sint16 x, sint16 y){ + rct_map_element *mapElement; + if (x >= 8192 || y >= 8192) + return true; + + mapElement = map_get_surface_element_at(x / 32, y / 32); + + sint16 water_height = mapElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK; + water_height *= 2; + if (water_height > mapElement->base_height) + return true; + + sint16 base_z = mapElement->base_height; + sint16 clear_z = mapElement->base_height + 2; + if (mapElement->properties.surface.slope & (1 << 4)) + clear_z += 2; + + while (!map_element_is_last_for_tile(mapElement++)){ + if (clear_z >= mapElement->clearance_height) + continue; + + if (base_z < mapElement->base_height) + continue; + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH || + map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_FENCE) + continue; + + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY) + return true; + + rct_scenery_entry* scenery = g_smallSceneryEntries[mapElement->properties.scenery.type]; + if (scenery->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE) + return true; + } + return false; +} + diff --git a/src/world/map.h b/src/world/map.h index b037e40e88..edbd136d2a 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -283,6 +283,7 @@ int map_coord_is_connected(int x, int y, int z, uint8 faceDirection); void sub_6A876D(); int map_is_location_owned(int x, int y, int z); int map_is_location_in_park(int x, int y); +bool map_surface_is_blocked(sint16 x, sint16 y); int map_get_station(rct_map_element *mapElement); void map_element_remove(rct_map_element *mapElement); void map_remove_all_rides();