Refactor peep logic for choosing rides

This commit is contained in:
Hielke Morsink 2018-04-02 01:44:44 +02:00 committed by duncanspumpkin
parent cbefe633d0
commit c47b9c65b0
3 changed files with 638 additions and 640 deletions

View File

@ -29,6 +29,7 @@
#include "../ride/Station.h"
#include "../ride/Track.h"
#include "../scenario/Scenario.h"
#include "../world/Climate.h"
#include "../world/Footpath.h"
#include "../world/Park.h"
#include "../world/Sprite.h"
@ -37,6 +38,7 @@
// Locations of the spiral slide platform that a peep walks from the entrance of the ride to the
// entrance of the slide. Up to 4 waypoints for each 4 sides that an ride entrance can be located
// and 4 different rotations of the ride. 4 * 4 * 4 = 64 locations.
// clang-format off
static constexpr const CoordsXY SpiralSlideWalkingPath[64] = {
{ 56, 8 },
{ 8, 8 },
@ -104,6 +106,17 @@ static constexpr const CoordsXY SpiralSlideWalkingPath[64] = {
{ 0, 32 },
};
// TODO: Remove duplicate (there's one in peep.cpp too)
static constexpr const ride_rating NauseaMaximumThresholds[] = {
300, 600, 800, 1000
};
// clang-format on
static bool peep_has_voucher_for_free_ride(rct_peep * peep, sint32 rideIndex);
static void peep_ride_is_too_intense(rct_peep * peep, sint32 rideIndex, bool peepAtRide);
static void peep_reset_ride_heading(rct_peep * peep);
static void peep_tried_to_enter_full_queue(rct_peep * peep, sint32 rideIndex);
/**
*
* rct2: 0x00691677
@ -282,6 +295,590 @@ void rct_peep::RemoveFromQueue()
}
}
/**
*
* rct2: 0x00695DD2
*/
void rct_peep::PickRideToGoOn()
{
Ride * ride;
if (this->state != PEEP_STATE_WALKING)
return;
if (this->guest_heading_to_ride_id != 255)
return;
if (this->peep_flags & PEEP_FLAGS_LEAVING_PARK)
return;
if (peep_has_food(this))
return;
if (this->x == LOCATION_NULL)
return;
uint32 rideConsideration[8]{};
// FIX Originally checked for a toy, likely a mistake and should be a map,
// but then again this seems to only allow the peep to go on
// rides they haven't been on before.
if (this->item_standard_flags & PEEP_ITEM_MAP)
{
// Consider rides that peep hasn't been on yet
sint32 i;
FOR_ALL_RIDES(i, ride)
{
if (!HasRidden(i))
{
rideConsideration[i >> 5] |= (1u << (i & 0x1F));
}
}
}
else
{
// Take nearby rides into consideration
sint32 cx = floor2(this->x, 32);
sint32 cy = floor2(this->y, 32);
for (sint32 tileX = cx - 320; tileX <= cx + 320; tileX += 32)
{
for (sint32 tileY = cy - 320; tileY <= cy + 320; tileY += 32)
{
if (tileX >= 0 && tileY >= 0 && tileX < (256 * 32) && tileY < (256 * 32))
{
rct_tile_element * tileElement = map_get_first_element_at(tileX >> 5, tileY >> 5);
do
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
continue;
sint32 rideIndex = track_element_get_ride_index(tileElement);
rideConsideration[rideIndex >> 5] |= (1u << (rideIndex & 0x1F));
} while (!tile_element_is_last_for_tile(tileElement++));
}
}
}
// Always take the tall rides into consideration (realistic as you can usually see them from anywhere in the park)
sint32 i;
FOR_ALL_RIDES(i, ride)
{
if (ride->status != RIDE_STATUS_OPEN)
continue;
if (!ride_has_ratings(ride))
continue;
if (ride->highest_drop_height <= 66 && ride->excitement < RIDE_RATING(8, 00))
continue;
rideConsideration[i >> 5] |= (1u << (i & 0x1F));
}
}
// Filter the considered rides
uint8 potentialRides[256];
uint8 * nextPotentialRide = &potentialRides[0];
sint32 numPotentialRides = 0;
for (sint32 i = 0; i < MAX_RIDES; i++)
{
if (!(rideConsideration[i >> 5] & (1u << (i & 0x1F))))
continue;
ride = get_ride(i);
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_QUEUE_FULL))
{
if (ShouldGoOnRide(i, 0, false, true))
{
*nextPotentialRide++ = i;
numPotentialRides++;
}
}
}
// Pick the most exciting ride
sint32 mostExcitingRideIndex = -1;
ride_rating mostExcitingRideRating = 0;
for (sint32 i = 0; i < numPotentialRides; i++)
{
ride = get_ride(potentialRides[i]);
if (!ride_has_ratings(ride))
continue;
if (ride->excitement > mostExcitingRideRating)
{
mostExcitingRideIndex = potentialRides[i];
mostExcitingRideRating = ride->excitement;
}
}
if (mostExcitingRideIndex == -1)
return;
// Head to that ride
this->guest_heading_to_ride_id = mostExcitingRideIndex;
this->peep_is_lost_countdown = 200;
peep_reset_pathfind_goal(this);
// Invalidate windows
rct_window * w = window_find_by_number(WC_PEEP, this->sprite_index);
if (w != nullptr)
{
window_event_invalidate_call(w);
widget_invalidate(w, WC_PEEP__WIDX_ACTION_LBL);
}
// Make peep look at their map if they have one
if (this->item_standard_flags & PEEP_ITEM_MAP)
{
ReadMap();
}
}
/**
* This function is called whenever a peep is deciding whether or not they want
* to go on a ride or visit a shop. They may be physically present at the
* ride/shop, or they may just be thinking about it.
* rct2: 0x006960AB
*/
bool rct_peep::ShouldGoOnRide(sint32 rideIndex, sint32 entranceNum, bool atQueue, bool thinking)
{
Ride * ride = get_ride(rideIndex);
// Indicates whether a peep is physically at the ride, or is just thinking about going on the ride.
bool peepAtRide = !thinking;
if (ride->status == RIDE_STATUS_OPEN && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
{
// Peeps that are leaving the park will refuse to go on any rides, with the exception of free transport rides.
if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_TRANSPORT_RIDE) || ride->value == 0xFFFF ||
ride_get_price(ride) != 0)
{
if (this->peep_flags & PEEP_FLAGS_LEAVING_PARK)
{
ChoseNotToGoOnRide(rideIndex, peepAtRide, false);
return false;
}
}
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
{
return ShouldGoToShop(rideIndex, peepAtRide);
}
// This used to check !(flags & 2), but the function is only ever called with flags = 0, 1 or 6.
// This means we can use the existing !(flags & 4) check.
if (peepAtRide)
{
// Peeps won't join a queue that has 1000 peeps already in it.
if (ride->queue_length[entranceNum] >= 1000)
{
peep_tried_to_enter_full_queue(this, rideIndex);
return false;
}
// Rides without queues can only have one peep waiting at a time.
if (!atQueue)
{
if (ride->last_peep_in_queue[entranceNum] != 0xFFFF)
{
peep_tried_to_enter_full_queue(this, rideIndex);
return false;
}
}
else
{
// Check if there's room in the queue for the peep to enter.
if (ride->last_peep_in_queue[entranceNum] != 0xFFFF)
{
rct_peep * lastPeepInQueue = GET_PEEP(ride->last_peep_in_queue[entranceNum]);
if (abs(lastPeepInQueue->z - this->z) <= 6)
{
sint32 dx = abs(lastPeepInQueue->x - this->x);
sint32 dy = abs(lastPeepInQueue->y - this->y);
sint32 maxD = Math::Max(dx, dy);
// Unlike normal paths, peeps cannot overlap when queueing for a ride.
// This check enforces a minimum distance between peeps entering the queue.
if (maxD < 8)
{
peep_tried_to_enter_full_queue(this, rideIndex);
return false;
}
// This checks if there's a peep standing still at the very end of the queue.
if (maxD <= 13 && lastPeepInQueue->time_in_queue > 10)
{
peep_tried_to_enter_full_queue(this, rideIndex);
return false;
}
}
}
}
}
// Assuming the queue conditions are met, peeps will always go on free transport rides.
// Ride ratings, recent crashes and weather will all be ignored.
money16 ridePrice = ride_get_price(ride);
if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_TRANSPORT_RIDE) || ride->value == 0xFFFF || ridePrice != 0)
{
if (this->previous_ride == rideIndex)
{
ChoseNotToGoOnRide(rideIndex, peepAtRide, false);
return false;
}
// Basic price checks
if (ridePrice != 0 && !peep_has_voucher_for_free_ride(this, rideIndex))
{
if (ridePrice > this->cash_in_pocket)
{
if (peepAtRide)
{
if (this->cash_in_pocket <= 0)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_SPENT_MONEY, PEEP_THOUGHT_ITEM_NONE);
}
else
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_CANT_AFFORD_0, rideIndex);
}
}
ChoseNotToGoOnRide(rideIndex, peepAtRide, true);
return false;
}
}
// If happy enough, peeps will ignore the fact that a ride has recently crashed.
if (ride->last_crash_type != RIDE_CRASH_TYPE_NONE && this->happiness < 225)
{
if (peepAtRide)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_NOT_SAFE, rideIndex);
if (this->happiness_target >= 64)
{
this->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
ChoseNotToGoOnRide(rideIndex, peepAtRide, true);
return false;
}
if (ride_has_ratings(ride))
{
// If a peep has already decided that they're going to go on a ride, they'll skip the weather and
// excitement check and will only do a basic intensity check when they arrive at the ride itself.
if (rideIndex == this->guest_heading_to_ride_id)
{
if (ride->intensity > RIDE_RATING(10, 00) && !gCheatsIgnoreRideIntensity)
{
peep_ride_is_too_intense(this, rideIndex, peepAtRide);
return false;
}
}
// Peeps won't go on rides that aren't sufficiently undercover while it's raining.
// The threshold is fairly low and only requires about 10-15% of the ride to be undercover.
if (climate_is_raining() && (ride->sheltered_eighths >> 5) < 3)
{
if (peepAtRide)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_NOT_WHILE_RAINING, rideIndex);
if (this->happiness_target >= 64)
{
this->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
ChoseNotToGoOnRide(rideIndex, peepAtRide, true);
return false;
}
if (!gCheatsIgnoreRideIntensity)
{
// Intensity calculations. Even though the max intensity can go up to 15, it's capped
// at 10.0 (before happiness calculations). A full happiness bar will increase the max
// intensity and decrease the min intensity by about 2.5.
ride_rating maxIntensity = Math::Min((this->intensity >> 4) * 100, 1000) + this->happiness;
ride_rating minIntensity = ((this->intensity & 0x0F) * 100) - this->happiness;
if (ride->intensity < minIntensity)
{
if (peepAtRide)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_MORE_THRILLING, rideIndex);
if (this->happiness_target >= 64)
{
this->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
ChoseNotToGoOnRide(rideIndex, peepAtRide, true);
return false;
}
if (ride->intensity > maxIntensity)
{
peep_ride_is_too_intense(this, rideIndex, peepAtRide);
return false;
}
// Nausea calculations.
ride_rating maxNausea = NauseaMaximumThresholds[(this->nausea_tolerance & 3)] + this->happiness;
if (ride->nausea > maxNausea)
{
if (peepAtRide)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_SICKENING, rideIndex);
if (this->happiness_target >= 64)
{
this->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
ChoseNotToGoOnRide(rideIndex, peepAtRide, true);
return false;
}
// Very nauseous peeps will only go on very gentle rides.
if (ride->nausea >= FIXED_2DP(1, 40) && this->nausea > 160)
{
ChoseNotToGoOnRide(rideIndex, peepAtRide, false);
return false;
}
}
}
// If the ride has not yet been rated and is capable of having g-forces,
// there's a 90% chance that the peep will ignore it.
if (!ride_has_ratings(ride) && (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_PEEP_CHECK_GFORCES))
{
if ((scenario_rand() & 0xFFFF) > 0x1999U)
{
ChoseNotToGoOnRide(rideIndex, peepAtRide, false);
return false;
}
if (!gCheatsIgnoreRideIntensity)
{
if (ride->max_positive_vertical_g > FIXED_2DP(5, 00) || ride->max_negative_vertical_g < FIXED_2DP(-4, 00) ||
ride->max_lateral_g > FIXED_2DP(4, 00))
{
ChoseNotToGoOnRide(rideIndex, peepAtRide, false);
return false;
}
}
}
uint32 value = ride->value;
// If the value of the ride hasn't yet been calculated, peeps will be willing to pay any amount for the ride.
if (value != 0xFFFF && !peep_has_voucher_for_free_ride(this, rideIndex) && !(gParkFlags & PARK_FLAGS_NO_MONEY))
{
// The amount peeps are willing to pay is decreased by 75% if they had to pay to enter the park.
if (this->peep_flags & PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY)
value /= 4;
// Peeps won't pay more than twice the value of the ride.
ridePrice = ride_get_price(ride);
if (ridePrice > (money16)(value * 2))
{
if (peepAtRide)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_BAD_VALUE, rideIndex);
if (this->happiness_target >= 60)
{
this->happiness_target -= 16;
}
ride_update_popularity(ride, 0);
}
ChoseNotToGoOnRide(rideIndex, peepAtRide, true);
return false;
}
// A ride is good value if the price is 50% or less of the ride value and the peep didn't pay to enter the park.
if (ridePrice <= (money16)(value / 2) && peepAtRide)
{
if (!(gParkFlags & PARK_FLAGS_NO_MONEY))
{
if (!(this->peep_flags & PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY))
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_GOOD_VALUE, rideIndex);
}
}
}
}
}
// At this point, the peep has decided to go on the ride.
if (peepAtRide)
{
ride_update_popularity(ride, 1);
}
if (rideIndex == this->guest_heading_to_ride_id)
{
peep_reset_ride_heading(this);
}
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_QUEUE_FULL;
return true;
}
ChoseNotToGoOnRide(rideIndex, peepAtRide, false);
return false;
}
bool rct_peep::ShouldGoToShop(sint32 rideIndex, bool peepAtShop)
{
Ride * ride = get_ride(rideIndex);
// Peeps won't go to the same shop twice in a row.
if (rideIndex == this->previous_ride)
{
this->ChoseNotToGoOnRide(rideIndex, peepAtShop, true);
return false;
}
if (ride->type == RIDE_TYPE_TOILETS)
{
if (this->toilet < 70)
{
this->ChoseNotToGoOnRide(rideIndex, peepAtShop, true);
return false;
}
// The amount that peeps are willing to pay to use the Toilets scales with their bathroom stat.
// It effectively has a minimum of $0.10 (due to the check above) and a maximum of $0.60.
if (ride->price * 40 > this->toilet)
{
if (peepAtShop)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_NOT_PAYING, rideIndex);
if (this->happiness_target >= 60)
{
this->happiness_target -= 16;
}
ride_update_popularity(ride, 0);
}
this->ChoseNotToGoOnRide(rideIndex, peepAtShop, true);
return false;
}
}
if (ride->type == RIDE_TYPE_FIRST_AID)
{
if (this->nausea < 128)
{
this->ChoseNotToGoOnRide(rideIndex, peepAtShop, true);
return false;
}
}
// Basic price checks
if (ride->price != 0 && ride->price > this->cash_in_pocket)
{
if (peepAtShop)
{
if (this->cash_in_pocket <= 0)
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_SPENT_MONEY, PEEP_THOUGHT_ITEM_NONE);
}
else
{
peep_insert_new_thought(this, PEEP_THOUGHT_TYPE_CANT_AFFORD_0, rideIndex);
}
}
this->ChoseNotToGoOnRide(rideIndex, peepAtShop, true);
return false;
}
if (peepAtShop)
{
ride_update_popularity(ride, 1);
if (rideIndex == this->guest_heading_to_ride_id)
{
peep_reset_ride_heading(this);
}
}
return true;
}
void rct_peep::ChoseNotToGoOnRide(sint32 rideIndex, bool peepAtRide, bool updateLastRide)
{
if (peepAtRide && updateLastRide)
{
previous_ride = rideIndex;
previous_ride_time_out = 0;
}
if (rideIndex == guest_heading_to_ride_id)
{
peep_reset_ride_heading(this);
}
}
void rct_peep::ReadMap()
{
if (action == PEEP_ACTION_NONE_1 || action == PEEP_ACTION_NONE_2)
{
action = PEEP_ACTION_READ_MAP;
action_frame = 0;
action_sprite_image_offset = 0;
UpdateCurrentActionSpriteType();
Invalidate();
}
}
static bool peep_has_voucher_for_free_ride(rct_peep * peep, sint32 rideIndex)
{
return peep->item_standard_flags & PEEP_ITEM_VOUCHER && peep->voucher_type == VOUCHER_TYPE_RIDE_FREE &&
peep->voucher_arguments == rideIndex;
}
/**
* When the queue is full, peeps will ignore the ride when thinking about what to go on next.
* Does not effect peeps that walk up to the queue entrance.
* This flag is reset the next time a peep successfully joins the queue.
*/
static void peep_tried_to_enter_full_queue(rct_peep * peep, sint32 rideIndex)
{
Ride * ride = get_ride(rideIndex);
ride->lifecycle_flags |= RIDE_LIFECYCLE_QUEUE_FULL;
peep->previous_ride = rideIndex;
peep->previous_ride_time_out = 0;
// Change status "Heading to" to "Walking" if queue is full
if (rideIndex == peep->guest_heading_to_ride_id)
{
peep_reset_ride_heading(peep);
}
}
static void peep_reset_ride_heading(rct_peep * peep)
{
rct_window * w;
peep->guest_heading_to_ride_id = 255;
w = window_find_by_number(WC_PEEP, peep->sprite_index);
if (w != nullptr)
{
window_event_invalidate_call(w);
widget_invalidate(w, WC_PEEP__WIDX_ACTION_LBL);
}
}
static void peep_ride_is_too_intense(rct_peep * peep, sint32 rideIndex, bool peepAtRide)
{
Ride * ride = get_ride(rideIndex);
if (peepAtRide)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_INTENSE, rideIndex);
if (peep->happiness_target >= 64)
{
peep->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
peep->ChoseNotToGoOnRide(rideIndex, peepAtRide, true);
}
/**
*
* rct2: 0x00691C6E

View File

@ -96,8 +96,6 @@ static struct
static uint8 _unk_F1AEF0;
static uint16 _unk_F1EE18;
static rct_tile_element * _peepRideEntranceExitElement;
static uint32 _peepRideConsideration[8];
static uint8 _peepPotentialRides[256];
enum
{
@ -126,27 +124,18 @@ static sint32 peep_has_food_extra_flag(rct_peep * peep);
static sint32 peep_empty_container_standard_flag(rct_peep * peep);
static sint32 peep_empty_container_extra_flag(rct_peep * peep);
static bool peep_should_find_bench(rct_peep * peep);
static void peep_set_has_ridden(rct_peep * peep, sint32 rideIndex);
static bool peep_has_ridden(rct_peep * peep, sint32 rideIndex);
static void peep_set_has_ridden_ride_type(rct_peep * peep, sint32 rideType);
static bool peep_has_ridden_ride_type(rct_peep * peep, sint32 rideType);
static void peep_update_favourite_ride(rct_peep * peep, Ride * ride);
static sint16 peep_calculate_ride_satisfaction(rct_peep * peep, Ride * ride);
static void peep_update_ride_nausea_growth(rct_peep * peep, Ride * ride);
static bool peep_should_go_on_ride(rct_peep * peep, sint32 rideIndex, sint32 entranceNum, sint32 flags);
static void peep_ride_is_too_intense(rct_peep * peep, sint32 rideIndex, bool peepAtRide);
static void peep_chose_not_to_go_on_ride(rct_peep * peep, sint32 rideIndex, bool peepAtRide, bool updateLastRide);
static void peep_tried_to_enter_full_queue(rct_peep * peep, sint32 rideIndex);
static bool peep_should_go_to_shop(rct_peep * peep, sint32 rideIndex, bool peepAtShop);
static bool peep_find_ride_to_look_at(rct_peep * peep, uint8 edge, uint8 * rideToView, uint8 * rideSeatToView);
static void peep_easter_egg_peep_interactions(rct_peep * peep);
static sint32 peep_get_height_on_slope(rct_peep * peep, sint32 x, sint32 y);
static void peep_pick_ride_to_go_on(rct_peep * peep);
static void peep_head_for_nearest_ride_type(rct_peep * peep, sint32 rideType);
static void peep_head_for_nearest_ride_with_flags(rct_peep * peep, sint32 rideTypeFlags);
static void peep_give_real_name(rct_peep * peep);
static sint32 guest_surface_path_finding(rct_peep * peep);
static void peep_read_map(rct_peep * peep);
static bool peep_heading_for_ride_or_park_exit(rct_peep * peep);
static bool peep_update_fixing_enter_station(Ride * ride);
static bool peep_update_fixing_move_to_broken_down_vehicle(bool firstRun, rct_peep * peep, Ride * ride);
@ -1026,7 +1015,7 @@ static void peep_128_tick_update(rct_peep * peep, sint32 index)
if (time_duration >= 5)
{
peep_pick_ride_to_go_on(peep);
peep->PickRideToGoOn();
if (peep->guest_heading_to_ride_id == 0xFF)
{
@ -1040,7 +1029,7 @@ static void peep_128_tick_update(rct_peep * peep, sint32 index)
if ((scenario_rand() & 0xFFFF) <= ((peep->item_standard_flags & PEEP_ITEM_MAP) ? 8192U : 2184U))
{
peep_pick_ride_to_go_on(peep);
peep->PickRideToGoOn();
}
if ((uint32)(index & 0x3FF) == (gCurrentTicks & 0x3FF))
@ -6538,7 +6527,7 @@ static sint32 peep_interact_with_entrance(rct_peep * peep, sint16 x, sint16 y, r
// Guest walks up to the ride for the first time since entering
// the path tile or since considering another ride attached to
// the path tile.
if (!peep_should_go_on_ride(peep, rideIndex, stationNum, 0))
if (!peep->ShouldGoOnRide(rideIndex, stationNum, false, false))
{
// Peep remembers that this is the last ride they
// considered while on this path tile.
@ -6966,7 +6955,7 @@ static sint32 peep_interact_with_path(rct_peep * peep, sint16 x, sint16 y, rct_t
{
/* Peep is approaching the entrance of a ride queue.
* Decide whether to go on the ride. */
if (!peep_should_go_on_ride(peep, rideIndex, stationNum, PEEP_RIDE_DECISION_AT_QUEUE))
if (!peep->ShouldGoOnRide(rideIndex, stationNum, true, false))
{
// Peep has decided not to go on the ride.
return peep_return_to_centre_of_tile(peep);
@ -7054,7 +7043,7 @@ static sint32 peep_interact_with_shop(rct_peep * peep, sint16 x, sint16 y, rct_t
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_PEEP_SHOULD_GO_INSIDE_FACILITY))
{
peep->time_lost = 0;
if (!peep_should_go_on_ride(peep, rideIndex, 0, 0))
if (!peep->ShouldGoOnRide(rideIndex, 0, false, false))
return peep_return_to_centre_of_tile(peep);
money16 cost = ride->price;
@ -9107,7 +9096,7 @@ static sint32 guest_path_finding(rct_peep * peep)
}
if ((scenario_rand() & 0xFFFF) < probability)
{
peep_read_map(peep);
peep->ReadMap();
}
}
}
@ -9434,26 +9423,26 @@ void rct_peep::SpendMoney(money16 & peep_expend_type, money32 amount)
audio_play_sound_at_location(SOUND_PURCHASE, x, y, z);
}
static void peep_set_has_ridden(rct_peep * peep, sint32 rideIndex)
void rct_peep::SetHasRidden(sint32 rideIndex)
{
peep->rides_been_on[rideIndex / 8] |= 1 << (rideIndex % 8);
rides_been_on[rideIndex / 8] |= 1 << (rideIndex % 8);
Ride * ride = get_ride(rideIndex);
peep_set_has_ridden_ride_type(peep, ride->type);
SetHasRiddenRideType(ride->type);
}
static bool peep_has_ridden(rct_peep * peep, sint32 rideIndex)
bool rct_peep::HasRidden(sint32 rideIndex) const
{
return peep->rides_been_on[rideIndex / 8] & (1 << (rideIndex % 8));
return rides_been_on[rideIndex / 8] & (1 << (rideIndex % 8));
}
static void peep_set_has_ridden_ride_type(rct_peep * peep, sint32 rideType)
void rct_peep::SetHasRiddenRideType(sint32 rideType)
{
peep->ride_types_been_on[rideType / 8] |= 1 << (rideType % 8);
ride_types_been_on[rideType / 8] |= 1 << (rideType % 8);
}
static bool peep_has_ridden_ride_type(rct_peep * peep, sint32 rideType)
bool rct_peep::HasRiddenRideType(sint32 rideType) const
{
return peep->ride_types_been_on[rideType / 8] & (1 << (rideType % 8));
return ride_types_been_on[rideType / 8] & (1 << (rideType % 8));
}
/**
@ -9483,7 +9472,7 @@ void rct_peep::OnEnterRide(uint8 rideIndex)
if (no_of_rides < 255)
no_of_rides++;
peep_set_has_ridden(this, current_ride);
SetHasRidden(current_ride);
peep_update_favourite_ride(this, ride);
happiness_target = Math::Clamp(0, happiness_target + satisfaction, PEEP_MAX_HAPPINESS);
peep_update_ride_nausea_growth(this, ride);
@ -9664,10 +9653,10 @@ static sint16 peep_calculate_ride_satisfaction(rct_peep * peep, Ride * ride)
// Peeps get a small boost in satisfaction if they've been on a ride of the same type before,
// and this boost is doubled if they've already been on this particular ride.
if (peep_has_ridden_ride_type(peep, ride->type))
if (peep->HasRiddenRideType(ride->type))
satisfaction += 10;
if (peep_has_ridden(peep, peep->current_ride))
if (peep->HasRidden(peep->current_ride))
satisfaction += 10;
return satisfaction;
@ -10709,584 +10698,6 @@ static sint32 peep_get_height_on_slope(rct_peep * peep, sint32 x, sint32 y)
return z + map_height_from_slope(x, y, peep->next_var_29);
}
static bool peep_has_voucher_for_free_ride(rct_peep * peep, sint32 rideIndex)
{
return peep->item_standard_flags & PEEP_ITEM_VOUCHER && peep->voucher_type == VOUCHER_TYPE_RIDE_FREE &&
peep->voucher_arguments == rideIndex;
}
static void peep_reset_ride_heading(rct_peep * peep)
{
rct_window * w;
peep->guest_heading_to_ride_id = 255;
w = window_find_by_number(WC_PEEP, peep->sprite_index);
if (w != nullptr)
{
window_event_invalidate_call(w);
widget_invalidate(w, WC_PEEP__WIDX_ACTION_LBL);
}
}
/**
* This function is called whenever a peep is deciding whether or not they want
* to go on a ride or visit a shop. They may be physically present at the
* ride/shop, or they may just be thinking about it.
* rct2: 0x006960AB
*/
static bool peep_should_go_on_ride(rct_peep * peep, sint32 rideIndex, sint32 entranceNum, sint32 flags)
{
Ride * ride = get_ride(rideIndex);
// Indicates if the peep is about to enter a queue (as opposed to entering an entrance directly from a path)
bool peepAtQueue = flags & PEEP_RIDE_DECISION_AT_QUEUE;
// Indicates whether a peep is physically at the ride, or is just thinking about going on the ride.
bool peepAtRide = !(flags & PEEP_RIDE_DECISION_THINKING);
if (ride->status == RIDE_STATUS_OPEN && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
{
// Peeps that are leaving the park will refuse to go on any rides, with the exception of free transport rides.
if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_TRANSPORT_RIDE) || ride->value == 0xFFFF ||
ride_get_price(ride) != 0)
{
if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)
{
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false);
return false;
}
}
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
{
return peep_should_go_to_shop(peep, rideIndex, peepAtRide);
}
// This used to check !(flags & 2), but the function is only ever called with flags = 0, 1 or 6.
// This means we can use the existing !(flags & 4) check.
if (peepAtRide)
{
// Peeps won't join a queue that has 1000 peeps already in it.
if (ride->queue_length[entranceNum] >= 1000)
{
peep_tried_to_enter_full_queue(peep, rideIndex);
return false;
}
// Rides without queues can only have one peep waiting at a time.
if (!peepAtQueue)
{
if (ride->last_peep_in_queue[entranceNum] != 0xFFFF)
{
peep_tried_to_enter_full_queue(peep, rideIndex);
return false;
}
}
else
{
// Check if there's room in the queue for the peep to enter.
if (ride->last_peep_in_queue[entranceNum] != 0xFFFF)
{
rct_peep * lastPeepInQueue = GET_PEEP(ride->last_peep_in_queue[entranceNum]);
if (abs(lastPeepInQueue->z - peep->z) <= 6)
{
sint32 dx = abs(lastPeepInQueue->x - peep->x);
sint32 dy = abs(lastPeepInQueue->y - peep->y);
sint32 maxD = Math::Max(dx, dy);
// Unlike normal paths, peeps cannot overlap when queueing for a ride.
// This check enforces a minimum distance between peeps entering the queue.
if (maxD < 8)
{
peep_tried_to_enter_full_queue(peep, rideIndex);
return false;
}
// This checks if there's a peep standing still at the very end of the queue.
if (maxD <= 13 && lastPeepInQueue->time_in_queue > 10)
{
peep_tried_to_enter_full_queue(peep, rideIndex);
return false;
}
}
}
}
}
// Assuming the queue conditions are met, peeps will always go on free transport rides.
// Ride ratings, recent crashes and weather will all be ignored.
money16 ridePrice = ride_get_price(ride);
if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_TRANSPORT_RIDE) || ride->value == 0xFFFF || ridePrice != 0)
{
if (peep->previous_ride == rideIndex)
{
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false);
return false;
}
// Basic price checks
if (ridePrice != 0 && !peep_has_voucher_for_free_ride(peep, rideIndex))
{
if (ridePrice > peep->cash_in_pocket)
{
if (peepAtRide)
{
if (peep->cash_in_pocket <= 0)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SPENT_MONEY, PEEP_THOUGHT_ITEM_NONE);
}
else
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_AFFORD_0, rideIndex);
}
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true);
return false;
}
}
// If happy enough, peeps will ignore the fact that a ride has recently crashed.
if (ride->last_crash_type != RIDE_CRASH_TYPE_NONE && peep->happiness < 225)
{
if (peepAtRide)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_NOT_SAFE, rideIndex);
if (peep->happiness_target >= 64)
{
peep->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true);
return false;
}
if (ride_has_ratings(ride))
{
// If a peep has already decided that they're going to go on a ride, they'll skip the weather and
// excitement check and will only do a basic intensity check when they arrive at the ride itself.
if (rideIndex == peep->guest_heading_to_ride_id)
{
if (ride->intensity > RIDE_RATING(10, 00) && !gCheatsIgnoreRideIntensity)
{
peep_ride_is_too_intense(peep, rideIndex, peepAtRide);
return false;
}
}
// Peeps won't go on rides that aren't sufficiently undercover while it's raining.
// The threshold is fairly low and only requires about 10-15% of the ride to be undercover.
if (climate_is_raining() && (ride->sheltered_eighths >> 5) < 3)
{
if (peepAtRide)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_NOT_WHILE_RAINING, rideIndex);
if (peep->happiness_target >= 64)
{
peep->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true);
return false;
}
if (!gCheatsIgnoreRideIntensity)
{
// Intensity calculations. Even though the max intensity can go up to 15, it's capped
// at 10.0 (before happiness calculations). A full happiness bar will increase the max
// intensity and decrease the min intensity by about 2.5.
ride_rating maxIntensity = Math::Min((peep->intensity >> 4) * 100, 1000) + peep->happiness;
ride_rating minIntensity = ((peep->intensity & 0x0F) * 100) - peep->happiness;
if (ride->intensity < minIntensity)
{
if (peepAtRide)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_MORE_THRILLING, rideIndex);
if (peep->happiness_target >= 64)
{
peep->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true);
return false;
}
if (ride->intensity > maxIntensity)
{
peep_ride_is_too_intense(peep, rideIndex, peepAtRide);
return false;
}
// Nausea calculations.
ride_rating maxNausea = NauseaMaximumThresholds[(peep->nausea_tolerance & 3)] + peep->happiness;
if (ride->nausea > maxNausea)
{
if (peepAtRide)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SICKENING, rideIndex);
if (peep->happiness_target >= 64)
{
peep->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true);
return false;
}
// Very nauseous peeps will only go on very gentle rides.
if (ride->nausea >= FIXED_2DP(1, 40) && peep->nausea > 160)
{
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false);
return false;
}
}
}
// If the ride has not yet been rated and is capable of having g-forces,
// there's a 90% chance that the peep will ignore it.
if (!ride_has_ratings(ride) && (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_PEEP_CHECK_GFORCES))
{
if ((scenario_rand() & 0xFFFF) > 0x1999U)
{
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false);
return false;
}
if (!gCheatsIgnoreRideIntensity)
{
if (ride->max_positive_vertical_g > FIXED_2DP(5, 00) || ride->max_negative_vertical_g < FIXED_2DP(-4, 00) ||
ride->max_lateral_g > FIXED_2DP(4, 00))
{
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false);
return false;
}
}
}
uint32 value = ride->value;
// If the value of the ride hasn't yet been calculated, peeps will be willing to pay any amount for the ride.
if (value != 0xFFFF && !peep_has_voucher_for_free_ride(peep, rideIndex) && !(gParkFlags & PARK_FLAGS_NO_MONEY))
{
// The amount peeps are willing to pay is decreased by 75% if they had to pay to enter the park.
if (peep->peep_flags & PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY)
value /= 4;
// Peeps won't pay more than twice the value of the ride.
ridePrice = ride_get_price(ride);
if (ridePrice > (money16)(value * 2))
{
if (peepAtRide)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_BAD_VALUE, rideIndex);
if (peep->happiness_target >= 60)
{
peep->happiness_target -= 16;
}
ride_update_popularity(ride, 0);
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true);
return false;
}
// A ride is good value if the price is 50% or less of the ride value and the peep didn't pay to enter the park.
if (ridePrice <= (money16)(value / 2) && peepAtRide)
{
if (!(gParkFlags & PARK_FLAGS_NO_MONEY))
{
if (!(peep->peep_flags & PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY))
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_GOOD_VALUE, rideIndex);
}
}
}
}
}
// At this point, the peep has decided to go on the ride.
if (peepAtRide)
{
ride_update_popularity(ride, 1);
}
if (rideIndex == peep->guest_heading_to_ride_id)
{
peep_reset_ride_heading(peep);
}
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_QUEUE_FULL;
return true;
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false);
return false;
}
static void peep_ride_is_too_intense(rct_peep * peep, sint32 rideIndex, bool peepAtRide)
{
Ride * ride = get_ride(rideIndex);
if (peepAtRide)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_INTENSE, rideIndex);
if (peep->happiness_target >= 64)
{
peep->happiness_target -= 8;
}
ride_update_popularity(ride, 0);
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true);
}
static void peep_chose_not_to_go_on_ride(rct_peep * peep, sint32 rideIndex, bool peepAtRide, bool updateLastRide)
{
if (peepAtRide && updateLastRide)
{
peep->previous_ride = rideIndex;
peep->previous_ride_time_out = 0;
}
if (rideIndex == peep->guest_heading_to_ride_id)
{
peep_reset_ride_heading(peep);
}
}
/**
* When the queue is full, peeps will ignore the ride when thinking about what to go on next.
* Does not effect peeps that walk up to the queue entrance.
* This flag is reset the next time a peep successfully joins the queue.
*/
static void peep_tried_to_enter_full_queue(rct_peep * peep, sint32 rideIndex)
{
Ride * ride = get_ride(rideIndex);
ride->lifecycle_flags |= RIDE_LIFECYCLE_QUEUE_FULL;
peep->previous_ride = rideIndex;
peep->previous_ride_time_out = 0;
// Change status "Heading to" to "Walking" if queue is full
if (rideIndex == peep->guest_heading_to_ride_id)
{
peep_reset_ride_heading(peep);
}
}
static bool peep_should_go_to_shop(rct_peep * peep, sint32 rideIndex, bool peepAtShop)
{
Ride * ride = get_ride(rideIndex);
// Peeps won't go to the same shop twice in a row.
if (rideIndex == peep->previous_ride)
{
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtShop, true);
return false;
}
if (ride->type == RIDE_TYPE_TOILETS)
{
if (peep->toilet < 70)
{
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtShop, true);
return false;
}
// The amount that peeps are willing to pay to use the Toilets scales with their bathroom stat.
// It effectively has a minimum of $0.10 (due to the check above) and a maximum of $0.60.
if (ride->price * 40 > peep->toilet)
{
if (peepAtShop)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_NOT_PAYING, rideIndex);
if (peep->happiness_target >= 60)
{
peep->happiness_target -= 16;
}
ride_update_popularity(ride, 0);
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtShop, true);
return false;
}
}
if (ride->type == RIDE_TYPE_FIRST_AID)
{
if (peep->nausea < 128)
{
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtShop, true);
return false;
}
}
// Basic price checks
if (ride->price != 0 && ride->price > peep->cash_in_pocket)
{
if (peepAtShop)
{
if (peep->cash_in_pocket <= 0)
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SPENT_MONEY, PEEP_THOUGHT_ITEM_NONE);
}
else
{
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_AFFORD_0, rideIndex);
}
}
peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtShop, true);
return false;
}
if (peepAtShop)
{
ride_update_popularity(ride, 1);
if (rideIndex == peep->guest_heading_to_ride_id)
{
peep_reset_ride_heading(peep);
}
}
return true;
}
/**
*
* rct2: 0x00695DD2
*/
static void peep_pick_ride_to_go_on(rct_peep * peep)
{
Ride * ride;
if (peep->state != PEEP_STATE_WALKING)
return;
if (peep->guest_heading_to_ride_id != 255)
return;
if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)
return;
if (peep_has_food(peep))
return;
if (peep->x == LOCATION_NULL)
return;
for (auto &rideConsideration : _peepRideConsideration)
{
rideConsideration = 0;
}
// FIX Originally checked for a toy, likely a mistake and should be a map,
// but then again this seems to only allow the peep to go on
// rides they haven't been on before.
if (peep->item_standard_flags & PEEP_ITEM_MAP)
{
// Consider rides that peep hasn't been on yet
sint32 i;
FOR_ALL_RIDES(i, ride)
{
if (!peep_has_ridden(peep, i))
{
_peepRideConsideration[i >> 5] |= (1u << (i & 0x1F));
}
}
}
else
{
// Take nearby rides into consideration
sint32 cx = floor2(peep->x, 32);
sint32 cy = floor2(peep->y, 32);
for (sint32 x = cx - 320; x <= cx + 320; x += 32)
{
for (sint32 y = cy - 320; y <= cy + 320; y += 32)
{
if (x >= 0 && y >= 0 && x < (256 * 32) && y < (256 * 32))
{
rct_tile_element * tileElement = map_get_first_element_at(x >> 5, y >> 5);
do
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
continue;
sint32 rideIndex = track_element_get_ride_index(tileElement);
_peepRideConsideration[rideIndex >> 5] |= (1u << (rideIndex & 0x1F));
} while (!tile_element_is_last_for_tile(tileElement++));
}
}
}
// Always take the tall rides into consideration (realistic as you can usually see them from anywhere in the park)
sint32 i;
FOR_ALL_RIDES(i, ride)
{
if (ride->status != RIDE_STATUS_OPEN)
continue;
if (!ride_has_ratings(ride))
continue;
if (ride->highest_drop_height <= 66 && ride->excitement < RIDE_RATING(8, 00))
continue;
_peepRideConsideration[i >> 5] |= (1u << (i & 0x1F));
}
}
// Filter the considered rides
uint8 * potentialRides = _peepPotentialRides;
uint8 * nextPotentialRide = potentialRides;
sint32 numPotentialRides = 0;
for (sint32 i = 0; i < MAX_RIDES; i++)
{
if (!(_peepRideConsideration[i >> 5] & (1u << (i & 0x1F))))
continue;
ride = get_ride(i);
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_QUEUE_FULL))
{
if (peep_should_go_on_ride(peep, i, 0, PEEP_RIDE_DECISION_THINKING))
{
*nextPotentialRide++ = i;
numPotentialRides++;
}
}
}
// Pick the most exciting ride
sint32 mostExcitingRideIndex = -1;
ride_rating mostExcitingRideRating = 0;
for (sint32 i = 0; i < numPotentialRides; i++)
{
ride = get_ride(potentialRides[i]);
if (!ride_has_ratings(ride))
continue;
if (ride->excitement > mostExcitingRideRating)
{
mostExcitingRideIndex = potentialRides[i];
mostExcitingRideRating = ride->excitement;
}
}
if (mostExcitingRideIndex == -1)
return;
// Head to that ride
peep->guest_heading_to_ride_id = mostExcitingRideIndex;
peep->peep_is_lost_countdown = 200;
peep_reset_pathfind_goal(peep);
// Invalidate windows
rct_window * w = window_find_by_number(WC_PEEP, peep->sprite_index);
if (w != nullptr)
{
window_event_invalidate_call(w);
widget_invalidate(w, WC_PEEP__WIDX_ACTION_LBL);
}
// Make peep look at their map if they have one
if (peep->item_standard_flags & PEEP_ITEM_MAP)
{
peep_read_map(peep);
}
}
/**
*
* rct2: 0x00695B70
@ -11312,10 +10723,7 @@ static void peep_head_for_nearest_ride_type(rct_peep * peep, sint32 rideType)
}
}
for (auto &rideConsideration : _peepRideConsideration)
{
rideConsideration = 0;
}
uint32 rideConsideration[8]{};
// FIX Originally checked for a toy,.likely a mistake and should be a map
if ((peep->item_standard_flags & PEEP_ITEM_MAP) && rideType != RIDE_TYPE_FIRST_AID)
@ -11326,7 +10734,7 @@ static void peep_head_for_nearest_ride_type(rct_peep * peep, sint32 rideType)
{
if (ride->type == rideType)
{
_peepRideConsideration[i >> 5] |= (1u << (i & 0x1F));
rideConsideration[i >> 5] |= (1u << (i & 0x1F));
}
}
}
@ -11351,7 +10759,7 @@ static void peep_head_for_nearest_ride_type(rct_peep * peep, sint32 rideType)
ride = get_ride(rideIndex);
if (ride->type == rideType)
{
_peepRideConsideration[rideIndex >> 5] |= (1u << (rideIndex & 0x1F));
rideConsideration[rideIndex >> 5] |= (1u << (rideIndex & 0x1F));
}
} while (!tile_element_is_last_for_tile(tileElement++));
}
@ -11360,18 +10768,18 @@ static void peep_head_for_nearest_ride_type(rct_peep * peep, sint32 rideType)
}
// Filter the considered rides
uint8 * potentialRides = _peepPotentialRides;
uint8 * nextPotentialRide = potentialRides;
uint8 potentialRides[256];
uint8 * nextPotentialRide = &potentialRides[0];
sint32 numPotentialRides = 0;
for (sint32 i = 0; i < MAX_RIDES; i++)
{
if (!(_peepRideConsideration[i >> 5] & (1u << (i & 0x1F))))
if (!(rideConsideration[i >> 5] & (1u << (i & 0x1F))))
continue;
ride = get_ride(i);
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_QUEUE_FULL))
{
if (peep_should_go_on_ride(peep, i, 0, PEEP_RIDE_DECISION_THINKING))
if (peep->ShouldGoOnRide(i, 0, false, true))
{
*nextPotentialRide++ = i;
numPotentialRides++;
@ -11444,10 +10852,7 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep * peep, sint32 rideTy
return;
}
for (auto &rideConsideration : _peepRideConsideration)
{
rideConsideration = 0;
}
uint32 rideConsideration[8]{};
// FIX Originally checked for a toy,.likely a mistake and should be a map
if (peep->item_standard_flags & PEEP_ITEM_MAP)
@ -11458,7 +10863,7 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep * peep, sint32 rideTy
{
if (ride_type_has_flag(ride->type, rideTypeFlags))
{
_peepRideConsideration[i >> 5] |= (1u << (i & 0x1F));
rideConsideration[i >> 5] |= (1u << (i & 0x1F));
}
}
}
@ -11483,7 +10888,7 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep * peep, sint32 rideTy
ride = get_ride(rideIndex);
if (ride_type_has_flag(ride->type, rideTypeFlags))
{
_peepRideConsideration[rideIndex >> 5] |= (1u << (rideIndex & 0x1F));
rideConsideration[rideIndex >> 5] |= (1u << (rideIndex & 0x1F));
}
} while (!tile_element_is_last_for_tile(tileElement++));
}
@ -11492,18 +10897,18 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep * peep, sint32 rideTy
}
// Filter the considered rides
uint8 * potentialRides = _peepPotentialRides;
uint8 * nextPotentialRide = potentialRides;
uint8 potentialRides[256];
uint8 * nextPotentialRide = &potentialRides[0];
sint32 numPotentialRides = 0;
for (sint32 i = 0; i < MAX_RIDES; i++)
{
if (!(_peepRideConsideration[i >> 5] & (1u << (i & 0x1F))))
if (!(rideConsideration[i >> 5] & (1u << (i & 0x1F))))
continue;
ride = get_ride(i);
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_QUEUE_FULL))
{
if (peep_should_go_on_ride(peep, i, 0, PEEP_RIDE_DECISION_THINKING))
if (peep->ShouldGoOnRide(i, 0, false, true))
{
*nextPotentialRide++ = i;
numPotentialRides++;
@ -11785,18 +11190,6 @@ void peep_update_names(bool realNames)
gfx_invalidate_screen();
}
static void peep_read_map(rct_peep * peep)
{
if (peep->action == PEEP_ACTION_NONE_1 || peep->action == PEEP_ACTION_NONE_2)
{
peep->action = PEEP_ACTION_READ_MAP;
peep->action_frame = 0;
peep->action_sprite_image_offset = 0;
peep->UpdateCurrentActionSpriteType();
invalidate_sprite_2((rct_sprite *)peep);
}
}
static bool peep_heading_for_ride_or_park_exit(rct_peep * peep)
{
return (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) || peep->guest_heading_to_ride_id != 0xFF;

View File

@ -739,7 +739,6 @@ private:
void TryGetUpFromSitting();
bool CheckForPath();
sint32 PerformNextAction(uint8 & pathing_result);
void StopPurchaseThought(uint8 ride_type);
@ -748,10 +747,19 @@ public: // TODO: Make these private again when done refactoring - they need to b
// peep functions
bool UpdateAction(sint16 * actionX, sint16 * actionY, sint16 * xy_distance);
bool UpdateAction();
void ChoseNotToGoOnRide(sint32 rideIndex, bool peepAtRide, bool updateLastRide);
void PickRideToGoOn();
void ReadMap();
bool ShouldGoOnRide(sint32 rideIndex, sint32 entranceNum, bool atQueue, bool thinking);
bool ShouldGoToShop(sint32 rideIndex, bool peepAtShop);
void SwitchNextActionSpriteType();
uint8 GetActionSpriteType();
void SpendMoney(money16 & peep_expend_type, money32 amount);
void SpendMoney(money32 amount);
void SetHasRidden(sint32 rideIndex);
bool HasRidden(sint32 rideIndex) const;
void SetHasRiddenRideType(sint32 rideType);
bool HasRiddenRideType(sint32 rideType) const;
private:
bool DecideAndBuyItem(uint8 rideIndex, sint32 shopItem, money32 price);
};