mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-25 07:44:38 +01:00
476 lines
15 KiB
C++
476 lines
15 KiB
C++
/*****************************************************************************
|
|
* Copyright (c) 2014-2024 OpenRCT2 developers
|
|
*
|
|
* For a complete list of all authors, please refer to contributors.md
|
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
|
*
|
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
|
*****************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include "../core/BitSet.hpp"
|
|
#include "../management/Finance.h"
|
|
#include "../ride/Ride.h"
|
|
#include "../ride/ShopItem.h"
|
|
#include "Peep.h"
|
|
|
|
constexpr int8_t kPeepMaxThoughts = 5;
|
|
|
|
constexpr int8_t kPeepHungerWarningThreshold = 25;
|
|
constexpr int8_t kPeepThirstWarningThreshold = 25;
|
|
constexpr int8_t kPeepToiletWarningThreshold = 28;
|
|
constexpr int8_t kPeepLitterWarningThreshold = 23;
|
|
constexpr int8_t kPeepDisgustWarningThreshold = 22;
|
|
constexpr int8_t kPeepVandalismWarningThreshold = 15;
|
|
constexpr int8_t kPeepNoExitWarningThreshold = 8;
|
|
constexpr int8_t kPeepLostWarningThreshold = 8;
|
|
constexpr int8_t kPeepTooLongQueueThreshold = 25;
|
|
|
|
constexpr int kPeepMaxHappiness = 255;
|
|
constexpr int kPeepMaxHunger = 255;
|
|
constexpr int16_t kPeepMaxToilet = 255;
|
|
constexpr int16_t kPeepMaxNausea = 255;
|
|
constexpr int kPeepMaxThirst = 255;
|
|
|
|
enum class PeepThoughtType : uint8_t
|
|
{
|
|
CantAffordRide = 0, // "I can't afford"
|
|
SpentMoney = 1, // "I've spent all my money"
|
|
Sick = 2, // "I feel sick"
|
|
VerySick = 3, // "I feel very sick"
|
|
MoreThrilling = 4, // "I want to go on something more thrilling than X"
|
|
Intense = 5, // "X looks too intense for me"
|
|
HaventFinished = 6, // "I haven't finished my X yet"
|
|
Sickening = 7, // "Just looking at X makes me feel sick"
|
|
BadValue = 8, // "I'm not paying that much to go on X"
|
|
GoHome = 9, // "I want to go home"
|
|
GoodValue = 10, // "X is really good value"
|
|
AlreadyGot = 11, // "I've already got"
|
|
CantAffordItem = 12, // "I can't afford"
|
|
NotHungry = 13, // "I'm not hungry"
|
|
NotThirsty = 14, // "I'm not thirsty"
|
|
Drowning = 15, // "Help! I'm drowning!"
|
|
Lost = 16, // "I'm lost!"
|
|
WasGreat = 17, // "X was great"
|
|
QueuingAges = 18, // "I've been queuing for X for ages"
|
|
Tired = 19, // "I'm tired"
|
|
Hungry = 20, // "I'm hungry"
|
|
Thirsty = 21, // "I'm thirsty"
|
|
Toilet = 22, // "I need to go to the toilet"
|
|
CantFind = 23, // "I can't find X"
|
|
NotPaying = 24, // "I'm not paying that much to use X"
|
|
NotWhileRaining = 25, // "I'm not going on X while it's raining"
|
|
BadLitter = 26, // "The litter here is really bad"
|
|
CantFindExit = 27, // "I can't find the exit"
|
|
GetOff = 28, // "I want to get off X"
|
|
GetOut = 29, // "I want to get out of X"
|
|
NotSafe = 30, // "I'm not going on X - it isn't safe"
|
|
PathDisgusting = 31, // "This path is disgusting"
|
|
Crowded = 32, // "It's too crowded here"
|
|
Vandalism = 33, // "The vandalism here is really bad"
|
|
Scenery = 34, // "Great scenery!"
|
|
VeryClean = 35, // "This park is very clean and tidy"
|
|
Fountains = 36, // "The jumping fountains are great"
|
|
Music = 37, // "The music is nice here"
|
|
Balloon = 38, // "This balloon from X is really good value"
|
|
Toy = 39, // "This cuddly toy from X is really good value"
|
|
Map = 40,
|
|
Photo = 41, // "This on ride photo from X is really good value"
|
|
Umbrella = 42,
|
|
Drink = 43,
|
|
Burger = 44,
|
|
Chips = 45,
|
|
IceCream = 46,
|
|
Candyfloss = 47,
|
|
|
|
Pizza = 51,
|
|
|
|
Popcorn = 53,
|
|
HotDog = 54,
|
|
Tentacle = 55,
|
|
Hat = 56,
|
|
ToffeeApple = 57,
|
|
Tshirt = 58,
|
|
Doughnut = 59,
|
|
Coffee = 60,
|
|
|
|
Chicken = 62,
|
|
Lemonade = 63,
|
|
|
|
Wow = 67, // "Wow!"
|
|
|
|
Wow2 = 70, // "Wow!"
|
|
Watched = 71, // "I have the strangest feeling someone is watching me"
|
|
BalloonMuch = 72, // "I'm not paying that much to get a balloon from X"
|
|
ToyMuch = 73,
|
|
MapMuch = 74,
|
|
PhotoMuch = 75,
|
|
UmbrellaMuch = 76,
|
|
DrinkMuch = 77,
|
|
BurgerMuch = 78,
|
|
ChipsMuch = 79,
|
|
IceCreamMuch = 80,
|
|
CandyflossMuch = 81,
|
|
|
|
PizzaMuch = 85,
|
|
|
|
PopcornMuch = 87,
|
|
HotDogMuch = 88,
|
|
TentacleMuch = 89,
|
|
HatMuch = 90,
|
|
ToffeeAppleMuch = 91,
|
|
TshirtMuch = 92,
|
|
DoughnutMuch = 93,
|
|
CoffeeMuch = 94,
|
|
|
|
ChickenMuch = 96,
|
|
LemonadeMuch = 97,
|
|
|
|
Photo2 = 104, // "This on-ride photo from X is really good value"
|
|
Photo3 = 105,
|
|
Photo4 = 106,
|
|
Pretzel = 107,
|
|
HotChocolate = 108,
|
|
IcedTea = 109,
|
|
FunnelCake = 110,
|
|
Sunglasses = 111,
|
|
BeefNoodles = 112,
|
|
FriedRiceNoodles = 113,
|
|
WontonSoup = 114,
|
|
MeatballSoup = 115,
|
|
FruitJuice = 116,
|
|
SoybeanMilk = 117,
|
|
Sujongkwa = 118,
|
|
SubSandwich = 119,
|
|
Cookie = 120,
|
|
|
|
RoastSausage = 124,
|
|
|
|
Photo2Much = 136,
|
|
Photo3Much = 137,
|
|
Photo4Much = 138,
|
|
PretzelMuch = 139,
|
|
HotChocolateMuch = 140,
|
|
IcedTeaMuch = 141,
|
|
FunnelCakeMuch = 142,
|
|
SunglassesMuch = 143,
|
|
BeefNoodlesMuch = 144,
|
|
FriedRiceNoodlesMuch = 145,
|
|
WontonSoupMuch = 146,
|
|
MeatballSoupMuch = 147,
|
|
FruitJuiceMuch = 148,
|
|
SoybeanMilkMuch = 149,
|
|
SujongkwaMuch = 150,
|
|
SubSandwichMuch = 151,
|
|
CookieMuch = 152,
|
|
|
|
RoastSausageMuch = 156,
|
|
|
|
Help = 168, // "Help! Put me down!"
|
|
RunningOut = 169, // "I'm running out of cash!"
|
|
NewRide = 170, // "Wow! A new ride being built!"
|
|
NiceRideDeprecated = 171, // "Nice ride! But not as good as the Phoenix..."
|
|
ExcitedDeprecated = 172, // "I'm so excited - It's an Intamin ride!"
|
|
HereWeAre = 173, // "...and here we are on X!"
|
|
|
|
None = 255
|
|
};
|
|
|
|
enum class PeepNauseaTolerance : uint8_t
|
|
{
|
|
None,
|
|
Low,
|
|
Average,
|
|
High
|
|
};
|
|
|
|
static constexpr uint16_t PeepThoughtItemNone = std::numeric_limits<uint16_t>::max();
|
|
|
|
struct PeepThought
|
|
{
|
|
PeepThoughtType type;
|
|
union
|
|
{
|
|
RideId rideId;
|
|
ShopItem shopItem;
|
|
uint16_t item;
|
|
};
|
|
uint8_t freshness; // larger is less fresh
|
|
uint8_t fresh_timeout; // updates every tick
|
|
};
|
|
|
|
struct Guest;
|
|
struct Staff;
|
|
struct CarEntry;
|
|
|
|
struct IntensityRange
|
|
{
|
|
private:
|
|
uint8_t _value{};
|
|
|
|
public:
|
|
explicit IntensityRange(uint8_t value)
|
|
: _value(value)
|
|
{
|
|
}
|
|
|
|
IntensityRange(uint8_t min, uint8_t max)
|
|
: _value(std::min<uint8_t>(min, 15) | (std::min<uint8_t>(max, 15) << 4))
|
|
{
|
|
}
|
|
|
|
uint8_t GetMinimum() const
|
|
{
|
|
return _value & 0x0F;
|
|
}
|
|
|
|
uint8_t GetMaximum() const
|
|
{
|
|
return _value >> 4;
|
|
}
|
|
|
|
IntensityRange WithMinimum(uint8_t value) const
|
|
{
|
|
return IntensityRange(value, GetMaximum());
|
|
}
|
|
|
|
IntensityRange WithMaximum(uint8_t value) const
|
|
{
|
|
return IntensityRange(GetMinimum(), value);
|
|
}
|
|
|
|
explicit operator uint8_t() const
|
|
{
|
|
return _value;
|
|
}
|
|
|
|
friend bool operator==(const IntensityRange& lhs, const IntensityRange& rhs)
|
|
{
|
|
return lhs._value == rhs._value;
|
|
}
|
|
|
|
friend bool operator!=(const IntensityRange& lhs, const IntensityRange& rhs)
|
|
{
|
|
return lhs._value != rhs._value;
|
|
}
|
|
};
|
|
|
|
struct Guest : Peep
|
|
{
|
|
static constexpr auto cEntityType = EntityType::Guest;
|
|
|
|
public:
|
|
uint8_t GuestNumRides;
|
|
EntityId GuestNextInQueue;
|
|
int32_t ParkEntryTime;
|
|
RideId GuestHeadingToRideId;
|
|
uint8_t GuestIsLostCountdown;
|
|
uint8_t GuestTimeOnRide;
|
|
money64 PaidToEnter;
|
|
money64 PaidOnRides;
|
|
money64 PaidOnFood;
|
|
money64 PaidOnDrink;
|
|
money64 PaidOnSouvenirs;
|
|
bool OutsideOfPark;
|
|
uint8_t Happiness;
|
|
uint8_t HappinessTarget;
|
|
uint8_t Nausea;
|
|
uint8_t NauseaTarget;
|
|
uint8_t Hunger;
|
|
uint8_t Thirst;
|
|
uint8_t Toilet;
|
|
uint8_t TimeToConsume;
|
|
IntensityRange Intensity{ 0 };
|
|
PeepNauseaTolerance NauseaTolerance;
|
|
uint16_t TimeInQueue;
|
|
money64 CashInPocket;
|
|
money64 CashSpent;
|
|
RideId Photo1RideRef;
|
|
RideId Photo2RideRef;
|
|
RideId Photo3RideRef;
|
|
RideId Photo4RideRef;
|
|
|
|
int8_t RejoinQueueTimeout; // whilst waiting for a free vehicle (or pair) in the entrance
|
|
RideId PreviousRide;
|
|
uint16_t PreviousRideTimeOut;
|
|
std::array<PeepThought, kPeepMaxThoughts> Thoughts;
|
|
// 0x3F Litter Count split into lots of 3 with time, 0xC0 Time since last recalc
|
|
uint8_t LitterCount;
|
|
// 0x3F Sick Count split into lots of 3 with time, 0xC0 Time since last recalc
|
|
uint8_t DisgustingCount;
|
|
uint8_t AmountOfFood;
|
|
uint8_t AmountOfDrinks;
|
|
uint8_t AmountOfSouvenirs;
|
|
uint8_t VandalismSeen; // 0xC0 vandalism thought timeout, 0x3F vandalism tiles seen
|
|
uint8_t VoucherType;
|
|
union
|
|
{
|
|
RideId VoucherRideId;
|
|
ShopItemIndex VoucherShopItem;
|
|
};
|
|
uint8_t SurroundingsThoughtTimeout;
|
|
uint8_t Angriness;
|
|
uint8_t TimeLost; // the time the peep has been lost when it reaches 254 generates the lost thought
|
|
uint8_t DaysInQueue;
|
|
uint8_t BalloonColour;
|
|
uint8_t UmbrellaColour;
|
|
uint8_t HatColour;
|
|
RideId FavouriteRide;
|
|
uint8_t FavouriteRideRating;
|
|
uint64_t ItemFlags;
|
|
|
|
void UpdateGuest();
|
|
void Tick128UpdateGuest(uint32_t index);
|
|
int64_t GetFoodOrDrinkFlags() const;
|
|
int64_t GetEmptyContainerFlags() const;
|
|
bool HasDrink() const;
|
|
bool HasFoodOrDrink() const;
|
|
bool HasEmptyContainer() const;
|
|
void OnEnterRide(Ride& ride);
|
|
void OnExitRide(Ride& ride);
|
|
void UpdateSpriteType();
|
|
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();
|
|
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 amount, ExpenditureType type);
|
|
void SetHasRidden(const Ride& ride);
|
|
bool HasRidden(const Ride& ride) const;
|
|
void SetHasRiddenRideType(int32_t rideType);
|
|
bool HasRiddenRideType(int32_t rideType) const;
|
|
void SetParkEntryTime(int32_t entryTime);
|
|
int32_t GetParkEntryTime() const;
|
|
void CheckIfLost();
|
|
void CheckCantFindRide();
|
|
void CheckCantFindExit();
|
|
bool DecideAndBuyItem(Ride& ride, ShopItem shopItem, money64 price);
|
|
void SetSpriteType(PeepSpriteType new_sprite_type);
|
|
void HandleEasterEggName();
|
|
int32_t GetEasterEggNameId() const;
|
|
void UpdateEasterEggInteractions();
|
|
void InsertNewThought(PeepThoughtType thought_type);
|
|
void InsertNewThought(PeepThoughtType thought_type, ShopItem thought_arguments);
|
|
void InsertNewThought(PeepThoughtType thought_type, RideId rideId);
|
|
void InsertNewThought(PeepThoughtType thought_type, uint16_t thought_arguments);
|
|
static Guest* Generate(const CoordsXYZ& coords);
|
|
bool UpdateQueuePosition(PeepActionType previous_action);
|
|
void RemoveFromQueue();
|
|
|
|
uint64_t GetItemFlags() const;
|
|
void SetItemFlags(uint64_t itemFlags);
|
|
void RemoveAllItems();
|
|
void RemoveItem(ShopItem item);
|
|
void GiveItem(ShopItem item);
|
|
bool HasItem(ShopItem peepItem) const;
|
|
void Serialise(DataSerialiser& stream);
|
|
|
|
// Removes the ride from the guests memory, this includes
|
|
// the history, thoughts, etc.
|
|
void RemoveRideFromMemory(RideId rideId);
|
|
|
|
private:
|
|
void UpdateRide();
|
|
void UpdateOnRide(){}; // TODO
|
|
void UpdateWalking();
|
|
void UpdateWaitingAtCrossing();
|
|
void UpdateQueuing();
|
|
void UpdateSitting();
|
|
void UpdateEnteringPark();
|
|
void UpdateLeavingPark();
|
|
void UpdateBuying();
|
|
void UpdateWatching();
|
|
void UpdateUsingBin();
|
|
void UpdateRideAtEntrance();
|
|
void UpdateRideAdvanceThroughEntrance();
|
|
void UpdateRideLeaveEntranceWaypoints(const Ride& ride);
|
|
uint8_t GetWaypointedSeatLocation(const Ride& ride, const CarEntry* vehicle_type, uint8_t track_direction) const;
|
|
void UpdateRideFreeVehicleCheck();
|
|
void UpdateRideFreeVehicleEnterRide(Ride& ride);
|
|
void UpdateRideApproachVehicle();
|
|
void UpdateRideEnterVehicle();
|
|
void UpdateRideLeaveVehicle();
|
|
void UpdateRideApproachExit();
|
|
void UpdateRideInExit();
|
|
|
|
void UpdateRideApproachVehicleWaypoints();
|
|
|
|
void UpdateRideApproachExitWaypoints();
|
|
void UpdateRideApproachSpiralSlide();
|
|
void UpdateRideOnSpiralSlide();
|
|
void UpdateRideLeaveSpiralSlide();
|
|
void UpdateRideMazePathfinding();
|
|
void UpdateRideLeaveExit();
|
|
void UpdateRideShopApproach();
|
|
void UpdateRideShopInteract();
|
|
void UpdateRideShopLeave();
|
|
void UpdateRidePrepareForExit();
|
|
void UpdateMotivesIdle();
|
|
void UpdateConsumptionMotives();
|
|
int32_t CheckEasterEggName(int32_t index) const;
|
|
void GivePassingPeepsPurpleClothes(Guest* passingPeep);
|
|
void GivePassingPeepsPizza(Guest* passingPeep);
|
|
void MakePassingPeepsSick(Guest* passingPeep);
|
|
void GivePassingPeepsIceCream(Guest* passingPeep);
|
|
Ride* FindBestRideToGoOn();
|
|
OpenRCT2::BitSet<OpenRCT2::Limits::kMaxRidesInPark> FindRidesToGoOn();
|
|
bool FindVehicleToEnter(const Ride& ride, std::vector<uint8_t>& car_array);
|
|
void GoToRideEntrance(const Ride& ride);
|
|
};
|
|
|
|
void UpdateRideApproachVehicleWaypointsMotionSimulator(Guest&, const CoordsXY&, int16_t&);
|
|
void UpdateRideApproachVehicleWaypointsDefault(Guest&, const CoordsXY&, int16_t&);
|
|
|
|
static_assert(sizeof(Guest) <= 512);
|
|
|
|
enum
|
|
{
|
|
EASTEREGG_PEEP_NAME_MICHAEL_SCHUMACHER,
|
|
EASTEREGG_PEEP_NAME_JACQUES_VILLENEUVE,
|
|
EASTEREGG_PEEP_NAME_DAMON_HILL,
|
|
EASTEREGG_PEEP_NAME_MR_BEAN,
|
|
EASTEREGG_PEEP_NAME_CHRIS_SAWYER,
|
|
EASTEREGG_PEEP_NAME_KATIE_BRAYSHAW,
|
|
EASTEREGG_PEEP_NAME_MELANIE_WARN,
|
|
EASTEREGG_PEEP_NAME_SIMON_FOSTER,
|
|
EASTEREGG_PEEP_NAME_JOHN_WARDLEY,
|
|
EASTEREGG_PEEP_NAME_LISA_STIRLING,
|
|
EASTEREGG_PEEP_NAME_DONALD_MACRAE,
|
|
EASTEREGG_PEEP_NAME_KATHERINE_MCGOWAN,
|
|
EASTEREGG_PEEP_NAME_FRANCES_MCGOWAN,
|
|
EASTEREGG_PEEP_NAME_CORINA_MASSOURA,
|
|
EASTEREGG_PEEP_NAME_CAROL_YOUNG,
|
|
EASTEREGG_PEEP_NAME_MIA_SHERIDAN,
|
|
EASTEREGG_PEEP_NAME_KATIE_RODGER,
|
|
EASTEREGG_PEEP_NAME_EMMA_GARRELL,
|
|
EASTEREGG_PEEP_NAME_JOANNE_BARTON,
|
|
EASTEREGG_PEEP_NAME_FELICITY_ANDERSON,
|
|
EASTEREGG_PEEP_NAME_KATIE_SMITH,
|
|
EASTEREGG_PEEP_NAME_EILIDH_BELL,
|
|
EASTEREGG_PEEP_NAME_NANCY_STILLWAGON,
|
|
EASTEREGG_PEEP_NAME_DAVID_ELLIS
|
|
};
|
|
|
|
void PeepThoughtSetFormatArgs(const PeepThought* thought, Formatter& ft);
|
|
|
|
void IncrementGuestsInPark();
|
|
void IncrementGuestsHeadingForPark();
|
|
void DecrementGuestsInPark();
|
|
void DecrementGuestsHeadingForPark();
|
|
|
|
void PeepUpdateRideLeaveEntranceMaze(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);
|
|
|
|
CoordsXY GetGuestWaypointLocationDefault(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation);
|
|
CoordsXY GetGuestWaypointLocationEnterprise(const Vehicle& vehicle, const Ride& ride, const StationIndex& CurrentRideStation);
|