1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
11 //
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
16 //
17 // DESCRIPTION:
18 //
19 //
20 //-----------------------------------------------------------------------------
21
22
23 #ifndef __D_PLAYER_H__
24 #define __D_PLAYER_H__
25
26 // Finally, for odd reasons, the player input
27 // is buffered within the player data struct,
28 // as commands per game tick.
29 #include "d_ticcmd.h"
30 #include "doomstat.h"
31
32 #include "a_artifacts.h"
33
34 // The player data structure depends on a number
35 // of other structs: items (internal inventory),
36 // animation states (closely tied to the sprites
37 // used to represent them, unfortunately).
38 #include "p_pspr.h"
39
40 // In addition, the player is just a special
41 // case of the generic moving object/actor.
42 #include "actor.h"
43
44 //Added by MC:
45 #include "b_bot.h"
46
47 enum
48 {
49 APMETA_BASE = 0x95000,
50
51 APMETA_DisplayName, // display name (used in menus etc.)
52 APMETA_SoundClass, // sound class
53 APMETA_Face, // doom status bar face (when used)
54 APMETA_ColorRange, // skin color range
55 APMETA_InvulMode,
56 APMETA_HealingRadius,
57 APMETA_Portrait,
58 APMETA_Hexenarmor0,
59 APMETA_Hexenarmor1,
60 APMETA_Hexenarmor2,
61 APMETA_Hexenarmor3,
62 APMETA_Hexenarmor4,
63 APMETA_Slot0,
64 APMETA_Slot1,
65 APMETA_Slot2,
66 APMETA_Slot3,
67 APMETA_Slot4,
68 APMETA_Slot5,
69 APMETA_Slot6,
70 APMETA_Slot7,
71 APMETA_Slot8,
72 APMETA_Slot9,
73 };
74
75 FPlayerColorSet *P_GetPlayerColorSet(FName classname, int setnum);
76 void P_EnumPlayerColorSets(FName classname, TArray<int> *out);
77 const char *GetPrintableDisplayName(const PClass *cls);
78
79 class APlayerPawn : public AActor
80 {
81 DECLARE_CLASS (APlayerPawn, AActor)
82 HAS_OBJECT_POINTERS
83 public:
84 virtual void Serialize (FArchive &arc);
85
86 virtual void PostBeginPlay();
87 virtual void Tick();
88 virtual void AddInventory (AInventory *item);
89 virtual void RemoveInventory (AInventory *item);
90 virtual bool UseInventory (AInventory *item);
91 virtual void MarkPrecacheSounds () const;
92
93 virtual void PlayIdle ();
94 virtual void PlayRunning ();
95 virtual void ThrowPoisonBag ();
96 virtual void TweakSpeeds (int &forwardmove, int &sidemove);
97 virtual void MorphPlayerThink ();
98 virtual void ActivateMorphWeapon ();
99 AWeapon *PickNewWeapon (const PClass *ammotype);
100 AWeapon *BestWeapon (const PClass *ammotype);
101 void CheckWeaponSwitch(const PClass *ammotype);
102 virtual void GiveDeathmatchInventory ();
103 virtual void FilterCoopRespawnInventory (APlayerPawn *oldplayer);
104
105 void SetupWeaponSlots ();
106 void GiveDefaultInventory ();
107 void PlayAttacking ();
108 void PlayAttacking2 ();
109 const char *GetSoundClass () const;
110
111 enum EInvulState
112 {
113 INVUL_Start,
114 INVUL_Active,
115 INVUL_Stop,
116 INVUL_GetAlpha
117 };
118
119 void BeginPlay ();
120 void Die (AActor *source, AActor *inflictor, int dmgflags);
121
122 int crouchsprite;
123 int MaxHealth;
124 int MugShotMaxHealth;
125 int RunHealth;
126 int PlayerFlags;
127 TObjPtr<AInventory> InvFirst; // first inventory item displayed on inventory bar
128 TObjPtr<AInventory> InvSel; // selected inventory item
129
130 // [GRB] Player class properties
131 fixed_t JumpZ;
132 fixed_t GruntSpeed;
133 fixed_t FallingScreamMinSpeed, FallingScreamMaxSpeed;
134 fixed_t ViewHeight;
135 fixed_t ForwardMove1, ForwardMove2;
136 fixed_t SideMove1, SideMove2;
137 FTextureID ScoreIcon;
138 int SpawnMask;
139 FNameNoInit MorphWeapon;
140 fixed_t AttackZOffset; // attack height, relative to player center
141 fixed_t UseRange; // [NS] Distance at which player can +use
142 fixed_t AirCapacity; // Multiplier for air supply underwater.
143 const PClass *FlechetteType;
144
145 // [CW] Fades for when you are being damaged.
146 PalEntry DamageFade;
147
148 bool UpdateWaterLevel (fixed_t oldz, bool splash);
149 bool ResetAirSupply (bool playgasp = true);
150
151 int GetMaxHealth() const;
152 };
153
154 class APlayerChunk : public APlayerPawn
155 {
156 DECLARE_CLASS (APlayerChunk, APlayerPawn)
157 };
158
159 //
160 // PlayerPawn flags
161 //
162 enum
163 {
164 PPF_NOTHRUSTWHENINVUL = 1, // Attacks do not thrust the player if they are invulnerable.
165 PPF_CANSUPERMORPH = 2, // Being remorphed into this class can give you a Tome of Power
166 PPF_CROUCHABLEMORPH = 4, // This morphed player can crouch
167 };
168
169 //
170 // Player states.
171 //
172 typedef enum
173 {
174 PST_LIVE, // Playing or camping.
175 PST_DEAD, // Dead on the ground, view follows killer.
176 PST_REBORN, // Ready to restart/respawn???
177 PST_ENTER, // [BC] Entered the game
178 PST_GONE // Player has left the game
179 } playerstate_t;
180
181
182 //
183 // Player internal flags, for cheats and debug.
184 //
185 typedef enum
186 {
187 CF_NOCLIP = 1 << 0, // No clipping, walk through barriers.
188 CF_GODMODE = 1 << 1, // No damage, no health loss.
189 CF_NOVELOCITY = 1 << 2, // Not really a cheat, just a debug aid.
190 CF_NOTARGET = 1 << 3, // [RH] Monsters don't target
191 CF_FLY = 1 << 4, // [RH] Flying player
192 CF_CHASECAM = 1 << 5, // [RH] Put camera behind player
193 CF_FROZEN = 1 << 6, // [RH] Don't let the player move
194 CF_REVERTPLEASE = 1 << 7, // [RH] Stick camera in player's head if (s)he moves
195 CF_STEPLEFT = 1 << 9, // [RH] Play left footstep sound next time
196 CF_FRIGHTENING = 1 << 10, // [RH] Scare monsters away
197 CF_INSTANTWEAPSWITCH= 1 << 11, // [RH] Switch weapons instantly
198 CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use
199 CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted
200 CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame
201 CF_DRAIN = 1 << 16, // Player owns a drain powerup
202 CF_HIGHJUMP = 1 << 18, // more Skulltag flags. Implementation not guaranteed though. ;)
203 CF_REFLECTION = 1 << 19,
204 CF_PROSPERITY = 1 << 20,
205 CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact
206 CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths.
207 CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact
208 CF_BUDDHA2 = 1 << 24, // [MC] Absolute buddha. No voodoo can kill it either.
209 CF_GODMODE2 = 1 << 25, // [MC] Absolute godmode. No voodoo can kill it either.
210 CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die
211 CF_NOCLIP2 = 1 << 30, // [RH] More Quake-like noclip
212 } cheat_t;
213
214 enum
215 {
216 WF_WEAPONREADY = 1 << 0, // [RH] Weapon is in the ready state and can fire its primary attack
217 WF_WEAPONBOBBING = 1 << 1, // [HW] Bob weapon while the player is moving
218 WF_WEAPONREADYALT = 1 << 2, // Weapon can fire its secondary attack
219 WF_WEAPONSWITCHOK = 1 << 3, // It is okay to switch away from this weapon
220 WF_DISABLESWITCH = 1 << 4, // Disable weapon switching completely
221 WF_WEAPONRELOADOK = 1 << 5, // [XA] Okay to reload this weapon.
222 WF_WEAPONZOOMOK = 1 << 6, // [XA] Okay to use weapon zoom function.
223 WF_REFIRESWITCHOK = 1 << 7, // Mirror WF_WEAPONSWITCHOK for A_ReFire
224 WF_USER1OK = 1 << 8, // [MC] Allow pushing of custom state buttons 1-4
225 WF_USER2OK = 1 << 9,
226 WF_USER3OK = 1 << 10,
227 WF_USER4OK = 1 << 11,
228 };
229
230 #define WPIECE1 1
231 #define WPIECE2 2
232 #define WPIECE3 4
233
234 #define WP_NOCHANGE ((AWeapon*)~0)
235
236
237 #define MAXPLAYERNAME 15
238
239 // [GRB] Custom player classes
240 enum
241 {
242 PCF_NOMENU = 1, // Hide in new game menu
243 };
244
245 class FPlayerClass
246 {
247 public:
248 FPlayerClass ();
249 FPlayerClass (const FPlayerClass &other);
250 ~FPlayerClass ();
251
252 bool CheckSkin (int skin);
253
254 const PClass *Type;
255 DWORD Flags;
256 TArray<int> Skins;
257 };
258
259 extern TArray<FPlayerClass> PlayerClasses;
260
261 // User info (per-player copies of each CVAR_USERINFO cvar)
262 enum
263 {
264 GENDER_MALE,
265 GENDER_FEMALE,
266 GENDER_NEUTER
267 };
268
269 struct userinfo_t : TMap<FName,FBaseCVar *>
270 {
271 ~userinfo_t();
272
GetAimDistuserinfo_t273 int GetAimDist() const
274 {
275 if (dmflags2 & DF2_NOAUTOAIM)
276 {
277 return 0;
278 }
279
280 float aim = *static_cast<FFloatCVar *>(*CheckKey(NAME_Autoaim));
281 if (aim > 35 || aim < 0)
282 {
283 return ANGLE_1*35;
284 }
285 else
286 {
287 return xs_RoundToInt(fabs(aim * ANGLE_1));
288 }
289 }
GetNameuserinfo_t290 const char *GetName() const
291 {
292 return *static_cast<FStringCVar *>(*CheckKey(NAME_Name));
293 }
GetTeamuserinfo_t294 int GetTeam() const
295 {
296 return *static_cast<FIntCVar *>(*CheckKey(NAME_Team));
297 }
GetColorSetuserinfo_t298 int GetColorSet() const
299 {
300 return *static_cast<FIntCVar *>(*CheckKey(NAME_ColorSet));
301 }
GetColoruserinfo_t302 uint32 GetColor() const
303 {
304 return *static_cast<FColorCVar *>(*CheckKey(NAME_Color));
305 }
GetNeverSwitchuserinfo_t306 bool GetNeverSwitch() const
307 {
308 return *static_cast<FBoolCVar *>(*CheckKey(NAME_NeverSwitchOnPickup));
309 }
GetMoveBobuserinfo_t310 fixed_t GetMoveBob() const
311 {
312 return FLOAT2FIXED(*static_cast<FFloatCVar *>(*CheckKey(NAME_MoveBob)));
313 }
GetStillBobuserinfo_t314 fixed_t GetStillBob() const
315 {
316 return FLOAT2FIXED(*static_cast<FFloatCVar *>(*CheckKey(NAME_StillBob)));
317 }
GetPlayerClassNumuserinfo_t318 int GetPlayerClassNum() const
319 {
320 return *static_cast<FIntCVar *>(*CheckKey(NAME_PlayerClass));
321 }
GetPlayerClassTypeuserinfo_t322 const PClass *GetPlayerClassType() const
323 {
324 return PlayerClasses[GetPlayerClassNum()].Type;
325 }
GetSkinuserinfo_t326 int GetSkin() const
327 {
328 return *static_cast<FIntCVar *>(*CheckKey(NAME_Skin));
329 }
GetGenderuserinfo_t330 int GetGender() const
331 {
332 return *static_cast<FIntCVar *>(*CheckKey(NAME_Gender));
333 }
GetNoAutostartMapuserinfo_t334 bool GetNoAutostartMap() const
335 {
336 return *static_cast<FBoolCVar *>(*CheckKey(NAME_Wi_NoAutostartMap));
337 }
338
339 void Reset();
340 int TeamChanged(int team);
341 int SkinChanged(const char *skinname, int playerclass);
342 int SkinNumChanged(int skinnum);
343 int GenderChanged(const char *gendername);
344 int PlayerClassChanged(const char *classname);
345 int PlayerClassNumChanged(int classnum);
346 uint32 ColorChanged(const char *colorname);
347 uint32 ColorChanged(uint32 colorval);
348 int ColorSetChanged(int setnum);
349 };
350
351 void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin);
352 void WriteUserInfo(FArchive &arc, userinfo_t &info);
353
354 //
355 // Extended player object info: player_t
356 //
357 class player_t
358 {
359 public:
360 player_t();
361 player_t &operator= (const player_t &p);
362
363 void Serialize (FArchive &arc);
364 size_t FixPointers (const DObject *obj, DObject *replacement);
365 size_t PropagateMark();
366
367 void SetLogNumber (int num);
368 void SetLogText (const char *text);
369 void SendPitchLimits() const;
370
371 APlayerPawn *mo;
372 BYTE playerstate;
373 ticcmd_t cmd;
374 usercmd_t original_cmd;
375 DWORD original_oldbuttons;
376
377 userinfo_t userinfo; // [RH] who is this?
378
379 const PClass *cls; // class of associated PlayerPawn
380
381 float DesiredFOV; // desired field of vision
382 float FOV; // current field of vision
383 fixed_t viewz; // focal origin above r.z
384 fixed_t viewheight; // base height above floor for viewz
385 fixed_t deltaviewheight; // squat speed.
386 fixed_t bob; // bounded/scaled total velocity
387
388 // killough 10/98: used for realistic bobbing (i.e. not simply overall speed)
389 // mo->velx and mo->vely represent true velocity experienced by player.
390 // This only represents the thrust that the player applies himself.
391 // This avoids anomalies with such things as Boom ice and conveyors.
392 fixed_t velx, vely; // killough 10/98
393
394 bool centering;
395 BYTE turnticks;
396
397
398 bool attackdown;
399 bool usedown;
400 DWORD oldbuttons;
401 int health; // only used between levels, mo->health
402 // is used during levels
403
404 int inventorytics;
405 BYTE CurrentPlayerClass; // class # for this player instance
406
407 int frags[MAXPLAYERS]; // kills of other players
408 int fragcount; // [RH] Cumulative frags for this player
409 int lastkilltime; // [RH] For multikills
410 BYTE multicount;
411 BYTE spreecount; // [RH] Keep track of killing sprees
412 WORD WeaponState;
413
414 AWeapon *ReadyWeapon;
415 AWeapon *PendingWeapon; // WP_NOCHANGE if not changing
416
417 int cheats; // bit flags
418 int timefreezer; // Player has an active time freezer
419 short refire; // refired shots are less accurate
420 short inconsistant;
421 bool waiting;
422 int killcount, itemcount, secretcount; // for intermission
423 int damagecount, bonuscount;// for screen flashing
424 int hazardcount; // for delayed Strife damage
425 int hazardinterval; // Frequency of damage infliction
426 FName hazardtype; // Damage type of last hazardous damage encounter.
427 int poisoncount; // screen flash for poison damage
428 FName poisontype; // type of poison damage to apply
429 FName poisonpaintype; // type of Pain state to enter for poison damage
430 TObjPtr<AActor> poisoner; // NULL for non-player actors
431 TObjPtr<AActor> attacker; // who did damage (NULL for floors)
432 int extralight; // so gun flashes light up areas
433 short fixedcolormap; // can be set to REDCOLORMAP, etc.
434 short fixedlightlevel;
435 pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc)
436 int morphTics; // player is a chicken/pig if > 0
437 const PClass *MorphedPlayerClass; // [MH] (for SBARINFO) class # for this player instance when morphed
438 int MorphStyle; // which effects to apply for this player instance when morphed
439 const PClass *MorphExitFlash; // flash to apply when demorphing (cache of value given to P_MorphPlayer)
440 TObjPtr<AWeapon> PremorphWeapon; // ready weapon before morphing
441 int chickenPeck; // chicken peck countdown
442 int jumpTics; // delay the next jump for a moment
443 bool onground; // Identifies if this player is on the ground or other object
444
445 int respawn_time; // [RH] delay respawning until this tic
446 TObjPtr<AActor> camera; // [RH] Whose eyes this player sees through
447
448 int air_finished; // [RH] Time when you start drowning
449
450 FName LastDamageType; // [RH] For damage-specific pain and death sounds
451
452 TObjPtr<AActor> MUSINFOactor; // For MUSINFO purposes
453 SBYTE MUSINFOtics;
454
455 bool settings_controller; // Player can control game settings.
456 SBYTE crouching;
457 SBYTE crouchdir;
458
459 //Added by MC:
460 TObjPtr<DBot> Bot;
461
462 float BlendR; // [RH] Final blending values
463 float BlendG;
464 float BlendB;
465 float BlendA;
466
467 FString LogText; // [RH] Log for Strife
468
469 int MinPitch; // Viewpitch limits (negative is up, positive is down)
470 int MaxPitch;
471
472 fixed_t crouchfactor;
473 fixed_t crouchoffset;
474 fixed_t crouchviewdelta;
475
476 FWeaponSlots weapons;
477
478 // [CW] I moved these here for multiplayer conversation support.
479 TObjPtr<AActor> ConversationNPC, ConversationPC;
480 angle_t ConversationNPCAngle;
481 bool ConversationFaceTalker;
482
GetDeltaViewHeight()483 fixed_t GetDeltaViewHeight() const
484 {
485 return (mo->ViewHeight + crouchviewdelta - viewheight) >> 3;
486 }
487
Uncrouch()488 void Uncrouch()
489 {
490 if (crouchfactor != FRACUNIT)
491 {
492 crouchfactor = FRACUNIT;
493 crouchoffset = 0;
494 crouchdir = 0;
495 crouching = 0;
496 crouchviewdelta = 0;
497 viewheight = mo->ViewHeight;
498 }
499 }
500
CanCrouch()501 bool CanCrouch() const
502 {
503 return morphTics == 0 || mo->PlayerFlags & PPF_CROUCHABLEMORPH;
504 }
505
506 int GetSpawnClass();
507 };
508
509 // Bookkeeping on players - state.
510 extern player_t players[MAXPLAYERS];
511
512 FArchive &operator<< (FArchive &arc, player_t *&p);
513
514 void P_CheckPlayerSprite(AActor *mo, int &spritenum, fixed_t &scalex, fixed_t &scaley);
515
SetFriendPlayer(player_t * player)516 inline void AActor::SetFriendPlayer(player_t *player)
517 {
518 if (player == NULL)
519 {
520 FriendPlayer = 0;
521 }
522 else
523 {
524 FriendPlayer = int(player - players) + 1;
525 }
526 }
527
IsNoClip2()528 inline bool AActor::IsNoClip2() const
529 {
530 if (player != NULL && player->mo == this)
531 {
532 return (player->cheats & CF_NOCLIP2) != 0;
533 }
534 return false;
535 }
536
537 #define CROUCHSPEED (FRACUNIT/12)
538
539 bool P_IsPlayerTotallyFrozen(const player_t *player);
540
541 #endif // __D_PLAYER_H__
542