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