From 9cf5240c90f1f3dc8df58298abab842310aa0cc2 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Tue, 21 Jul 2015 19:17:25 +0100 Subject: [PATCH 1/6] Start implementing sub_693C9E --- src/peep/peep.c | 459 +++++++++++++++++++++++++++++++++++++++++++++++- src/peep/peep.h | 4 +- 2 files changed, 459 insertions(+), 4 deletions(-) diff --git a/src/peep/peep.c b/src/peep/peep.c index cfc31c828d..29d90d3d04 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -33,6 +33,7 @@ #include "../sprites.h" #include "../world/sprite.h" #include "../world/scenery.h" +#include "../world/footpath.h" #include "../management/marketing.h" #include "peep.h" #include "staff.h" @@ -48,7 +49,7 @@ static int peep_empty_container_extra_flag(rct_peep* peep); static int peep_should_find_bench(rct_peep* peep); static void peep_stop_purchase_thought(rct_peep* peep, uint8 ride_type); static void sub_693BAB(rct_peep* peep); -static void sub_693C9E(rct_peep *peep); +static int sub_693C9E(rct_peep *peep); static void peep_spend_money(rct_peep *peep, money16 *peep_expend_type, money32 amount); static void peep_set_has_ridden(rct_peep *peep, int rideIndex); static bool peep_has_ridden(rct_peep *peep, int rideIndex); @@ -57,6 +58,7 @@ static bool peep_has_ridden_ride_type(rct_peep *peep, int rideType); static void peep_on_enter_or_exit_ride(rct_peep *peep, int rideIndex, int flags); static bool sub_69AF1E(rct_peep *peep, int rideIndex, int shopItem, money32 price); static bool peep_should_use_cash_machine(rct_peep *peep, int rideIndex); +static bool sub_6960AB(rct_peep *peep, int rideIndex, int dh, int bp); static void sub_69A98C(rct_peep *peep); static void sub_68FD3A(rct_peep *peep); static bool sub_690B99(rct_peep *peep, int edge, uint8 *rideToView, uint8 *rideSeatToView); @@ -5955,12 +5957,465 @@ void sub_693BAB(rct_peep* peep) { } } +/** + * + * rct2: 0x00693CBB + */ +static int peep_update_queue_position(rct_peep* peep){ + peep->time_in_queue++; + if (peep->next_in_queue == 0xFFFF) + return 0; + + rct_peep* peep_next = GET_PEEP(peep->next_in_queue); + + sint16 x_diff = abs(peep_next->x - peep->x); + sint16 y_diff = abs(peep_next->y - peep->y); + sint16 z_diff = abs(peep_next->z - peep->z); + + if (z_diff > 10) + return 0; + + if (x_diff < y_diff){ + sint16 temp_x = x_diff; + x_diff = y_diff; + y_diff = temp_x; + } + + x_diff += y_diff / 2; + if (x_diff > 7){ + if (x_diff > 13){ + if ((peep->x & 0xFFE0) != (peep_next->x & 0xFFE0) || + (peep->y & 0xFFE0) != (peep_next->y & 0xFFE0)) + return 0; + } + + if (peep->sprite_direction != peep_next->sprite_direction) + return 0; + + switch (peep->sprite_direction / 8){ + case 0: + if (peep->x >= peep_next->x) + return 0; + break; + case 1: + if (peep->y <= peep_next->y) + return 0; + break; + case 2: + if (peep->x <= peep_next->x) + return 0; + break; + case 3: + if (peep->y >= peep_next->y) + return 0; + break; + } + } + + sint16 xy_dist, x, y; + if (peep->action < PEEP_ACTION_NONE_1) + peep_update_action(&x, &y, &xy_dist, peep); + + if (peep->action != PEEP_ACTION_NONE_2) + return 1; + + peep->action = PEEP_ACTION_NONE_1; + peep->var_6F = 2; + if (RCT2_GLOBAL(0x00F1AEF1, uint8) != 0xFE) + invalidate_sprite((rct_sprite*)peep); + return 1; +} + +/* rct2: 0x00693EF2 */ +static int peep_return_to_center_of_tile(rct_peep* peep){ + peep->var_78 ^= (1 << 1); + peep->destination_x = peep->x & 0xFFE0 + 16; + peep->destination_y = peep->y & 0xFFE0 + 16; + peep->destination_tolerence = 5; + return 1; +} + +/* rct2: 0x00693f2C*/ +static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element){ + uint8 entranceType = map_element->properties.entrance.type; + uint8 rideIndex = map_element->properties.entrance.ride_index; + + if (entranceType == ENTRANCE_TYPE_RIDE_EXIT){ + RCT2_GLOBAL(0x00F1EE18, uint8) |= (1 << 2); + RCT2_GLOBAL(0x00F1EE1A, rct_map_element*) = map_element; + } + else if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE){ + RCT2_GLOBAL(0x00F1EE18, uint8) |= (1 << 3); + RCT2_GLOBAL(0x00F1EE1A, rct_map_element*) = map_element; + } + + if (entranceType == ENTRANCE_TYPE_RIDE_EXIT){ + peep->var_79 = 0xFF; + return peep_return_to_center_of_tile(peep); + } + + if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE){ + if (peep->type == PEEP_TYPE_STAFF){ + peep->var_79 = 0xFF; + return peep_return_to_center_of_tile(peep); + } + + if (peep->state = PEEP_STATE_QUEUING){ + peep->sub_state = 11; + peep->action_sprite_image_offset = RCT2_GLOBAL(0x00F1AEF0, uint8); + return 1; + } + + if (peep->var_79 == rideIndex) + return peep_return_to_center_of_tile(peep); + + peep->var_F4 = 0; + uint8 stationNum = (map_element->properties.entrance.index >> 4) & 0x7; + if (!sub_6960AB(peep, rideIndex, stationNum, 0)){ + peep->var_79 = rideIndex; + return peep_return_to_center_of_tile(peep); + } + + peep->action_sprite_image_offset = RCT2_GLOBAL(0x00F1AEF0, uint8); + peep->var_79 = rideIndex; + + rct_ride* ride = GET_RIDE(rideIndex); + uint16 previous_first = ride->first_peep_in_queue[stationNum]; + ride->first_peep_in_queue[stationNum] = peep->sprite_index; + peep->next_in_queue = previous_first; + ride->queue_length[stationNum]++; + + peep_decrement_num_riders(peep); + peep->current_ride = rideIndex; + peep->current_ride_station = stationNum; + peep->state = PEEP_STATE_QUEUING; + peep->days_in_queue = 0; + peep_window_state_update(peep); + peep->sub_state = 11; + peep->time_in_queue = 0; + if (peep->flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(0x0013CE952, rct_string_id) = peep->name_string_idx; + RCT2_GLOBAL(0x0013CE954, uint32) = peep->id; + RCT2_GLOBAL(0x0013CE958, rct_string_id) = ride->name; + RCT2_GLOBAL(0x0013CE95A, uint32) = ride->name_arguments; + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, 1931, peep->sprite_index); + } + return 1; + } + else{ + // PARK_ENTRANCE + if (peep->type == PEEP_TYPE_STAFF) + return peep_return_to_center_of_tile(peep); + + // If not the center of the entrance arch + if (map_element->properties.entrance.index & 0xF) + return peep_return_to_center_of_tile(peep); + + uint8 entranceDirection = map_element->type & MAP_ELEMENT_DIRECTION_MASK; + if (entranceDirection != peep->var_78){ + if ((entranceDirection ^ (1 << 1)) != peep->var_78) + return peep_return_to_center_of_tile(peep); + // Peep is leaving the park. + if (peep->state != PEEP_STATE_WALKING) + return peep_return_to_center_of_tile(peep); + + if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK)){ + // If the park is open and leaving flag isnt set return to center + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN) + return peep_return_to_center_of_tile(peep); + } + + peep->destination_x += RCT2_ADDRESS(0x00993CCC, sint16)[peep->var_78 * 2]; + peep->destination_y += RCT2_ADDRESS(0x00993CCE, sint16)[peep->var_78 * 2]; + peep->destination_tolerence = 9; + invalidate_sprite((rct_sprite*)peep); + sprite_move(peep->destination_x, peep->destination_y, peep->z, (rct_sprite*)peep); + invalidate_sprite((rct_sprite*)peep); + + peep_decrement_num_riders(peep); + peep->state = PEEP_STATE_LEAVING_PARK; + peep_window_state_update(peep); + + peep->var_37 = 0; + if (peep->flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(0x0013CE952, rct_string_id) = peep->name_string_idx; + RCT2_GLOBAL(0x0013CE954, uint32) = peep->id; + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, 1935, peep->sprite_index); + } + return 1; + } + + // Peep is entering the park. + + if (peep->state != PEEP_STATE_ENTERING_PARK) + return peep_return_to_center_of_tile(peep); + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN)){ + peep->state = PEEP_STATE_LEAVING_PARK; + peep->var_37 = 1; + RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK, uint16)--; + peep_window_state_update(peep); + return peep_return_to_center_of_tile(peep); + } + + uint8 entranceIndex = 0; + while (1){ + if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, sint16)[entranceIndex] == (x & 0xFFE0) && + RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, sint16)[entranceIndex] == (y & 0xFFE0)) + break; + entranceIndex++; + } + + sint16 z = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, sint16)[entranceIndex] / 8; + entranceDirection = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_DIRECTION, uint8)[entranceIndex]; + + sint16 next_x = (x & 0xFFE0) + RCT2_ADDRESS(0x00993CCC, sint16)[entranceDirection * 2]; + sint16 next_y = (y & 0xFFE0) + RCT2_ADDRESS(0x00993CCE, sint16)[entranceDirection * 2]; + + uint8 found = 0; + rct_map_element* nextMapElement = map_get_first_element_at(next_x / 32, next_y / 32); + do{ + if (map_element_get_type(nextMapElement) != MAP_ELEMENT_TYPE_PATH) + continue; + + if (nextMapElement->type & 1) + continue; + + if (footpath_element_is_sloped(nextMapElement)){ + uint8 slopeDirection = footpath_element_get_slope_direction(nextMapElement); + if (slopeDirection == entranceDirection){ + if (z != nextMapElement->base_height){ + continue; + } + found = 1; + break; + } + + if ((slopeDirection ^ (1 << 1)) != entranceDirection) + continue; + + if (z - 2 != nextMapElement->base_height) + continue; + found = 1; + break; + } + else{ + if (z != nextMapElement->base_height){ + continue; + } + found = 1; + break; + } + } while (!map_element_is_last_for_tile(nextMapElement++)); + + if (!found){ + peep->state = PEEP_STATE_LEAVING_PARK; + peep->var_37 = 1; + RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK, uint16)--; + peep_window_state_update(peep); + return peep_return_to_center_of_tile(peep); + } + + money16 entranceFee = RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16); + if (entranceFee != 0){ + if (peep->item_standard_flags & PEEP_ITEM_VOUCHER){ + if (peep->voucher_type == VOUCHER_TYPE_PARK_ENTRY_HALF_PRICE){ + entranceFee /= 2; + peep->item_standard_flags &= ~PEEP_ITEM_VOUCHER; + peep->window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY; + } + else if (peep->voucher_type == VOUCHER_TYPE_PARK_ENTRY_FREE){ + entranceFee = 0; + peep->item_standard_flags &= ~PEEP_ITEM_VOUCHER; + peep->window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY; + } + } + if (entranceFee > peep->cash_in_pocket){ + peep->state = PEEP_STATE_LEAVING_PARK; + peep->var_37 = 1; + RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK, uint16)--; + peep_window_state_update(peep); + return peep_return_to_center_of_tile(peep); + } + + RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, money32) += entranceFee; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_PARK_ENTRANCE_TICKETS * 4; + peep_spend_money(peep, &peep->paid_to_enter, entranceFee); + peep->flags |= PEEP_FLAGS_5; + } + + RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_ADMISSIONS, uint32)++; + window_invalidate_by_number(WC_PARK_INFORMATION, 0); + + peep->var_37 = 1; + peep->destination_x += RCT2_ADDRESS(0x00993CCC, sint16)[peep->var_78 * 2]; + peep->destination_y += RCT2_ADDRESS(0x00993CCE, sint16)[peep->var_78 * 2]; + peep->destination_tolerence = 7; + + invalidate_sprite((rct_sprite*)peep); + sprite_move(peep->destination_x, peep->destination_y, peep->z, (rct_sprite*)peep); + invalidate_sprite((rct_sprite*)peep); + + return 1; + } +} + +/* rct2: 0x00693F70 */ +static int peep_interact_with_shop(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element){ + uint8 rideIndex = map_element->properties.track.ride_index; + rct_ride* ride = GET_RIDE(rideIndex); + + if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) + return 0; + + if (peep->type == PEEP_TYPE_STAFF) + return peep_return_to_center_of_tile(peep); + + peep->var_F4 = 0; + + if (ride->status != RIDE_STATUS_OPEN) + return peep_return_to_center_of_tile(peep); + + if (peep->var_79 == rideIndex) + return peep_return_to_center_of_tile(peep); + + if (peep->flags & PEEP_FLAGS_LEAVING_PARK) + return peep_return_to_center_of_tile(peep); + + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_21)){ + peep->var_F4 = 0; + if (!sub_6960AB(peep, rideIndex, 0, 0)) + return peep_return_to_center_of_tile(peep); + + money16 cost = ride->price; + if (cost != 0){ + ride->total_profit += cost; + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_PARK_RIDE_TICKETS * 4; + peep_spend_money(peep, NULL, cost); + } + peep->destination_x = x + 16; + peep->destination_y = y + 16; + peep->destination_tolerence = 3; + + peep_decrement_num_riders(peep); + peep->current_ride = rideIndex; + peep->state = PEEP_STATE_ENTERING_RIDE; + peep->sub_state = 19; + peep_window_state_update(peep); + + peep->time_on_ride = 0; + ride->var_120++; + if (peep->flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(0x0013CE952, rct_string_id) = peep->name_string_idx; + RCT2_GLOBAL(0x0013CE954, uint32) = peep->id; + RCT2_GLOBAL(0x0013CE958, rct_string_id) = ride->name; + RCT2_GLOBAL(0x0013CE95A, uint32) = ride->name_arguments; + rct_string_id string_id = ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IN_RIDE) ? 1933 : 1932; + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, string_id, peep->sprite_index); + } + return 1; + } + else{ + if (peep->guest_heading_to_ride_id == rideIndex) + peep->guest_heading_to_ride_id = 0xFF; + peep->action_sprite_image_offset = RCT2_GLOBAL(0x00F1AEF0, uint8); + peep_decrement_num_riders(peep); + peep->current_ride = rideIndex; + peep->state = PEEP_STATE_BUYING; + peep->sub_state = 0; + peep_window_state_update(peep); + return 1; + } +} + /** * * rct2: 0x00693C9E */ -static void sub_693C9E(rct_peep *peep) +static int sub_693C9E(rct_peep *peep) { + RCT2_GLOBAL(0x00F1EE18, uint16) = 0; + RCT2_GLOBAL(0x00F1AEF1, uint8) = peep->action; + + if (peep->action == PEEP_ACTION_NONE_1) + peep->action = PEEP_ACTION_NONE_2; + + if (peep->state == PEEP_STATE_QUEUING){ + if (peep_update_queue_position(peep)) + return 1; + } + + //693dc1 + sint16 x, y, xy_dist; + if (!peep_update_action(&x, &y, &xy_dist, peep)){ + RCT2_GLOBAL(0x00F1EE18, uint16) |= 1; + uint8 result = 0; + if (peep->type == PEEP_TYPE_GUEST){ + result = RCT2_CALLPROC_X(0x00694C35, x, 0, y, 0, (int)peep, 0, 0) & 0x100; + } + else{ + result = RCT2_CALLPROC_X(0x006BF926, x, 0, y, 0, (int)peep, 0, 0) & 0x100; + } + + if (result != 0) + return 1; + + if (peep_update_action(&x, &y, &xy_dist, peep)) + return 1; + } + + if ((x & 0xFFE0) == peep->next_x && (y & 0xFFE0) == peep->next_y){ + sint16 z = peep_get_height_on_slope(peep, x, y); + invalidate_sprite((rct_sprite*)peep); + sprite_move(x, y, z, (rct_sprite*)peep); + invalidate_sprite((rct_sprite*)peep); + return 1; + } + + //693e16 + if (x < 32 || y >= 32 || x < RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y < RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16)){ + if (peep->type == PEEP_TYPE_STAFF){ + RCT2_GLOBAL(0x00F1EE18, uint16) |= (1 << 1); + } + return peep_return_to_center_of_tile(peep); + } + + rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32); + sint16 base_z = max(0, (peep->z / 8) - 2); + sint16 top_z = (peep->z / 8) + 1; + + do{ + if (base_z > mapElement->base_height) + continue; + if (top_z < mapElement->base_height) + continue; + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH){ + if ((mapElement->flags & MAP_ELEMENT_FLAG_GHOST)) + continue; + //goto 69455e + } + else if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK){ + if (peep_interact_with_shop(peep, x, y, mapElement)) + return 1; + } + else if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE){ + if (peep_interact_with_entrance(peep, x, y, mapElement)) + return 1; + } + } while (!map_element_is_last_for_tile(mapElement++)); + + if (peep->type == PEEP_TYPE_STAFF || (peep->next_var_29 & 0x18)){ + sint16 z = abs(map_element_height(x, y) - peep->z); + + if (z <= 3 || (peep->type == PEEP_TYPE_STAFF && z <= 32)){ + //goto 6944d9 + } + } + return peep_return_to_center_of_tile(peep); + + RCT2_CALLPROC_X(0x00693C9E, 0, 0, 0, 0, (int)peep, 0, 0); } diff --git a/src/peep/peep.h b/src/peep/peep.h index 5399d760b1..a532ecd6bb 100644 --- a/src/peep/peep.h +++ b/src/peep/peep.h @@ -252,7 +252,7 @@ enum PEEP_FLAGS { PEEP_FLAGS_TRACKING = (1 << 3), PEEP_FLAGS_WAVING = (1 << 4), // Makes the peep wave - PEEP_FLAGS_5 = (1 << 5), + PEEP_FLAGS_5 = (1 << 5), // Set on paying to enter park? PEEP_FLAGS_PHOTO = (1 << 6), // Makes the peep take a picture PEEP_FLAGS_PAINTING = (1 << 7), PEEP_FLAGS_WOW = (1 << 8), // Makes a peep WOW2 @@ -451,7 +451,7 @@ typedef struct { uint8 pad_77; union{ uint8 maze_last_edge; // 0x78 - uint8 var_78; + uint8 var_78; //Direction ? }; uint8 var_79; uint16 time_in_queue; // 0x7A From 0ca26a7fca495bdd9961da774096a1a424f7148c Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Thu, 23 Jul 2015 21:22:58 +0100 Subject: [PATCH 2/6] Fix #1430 --- src/peep/peep.c | 287 +++++++++++++++++++++++++++++++++++++++++++++--- src/peep/peep.h | 6 +- 2 files changed, 274 insertions(+), 19 deletions(-) diff --git a/src/peep/peep.c b/src/peep/peep.c index 29d90d3d04..b64053b3fe 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -3882,8 +3882,8 @@ static void peep_update_walking_break_scenery(rct_peep* peep){ if (peep->energy < 85) return; if (peep->state != PEEP_STATE_WALKING) return; - if ((peep->var_E1 & 0xC0) != 0xC0 && - (peep->var_E3 & 0xC0) != 0xC0) return; + if ((peep->litter_count & 0xC0) != 0xC0 && + (peep->disgusting_count & 0xC0) != 0xC0) return; if ((scenario_rand() & 0xFFFF) > 3276) return; } @@ -5378,8 +5378,8 @@ rct_peep *peep_generate(int x, int y, int z) peep->item_standard_flags = 0; peep->item_extra_flags = 0; peep->guest_heading_to_ride_id = 0xFF; - peep->var_E1 = 0; - peep->var_E3 = 0; + peep->litter_count = 0; + peep->disgusting_count = 0; peep->var_EF = 0; peep->paid_to_enter = 0; peep->paid_on_rides = 0; @@ -6060,7 +6060,7 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m return peep_return_to_center_of_tile(peep); } - if (peep->state = PEEP_STATE_QUEUING){ + if (peep->state == PEEP_STATE_QUEUING){ peep->sub_state = 11; peep->action_sprite_image_offset = RCT2_GLOBAL(0x00F1AEF0, uint8); return 1; @@ -6217,7 +6217,7 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m } money16 entranceFee = RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16); - if (entranceFee != 0){ + if (entranceFee != 0 && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)){ if (peep->item_standard_flags & PEEP_ITEM_VOUCHER){ if (peep->voucher_type == VOUCHER_TYPE_PARK_ENTRY_HALF_PRICE){ entranceFee /= 2; @@ -6260,6 +6260,232 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m } } +/* rct2: 0x006946D8 */ +static int peep_queue_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element, bool vandalism){ + peep->next_x = (x & 0xFFE0); + peep->next_y = (y & 0xFFE0); + peep->next_z = map_element->base_height; + peep->next_var_29 = map_element->properties.path.type & 3; + + sint16 z = peep_get_height_on_slope(peep, x, y); + + if (peep->type == PEEP_TYPE_STAFF){ + invalidate_sprite((rct_sprite*)peep); + sprite_move(x, y, z, (rct_sprite*)peep); + invalidate_sprite((rct_sprite*)peep); + return 1; + } + //6946FB + uint8 var_EF = (peep->var_EF * 2) & 0x3F; + peep->var_EF &= 0xC0; + peep->var_EF |= var_EF; + + if (RCT2_GLOBAL(0x00F1AEE2, uint8) == 1){ + peep->var_EF |= 1; + if (peep->var_EF & 0x3E && + !(peep->var_EF & 0xC0)){ + + if ((scenario_rand() & 0xFFFF) <= 10922){ + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_VANDALISM, 0xFF); + peep->happiness_growth_rate = max(0, peep->happiness_growth_rate - 17); + } + peep->var_EF |= 0xC0; + } + } + + if (peep->var_EF & 0xC0 && + (scenario_rand()&0xFFFF) <= 4369){ + peep->var_EF -= 0x40; + } + + uint16 crowded = 0; + uint8 litter_count = 0; + uint8 sick_count = 0; + uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[((x & 0x1FE0) << 3) | (y >> 5)]; + for (rct_sprite* sprite; sprite_id != 0xFFFF; sprite_id = sprite->unknown.next_in_quadrant){ + sprite = &g_sprite_list[sprite_id]; + if (sprite->unknown.sprite_identifier == SPRITE_IDENTIFIER_PEEP){ + rct_peep* other_peep = (rct_peep*)sprite; + if (other_peep->state != PEEP_STATE_WALKING) + continue; + + if (abs(other_peep->z - peep->next_z * 8) > 16) + continue; + crowded++; + continue; + } + else if (sprite->unknown.sprite_identifier == SPRITE_IDENTIFIER_LITTER){ + rct_litter* litter = (rct_litter*)sprite; + if (abs(litter->z - peep->next_z * 8) > 16) + continue; + + litter_count++; + if (litter->type > 1) + continue; + + litter_count--; + sick_count++; + } + } + + if (crowded >= 10 && + peep->state == PEEP_STATE_WALKING && + (scenario_rand() & 0xFFFF) <= 21845){ + + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CROWDED, 0xFF); + peep->happiness_growth_rate = max(0, peep->happiness_growth_rate - 14); + } + + litter_count = min(3, litter_count); + sick_count = min(3, sick_count); + + uint8 disgusting_time = peep->disgusting_count & 0xC0; + uint8 disgusting_count = ((peep->disgusting_count & 0xF) << 2) | sick_count; + peep->disgusting_count = disgusting_count | disgusting_time; + + if (disgusting_time & 0xC0 && + (scenario_rand() & 0xFFFF) <= 4369){ + // Reduce the disgusting time + peep->disgusting_count -= 0x40; + } + else{ + uint8 total_sick = 0; + for (uint8 time = 0; time < 3; time++){ + total_sick += (disgusting_count >> (2 * time)) & 0x3; + } + + if (total_sick >= 3 && + (scenario_rand() & 0xFFFF) <= 10922){ + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_PATH_DISGUSTING, 0xFF); + peep->happiness_growth_rate = max(0, peep->happiness_growth_rate - 17); + // Reset disgusting time + peep->disgusting_count |= 0xC0; + } + } + + uint8 litter_time = peep->litter_count & 0xC0; + litter_count = ((peep->litter_count & 0xF) << 2) | litter_count; + peep->litter_count = litter_count | litter_time; + + if (litter_time & 0xC0 && + (scenario_rand() & 0xFFFF) <= 4369){ + // Reduce the litter time + peep->litter_count -= 0x40; + } + else{ + uint8 total_litter = 0; + for (uint8 time = 0; time < 3; time++){ + total_litter += (litter_count >> (2 * time)) & 0x3; + } + + if (total_litter >= 3 && + (scenario_rand() & 0xFFFF) <= 10922){ + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_BAD_LITTER, 0xFF); + peep->happiness_growth_rate = max(0, peep->happiness_growth_rate - 17); + // Reset litter time + peep->litter_count |= 0xC0; + } + } + + invalidate_sprite((rct_sprite*)peep); + sprite_move(x, y, z, (rct_sprite*)peep); + invalidate_sprite((rct_sprite*)peep); + return 1; +} + +/* rct2: 0x0069455E */ +static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element){ + + // 0x00F1AEE2 + bool vandalism_present = false; + if ((map_element->properties.path.additions & 0xF) != 0 && + (map_element->flags & MAP_ELEMENT_FLAG_BROKEN) && + (map_element->properties.path.edges & 0xF) != 0xF){ + vandalism_present = 1; + } + + sint16 z = map_element->base_height * 8; + if (!map_is_location_owned(x, y, z)){ + if (peep->var_2A == 0) + return peep_return_to_center_of_tile(peep); + } + else{ + if (peep->var_2A == 1) + return peep_return_to_center_of_tile(peep); + } + + if (peep->type == PEEP_TYPE_GUEST && + footpath_element_is_queue(map_element)){ + //6945d8 + uint8 rideIndex = map_element->properties.path.ride_index; + + if (rideIndex == 0xFF){ + peep->var_79 = 0xFF; + return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + } + + if (peep->state == PEEP_STATE_QUEUING){ + if (peep->current_ride == rideIndex){ + return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + } + remove_peep_from_queue(peep); + peep_decrement_num_riders(peep); + peep->state = PEEP_STATE_1; + peep_window_state_update(peep); + return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + } + + if (peep->var_79 == rideIndex){ + return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + } + + peep->var_F4 = 0; + uint8 stationNum = (map_element->properties.path.additions & 0x70) >> 4; + if (!sub_6960AB(peep, rideIndex, stationNum, 1)){ + peep->var_79 = rideIndex; + return peep_return_to_center_of_tile(peep); + } + + peep->var_79 = rideIndex; + rct_ride* ride = GET_RIDE(rideIndex); + + uint16 old_first_peep = ride->first_peep_in_queue[stationNum]; + ride->first_peep_in_queue[stationNum] = peep->sprite_index; + peep->next_in_queue = old_first_peep; + ride->queue_length[stationNum]++; + + peep_decrement_num_riders(peep); + peep->current_ride = rideIndex; + peep->current_ride_station = stationNum; + peep->state = PEEP_STATE_QUEUING; + peep->days_in_queue = 0; + peep_window_state_update(peep); + + peep->sub_state = 10; + peep->destination_tolerence = 2; + peep->time_in_queue = 0; + if (peep->flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(0x0013CE952, rct_string_id) = peep->name_string_idx; + RCT2_GLOBAL(0x0013CE954, uint32) = peep->id; + RCT2_GLOBAL(0x0013CE958, rct_string_id) = ride->name; + RCT2_GLOBAL(0x0013CE95A, uint32) = ride->name_arguments; + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, 1931, peep->sprite_index); + } + + return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + } + else{ + peep->var_79 = 0xFF; + if (peep->state == PEEP_STATE_QUEUING){ + remove_peep_from_queue(peep); + peep_decrement_num_riders(peep); + peep->state = PEEP_STATE_1; + peep_window_state_update(peep); + } + return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + } +} + /* rct2: 0x00693F70 */ static int peep_interact_with_shop(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element){ uint8 rideIndex = map_element->properties.track.ride_index; @@ -6294,8 +6520,8 @@ static int peep_interact_with_shop(rct_peep* peep, sint16 x, sint16 y, rct_map_e RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_PARK_RIDE_TICKETS * 4; peep_spend_money(peep, NULL, cost); } - peep->destination_x = x + 16; - peep->destination_y = y + 16; + peep->destination_x = (x & 0xFFE0) + 16; + peep->destination_y = (y & 0xFFE0) + 16; peep->destination_tolerence = 3; peep_decrement_num_riders(peep); @@ -6361,7 +6587,7 @@ static int sub_693C9E(rct_peep *peep) if (result != 0) return 1; - if (peep_update_action(&x, &y, &xy_dist, peep)) + if (!peep_update_action(&x, &y, &xy_dist, peep)) return 1; } @@ -6374,7 +6600,7 @@ static int sub_693C9E(rct_peep *peep) } //693e16 - if (x < 32 || y >= 32 || x < RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y < RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16)){ + if (x < 32 || y < 32 || x >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16)){ if (peep->type == PEEP_TYPE_STAFF){ RCT2_GLOBAL(0x00F1EE18, uint16) |= (1 << 1); } @@ -6394,7 +6620,8 @@ static int sub_693C9E(rct_peep *peep) if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH){ if ((mapElement->flags & MAP_ELEMENT_FLAG_GHOST)) continue; - //goto 69455e + if (peep_interact_with_path(peep, x, y, mapElement)) + return 1; } else if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK){ if (peep_interact_with_shop(peep, x, y, mapElement)) @@ -6410,13 +6637,39 @@ static int sub_693C9E(rct_peep *peep) sint16 z = abs(map_element_height(x, y) - peep->z); if (z <= 3 || (peep->type == PEEP_TYPE_STAFF && z <= 32)){ - //goto 6944d9 + peep->var_79 = 0xFF; + if (peep->state == PEEP_STATE_QUEUING){ + remove_peep_from_queue(peep); + peep_decrement_num_riders(peep); + peep->state = PEEP_STATE_1; + peep_window_state_update(peep); + } + + if (!map_is_location_in_park(x & 0xFFE0, y & 0xFFE0)){ + return peep_return_to_center_of_tile(peep); + } + + mapElement = map_get_surface_element_at(x / 32, y / 32); + if (mapElement == NULL) + return peep_return_to_center_of_tile(peep); + + sint16 water_height = mapElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK; + if (water_height) + return peep_return_to_center_of_tile(peep); + + peep->next_x = x & 0xFFE0; + peep->next_y = y & 0xFFE0; + peep->next_z = mapElement->base_height; + peep->next_var_29 = 8; + + sint16 z = peep_get_height_on_slope(peep, x, y); + invalidate_sprite((rct_sprite*)peep); + sprite_move(x, y, z, (rct_sprite*)peep); + invalidate_sprite((rct_sprite*)peep); + return 1; } } return peep_return_to_center_of_tile(peep); - - - RCT2_CALLPROC_X(0x00693C9E, 0, 0, 0, 0, (int)peep, 0, 0); } /** @@ -6867,7 +7120,7 @@ static bool sub_6960AB(rct_peep *peep, int rideIndex, int dh, int bp) } return true; } - if (bp & 2) { + if (!(bp & 2)) { if (ride->queue_length[dh] == 1000) goto loc_696645; if (!(bp & 1)) { @@ -6877,7 +7130,7 @@ static bool sub_6960AB(rct_peep *peep, int rideIndex, int dh, int bp) if (ride->first_peep_in_queue[dh] != 0xFFFF) { rct_peep *firstPeepInQueue = &(g_sprite_list[ride->first_peep_in_queue[dh]].peep); if (abs(firstPeepInQueue->z - peep->z) <= 6) { - int dx = abs(firstPeepInQueue->x = peep->x); + int dx = abs(firstPeepInQueue->x - peep->x); int dy = abs(firstPeepInQueue->y - peep->y); int maxD = max(dx, dy); if (maxD <= 13) { diff --git a/src/peep/peep.h b/src/peep/peep.h index a532ecd6bb..db10e81af4 100644 --- a/src/peep/peep.h +++ b/src/peep/peep.h @@ -481,12 +481,14 @@ typedef struct { uint32 var_CC; uint8 pad_D0[0x10]; uint8 no_action_frame_no; // 0xE0 - uint8 var_E1; + // 0x3F Litter Count split into lots of 3 with time, 0xC0 Time since last recalc + uint8 litter_count; // 0xE1 union{ uint8 time_on_ride; // 0xE2 uint8 var_E2; // 0xE2 }; - uint8 var_E3; + // 0x3F Sick Count split into lots of 3 with time, 0xC0 Time since last recalc + uint8 disgusting_count; // 0xE3 union{ money16 paid_to_enter; // 0xE4 uint16 staff_lawns_mown; // 0xE4 From c93671af3f4692123f10034a0ee28db90df31ad1 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Sat, 25 Jul 2015 00:35:34 +0100 Subject: [PATCH 3/6] Small refactor --- src/peep/peep.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/peep/peep.c b/src/peep/peep.c index b64053b3fe..5bf4a6411d 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -6261,7 +6261,7 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m } /* rct2: 0x006946D8 */ -static int peep_queue_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element, bool vandalism){ +static int peep_footpath_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element, bool vandalism){ peep->next_x = (x & 0xFFE0); peep->next_y = (y & 0xFFE0); peep->next_z = map_element->base_height; @@ -6421,22 +6421,22 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e if (rideIndex == 0xFF){ peep->var_79 = 0xFF; - return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + return peep_footpath_move_forward(peep, x, y, map_element, vandalism_present); } if (peep->state == PEEP_STATE_QUEUING){ if (peep->current_ride == rideIndex){ - return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + return peep_footpath_move_forward(peep, x, y, map_element, vandalism_present); } remove_peep_from_queue(peep); peep_decrement_num_riders(peep); peep->state = PEEP_STATE_1; peep_window_state_update(peep); - return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + return peep_footpath_move_forward(peep, x, y, map_element, vandalism_present); } if (peep->var_79 == rideIndex){ - return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + return peep_footpath_move_forward(peep, x, y, map_element, vandalism_present); } peep->var_F4 = 0; @@ -6472,7 +6472,7 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, 1931, peep->sprite_index); } - return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + return peep_footpath_move_forward(peep, x, y, map_element, vandalism_present); } else{ peep->var_79 = 0xFF; @@ -6482,7 +6482,7 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e peep->state = PEEP_STATE_1; peep_window_state_update(peep); } - return peep_queue_move_forward(peep, x, y, map_element, vandalism_present); + return peep_footpath_move_forward(peep, x, y, map_element, vandalism_present); } } From 074b2a6909aa8899b5feb8a970ae2ff84fe0add8 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Sat, 25 Jul 2015 09:09:26 +0100 Subject: [PATCH 4/6] Remove code offset comments, fix destination bug --- src/peep/peep.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/peep/peep.c b/src/peep/peep.c index 5bf4a6411d..427ec4813f 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -6029,8 +6029,8 @@ static int peep_update_queue_position(rct_peep* peep){ /* rct2: 0x00693EF2 */ static int peep_return_to_center_of_tile(rct_peep* peep){ peep->var_78 ^= (1 << 1); - peep->destination_x = peep->x & 0xFFE0 + 16; - peep->destination_y = peep->y & 0xFFE0 + 16; + peep->destination_x = (peep->x & 0xFFE0) + 16; + peep->destination_y = (peep->y & 0xFFE0) + 16; peep->destination_tolerence = 5; return 1; } @@ -6275,7 +6275,7 @@ static int peep_footpath_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_ma invalidate_sprite((rct_sprite*)peep); return 1; } - //6946FB + uint8 var_EF = (peep->var_EF * 2) & 0x3F; peep->var_EF &= 0xC0; peep->var_EF |= var_EF; @@ -6416,7 +6416,7 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e if (peep->type == PEEP_TYPE_GUEST && footpath_element_is_queue(map_element)){ - //6945d8 + uint8 rideIndex = map_element->properties.path.ride_index; if (rideIndex == 0xFF){ @@ -6572,7 +6572,6 @@ static int sub_693C9E(rct_peep *peep) return 1; } - //693dc1 sint16 x, y, xy_dist; if (!peep_update_action(&x, &y, &xy_dist, peep)){ RCT2_GLOBAL(0x00F1EE18, uint16) |= 1; @@ -6599,7 +6598,6 @@ static int sub_693C9E(rct_peep *peep) return 1; } - //693e16 if (x < 32 || y < 32 || x >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16)){ if (peep->type == PEEP_TYPE_STAFF){ RCT2_GLOBAL(0x00F1EE18, uint16) |= (1 << 1); From bff00b29bf5474c72de5b8c79ed4683d1bb9b02c Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Sat, 25 Jul 2015 10:12:51 +0100 Subject: [PATCH 5/6] Fix more small pathfinding bugs. Fix unset memory errors --- src/peep/peep.c | 10 +++++----- src/windows/guest.c | 2 +- src/windows/staff.c | 2 +- src/world/footpath.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/peep/peep.c b/src/peep/peep.c index 427ec4813f..001e328035 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -6129,7 +6129,7 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m peep->destination_y += RCT2_ADDRESS(0x00993CCE, sint16)[peep->var_78 * 2]; peep->destination_tolerence = 9; invalidate_sprite((rct_sprite*)peep); - sprite_move(peep->destination_x, peep->destination_y, peep->z, (rct_sprite*)peep); + sprite_move(x, y, peep->z, (rct_sprite*)peep); invalidate_sprite((rct_sprite*)peep); peep_decrement_num_riders(peep); @@ -6253,7 +6253,7 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m peep->destination_tolerence = 7; invalidate_sprite((rct_sprite*)peep); - sprite_move(peep->destination_x, peep->destination_y, peep->z, (rct_sprite*)peep); + sprite_move(x, y, peep->z, (rct_sprite*)peep); invalidate_sprite((rct_sprite*)peep); return 1; @@ -6265,7 +6265,7 @@ static int peep_footpath_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_ma peep->next_x = (x & 0xFFE0); peep->next_y = (y & 0xFFE0); peep->next_z = map_element->base_height; - peep->next_var_29 = map_element->properties.path.type & 3; + peep->next_var_29 = map_element->properties.path.type & 7; sint16 z = peep_get_height_on_slope(peep, x, y); @@ -6280,7 +6280,7 @@ static int peep_footpath_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_ma peep->var_EF &= 0xC0; peep->var_EF |= var_EF; - if (RCT2_GLOBAL(0x00F1AEE2, uint8) == 1){ + if (vandalism == true){ peep->var_EF |= 1; if (peep->var_EF & 0x3E && !(peep->var_EF & 0xC0)){ @@ -6599,7 +6599,7 @@ static int sub_693C9E(rct_peep *peep) } if (x < 32 || y < 32 || x >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16)){ - if (peep->type == PEEP_TYPE_STAFF){ + if (peep->var_2A == 1){ RCT2_GLOBAL(0x00F1EE18, uint16) |= (1 << 1); } return peep_return_to_center_of_tile(peep); diff --git a/src/windows/guest.c b/src/windows/guest.c index 9ede943524..bd068b719d 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -688,7 +688,7 @@ void window_guest_viewport_init(rct_window* w){ union{ sprite_focus sprite; coordinate_focus coordinate; - } focus; //The focus will be either a sprite or a coordinate. + } focus = { 0 }; //The focus will be either a sprite or a coordinate. focus.sprite.sprite_id = w->number; diff --git a/src/windows/staff.c b/src/windows/staff.c index 141ddc6b64..fd2d4bc17c 100644 --- a/src/windows/staff.c +++ b/src/windows/staff.c @@ -1177,7 +1177,7 @@ void window_staff_overview_unknown_14(rct_window *w) void window_staff_viewport_init(rct_window* w){ if (w->page != WINDOW_STAFF_OVERVIEW) return; - sprite_focus focus; + sprite_focus focus = { 0 }; focus.sprite_id = w->number; diff --git a/src/world/footpath.c b/src/world/footpath.c index 2426cac8fc..a212baf0e4 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -518,7 +518,7 @@ void footpath_provisional_update() */ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement) { - int z, interactionType; + int z = 0, interactionType; rct_map_element *myMapElement; rct_viewport *viewport; rct_xy16 map_pos = { 0 }; From 812010001d30b53d54a0247a4193cbb8bfcc05f1 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Sat, 25 Jul 2015 11:16:59 +0100 Subject: [PATCH 6/6] Implement guest surface path finding --- src/peep/peep.c | 95 ++++++++++++++++++++++++++++++++++++++++++++ src/world/footpath.c | 9 +++-- src/world/footpath.h | 1 + src/world/map.c | 39 ++++++++++++++++++ src/world/map.h | 1 + 5 files changed, 141 insertions(+), 4 deletions(-) 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();