1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-24 00:03:11 +01:00

Merge pull request #24465 from ZehMatt/peep-update-sep

Clean up peep/guest/staff code, reduce indirections and branching
This commit is contained in:
Matt
2025-05-22 14:52:24 +03:00
committed by GitHub
7 changed files with 712 additions and 694 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -320,28 +320,17 @@ public:
uint8_t FavouriteRideRating; uint8_t FavouriteRideRating;
uint64_t ItemFlags; uint64_t ItemFlags;
void UpdateGuest(); void Update();
void Tick128UpdateGuest(uint32_t index); void Tick128UpdateGuest(uint32_t index);
uint64_t GetFoodOrDrinkFlags() const; uint64_t GetFoodOrDrinkFlags() const;
uint64_t GetEmptyContainerFlags() const; uint64_t GetEmptyContainerFlags() const;
bool HasDrink() const; bool HasDrink() const;
bool HasFoodOrDrink() const; bool HasFoodOrDrink() const;
bool HasEmptyContainer() const; bool HasEmptyContainer() const;
void OnEnterRide(Ride& ride);
void OnExitRide(Ride& ride);
void UpdateAnimationGroup(); void UpdateAnimationGroup();
bool HeadingForRideOrParkExit() const; bool HeadingForRideOrParkExit() const;
void StopPurchaseThought(ride_type_t rideType);
void TryGetUpFromSitting();
bool ShouldRideWhileRaining(const Ride& ride);
void ChoseNotToGoOnRide(const Ride& ride, bool peepAtRide, bool updateLastRide);
void PickRideToGoOn();
void ReadMap(); void ReadMap();
bool ShouldGoOnRide(Ride& ride, StationIndex entranceNum, bool atQueue, bool thinking); bool ShouldGoOnRide(Ride& ride, StationIndex entranceNum, bool atQueue, bool thinking);
bool ShouldGoToShop(Ride& ride, bool peepAtShop);
bool ShouldFindBench();
bool UpdateWalkingFindBench();
bool UpdateWalkingFindBin();
void SpendMoney(money64& peep_expend_type, money64 amount, ExpenditureType type); void SpendMoney(money64& peep_expend_type, money64 amount, ExpenditureType type);
void SpendMoney(money64 amount, ExpenditureType type); void SpendMoney(money64 amount, ExpenditureType type);
void SetHasRidden(const Ride& ride); void SetHasRidden(const Ride& ride);
@@ -353,9 +342,7 @@ public:
void CheckIfLost(); void CheckIfLost();
void CheckCantFindRide(); void CheckCantFindRide();
void CheckCantFindExit(); void CheckCantFindExit();
bool DecideAndBuyItem(Ride& ride, ShopItem shopItem, money64 price);
void SetAnimationGroup(PeepAnimationGroup new_sprite_type); void SetAnimationGroup(PeepAnimationGroup new_sprite_type);
void HandleEasterEggName();
int32_t GetEasterEggNameId() const; int32_t GetEasterEggNameId() const;
void UpdateEasterEggInteractions(); void UpdateEasterEggInteractions();
void InsertNewThought(PeepThoughtType thought_type); void InsertNewThought(PeepThoughtType thought_type);
@@ -377,8 +364,15 @@ public:
// Removes the ride from the guests memory, this includes // Removes the ride from the guests memory, this includes
// the history, thoughts, etc. // the history, thoughts, etc.
void RemoveRideFromMemory(RideId rideId); void RemoveRideFromMemory(RideId rideId);
void HandleEasterEggName();
void ChoseNotToGoOnRide(const Ride& ride, bool peepAtRide, bool updateLastRide);
void OnEnterRide(Ride& ride);
void OnExitRide(Ride& ride);
private: private:
bool ShouldFindBench();
bool UpdateWalkingFindBin();
bool UpdateWalkingFindBench();
void UpdateRide(); void UpdateRide();
void UpdateOnRide() {}; // TODO void UpdateOnRide() {}; // TODO
void UpdateWalking(); void UpdateWalking();
@@ -417,12 +411,10 @@ private:
void UpdateMotivesIdle(); void UpdateMotivesIdle();
void UpdateConsumptionMotives(); void UpdateConsumptionMotives();
int32_t CheckEasterEggName(int32_t index) const; int32_t CheckEasterEggName(int32_t index) const;
void GivePassingPeepsPurpleClothes(Guest* passingPeep); void GivePassingGuestPurpleClothes(Guest& passingPeep);
void GivePassingPeepsPizza(Guest* passingPeep); void GivePassingGuestPizza(Guest& passingPeep);
void MakePassingPeepsSick(Guest* passingPeep); void MakePassingGuestSick(Guest& passingPeep);
void GivePassingPeepsIceCream(Guest* passingPeep); void GivePassingPeepsIceCream(Guest& passingPeep);
Ride* FindBestRideToGoOn();
OpenRCT2::BitSet<OpenRCT2::Limits::kMaxRidesInPark> FindRidesToGoOn();
void GoToRideEntrance(const Ride& ride); void GoToRideEntrance(const Ride& ride);
}; };
@@ -466,9 +458,9 @@ void IncrementGuestsHeadingForPark();
void DecrementGuestsInPark(); void DecrementGuestsInPark();
void DecrementGuestsHeadingForPark(); void DecrementGuestsHeadingForPark();
void PeepUpdateRideLeaveEntranceMaze(Guest* peep, Ride& ride, CoordsXYZD& entrance_loc); void PeepUpdateRideLeaveEntranceMaze(Guest& peep, Ride& ride, CoordsXYZD& entrance_loc);
void PeepUpdateRideLeaveEntranceSpiralSlide(Guest* peep, Ride& ride, CoordsXYZD& entrance_loc); void PeepUpdateRideLeaveEntranceSpiralSlide(Guest& peep, Ride& ride, CoordsXYZD& entrance_loc);
void PeepUpdateRideLeaveEntranceDefault(Guest* peep, Ride& ride, CoordsXYZD& entrance_loc); void PeepUpdateRideLeaveEntranceDefault(Guest& peep, Ride& ride, CoordsXYZD& entrance_loc);
CoordsXY GetGuestWaypointLocationDefault(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation); CoordsXY GetGuestWaypointLocationDefault(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation);
CoordsXY GetGuestWaypointLocationEnterprise(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation); CoordsXY GetGuestWaypointLocationEnterprise(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation);

View File

@@ -300,7 +300,7 @@ bool Peep::CheckForPath()
return false; return false;
} }
bool Peep::ShouldWaitForLevelCrossing() bool Peep::ShouldWaitForLevelCrossing() const
{ {
if (IsOnPathBlockedByVehicle()) if (IsOnPathBlockedByVehicle())
{ {
@@ -318,13 +318,13 @@ bool Peep::ShouldWaitForLevelCrossing()
return false; return false;
} }
bool Peep::IsOnLevelCrossing() bool Peep::IsOnLevelCrossing() const
{ {
auto trackElement = MapGetTrackElementAt(GetLocation()); auto trackElement = MapGetTrackElementAt(GetLocation());
return trackElement != nullptr; return trackElement != nullptr;
} }
bool Peep::IsOnPathBlockedByVehicle() bool Peep::IsOnPathBlockedByVehicle() const
{ {
auto curPos = TileCoordsXYZ(GetLocation()); auto curPos = TileCoordsXYZ(GetLocation());
return FootpathIsBlockedByVehicle(curPos); return FootpathIsBlockedByVehicle(curPos);
@@ -928,107 +928,8 @@ void Peep::UpdatePicked()
} }
} }
/* From peep_update */ uint32_t Peep::GetStepsToTake() const
static void GuestUpdateThoughts(Guest* peep)
{ {
// Thoughts must always have a gap of at least
// 220 ticks in age between them. In order to
// allow this when a thought is new it enters
// a holding zone. Before it becomes fresh.
int32_t add_fresh = 1;
int32_t fresh_thought = -1;
for (int32_t i = 0; i < kPeepMaxThoughts; i++)
{
if (peep->Thoughts[i].type == PeepThoughtType::None)
break;
if (peep->Thoughts[i].freshness == 1)
{
add_fresh = 0;
// If thought is fresh we wait 220 ticks
// before allowing a new thought to become fresh.
if (++peep->Thoughts[i].fresh_timeout >= 220)
{
peep->Thoughts[i].fresh_timeout = 0;
// Thought is no longer fresh
peep->Thoughts[i].freshness++;
add_fresh = 1;
}
}
else if (peep->Thoughts[i].freshness > 1)
{
if (++peep->Thoughts[i].fresh_timeout == 0)
{
// When thought is older than ~6900 ticks remove it
if (++peep->Thoughts[i].freshness >= 28)
{
peep->WindowInvalidateFlags |= PEEP_INVALIDATE_PEEP_THOUGHTS;
// Clear top thought, push others up
if (i < kPeepMaxThoughts - 2)
{
memmove(&peep->Thoughts[i], &peep->Thoughts[i + 1], sizeof(PeepThought) * (kPeepMaxThoughts - i - 1));
}
peep->Thoughts[kPeepMaxThoughts - 1].type = PeepThoughtType::None;
}
}
}
else
{
fresh_thought = i;
}
}
// If there are no fresh thoughts
// a previously new thought can become
// fresh.
if (add_fresh && fresh_thought != -1)
{
peep->Thoughts[fresh_thought].freshness = 1;
peep->WindowInvalidateFlags |= PEEP_INVALIDATE_PEEP_THOUGHTS;
}
}
/**
*
* rct2: 0x0068FC1E
*/
void Peep::Update()
{
if (PeepFlags & PEEP_FLAGS_POSITION_FROZEN)
{
if (!(PeepFlags & PEEP_FLAGS_ANIMATION_FROZEN))
{
// This is circumventing other logic, so only update every few ticks
if ((getGameState().currentTicks & 3) == 0)
{
if (IsActionWalking())
UpdateWalkingAnimation();
else
UpdateActionAnimation();
Invalidate();
}
}
return;
}
else if (PeepFlags & PEEP_FLAGS_ANIMATION_FROZEN)
{
// Animation is frozen while position is not. This allows a peep to walk
// around without its sprite being updated, which looks very glitchy.
// We'll just remove the flag and continue as normal, in this case.
PeepFlags &= ~PEEP_FLAGS_ANIMATION_FROZEN;
}
auto* guest = As<Guest>();
if (guest != nullptr)
{
if (!guest->PreviousRide.IsNull())
if (++guest->PreviousRideTimeOut >= 720)
guest->PreviousRide = RideId::GetNull();
GuestUpdateThoughts(guest);
}
// Walking speed logic
uint32_t stepsToTake = Energy; uint32_t stepsToTake = Energy;
if (stepsToTake < 95 && State == PeepState::Queuing) if (stepsToTake < 95 && State == PeepState::Queuing)
stepsToTake = 95; stepsToTake = 95;
@@ -1045,54 +946,7 @@ void Peep::Update()
if (stepsToTake < minStepsForCrossing && IsOnPathBlockedByVehicle()) if (stepsToTake < minStepsForCrossing && IsOnPathBlockedByVehicle())
stepsToTake = minStepsForCrossing; stepsToTake = minStepsForCrossing;
uint32_t carryCheck = StepProgress + stepsToTake; return stepsToTake;
StepProgress = carryCheck;
if (carryCheck <= 255)
{
if (guest != nullptr)
{
guest->UpdateEasterEggInteractions();
}
}
else
{
// Loc68FD2F
switch (State)
{
case PeepState::Falling:
UpdateFalling();
break;
case PeepState::One:
Update1();
break;
case PeepState::OnRide:
// No action
break;
case PeepState::Picked:
UpdatePicked();
break;
default:
{
if (guest != nullptr)
{
guest->UpdateGuest();
}
else
{
auto* staff = As<Staff>();
if (staff != nullptr)
{
staff->UpdateStaff(stepsToTake);
}
else
{
assert(false);
}
}
break;
}
}
}
} }
/** /**

View File

@@ -356,7 +356,6 @@ struct Peep : EntityBase
uint32_t PeepFlags; uint32_t PeepFlags;
public: // Peep public: // Peep
void Update();
std::optional<CoordsXY> UpdateAction(int16_t& xy_distance); std::optional<CoordsXY> UpdateAction(int16_t& xy_distance);
std::optional<CoordsXY> UpdateAction(); std::optional<CoordsXY> UpdateAction();
bool UpdateActionAnimation(); bool UpdateActionAnimation();
@@ -400,18 +399,19 @@ public: // Peep
// TODO: Make these private again when done refactoring // TODO: Make these private again when done refactoring
public: // Peep public: // Peep
[[nodiscard]] bool CheckForPath(); [[nodiscard]] bool CheckForPath();
bool ShouldWaitForLevelCrossing(); bool ShouldWaitForLevelCrossing() const;
bool IsOnLevelCrossing(); bool IsOnLevelCrossing() const;
bool IsOnPathBlockedByVehicle(); bool IsOnPathBlockedByVehicle() const;
std::pair<uint8_t, TileElement*> PerformNextAction(); std::pair<uint8_t, TileElement*> PerformNextAction();
[[nodiscard]] int32_t GetZOnSlope(int32_t tile_x, int32_t tile_y); [[nodiscard]] int32_t GetZOnSlope(int32_t tile_x, int32_t tile_y);
void SwitchNextAnimationType(); void SwitchNextAnimationType();
[[nodiscard]] PeepAnimationType GetAnimationType(); [[nodiscard]] PeepAnimationType GetAnimationType();
private: protected:
void UpdateFalling(); void UpdateFalling();
void Update1(); void Update1();
void UpdatePicked(); void UpdatePicked();
uint32_t GetStepsToTake() const;
}; };
enum enum

View File

@@ -1680,10 +1680,58 @@ bool Staff::IsMechanic() const
return AssignedStaffType == StaffType::Mechanic; return AssignedStaffType == StaffType::Mechanic;
} }
void Staff::UpdateStaff(uint32_t stepsToTake) void Staff::Update()
{ {
if (PeepFlags & PEEP_FLAGS_POSITION_FROZEN)
{
if (!(PeepFlags & PEEP_FLAGS_ANIMATION_FROZEN))
{
// This is circumventing other logic, so only update every few ticks
if ((getGameState().currentTicks & 3) == 0)
{
if (IsActionWalking())
UpdateWalkingAnimation();
else
UpdateActionAnimation();
Invalidate();
}
}
return;
}
else if (PeepFlags & PEEP_FLAGS_ANIMATION_FROZEN)
{
// Animation is frozen while position is not. This allows a peep to walk
// around without its sprite being updated, which looks very glitchy.
// We'll just remove the flag and continue as normal, in this case.
PeepFlags &= ~PEEP_FLAGS_ANIMATION_FROZEN;
}
// Walking speed logic
const auto stepsToTake = GetStepsToTake();
const auto carryCheck = StepProgress + stepsToTake;
StepProgress = carryCheck;
if (carryCheck <= 255)
{
// No-op: Keep replay working for now, can be eliminate with a replay update.
}
else
{
// Loc68FD2F
switch (State) switch (State)
{ {
case PeepState::Falling:
UpdateFalling();
break;
case PeepState::One:
Update1();
break;
case PeepState::OnRide:
// No action
break;
case PeepState::Picked:
UpdatePicked();
break;
case PeepState::Patrolling: case PeepState::Patrolling:
UpdatePatrolling(); UpdatePatrolling();
break; break;
@@ -1716,6 +1764,7 @@ void Staff::UpdateStaff(uint32_t stepsToTake)
assert(false); assert(false);
break; break;
} }
}
} }
/** /**

View File

@@ -59,7 +59,7 @@ public:
}; };
uint32_t StaffBinsEmptied; uint32_t StaffBinsEmptied;
void UpdateStaff(uint32_t stepsToTake); void Update();
void Tick128UpdateStaff(); void Tick128UpdateStaff();
bool IsMechanic() const; bool IsMechanic() const;
bool IsPatrolAreaSet(const CoordsXY& coords) const; bool IsPatrolAreaSet(const CoordsXY& coords) const;

View File

@@ -270,7 +270,7 @@ struct UpkeepCostsDescriptor
using RideTrackGroups = OpenRCT2::BitSet<EnumValue(TrackGroup::count)>; using RideTrackGroups = OpenRCT2::BitSet<EnumValue(TrackGroup::count)>;
using UpdateRideApproachVehicleWaypointsFunction = void (*)(Guest&, const CoordsXY&, int16_t&); using UpdateRideApproachVehicleWaypointsFunction = void (*)(Guest&, const CoordsXY&, int16_t&);
using RideMusicUpdateFunction = void (*)(Ride&); using RideMusicUpdateFunction = void (*)(Ride&);
using PeepUpdateRideLeaveEntranceFunc = void (*)(Guest*, Ride&, CoordsXYZD&); using PeepUpdateRideLeaveEntranceFunc = void (*)(Guest&, Ride&, CoordsXYZD&);
using StartRideMusicFunction = void (*)(const OpenRCT2::RideAudio::ViewportRideMusicInstance&); using StartRideMusicFunction = void (*)(const OpenRCT2::RideAudio::ViewportRideMusicInstance&);
using LightFXAddLightsMagicVehicleFunction = void (*)(const Vehicle* vehicle); using LightFXAddLightsMagicVehicleFunction = void (*)(const Vehicle* vehicle);
using RideLocationFunction = CoordsXY (*)(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation); using RideLocationFunction = CoordsXY (*)(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation);