1 /***************************************************************************** 2 * Copyright (c) 2014-2020 OpenRCT2 developers 3 * 4 * For a complete list of all authors, please refer to contributors.md 5 * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 6 * 7 * OpenRCT2 is licensed under the GNU General Public License version 3. 8 *****************************************************************************/ 9 10 #pragma once 11 12 #include "../management/Finance.h" 13 #include "../ride/ShopItem.h" 14 #include "Peep.h" 15 16 #include <bitset> 17 18 #define PEEP_MAX_THOUGHTS 5 19 20 #define PEEP_HUNGER_WARNING_THRESHOLD 25 21 #define PEEP_THIRST_WARNING_THRESHOLD 25 22 #define PEEP_TOILET_WARNING_THRESHOLD 28 23 #define PEEP_LITTER_WARNING_THRESHOLD 23 24 #define PEEP_DISGUST_WARNING_THRESHOLD 22 25 #define PEEP_VANDALISM_WARNING_THRESHOLD 15 26 #define PEEP_NOEXIT_WARNING_THRESHOLD 8 27 #define PEEP_LOST_WARNING_THRESHOLD 8 28 29 #define PEEP_MAX_HAPPINESS 255 30 #define PEEP_MAX_HUNGER 255 31 #define PEEP_MAX_TOILET 255 32 #define PEEP_MAX_NAUSEA 255 33 #define PEEP_MAX_THIRST 255 34 35 enum class PeepThoughtType : uint8_t 36 { 37 CantAffordRide = 0, // "I can't afford" 38 SpentMoney = 1, // "I've spent all my money" 39 Sick = 2, // "I feel sick" 40 VerySick = 3, // "I feel very sick" 41 MoreThrilling = 4, // "I want to go on something more thrilling than X" 42 Intense = 5, // "X looks too intense for me" 43 HaventFinished = 6, // "I haven't finished my X yet" 44 Sickening = 7, // "Just looking at X makes me feel sick" 45 BadValue = 8, // "I'm not paying that much to go on X" 46 GoHome = 9, // "I want to go home" 47 GoodValue = 10, // "X is really good value" 48 AlreadyGot = 11, // "I've already got" 49 CantAffordItem = 12, // "I can't afford" 50 NotHungry = 13, // "I'm not hungry" 51 NotThirsty = 14, // "I'm not thirsty" 52 Drowning = 15, // "Help! I'm drowning!" 53 Lost = 16, // "I'm lost!" 54 WasGreat = 17, // "X was great" 55 QueuingAges = 18, // "I've been queuing for X for ages" 56 Tired = 19, // "I'm tired" 57 Hungry = 20, // "I'm hungry" 58 Thirsty = 21, // "I'm thirsty" 59 Toilet = 22, // "I need to go to the toilet" 60 CantFind = 23, // "I can't find X" 61 NotPaying = 24, // "I'm not paying that much to use X" 62 NotWhileRaining = 25, // "I'm not going on X while it's raining" 63 BadLitter = 26, // "The litter here is really bad" 64 CantFindExit = 27, // "I can't find the exit" 65 GetOff = 28, // "I want to get off X" 66 GetOut = 29, // "I want to get out of X" 67 NotSafe = 30, // "I'm not going on X - it isn't safe" 68 PathDisgusting = 31, // "This path is disgusting" 69 Crowded = 32, // "It's too crowded here" 70 Vandalism = 33, // "The vandalism here is really bad" 71 Scenery = 34, // "Great scenery!" 72 VeryClean = 35, // "This park is very clean and tidy" 73 Fountains = 36, // "The jumping fountains are great" 74 Music = 37, // "The music is nice here" 75 Balloon = 38, // "This balloon from X is really good value" 76 Toy = 39, // "This cuddly toy from X is really good value" 77 Map = 40, 78 Photo = 41, // "This on ride photo from X is really good value" 79 Umbrella = 42, 80 Drink = 43, 81 Burger = 44, 82 Chips = 45, 83 IceCream = 46, 84 Candyfloss = 47, 85 86 Pizza = 51, 87 88 Popcorn = 53, 89 HotDog = 54, 90 Tentacle = 55, 91 Hat = 56, 92 ToffeeApple = 57, 93 Tshirt = 58, 94 Doughnut = 59, 95 Coffee = 60, 96 97 Chicken = 62, 98 Lemonade = 63, 99 100 Wow = 67, // "Wow!" 101 102 Wow2 = 70, // "Wow!" 103 Watched = 71, // "I have the strangest feeling someone is watching me" 104 BalloonMuch = 72, // "I'm not paying that much to get a balloon from X" 105 ToyMuch = 73, 106 MapMuch = 74, 107 PhotoMuch = 75, 108 UmbrellaMuch = 76, 109 DrinkMuch = 77, 110 BurgerMuch = 78, 111 ChipsMuch = 79, 112 IceCreamMuch = 80, 113 CandyflossMuch = 81, 114 115 PizzaMuch = 85, 116 117 PopcornMuch = 87, 118 HotDogMuch = 88, 119 TentacleMuch = 89, 120 HatMuch = 90, 121 ToffeeAppleMuch = 91, 122 TshirtMuch = 92, 123 DoughnutMuch = 93, 124 CoffeeMuch = 94, 125 126 ChickenMuch = 96, 127 LemonadeMuch = 97, 128 129 Photo2 = 104, // "This on-ride photo from X is really good value" 130 Photo3 = 105, 131 Photo4 = 106, 132 Pretzel = 107, 133 HotChocolate = 108, 134 IcedTea = 109, 135 FunnelCake = 110, 136 Sunglasses = 111, 137 BeefNoodles = 112, 138 FriedRiceNoodles = 113, 139 WontonSoup = 114, 140 MeatballSoup = 115, 141 FruitJuice = 116, 142 SoybeanMilk = 117, 143 Sujongkwa = 118, 144 SubSandwich = 119, 145 Cookie = 120, 146 147 RoastSausage = 124, 148 149 Photo2Much = 136, 150 Photo3Much = 137, 151 Photo4Much = 138, 152 PretzelMuch = 139, 153 HotChocolateMuch = 140, 154 IcedTeaMuch = 141, 155 FunnelCakeMuch = 142, 156 SunglassesMuch = 143, 157 BeefNoodlesMuch = 144, 158 FriedRiceNoodlesMuch = 145, 159 WontonSoupMuch = 146, 160 MeatballSoupMuch = 147, 161 FruitJuiceMuch = 148, 162 SoybeanMilkMuch = 149, 163 SujongkwaMuch = 150, 164 SubSandwichMuch = 151, 165 CookieMuch = 152, 166 167 RoastSausageMuch = 156, 168 169 Help = 168, // "Help! Put me down!" 170 RunningOut = 169, // "I'm running out of cash!" 171 NewRide = 170, // "Wow! A new ride being built!" 172 NiceRideDeprecated = 171, // "Nice ride! But not as good as the Phoenix..." 173 ExcitedDeprecated = 172, // "I'm so excited - It's an Intamin ride!" 174 HereWeAre = 173, // "...and here we are on X!" 175 176 None = 255 177 }; 178 179 enum class PeepNauseaTolerance : uint8_t 180 { 181 None, 182 Low, 183 Average, 184 High 185 }; 186 187 static constexpr uint16_t PeepThoughtItemNone = std::numeric_limits<uint16_t>::max(); 188 189 struct PeepThought 190 { 191 PeepThoughtType type; 192 union 193 { 194 ride_id_t rideId; 195 ShopItem shopItem; 196 uint16_t item; 197 }; 198 uint8_t freshness; // larger is less fresh 199 uint8_t fresh_timeout; // updates every tick 200 }; 201 202 struct Guest; 203 struct Staff; 204 205 struct IntensityRange 206 { 207 private: 208 uint8_t _value{}; 209 210 public: IntensityRangeIntensityRange211 explicit IntensityRange(uint8_t value) 212 : _value(value) 213 { 214 } 215 IntensityRangeIntensityRange216 IntensityRange(uint8_t min, uint8_t max) 217 : _value(std::min<uint8_t>(min, 15) | (std::min<uint8_t>(max, 15) << 4)) 218 { 219 } 220 GetMinimumIntensityRange221 uint8_t GetMinimum() const 222 { 223 return _value & 0x0F; 224 } 225 GetMaximumIntensityRange226 uint8_t GetMaximum() const 227 { 228 return _value >> 4; 229 } 230 WithMinimumIntensityRange231 IntensityRange WithMinimum(uint8_t value) const 232 { 233 return IntensityRange(value, GetMaximum()); 234 } 235 WithMaximumIntensityRange236 IntensityRange WithMaximum(uint8_t value) const 237 { 238 return IntensityRange(GetMinimum(), value); 239 } 240 uint8_tIntensityRange241 explicit operator uint8_t() const 242 { 243 return _value; 244 } 245 246 friend bool operator==(const IntensityRange& lhs, const IntensityRange& rhs) 247 { 248 return lhs._value == rhs._value; 249 } 250 251 friend bool operator!=(const IntensityRange& lhs, const IntensityRange& rhs) 252 { 253 return lhs._value != rhs._value; 254 } 255 }; 256 257 struct Guest : Peep 258 { 259 static constexpr auto cEntityType = EntityType::Guest; 260 261 public: 262 uint8_t GuestNumRides; 263 uint16_t GuestNextInQueue; 264 int32_t ParkEntryTime; 265 ride_id_t GuestHeadingToRideId; 266 uint8_t GuestIsLostCountdown; 267 uint8_t GuestTimeOnRide; 268 money16 PaidToEnter; 269 money16 PaidOnRides; 270 money16 PaidOnFood; 271 money16 PaidOnDrink; 272 money16 PaidOnSouvenirs; 273 bool OutsideOfPark; 274 uint8_t Happiness; 275 uint8_t HappinessTarget; 276 uint8_t Nausea; 277 uint8_t NauseaTarget; 278 uint8_t Hunger; 279 uint8_t Thirst; 280 uint8_t Toilet; 281 uint8_t TimeToConsume; 282 IntensityRange Intensity{ 0 }; 283 PeepNauseaTolerance NauseaTolerance; 284 uint16_t TimeInQueue; 285 money32 CashInPocket; 286 money32 CashSpent; 287 ride_id_t Photo1RideRef; 288 ride_id_t Photo2RideRef; 289 ride_id_t Photo3RideRef; 290 ride_id_t Photo4RideRef; 291 292 int8_t RejoinQueueTimeout; // whilst waiting for a free vehicle (or pair) in the entrance 293 ride_id_t PreviousRide; 294 uint16_t PreviousRideTimeOut; 295 std::array<PeepThought, PEEP_MAX_THOUGHTS> Thoughts; 296 // 0x3F Litter Count split into lots of 3 with time, 0xC0 Time since last recalc 297 uint8_t LitterCount; 298 // 0x3F Sick Count split into lots of 3 with time, 0xC0 Time since last recalc 299 uint8_t DisgustingCount; 300 uint8_t AmountOfFood; 301 uint8_t AmountOfDrinks; 302 uint8_t AmountOfSouvenirs; 303 uint8_t VandalismSeen; // 0xC0 vandalism thought timeout, 0x3F vandalism tiles seen 304 uint8_t VoucherType; 305 union 306 { 307 ride_id_t VoucherRideId; 308 ShopItemIndex VoucherShopItem; 309 }; 310 uint8_t SurroundingsThoughtTimeout; 311 uint8_t Angriness; 312 uint8_t TimeLost; // the time the peep has been lost when it reaches 254 generates the lost thought 313 uint8_t DaysInQueue; 314 uint8_t BalloonColour; 315 uint8_t UmbrellaColour; 316 uint8_t HatColour; 317 ride_id_t FavouriteRide; 318 uint8_t FavouriteRideRating; 319 uint64_t ItemFlags; 320 321 void UpdateGuest(); 322 void Tick128UpdateGuest(int32_t index); 323 int64_t GetFoodOrDrinkFlags() const; 324 int64_t GetEmptyContainerFlags() const; 325 bool HasDrink() const; 326 bool HasFoodOrDrink() const; 327 bool HasEmptyContainer() const; 328 void OnEnterRide(Ride* ride); 329 void OnExitRide(Ride* ride); 330 void UpdateSpriteType(); 331 bool HeadingForRideOrParkExit() const; 332 void StopPurchaseThought(uint8_t ride_type); 333 void TryGetUpFromSitting(); 334 void ChoseNotToGoOnRide(Ride* ride, bool peepAtRide, bool updateLastRide); 335 void PickRideToGoOn(); 336 void ReadMap(); 337 bool ShouldGoOnRide(Ride* ride, int32_t entranceNum, bool atQueue, bool thinking); 338 bool ShouldGoToShop(Ride* ride, bool peepAtShop); 339 bool ShouldFindBench(); 340 bool UpdateWalkingFindBench(); 341 bool UpdateWalkingFindBin(); 342 void SpendMoney(money16& peep_expend_type, money32 amount, ExpenditureType type); 343 void SpendMoney(money32 amount, ExpenditureType type); 344 void SetHasRidden(const Ride* ride); 345 bool HasRidden(const Ride* ride) const; 346 void SetHasRiddenRideType(int32_t rideType); 347 bool HasRiddenRideType(int32_t rideType) const; 348 void SetParkEntryTime(int32_t entryTime); 349 int32_t GetParkEntryTime() const; 350 void CheckIfLost(); 351 void CheckCantFindRide(); 352 void CheckCantFindExit(); 353 bool DecideAndBuyItem(Ride* ride, ShopItem shopItem, money32 price); 354 void SetSpriteType(PeepSpriteType new_sprite_type); 355 void HandleEasterEggName(); 356 int32_t GetEasterEggNameId() const; 357 void UpdateEasterEggInteractions(); 358 void InsertNewThought(PeepThoughtType thought_type); 359 void InsertNewThought(PeepThoughtType thought_type, ShopItem thought_arguments); 360 void InsertNewThought(PeepThoughtType thought_type, ride_id_t rideId); 361 void InsertNewThought(PeepThoughtType thought_type, uint16_t thought_arguments); 362 static Guest* Generate(const CoordsXYZ& coords); 363 bool UpdateQueuePosition(PeepActionType previous_action); 364 void RemoveFromQueue(); 365 366 uint64_t GetItemFlags() const; 367 void SetItemFlags(uint64_t itemFlags); 368 void RemoveAllItems(); 369 void RemoveItem(ShopItem item); 370 void GiveItem(ShopItem item); 371 bool HasItem(ShopItem peepItem) const; 372 void Serialise(DataSerialiser& stream); 373 374 // Removes the ride from the guests memory, this includes 375 // the history, thoughts, etc. 376 void RemoveRideFromMemory(ride_id_t rideId); 377 378 private: 379 void UpdateRide(); UpdateOnRideGuest380 void UpdateOnRide(){}; // TODO 381 void UpdateWalking(); 382 void UpdateQueuing(); 383 void UpdateSitting(); 384 void UpdateEnteringPark(); 385 void UpdateLeavingPark(); 386 void UpdateBuying(); 387 void UpdateWatching(); 388 void UpdateUsingBin(); 389 void UpdateRideAtEntrance(); 390 void UpdateRideAdvanceThroughEntrance(); 391 void UpdateRideLeaveEntranceWaypoints(const Ride& ride); 392 uint8_t GetWaypointedSeatLocation(const Ride& ride, rct_ride_entry_vehicle* vehicle_type, uint8_t track_direction) const; 393 void UpdateRideFreeVehicleCheck(); 394 void UpdateRideFreeVehicleEnterRide(Ride* ride); 395 void UpdateRideApproachVehicle(); 396 void UpdateRideEnterVehicle(); 397 void UpdateRideLeaveVehicle(); 398 void UpdateRideApproachExit(); 399 void UpdateRideInExit(); 400 void UpdateRideApproachVehicleWaypoints(); 401 void UpdateRideApproachExitWaypoints(); 402 void UpdateRideApproachSpiralSlide(); 403 void UpdateRideOnSpiralSlide(); 404 void UpdateRideLeaveSpiralSlide(); 405 void UpdateRideMazePathfinding(); 406 void UpdateRideLeaveExit(); 407 void UpdateRideShopApproach(); 408 void UpdateRideShopInteract(); 409 void UpdateRideShopLeave(); 410 void UpdateRidePrepareForExit(); 411 void loc_68F9F3(); 412 void loc_68FA89(); 413 int32_t CheckEasterEggName(int32_t index) const; 414 bool GuestHasValidXY() const; 415 void GivePassingPeepsPurpleClothes(Guest* passingPeep); 416 void GivePassingPeepsPizza(Guest* passingPeep); 417 void MakePassingPeepsSick(Guest* passingPeep); 418 void GivePassingPeepsIceCream(Guest* passingPeep); 419 Ride* FindBestRideToGoOn(); 420 std::bitset<MAX_RIDES> FindRidesToGoOn(); 421 bool FindVehicleToEnter(Ride* ride, std::vector<uint8_t>& car_array); 422 void GoToRideEntrance(Ride* ride); 423 }; 424 425 static_assert(sizeof(Guest) <= 512); 426 427 enum 428 { 429 EASTEREGG_PEEP_NAME_MICHAEL_SCHUMACHER, 430 EASTEREGG_PEEP_NAME_JACQUES_VILLENEUVE, 431 EASTEREGG_PEEP_NAME_DAMON_HILL, 432 EASTEREGG_PEEP_NAME_MR_BEAN, 433 EASTEREGG_PEEP_NAME_CHRIS_SAWYER, 434 EASTEREGG_PEEP_NAME_KATIE_BRAYSHAW, 435 EASTEREGG_PEEP_NAME_MELANIE_WARN, 436 EASTEREGG_PEEP_NAME_SIMON_FOSTER, 437 EASTEREGG_PEEP_NAME_JOHN_WARDLEY, 438 EASTEREGG_PEEP_NAME_LISA_STIRLING, 439 EASTEREGG_PEEP_NAME_DONALD_MACRAE, 440 EASTEREGG_PEEP_NAME_KATHERINE_MCGOWAN, 441 EASTEREGG_PEEP_NAME_FRANCES_MCGOWAN, 442 EASTEREGG_PEEP_NAME_CORINA_MASSOURA, 443 EASTEREGG_PEEP_NAME_CAROL_YOUNG, 444 EASTEREGG_PEEP_NAME_MIA_SHERIDAN, 445 EASTEREGG_PEEP_NAME_KATIE_RODGER, 446 EASTEREGG_PEEP_NAME_EMMA_GARRELL, 447 EASTEREGG_PEEP_NAME_JOANNE_BARTON, 448 EASTEREGG_PEEP_NAME_FELICITY_ANDERSON, 449 EASTEREGG_PEEP_NAME_KATIE_SMITH, 450 EASTEREGG_PEEP_NAME_EILIDH_BELL, 451 EASTEREGG_PEEP_NAME_NANCY_STILLWAGON, 452 EASTEREGG_PEEP_NAME_DAVID_ELLIS 453 }; 454 455 extern uint8_t gGuestChangeModifier; 456 extern uint32_t gNumGuestsInPark; 457 extern uint32_t gNumGuestsInParkLastWeek; 458 extern uint32_t gNumGuestsHeadingForPark; 459 460 extern money16 gGuestInitialCash; 461 extern uint8_t gGuestInitialHappiness; 462 extern uint8_t gGuestInitialHunger; 463 extern uint8_t gGuestInitialThirst; 464 465 extern uint32_t gNextGuestNumber; 466 467 void guest_set_name(uint16_t spriteIndex, const char* name); 468 469 void peep_thought_set_format_args(const PeepThought* thought, Formatter& ft); 470 471 void increment_guests_in_park(); 472 void increment_guests_heading_for_park(); 473 void decrement_guests_in_park(); 474 void decrement_guests_heading_for_park(); 475