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:
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user