1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 19:13:07 +01:00

Move Update state functions to correct files

This commit is contained in:
duncanspumpkin
2018-04-03 17:46:08 +01:00
parent 6e02d6af4c
commit f89b0927f6
3 changed files with 1535 additions and 1537 deletions

View File

@@ -3050,3 +3050,740 @@ void rct_peep::UpdateRide()
break;
}
}
/**
*
* rct2: 0x0069030A
*/
void rct_peep::UpdateWalking()
{
if (!CheckForPath())
return;
if (peep_flags & PEEP_FLAGS_WAVING)
{
if (action >= PEEP_ACTION_NONE_1)
{
if ((0xFFFF & scenario_rand()) < 936)
{
invalidate_sprite_2((rct_sprite *)this);
action = PEEP_ACTION_WAVE_2;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)this);
}
}
}
if (peep_flags & PEEP_FLAGS_PHOTO)
{
if (action >= PEEP_ACTION_NONE_1)
{
if ((0xFFFF & scenario_rand()) < 936)
{
invalidate_sprite_2((rct_sprite *)this);
action = PEEP_ACTION_TAKE_PHOTO;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)this);
}
}
}
if (peep_flags & PEEP_FLAGS_PAINTING)
{
if (action >= PEEP_ACTION_NONE_1)
{
if ((0xFFFF & scenario_rand()) < 936)
{
invalidate_sprite_2((rct_sprite *)this);
action = PEEP_ACTION_DRAW_PICTURE;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)this);
}
}
}
if (peep_flags & PEEP_FLAGS_LITTER)
{
if (!(next_var_29 & 0x18))
{
if ((0xFFFF & scenario_rand()) <= 4096)
{
static constexpr const uint8 litter_types[] = {
LITTER_TYPE_EMPTY_CAN,
LITTER_TYPE_RUBBISH,
LITTER_TYPE_EMPTY_BURGER_BOX,
LITTER_TYPE_EMPTY_CUP,
};
sint32 ebp = litter_types[scenario_rand() & 0x3];
sint32 litterX = x + (scenario_rand() & 0x7) - 3;
sint32 litterY = y + (scenario_rand() & 0x7) - 3;
sint32 litterDirection = (scenario_rand() & 0x3);
litter_create(litterX, litterY, z, litterDirection, ebp);
}
}
}
else if (peep_has_empty_container(this))
{
if ((!(next_var_29 & 0x18)) && ((uint32)(sprite_index & 0x1FF) == (gCurrentTicks & 0x1FF)) &&
((0xFFFF & scenario_rand()) <= 4096))
{
uint8 pos_stnd = 0;
for (sint32 container = peep_empty_container_standard_flag(this); pos_stnd < 32; pos_stnd++)
if (container & (1u << pos_stnd))
break;
sint32 bp = 0;
if (pos_stnd != 32)
{
item_standard_flags &= ~(1u << pos_stnd);
bp = item_standard_litter[pos_stnd];
}
else
{
uint8 pos_extr = 0;
for (sint32 container = peep_empty_container_extra_flag(this); pos_extr < 32; pos_extr++)
if (container & (1u << pos_extr))
break;
item_extra_flags &= ~(1u << pos_extr);
bp = item_extra_litter[pos_extr];
}
window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY;
peep_update_sprite_type(this);
sint32 litterX = x + (scenario_rand() & 0x7) - 3;
sint32 litterY = y + (scenario_rand() & 0x7) - 3;
sint32 litterDirection = (scenario_rand() & 0x3);
litter_create(litterX, litterY, z, litterDirection, bp);
}
}
uint8 pathingResult;
PerformNextAction(pathingResult);
if (!(pathingResult & PATHING_DESTINATION_REACHED))
return;
if ((next_var_29 & 0x18) == 8)
{
rct_tile_element * tile_element = map_get_surface_element_at({next_x, next_y});
sint32 water_height = surface_get_water_height(tile_element);
if (water_height)
{
invalidate_sprite_2((rct_sprite *)this);
water_height *= 16;
sprite_move(x, y, water_height, (rct_sprite *)this);
invalidate_sprite_2((rct_sprite *)this);
SetState(PEEP_STATE_FALLING);
return;
}
}
peep_check_if_lost(this);
peep_check_cant_find_ride(this);
peep_check_cant_find_exit(this);
if (peep_update_walking_find_bench(this))
return;
if (peep_update_walking_find_bin(this))
return;
peep_update_walking_break_scenery(this);
if (state != PEEP_STATE_WALKING)
return;
if (peep_flags & PEEP_FLAGS_LEAVING_PARK)
return;
if (nausea > 140)
return;
if (happiness < 120)
return;
if (toilet > 140)
return;
uint16 chance = HasFoodExtraFlag() ? 13107 : 2849;
if ((scenario_rand() & 0xFFFF) > chance)
return;
if (next_var_29 & 0x1C)
return;
rct_tile_element * tile_element = map_get_first_element_at(next_x / 32, next_y / 32);
for (;; tile_element++)
{
if (tile_element->GetType() == TILE_ELEMENT_TYPE_PATH)
{
if (next_z == tile_element->base_height)
break;
}
if (tile_element_is_last_for_tile(tile_element))
{
return;
}
}
sint32 positions_free = 15;
if (footpath_element_has_path_scenery(tile_element))
{
if (!footpath_element_path_scenery_is_ghost(tile_element))
{
rct_scenery_entry * sceneryEntry = get_footpath_item_entry(footpath_element_get_path_scenery_index(tile_element));
if (sceneryEntry == nullptr)
{
return;
}
if (!(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BENCH))
positions_free = 9;
}
}
sint32 edges = (tile_element->properties.path.edges & 0xF) ^ 0xF;
if (edges == 0)
return;
uint8 chosen_edge = scenario_rand() & 0x3;
for (; !(edges & (1 << chosen_edge));)
chosen_edge = (chosen_edge + 1) & 3;
uint8 ride_to_view, ride_seat_to_view;
if (!peep_find_ride_to_look_at(this, chosen_edge, &ride_to_view, &ride_seat_to_view))
return;
// Check if there is a peep watching (and if there is place for us)
uint16 sprite_id = sprite_get_first_in_quadrant(x, y);
for (rct_sprite * sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->unknown.next_in_quadrant)
{
sprite = get_sprite(sprite_id);
if (sprite->unknown.linked_list_type_offset != SPRITE_LIST_PEEP * 2)
continue;
if (sprite->peep.state != PEEP_STATE_WATCHING)
continue;
if (z != sprite->peep.z)
continue;
if ((sprite->peep.var_37 & 0x3) != chosen_edge)
continue;
positions_free &= ~(1 << ((sprite->peep.var_37 & 0x1C) >> 2));
}
if (!positions_free)
return;
uint8 chosen_position = scenario_rand() & 0x3;
for (; !(positions_free & (1 << chosen_position));)
chosen_position = (chosen_position + 1) & 3;
current_ride = ride_to_view;
current_seat = ride_seat_to_view;
var_37 = chosen_edge | (chosen_position << 2);
SetState(PEEP_STATE_WATCHING);
sub_state = 0;
sint32 ebx = var_37 & 0x1F;
sint32 destX = (x & 0xFFE0) + _981F4C[ebx].x;
sint32 destY = (y & 0xFFE0) + _981F4C[ebx].y;
destination_x = destX;
destination_y = destY;
destination_tolerance = 3;
if (current_seat & 1)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_NEW_RIDE, PEEP_THOUGHT_ITEM_NONE);
}
if (current_ride == 0xFF)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_SCENERY, PEEP_THOUGHT_ITEM_NONE);
}
}
/**
*
* rct2: 0x69185D
*/
void rct_peep::UpdateQueuing()
{
if (!CheckForPath())
{
RemoveFromQueue();
return;
}
Ride * ride = get_ride(current_ride);
if (ride->status == RIDE_STATUS_CLOSED || ride->status == RIDE_STATUS_TESTING)
{
RemoveFromQueue();
SetState(PEEP_STATE_1);
return;
}
if (sub_state != 10)
{
bool is_front = true;
if (next_in_queue != SPRITE_INDEX_NULL)
{
// Fix #4819: Occasionally the peep->next_in_queue is incorrectly set
// to prevent this from causing the peeps to enter a loop
// first check if the next in queue is actually nearby
// if they are not then it's safe to assume that this is
// the front of the queue.
rct_peep * next_peep = GET_PEEP(next_in_queue);
if (abs(next_peep->x - x) < 32 && abs(next_peep->y - y) < 32)
{
is_front = false;
}
}
if (is_front)
{
// Happens every time peep goes onto ride.
destination_tolerance = 0;
SetState(PEEP_STATE_QUEUING_FRONT);
sub_state = PEEP_RIDE_AT_ENTRANCE;
return;
}
// Give up queueing for the ride
sprite_direction ^= (1 << 4);
invalidate_sprite_2((rct_sprite *)this);
RemoveFromQueue();
SetState(PEEP_STATE_1);
return;
}
uint8 pathingResult;
PerformNextAction(pathingResult);
if (action < 0xFE)
return;
if (sprite_type == PEEP_SPRITE_TYPE_NORMAL)
{
if (time_in_queue >= 2000 && (0xFFFF & scenario_rand()) <= 119)
{
// Eat Food/Look at watch
action = PEEP_ACTION_EAT_FOOD;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)this);
}
if (time_in_queue >= 3500 && (0xFFFF & scenario_rand()) <= 93)
{
// Create the I have been waiting in line ages thought
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_QUEUING_AGES, current_ride);
}
}
else
{
if (!(time_in_queue & 0x3F) && action == 0xFE && next_action_sprite_type == 2)
{
switch (sprite_type)
{
case PEEP_SPRITE_TYPE_ICE_CREAM:
case PEEP_SPRITE_TYPE_CHIPS:
case PEEP_SPRITE_TYPE_BURGER:
case PEEP_SPRITE_TYPE_DRINK:
case PEEP_SPRITE_TYPE_CANDYFLOSS:
case PEEP_SPRITE_TYPE_PIZZA:
case PEEP_SPRITE_TYPE_POPCORN:
case PEEP_SPRITE_TYPE_HOT_DOG:
case PEEP_SPRITE_TYPE_TENTACLE:
case PEEP_SPRITE_TYPE_TOFFEE_APPLE:
case PEEP_SPRITE_TYPE_DOUGHNUT:
case PEEP_SPRITE_TYPE_COFFEE:
case PEEP_SPRITE_TYPE_CHICKEN:
case PEEP_SPRITE_TYPE_LEMONADE:
case PEEP_SPRITE_TYPE_PRETZEL:
case PEEP_SPRITE_TYPE_SU_JONGKWA:
case PEEP_SPRITE_TYPE_JUICE:
case PEEP_SPRITE_TYPE_FUNNEL_CAKE:
case PEEP_SPRITE_TYPE_NOODLES:
case PEEP_SPRITE_TYPE_SAUSAGE:
case PEEP_SPRITE_TYPE_SOUP:
case PEEP_SPRITE_TYPE_SANDWICH:
// Eat food
action = PEEP_ACTION_EAT_FOOD;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)this);
break;
}
}
}
if (time_in_queue < 4300)
return;
if (happiness <= 65 && (0xFFFF & scenario_rand()) < 2184)
{
// Give up queueing for the ride
sprite_direction ^= (1 << 4);
invalidate_sprite_2((rct_sprite *)this);
RemoveFromQueue();
SetState(PEEP_STATE_1);
}
}
/**
* rct2: 0x691451
*/
void rct_peep::UpdateEnteringPark()
{
if (var_37 != 1)
{
uint8 pathingResult;
PerformNextAction(pathingResult);
if ((pathingResult & PATHING_OUTSIDE_PARK))
{
decrement_guests_heading_for_park();
peep_sprite_remove(this);
}
return;
}
sint16 actionX = 0;
sint16 actionY = 0;
sint16 xy_distance;
if (UpdateAction(&actionX, &actionY, &xy_distance))
{
invalidate_sprite_2((rct_sprite *)this);
sprite_move(actionX, actionY, z, (rct_sprite *)this);
invalidate_sprite_2((rct_sprite *)this);
return;
}
SetState(PEEP_STATE_FALLING);
outside_of_park = 0;
time_in_park = gScenarioTicks;
increment_guests_in_park();
decrement_guests_heading_for_park();
auto intent = Intent(INTENT_ACTION_UPDATE_GUEST_COUNT);
context_broadcast_intent(&intent);
}
/**
*
* rct2: 0x6914CD
*/
void rct_peep::UpdateLeavingPark()
{
if (var_37 != 0)
{
uint8 pathingResult;
PerformNextAction(pathingResult);
if (!(pathingResult & PATHING_OUTSIDE_PARK))
return;
peep_sprite_remove(this);
return;
}
sint16 actionX = 0;
sint16 actionY = 0;
sint16 xy_distance;
if (UpdateAction(&actionX, &actionY, &xy_distance))
{
invalidate_sprite_2((rct_sprite *)this);
sprite_move(actionX, actionY, z, (rct_sprite *)this);
invalidate_sprite_2((rct_sprite *)this);
return;
}
outside_of_park = 1;
destination_tolerance = 5;
decrement_guests_in_park();
auto intent = Intent(INTENT_ACTION_UPDATE_GUEST_COUNT);
context_broadcast_intent(&intent);
var_37 = 1;
window_invalidate_by_class(WC_GUEST_LIST);
uint8 pathingResult;
PerformNextAction(pathingResult);
if (!(pathingResult & PATHING_OUTSIDE_PARK))
return;
peep_sprite_remove(this);
}
/**
*
* rct2: 0x6916D6
*/
void rct_peep::UpdateWatching()
{
if (sub_state == 0)
{
if (!CheckForPath())
return;
uint8 pathingResult;
PerformNextAction(pathingResult);
if (!(pathingResult & PATHING_DESTINATION_REACHED))
return;
destination_x = x;
destination_y = y;
sprite_direction = (var_37 & 3) * 8;
invalidate_sprite_2((rct_sprite *)this);
action = 0xFE;
next_action_sprite_type = 2;
SwitchNextActionSpriteType();
sub_state++;
time_to_stand = Math::Clamp(0, ((129 - energy) * 16 + 50) / 2, 255);
peep_update_sprite_type(this);
}
else if (sub_state == 1)
{
if (action < 0xFE)
{
// 6917F6
sint16 actionX = 0;
sint16 actionY = 0;
sint16 xy_distance;
UpdateAction(&actionX, &actionY, &xy_distance);
if (action != 0xFF)
return;
action = 0xFE;
}
else
{
if (HasFood())
{
if ((scenario_rand() & 0xFFFF) <= 1310)
{
action = PEEP_ACTION_EAT_FOOD;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)this);
return;
}
}
if ((scenario_rand() & 0xFFFF) <= 655)
{
action = PEEP_ACTION_TAKE_PHOTO;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)this);
return;
}
if ((standing_flags & 1))
{
if ((scenario_rand() & 0xFFFF) <= 655)
{
action = PEEP_ACTION_WAVE;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)this);
return;
}
}
}
standing_flags ^= (1 << 7);
if (!(standing_flags & (1 << 7)))
return;
time_to_stand--;
if (time_to_stand != 0)
return;
SetState(PEEP_STATE_WALKING);
peep_update_sprite_type(this);
// Send peep to the centre of current tile.
destination_x = (x & 0xFFE0) + 16;
destination_y = (y & 0xFFE0) + 16;
destination_tolerance = 5;
UpdateCurrentActionSpriteType();
}
}
/**
*
* rct2: 0x00691089
*/
void rct_peep::UpdateUsingBin()
{
if (sub_state == 0)
{
if (!CheckForPath())
return;
uint8 pathingResult;
PerformNextAction(pathingResult);
if (!(pathingResult & PATHING_DESTINATION_REACHED))
return;
sub_state = 1;
}
else if (sub_state == 1)
{
if (action != PEEP_ACTION_NONE_2)
{
sint16 actionX, actionY, xy_distance;
UpdateAction(&actionX, &actionY, &xy_distance);
return;
}
rct_tile_element * tile_element = map_get_first_element_at(next_x / 32, next_y / 32);
for (;; tile_element++)
{
if (tile_element->GetType() != TILE_ELEMENT_TYPE_PATH)
{
continue;
}
if (tile_element->base_height == next_z)
break;
if (tile_element_is_last_for_tile(tile_element))
{
StateReset();
return;
}
}
if (!footpath_element_has_path_scenery(tile_element))
{
StateReset();
return;
}
rct_scenery_entry * sceneryEntry = get_footpath_item_entry(footpath_element_get_path_scenery_index(tile_element));
if (!(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BIN))
{
StateReset();
return;
}
if (tile_element->flags & TILE_ELEMENT_FLAG_BROKEN)
{
StateReset();
return;
}
if (footpath_element_path_scenery_is_ghost(tile_element))
{
StateReset();
return;
}
// Bin selection is one of 4 corners
uint8 selected_bin = var_37 * 2;
// This counts down 2 = No rubbish, 0 = full
uint8 space_left_in_bin = 0x3 & (tile_element->properties.path.addition_status >> selected_bin);
uint32 empty_containers = peep_empty_container_standard_flag(this);
for (uint8 cur_container = 0; cur_container < 32; cur_container++)
{
if (!(empty_containers & (1u << cur_container)))
continue;
if (space_left_in_bin != 0)
{
// OpenRCT2 modification: This previously used
// the tick count as a simple random function
// switched to scenario_rand as it is more reliable
if ((scenario_rand() & 7) == 0)
space_left_in_bin--;
item_standard_flags &= ~(1 << cur_container);
window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY;
peep_update_sprite_type(this);
continue;
}
uint8 bp = item_standard_litter[cur_container];
sint32 litterX = x + (scenario_rand() & 7) - 3;
sint32 litterY = y + (scenario_rand() & 7) - 3;
litter_create(litterX, litterY, z, scenario_rand() & 3, bp);
item_standard_flags &= ~(1 << cur_container);
window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY;
peep_update_sprite_type(this);
}
// Original bug: This would clear any rubbish placed by the previous function
// space_left_in_bin = 0x3 & (tile_element->properties.path.addition_status >> selected_bin);
empty_containers = peep_empty_container_extra_flag(this);
for (uint8 cur_container = 0; cur_container < 32; cur_container++)
{
if (!(empty_containers & (1u << cur_container)))
continue;
if (space_left_in_bin != 0)
{
// OpenRCT2 modification: This previously used
// the tick count as a simple random function
// switched to scenario_rand as it is more reliable
if ((scenario_rand() & 7) == 0)
space_left_in_bin--;
item_extra_flags &= ~(1 << cur_container);
window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY;
peep_update_sprite_type(this);
continue;
}
uint8 bp = item_extra_litter[cur_container];
sint32 litterX = x + (scenario_rand() & 7) - 3;
sint32 litterY = y + (scenario_rand() & 7) - 3;
litter_create(litterX, litterY, z, scenario_rand() & 3, bp);
item_extra_flags &= ~(1 << cur_container);
window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY;
peep_update_sprite_type(this);
}
// Place new amount in bin by first clearing the value
tile_element->properties.path.addition_status &= ~(3 << selected_bin);
// Then placing the new value.
tile_element->properties.path.addition_status |= space_left_in_bin << selected_bin;
map_invalidate_tile_zoom0(next_x, next_y, tile_element->base_height << 3,
tile_element->clearance_height << 3);
StateReset();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -2357,3 +2357,801 @@ void rct_peep::UpdatePatrolling()
peep_update_patrolling_find_watering(this);
}
enum {
PEEP_FIXING_ENTER_STATION = 1 << 0,
PEEP_FIXING_MOVE_TO_BROKEN_DOWN_VEHICLE = 1 << 1,
PEEP_FIXING_FIX_VEHICLE_CLOSED_RESTRAINTS = 1 << 2,
PEEP_FIXING_FIX_VEHICLE_CLOSED_DOORS = 1 << 3,
PEEP_FIXING_FIX_VEHICLE_OPEN_RESTRAINTS = 1 << 4,
PEEP_FIXING_FIX_VEHICLE_OPEN_DOORS = 1 << 5,
PEEP_FIXING_FIX_VEHICLE_MALFUNCTION = 1 << 6,
PEEP_FIXING_MOVE_TO_STATION_END = 1 << 7,
PEEP_FIXING_FIX_STATION_END = 1 << 8,
PEEP_FIXING_MOVE_TO_STATION_START = 1 << 9,
PEEP_FIXING_FIX_STATION_START = 1 << 10,
PEEP_FIXING_FIX_STATION_BRAKES = 1 << 11,
PEEP_FIXING_MOVE_TO_STATION_EXIT = 1 << 12,
PEEP_FIXING_FINISH_FIX_OR_INSPECT = 1 << 13,
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT = 1 << 14,
};
/**
* peep_fixing_sub_state_mask[] defines the applicable peep sub_states for
* mechanics fixing a ride. The array is indexed by breakdown_reason:
* - indexes 0-7 are the 8 breakdown reasons (see BREAKDOWN_* in Ride.h)
* when fixing a broken down ride;
* - index 8 is for inspecting a ride.
*/
static constexpr const uint32 peep_fixing_sub_state_mask[9] = {
( // BREAKDOWN_SAFETY_CUT_OUT
PEEP_FIXING_MOVE_TO_STATION_END |
PEEP_FIXING_FIX_STATION_END |
PEEP_FIXING_MOVE_TO_STATION_START |
PEEP_FIXING_FIX_STATION_START |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
),
( // BREAKDOWN_RESTRAINTS_STUCK_CLOSED
PEEP_FIXING_MOVE_TO_BROKEN_DOWN_VEHICLE |
PEEP_FIXING_FIX_VEHICLE_CLOSED_RESTRAINTS |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
),
( // BREAKDOWN_RESTRAINTS_STUCK_OPEN
PEEP_FIXING_MOVE_TO_BROKEN_DOWN_VEHICLE |
PEEP_FIXING_FIX_VEHICLE_OPEN_RESTRAINTS |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
),
( // BREAKDOWN_DOORS_STUCK_CLOSED
PEEP_FIXING_MOVE_TO_BROKEN_DOWN_VEHICLE |
PEEP_FIXING_FIX_VEHICLE_CLOSED_DOORS |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
),
( // BREAKDOWN_DOORS_STUCK_OPEN
PEEP_FIXING_MOVE_TO_BROKEN_DOWN_VEHICLE |
PEEP_FIXING_FIX_VEHICLE_OPEN_DOORS |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
),
( // BREAKDOWN_VEHICLE_MALFUNCTION
PEEP_FIXING_MOVE_TO_BROKEN_DOWN_VEHICLE |
PEEP_FIXING_FIX_VEHICLE_MALFUNCTION |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
),
( // BREAKDOWN_BRAKES_FAILURE
PEEP_FIXING_MOVE_TO_STATION_START |
PEEP_FIXING_FIX_STATION_BRAKES |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
),
( // BREAKDOWN_CONTROL_FAILURE
PEEP_FIXING_MOVE_TO_STATION_END |
PEEP_FIXING_FIX_STATION_END |
PEEP_FIXING_MOVE_TO_STATION_START |
PEEP_FIXING_FIX_STATION_START |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
),
( // INSPECTION
PEEP_FIXING_MOVE_TO_STATION_END |
PEEP_FIXING_FIX_STATION_END |
PEEP_FIXING_MOVE_TO_STATION_START |
PEEP_FIXING_FIX_STATION_START |
PEEP_FIXING_MOVE_TO_STATION_EXIT |
PEEP_FIXING_FINISH_FIX_OR_INSPECT |
PEEP_FIXING_LEAVE_BY_ENTRANCE_EXIT
)
};
/**
*
* rct2: 0x006C0E8B
* Also used by inspecting.
*/
void rct_peep::UpdateFixing(sint32 steps)
{
Ride * ride = get_ride(current_ride);
if (ride->type == RIDE_TYPE_NULL)
{
SetState(PEEP_STATE_FALLING);
return;
}
bool progressToNextSubstate = true;
bool firstRun = true;
if ((state == PEEP_STATE_INSPECTING) &&
(ride->lifecycle_flags & ( RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN)))
{
// Ride has broken down since Mechanic was called to inspect it.
// Mechanic identifies the breakdown and switches to fixing it.
state = PEEP_STATE_FIXING;
}
while (progressToNextSubstate)
{
switch (sub_state)
{
case 0:
progressToNextSubstate = peep_update_fixing_enter_station(ride);
break;
case 1:
progressToNextSubstate = peep_update_fixing_move_to_broken_down_vehicle(firstRun, this, ride);
break;
case 2:
case 3:
case 4:
case 5:
progressToNextSubstate = peep_update_fixing_fix_vehicle(firstRun, this, ride);
break;
case 6:
progressToNextSubstate = peep_update_fixing_fix_vehicle_malfunction(firstRun, this, ride);
break;
case 7:
progressToNextSubstate = peep_update_fixing_move_to_station_end(firstRun, this, ride);
break;
case 8:
progressToNextSubstate = peep_update_fixing_fix_station_end(firstRun, this);
break;
case 9:
progressToNextSubstate = peep_update_fixing_move_to_station_start(firstRun, this, ride);
break;
case 10:
progressToNextSubstate = peep_update_fixing_fix_station_start(firstRun, this, ride);
break;
case 11:
progressToNextSubstate = peep_update_fixing_fix_station_brakes(firstRun, this, ride);
break;
case 12:
progressToNextSubstate = peep_update_fixing_move_to_station_exit(firstRun, this, ride);
break;
case 13:
progressToNextSubstate = peep_update_fixing_finish_fix_or_inspect(firstRun, steps, this, ride);
break;
case 14:
progressToNextSubstate = peep_update_fixing_leave_by_entrance_exit(firstRun, this, ride);
break;
default:
log_error("Invalid substate");
progressToNextSubstate = false;
}
firstRun = false;
if (!progressToNextSubstate)
{
break;
}
sint32 subState = sub_state;
uint32 sub_state_sequence_mask = peep_fixing_sub_state_mask[8];
if (state != PEEP_STATE_INSPECTING)
{
sub_state_sequence_mask = peep_fixing_sub_state_mask[ride->breakdown_reason_pending];
}
do
{
subState++;
} while ((sub_state_sequence_mask & (1 << subState)) == 0);
sub_state = subState & 0xFF;
}
}
/**
* rct2: 0x006C0EEC
* fixing sub_state: enter_station - applies to fixing all break down reasons and ride inspections.
*/
static bool peep_update_fixing_enter_station(Ride * ride)
{
ride->mechanic_status = RIDE_MECHANIC_STATUS_FIXING;
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE;
return true;
}
/**
* rct2: 0x006C0F09
* fixing sub_state: move_to_broken_down_vehicle - applies to fixing all vehicle specific breakdown reasons
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_move_to_broken_down_vehicle(bool firstRun, rct_peep * peep, Ride * ride)
{
sint16 x, y, tmp_xy_distance;
if (!firstRun)
{
rct_vehicle * vehicle = ride_get_broken_vehicle(ride);
if (vehicle == nullptr)
{
return true;
}
while (true)
{
if (vehicle->is_child == 0)
{
break;
}
uint8 trackType = vehicle->track_type >> 2;
if (trackType == TRACK_ELEM_END_STATION)
{
break;
}
if (trackType == TRACK_ELEM_BEGIN_STATION)
{
break;
}
if (trackType == TRACK_ELEM_MIDDLE_STATION)
{
break;
}
vehicle = GET_VEHICLE(vehicle->prev_vehicle_on_ride);
}
LocationXY16 offset = word_981D6C[peep->direction];
peep->destination_x = (offset.x * -12) + vehicle->x;
peep->destination_y = (offset.y * -12) + vehicle->y;
peep->destination_tolerance = 2;
}
invalidate_sprite_2((rct_sprite *)peep);
if (peep->UpdateAction(&x, &y, &tmp_xy_distance))
{
sprite_move(x, y, peep->z, (rct_sprite *)peep);
invalidate_sprite_2((rct_sprite *)peep);
return false;
}
return true;
}
/**
* rct2: 0x006C0FD3
* fixing sub_state: fix_vehicle - applies to fixing vehicle with:
* 1. restraints stuck closed,
* 2. doors stuck closed,
* 3. restrains stuck open,
* 4. doors stuck open.
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_fix_vehicle(bool firstRun, rct_peep * peep, Ride * ride)
{
if (!firstRun)
{
peep->sprite_direction = peep->direction << 3;
peep->action = (scenario_rand() & 1) ? PEEP_ACTION_STAFF_FIX_2 : PEEP_ACTION_STAFF_FIX;
peep->action_sprite_image_offset = 0;
peep->action_frame = 0;
peep->UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)peep);
}
if (peep->action == PEEP_ACTION_NONE_2)
{
return true;
}
peep->UpdateAction();
uint8 actionFrame = (peep->action == PEEP_ACTION_STAFF_FIX) ? 0x25 : 0x50;
if (peep->action_frame != actionFrame)
{
return false;
}
rct_vehicle * vehicle = ride_get_broken_vehicle(ride);
if (vehicle == nullptr)
{
return true;
}
vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_BROKEN_CAR;
return false;
}
/**
* rct2: 0x006C107B
* fixing sub_state: fix_vehicle_malfunction - applies fixing to vehicle malfunction.
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_fix_vehicle_malfunction(bool firstRun, rct_peep * peep, Ride * ride)
{
if (!firstRun)
{
peep->sprite_direction = peep->direction << 3;
peep->action = PEEP_ACTION_STAFF_FIX_3;
peep->action_sprite_image_offset = 0;
peep->action_frame = 0;
peep->UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)peep);
}
if (peep->action == PEEP_ACTION_NONE_2)
{
return true;
}
peep->UpdateAction();
if (peep->action_frame != 0x65)
{
return false;
}
rct_vehicle * vehicle = ride_get_broken_vehicle(ride);
if (vehicle == nullptr)
{
return true;
}
vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_BROKEN_TRAIN;
return false;
}
/** rct2: 0x00992A3C */
static constexpr const CoordsXY _992A3C[] = {
{ -12, 0 },
{ 0, 12 },
{ 12, 0 },
{ 0, -12 },
};
/**
* rct2: 0x006C1114
* fixing sub_state: move_to_station_end - applies to fixing station specific breakdowns: safety cut-out, control failure, inspection.
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_move_to_station_end(bool firstRun, rct_peep * peep, Ride * ride)
{
sint16 x, y, tmp_distance;
if (!firstRun)
{
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_HAS_NO_TRACK))
{
return true;
}
LocationXY8 stationPosition = ride->station_starts[peep->current_ride_station];
if (stationPosition.xy == RCT_XY8_UNDEFINED)
{
return true;
}
uint8 stationZ = ride->station_heights[peep->current_ride_station];
uint16 stationX = stationPosition.x * 32;
uint16 stationY = stationPosition.y * 32;
rct_tile_element * tileElement = map_get_track_element_at(stationX, stationY, stationZ);
if (tileElement == nullptr)
{
log_error("Couldn't find tile_element");
return false;
}
sint32 direction = tile_element_get_direction(tileElement);
CoordsXY offset = _992A3C[direction];
stationX += 16 + offset.x;
if (offset.x == 0)
{
stationX = peep->destination_x;
}
stationY += 16 + offset.y;
if (offset.y == 0)
{
stationY = peep->destination_y;
}
peep->destination_x = stationX;
peep->destination_y = stationY;
peep->destination_tolerance = 2;
}
invalidate_sprite_2((rct_sprite *)peep);
if (!peep->UpdateAction(&x, &y, &tmp_distance))
{
return true;
}
sprite_move(x, y, peep->z, (rct_sprite *)peep);
invalidate_sprite_2((rct_sprite *)peep);
return false;
}
/**
* rct2: 0x006C11F5
* fixing sub_state: fix_station_end - applies to fixing station specific breakdowns: safety cut-out, control failure, inspection.
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_fix_station_end(bool firstRun, rct_peep * peep)
{
if (!firstRun)
{
peep->sprite_direction = peep->direction << 3;
peep->action = PEEP_ACTION_STAFF_CHECKBOARD;
peep->action_frame = 0;
peep->action_sprite_image_offset = 0;
peep->UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)peep);
}
if (peep->action == PEEP_ACTION_NONE_2)
{
return true;
}
peep->UpdateAction();
return false;
}
/**
* rct2: 0x006C1239
* fixing sub_state: move_to_station_start
* 1. applies to fixing station specific breakdowns: safety cut-out, control failure,
* 2. applies to fixing brake failure,
* 3. applies to inspection.
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_move_to_station_start(bool firstRun, rct_peep * peep, Ride * ride)
{
sint16 x, y, tmp_xy_distance;
if (!firstRun)
{
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_HAS_NO_TRACK))
{
return true;
}
LocationXY8 stationPosition = ride->station_starts[peep->current_ride_station];
if (stationPosition.xy == RCT_XY8_UNDEFINED)
{
return true;
}
uint8 stationZ = ride->station_heights[peep->current_ride_station];
CoordsXYE input;
input.x = stationPosition.x * 32;
input.y = stationPosition.y * 32;
input.element = map_get_track_element_at_from_ride(input.x, input.y, stationZ, peep->current_ride);
if (input.element == nullptr)
{
return true;
}
uint8 direction = 0;
track_begin_end trackBeginEnd;
while (track_block_get_previous(input.x, input.y, input.element, &trackBeginEnd))
{
if (track_element_is_station(trackBeginEnd.begin_element))
{
input.x = trackBeginEnd.begin_x;
input.y = trackBeginEnd.begin_y;
input.element = trackBeginEnd.begin_element;
direction = tile_element_get_direction(trackBeginEnd.begin_element);
continue;
}
break;
}
// loc_6C12ED:
uint16 destinationX = input.x + 16;
uint16 destinationY = input.y + 16;
CoordsXY offset = _992A3C[direction];
destinationX -= offset.x;
if (offset.x == 0)
{
destinationX = peep->destination_x;
}
destinationY -= offset.y;
if (offset.y == 0)
{
destinationY = peep->destination_y;
}
peep->destination_x = destinationX;
peep->destination_y = destinationY;
peep->destination_tolerance = 2;
}
invalidate_sprite_2((rct_sprite *)peep);
if (!peep->UpdateAction(&x, &y, &tmp_xy_distance))
{
return true;
}
sprite_move(x, y, peep->z, (rct_sprite *)peep);
invalidate_sprite_2((rct_sprite *)peep);
return false;
}
/**
* rct2: 0x006C1368
* fixing sub_state: fix_station_start
* 1. applies to fixing station specific breakdowns: safety cut-out, control failure,
* 2. applies to inspection.
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_fix_station_start(bool firstRun, rct_peep * peep, Ride * ride)
{
if (!firstRun)
{
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_HAS_NO_TRACK))
{
return true;
}
peep->sprite_direction = peep->direction << 3;
peep->action = PEEP_ACTION_STAFF_FIX;
peep->action_frame = 0;
peep->action_sprite_image_offset = 0;
peep->UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)peep);
}
if (peep->action == PEEP_ACTION_NONE_2)
{
return true;
}
peep->UpdateAction();
return false;
}
/**
* rct2: 0x006C13CE
* fixing sub_state: fix_station_brakes - applies to fixing brake failure
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_fix_station_brakes(bool firstRun, rct_peep * peep, Ride * ride)
{
if (!firstRun)
{
peep->sprite_direction = peep->direction << 3;
peep->action = PEEP_ACTION_STAFF_FIX_GROUND;
peep->action_frame = 0;
peep->action_sprite_image_offset = 0;
peep->UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)peep);
}
if (peep->action == PEEP_ACTION_NONE_2)
{
return true;
}
peep->UpdateAction();
if (peep->action_frame == 0x28)
{
ride->mechanic_status = RIDE_MECHANIC_STATUS_HAS_FIXED_STATION_BRAKES;
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE;
}
if (peep->action_frame == 0x13 || peep->action_frame == 0x19 || peep->action_frame == 0x1F || peep->action_frame == 0x25 ||
peep->action_frame == 0x2B)
{
audio_play_sound_at_location(SOUND_MECHANIC_FIX, peep->x, peep->y, peep->z);
}
return false;
}
/**
* rct2: 0x006C1474
* fixing sub_state: move_to_station_exit - applies to fixing all failures & inspections
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_move_to_station_exit(bool firstRun, rct_peep * peep, Ride * ride)
{
sint16 x, y, tmp_xy_distance;
if (!firstRun)
{
TileCoordsXYZD stationPosition = ride_get_exit_location(ride, peep->current_ride_station);
if (stationPosition.isNull())
{
stationPosition = ride_get_entrance_location(ride, peep->current_ride_station);
if (stationPosition.isNull())
{
return true;
}
}
uint16 stationX = stationPosition.x * 32;
uint16 stationY = stationPosition.y * 32;
stationX += 16;
stationY += 16;
LocationXY16 direction = word_981D6C[peep->direction];
stationX += direction.x * 20;
stationY += direction.y * 20;
peep->destination_x = stationX;
peep->destination_y = stationY;
peep->destination_tolerance = 2;
}
invalidate_sprite_2((rct_sprite *)peep);
if (!peep->UpdateAction(&x, &y, &tmp_xy_distance))
{
return true;
}
else
{
sprite_move(x, y, peep->z, (rct_sprite *)peep);
invalidate_sprite_2((rct_sprite *)peep);
}
return false;
}
/**
* rct2: 0x006C1504
* fixing sub_state: finish_fix_or_inspect - applies to fixing all failures & inspections
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_finish_fix_or_inspect(bool firstRun, sint32 steps, rct_peep * peep, Ride * ride)
{
if (!firstRun)
{
ride->mechanic_status = RIDE_MECHANIC_STATUS_UNDEFINED;
if (peep->state == PEEP_STATE_INSPECTING)
{
peep_update_ride_inspected(peep->current_ride);
peep->staff_rides_inspected++;
peep->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME | RIDE_INVALIDATE_RIDE_LIST;
return true;
}
peep->staff_rides_fixed++;
peep->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME | RIDE_INVALIDATE_RIDE_LIST;
peep->sprite_direction = peep->direction << 3;
peep->action = PEEP_ACTION_STAFF_ANSWER_CALL_2;
peep->action_frame = 0;
peep->action_sprite_image_offset = 0;
peep->UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)peep);
}
if (peep->action != 0xFF)
{
peep->UpdateAction();
return false;
}
ride_fix_breakdown(peep->current_ride, steps);
return true;
}
/**
* rct2: 0x006C157E
* fixing sub_state: leave_by_entrance_exit - applies to fixing all failures & inspections
* - see peep_fixing_sub_state_mask[]
*/
static bool peep_update_fixing_leave_by_entrance_exit(bool firstRun, rct_peep * peep, Ride * ride)
{
sint16 x, y, xy_distance;
if (!firstRun)
{
TileCoordsXYZD exitPosition = ride_get_exit_location(ride, peep->current_ride_station);
if (exitPosition.isNull())
{
exitPosition = ride_get_entrance_location(ride, peep->current_ride_station);
if (exitPosition.isNull())
{
peep->SetState(PEEP_STATE_FALLING);
return false;
}
}
uint16 exitX = exitPosition.x * 32;
uint16 exitY = exitPosition.y * 32;
exitX += 16;
exitY += 16;
LocationXY16 ebx_direction = word_981D6C[peep->direction];
exitX -= ebx_direction.x * 19;
exitY -= ebx_direction.y * 19;
peep->destination_x = exitX;
peep->destination_y = exitY;
peep->destination_tolerance = 2;
}
invalidate_sprite_2((rct_sprite *)peep);
if (!peep->UpdateAction(&x, &y, &xy_distance))
{
peep->SetState(PEEP_STATE_FALLING);
return false;
}
uint16 z = ride->station_heights[peep->current_ride_station] * 8;
if (xy_distance >= 16)
{
z += RideData5[ride->type].z;
}
sprite_move(x, y, z, (rct_sprite *)peep);
invalidate_sprite_2((rct_sprite *)peep);
return false;
}
/**
* rct2: 0x6B7588
*/
static void peep_update_ride_inspected(sint32 rideIndex)
{
Ride * ride = get_ride(rideIndex);
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_DUE_INSPECTION;
ride->reliability += ((100 - ride->reliability_percentage) / 4) * (scenario_rand() & 0xFF);
ride->last_inspection = 0;
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE | RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
}