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 "../common.h" 13 #include "../ride/RideTypes.h" 14 #include "../ride/Station.h" 15 #include "../util/Util.h" 16 #include "../world/EntityBase.h" 17 #include "../world/Location.hpp" 18 19 #include <algorithm> 20 #include <optional> 21 22 #define PEEP_MIN_ENERGY 32 23 #define PEEP_MAX_ENERGY 128 24 #define PEEP_MAX_ENERGY_TARGET 255 // Oddly, this differs from max energy! 25 26 constexpr auto PEEP_CLEARANCE_HEIGHT = 4 * COORDS_Z_STEP; 27 28 class Formatter; 29 struct TileElement; 30 31 namespace GameActions 32 { 33 class Result; 34 } 35 using ParkEntranceIndex = uint8_t; 36 37 enum class StaffType : uint8_t 38 { 39 Handyman, 40 Mechanic, 41 Security, 42 Entertainer, 43 44 Count 45 }; 46 47 enum class PeepState : uint8_t 48 { 49 Falling = 0, // Drowning is part of falling 50 One = 1, // was PEEP_STATE_1 51 QueuingFront = 2, 52 OnRide = 3, 53 LeavingRide = 4, 54 Walking = 5, 55 Queuing = 6, 56 EnteringRide = 7, 57 Sitting = 8, 58 Picked = 9, 59 Patrolling = 10, // Not sure 60 Mowing = 11, 61 Sweeping = 12, 62 EnteringPark = 13, 63 LeavingPark = 14, 64 Answering = 15, 65 Fixing = 16, 66 Buying = 17, 67 Watching = 18, 68 EmptyingBin = 19, 69 UsingBin = 20, 70 Watering = 21, 71 HeadingToInspection = 22, 72 Inspecting = 23 73 }; 74 75 enum class PeepSittingSubState : uint8_t 76 { 77 TryingToSit, // was = 0 78 SatDown // was unassigned 79 }; 80 81 enum class PeepRideSubState : uint8_t 82 { 83 AtEntrance = 0, 84 InEntrance = 1, 85 FreeVehicleCheck = 2, // Spend money on ride 86 LeaveEntrance = 3, // Calculate what direction and where to go after committing to entering vehicle 87 ApproachVehicle = 4, 88 EnterVehicle = 5, 89 OnRide = 6, 90 LeaveVehicle = 7, 91 ApproachExit = 8, 92 InExit = 9, 93 InQueue = 10, 94 AtQueueFront = 11, 95 ApproachVehicleWaypoints = 12, 96 ApproachExitWaypoints = 13, 97 ApproachSpiralSlide = 14, 98 OnSpiralSlide = 15, 99 LeaveSpiralSlide = 16, 100 MazePathfinding = 17, 101 LeaveExit = 18, 102 ApproachShop = 19, 103 InteractShop = 20, 104 LeaveShop = 21 105 }; 106 107 enum class PeepUsingBinSubState : uint8_t 108 { 109 WalkingToBin = 0, 110 GoingBack, 111 }; 112 113 enum class PeepActionType : uint8_t 114 { 115 CheckTime = 0, 116 // If no food then check watch 117 EatFood = 1, 118 ShakeHead = 2, 119 EmptyPockets = 3, 120 SittingEatFood = 4, 121 SittingCheckWatch = 4, 122 SittingLookAroundLeft = 5, 123 SittingLookAroundRight = 6, 124 Wow = 7, 125 ThrowUp = 8, 126 Jump = 9, 127 StaffSweep = 10, 128 Drowning = 11, 129 StaffAnswerCall = 12, 130 StaffAnswerCall2 = 13, 131 StaffCheckboard = 14, 132 StaffFix = 15, 133 StaffFix2 = 16, 134 StaffFixGround = 17, 135 StaffFix3 = 18, 136 StaffWatering = 19, 137 Joy = 20, 138 ReadMap = 21, 139 Wave = 22, 140 StaffEmptyBin = 23, 141 Wave2 = 24, 142 TakePhoto = 25, 143 Clap = 26, 144 Disgust = 27, 145 DrawPicture = 28, 146 BeingWatched = 29, 147 WithdrawMoney = 30, 148 149 Idle = 254, 150 Walking = 255, 151 }; 152 153 enum class PeepActionSpriteType : uint8_t 154 { 155 None = 0, 156 CheckTime = 1, 157 WatchRide = 2, 158 EatFood = 3, 159 ShakeHead = 4, 160 EmptyPockets = 5, 161 HoldMat = 6, 162 SittingIdle = 7, 163 SittingEatFood = 8, 164 SittingLookAroundLeft = 9, 165 SittingLookAroundRight = 10, 166 Ui = 11, 167 StaffMower = 12, 168 Wow = 13, 169 ThrowUp = 14, 170 Jump = 15, 171 StaffSweep = 16, 172 Drowning = 17, 173 StaffAnswerCall = 18, 174 StaffAnswerCall2 = 19, 175 StaffCheckboard = 20, 176 StaffFix = 21, 177 StaffFix2 = 22, 178 StaffFixGround = 23, 179 StaffFix3 = 24, 180 StaffWatering = 25, 181 Joy = 26, 182 ReadMap = 27, 183 Wave = 28, 184 StaffEmptyBin = 29, 185 Wave2 = 30, 186 TakePhoto = 31, 187 Clap = 32, 188 Disgust = 33, 189 DrawPicture = 34, 190 BeingWatched = 35, 191 WithdrawMoney = 36, 192 193 Invalid = 255 194 }; 195 196 enum PeepFlags : uint32_t 197 { 198 PEEP_FLAGS_LEAVING_PARK = (1 << 0), 199 PEEP_FLAGS_SLOW_WALK = (1 << 1), 200 PEEP_FLAGS_2 = (1 << 2), 201 PEEP_FLAGS_TRACKING = (1 << 3), 202 PEEP_FLAGS_WAVING = (1 << 4), // Makes the peep wave 203 PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY = (1 << 5), // Set on paying to enter park 204 PEEP_FLAGS_PHOTO = (1 << 6), // Makes the peep take a picture 205 PEEP_FLAGS_PAINTING = (1 << 7), 206 PEEP_FLAGS_WOW = (1 << 8), // Makes a peep WOW2 207 PEEP_FLAGS_LITTER = (1 << 9), // Makes the peep throw litter 208 PEEP_FLAGS_LOST = (1 << 10), // Makes the peep feel lost (animation triggered) 209 PEEP_FLAGS_HUNGER = (1 << 11), // Makes the peep become hungry quicker 210 PEEP_FLAGS_TOILET = (1 << 12), // Makes the peep want to go to the toilet 211 PEEP_FLAGS_CROWDED = (1 << 13), // The peep will start feeling crowded 212 PEEP_FLAGS_HAPPINESS = (1 << 14), // The peep will start increasing happiness 213 PEEP_FLAGS_NAUSEA = (1 << 15), // Makes the peep feel sick (e.g. after an extreme ride) 214 PEEP_FLAGS_PURPLE = (1 << 16), // Makes surrounding peeps purple 215 PEEP_FLAGS_PIZZA = (1 << 17), // Gives passing peeps pizza 216 PEEP_FLAGS_EXPLODE = (1 << 18), 217 PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE = (1 << 19), 218 PEEP_FLAGS_PARK_ENTRANCE_CHOSEN = (1 << 20), // Set when the nearest park entrance has been chosen 219 PEEP_FLAGS_21 = (1 << 21), 220 PEEP_FLAGS_CONTAGIOUS = (1 << 22), // Makes any peeps in surrounding tiles sick 221 PEEP_FLAGS_JOY = (1 << 23), // Makes the peep jump in joy 222 PEEP_FLAGS_ANGRY = (1 << 24), 223 PEEP_FLAGS_ICE_CREAM = (1 << 25), // Gives passing peeps ice cream and they wave back 224 PEEP_FLAGS_NICE_RIDE_DEPRECATED = (1 << 26), // Used to make the peep think "Nice ride! But not as good as the Phoenix..." 225 // on exiting a ride 226 PEEP_FLAGS_INTAMIN_DEPRECATED = (1 << 27), // Used to make the peep think "I'm so excited - It's an Intamin ride!" while 227 // riding on a Intamin ride. 228 PEEP_FLAGS_HERE_WE_ARE = (1 << 28), // Makes the peep think "...and here we are on X!" while riding a ride 229 PEEP_FLAGS_TWITCH_DEPRECATED = (1u << 31), // Formerly used for twitch integration 230 }; 231 232 enum PeepNextFlags 233 { 234 PEEP_NEXT_FLAG_DIRECTION_MASK = 0x3, 235 PEEP_NEXT_FLAG_IS_SLOPED = (1 << 2), 236 PEEP_NEXT_FLAG_IS_SURFACE = (1 << 3), 237 PEEP_NEXT_FLAG_UNUSED = (1 << 4), 238 }; 239 240 enum class PeepSpriteType : uint8_t 241 { 242 Normal = 0, 243 Handyman = 1, 244 Mechanic = 2, 245 Security = 3, 246 EntertainerPanda = 4, 247 EntertainerTiger = 5, 248 EntertainerElephant = 6, 249 EntertainerRoman = 7, 250 EntertainerGorilla = 8, 251 EntertainerSnowman = 9, 252 EntertainerKnight = 10, 253 EntertainerAstronaut = 11, 254 EntertainerBandit = 12, 255 EntertainerSheriff = 13, 256 EntertainerPirate = 14, 257 IceCream = 15, 258 Chips = 16, 259 Burger = 17, 260 Drink = 18, 261 Balloon = 19, 262 Candyfloss = 20, 263 Umbrella = 21, 264 Pizza = 22, 265 SecurityAlt = 23, 266 Popcorn = 24, 267 ArmsCrossed = 25, 268 HeadDown = 26, 269 Nauseous = 27, 270 VeryNauseous = 28, 271 RequireToilet = 29, 272 Hat = 30, 273 HotDog = 31, 274 Tentacle = 32, 275 ToffeeApple = 33, 276 Doughnut = 34, 277 Coffee = 35, 278 Chicken = 36, 279 Lemonade = 37, 280 Watching = 38, 281 Pretzel = 39, 282 Sunglasses = 40, 283 SuJongkwa = 41, 284 Juice = 42, 285 FunnelCake = 43, 286 Noodles = 44, 287 Sausage = 45, 288 Soup = 46, 289 Sandwich = 47, 290 Count = 48, 291 292 Invalid = 255 293 }; 294 295 // Flags used by peep->WindowInvalidateFlags 296 enum PeepInvalidate 297 { 298 PEEP_INVALIDATE_PEEP_THOUGHTS = 1, 299 PEEP_INVALIDATE_PEEP_STATS = 1 << 1, 300 PEEP_INVALIDATE_PEEP_2 = 1 << 2, 301 PEEP_INVALIDATE_PEEP_INVENTORY = 1 << 3, 302 PEEP_INVALIDATE_STAFF_STATS = 1 << 4, 303 PEEP_INVALIDATE_PEEP_ACTION = 1 << 5, // Currently set only when GuestHeadingToRideId is changed 304 }; 305 306 struct Guest; 307 struct Staff; 308 309 struct Peep : EntityBase 310 { 311 char* Name; 312 CoordsXYZ NextLoc; 313 uint8_t NextFlags; 314 PeepState State; 315 union 316 { 317 uint8_t SubState; 318 PeepSittingSubState SittingSubState; 319 PeepRideSubState RideSubState; 320 PeepUsingBinSubState UsingBinSubState; 321 }; 322 PeepSpriteType SpriteType; 323 uint8_t TshirtColour; 324 uint8_t TrousersColour; 325 uint16_t DestinationX; // Location that the peep is trying to get to 326 uint16_t DestinationY; 327 uint8_t DestinationTolerance; // How close to destination before next action/state 0 = exact 328 uint8_t Var37; 329 uint8_t Energy; 330 uint8_t EnergyTarget; 331 uint8_t Mass; 332 uint8_t WindowInvalidateFlags; 333 union 334 { 335 ride_id_t CurrentRide; 336 ParkEntranceIndex ChosenParkEntrance; 337 }; 338 StationIndex CurrentRideStation; 339 uint8_t CurrentTrain; 340 union 341 { 342 struct 343 { 344 uint8_t CurrentCar; 345 uint8_t CurrentSeat; 346 }; 347 uint16_t TimeToSitdown; 348 struct 349 { 350 uint8_t TimeToStand; 351 uint8_t StandingFlags; 352 }; 353 }; 354 // Normally 0, 1 for carrying sliding board on spiral slide ride, 2 for carrying lawn mower 355 uint8_t SpecialSprite; 356 PeepActionSpriteType ActionSpriteType; 357 // Seems to be used like a local variable, as it's always set before calling SwitchNextActionSpriteType, which 358 // reads this again 359 PeepActionSpriteType NextActionSpriteType; 360 uint8_t ActionSpriteImageOffset; 361 PeepActionType Action; 362 uint8_t ActionFrame; 363 uint8_t StepProgress; 364 union 365 { 366 uint8_t MazeLastEdge; 367 Direction PeepDirection; // Direction ? 368 }; 369 ride_id_t InteractionRideIndex; 370 uint32_t Id; 371 uint8_t PathCheckOptimisation; // see peep.checkForPath 372 TileCoordsXYZD PathfindGoal; 373 std::array<TileCoordsXYZD, 4> PathfindHistory; 374 uint8_t WalkingFrameNum; 375 uint32_t PeepFlags; 376 377 public: // Peep 378 void Update(); 379 std::optional<CoordsXY> UpdateAction(int16_t& xy_distance); 380 std::optional<CoordsXY> UpdateAction(); 381 void SetState(PeepState new_state); 382 void Remove(); 383 void UpdateCurrentActionSpriteType(); 384 void SwitchToSpecialSprite(uint8_t special_sprite_id); 385 void StateReset(); 386 [[nodiscard]] uint8_t GetNextDirection() const; 387 bool GetNextIsSloped() const; 388 bool GetNextIsSurface() const; 389 void SetNextFlags(uint8_t next_direction, bool is_sloped, bool is_surface); 390 bool CanBePickedUp() const; 391 void Pickup(); 392 void PickupAbort(int32_t old_x); 393 [[nodiscard]] std::unique_ptr<GameActions::Result> Place(const TileCoordsXYZ& location, bool apply); 394 void RemoveFromRide(); 395 void FormatActionTo(Formatter&) const; 396 void FormatNameTo(Formatter&) const; 397 [[nodiscard]] std::string GetName() const; 398 bool SetName(std::string_view value); 399 bool IsActionWalking() const; 400 bool IsActionIdle() const; 401 bool IsActionInterruptable() const; 402 403 // Reset the peep's stored goal, which means they will forget any stored pathfinding history 404 // on the next peep_pathfind_choose_direction call. 405 void ResetPathfindGoal(); 406 407 void SetDestination(const CoordsXY& coords); 408 void SetDestination(const CoordsXY& coords, int32_t tolerance); 409 [[nodiscard]] CoordsXY GetDestination() const; 410 411 // TODO: Make these private again when done refactoring 412 public: // Peep 413 [[nodiscard]] bool CheckForPath(); 414 void PerformNextAction(uint8_t& pathing_result); 415 void PerformNextAction(uint8_t& pathing_result, TileElement*& tile_result); 416 [[nodiscard]] int32_t GetZOnSlope(int32_t tile_x, int32_t tile_y); 417 void SwitchNextActionSpriteType(); 418 [[nodiscard]] PeepActionSpriteType GetActionSpriteType(); 419 420 private: 421 void UpdateFalling(); 422 void Update1(); 423 void UpdatePicked(); 424 }; 425 426 struct rct_sprite_bounds 427 { 428 uint8_t sprite_width; // 0x00 429 uint8_t sprite_height_negative; // 0x01 430 uint8_t sprite_height_positive; // 0x02 431 }; 432 433 struct rct_peep_animation 434 { 435 uint32_t base_image; // 0x00 436 size_t num_frames; 437 const uint8_t* frame_offsets; 438 }; 439 440 struct rct_peep_animation_entry 441 { 442 const rct_peep_animation* sprite_animation; // 0x00 443 const rct_sprite_bounds* sprite_bounds; // 0x04 444 }; 445 446 enum 447 { 448 PATHING_DESTINATION_REACHED = 1 << 0, 449 PATHING_OUTSIDE_PARK = 1 << 1, 450 PATHING_RIDE_EXIT = 1 << 2, 451 PATHING_RIDE_ENTRANCE = 1 << 3, 452 }; 453 454 // rct2: 0x00982708 455 extern const rct_peep_animation_entry g_peep_animation_entries[EnumValue(PeepSpriteType::Count)]; 456 extern const bool gSpriteTypeToSlowWalkMap[48]; 457 458 extern uint8_t gPeepWarningThrottle[16]; 459 460 int32_t peep_get_staff_count(); 461 void peep_update_all(); 462 void peep_problem_warnings_update(); 463 void peep_stop_crowd_noise(); 464 void peep_update_crowd_noise(); 465 void peep_update_days_in_queue(); 466 void peep_applause(); 467 int32_t get_peep_face_sprite_small(Guest* peep); 468 int32_t get_peep_face_sprite_large(Guest* peep); 469 void peep_sprite_remove(Peep* peep); 470 471 void peep_window_state_update(Peep* peep); 472 void peep_decrement_num_riders(Peep* peep); 473 474 void peep_set_map_tooltip(Peep* peep); 475 int32_t peep_compare(const uint16_t sprite_index_a, const uint16_t sprite_index_b); 476 477 void peep_update_names(bool realNames); 478 479 rct_string_id get_real_name_string_id_from_id(uint32_t id); 480 481 inline const rct_peep_animation& GetPeepAnimation( 482 PeepSpriteType spriteType, PeepActionSpriteType actionSpriteType = PeepActionSpriteType::None) 483 { 484 return g_peep_animation_entries[EnumValue(spriteType)].sprite_animation[EnumValue(actionSpriteType)]; 485 }; 486 487 inline const rct_sprite_bounds& GetSpriteBounds( 488 PeepSpriteType spriteType, PeepActionSpriteType actionSpriteType = PeepActionSpriteType::None) 489 { 490 return g_peep_animation_entries[EnumValue(spriteType)].sprite_bounds[EnumValue(actionSpriteType)]; 491 }; 492