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