1 #ifndef __A_PICKUPS_H__
2 #define __A_PICKUPS_H__
3 
4 #include "actor.h"
5 #include "info.h"
6 #include "s_sound.h"
7 
8 #define NUM_WEAPON_SLOTS		10
9 
10 class player_t;
11 class FConfigFile;
12 class AWeapon;
13 struct visstyle_t;
14 
15 class FWeaponSlot
16 {
17 public:
FWeaponSlot()18 	FWeaponSlot() { Clear(); }
FWeaponSlot(const FWeaponSlot & other)19 	FWeaponSlot(const FWeaponSlot &other) { Weapons = other.Weapons; }
20 	FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; }
Clear()21 	void Clear() { Weapons.Clear(); }
22 	bool AddWeapon (const char *type);
23 	bool AddWeapon (const PClass *type);
24 	void AddWeaponList (const char *list, bool clear);
25 	AWeapon *PickWeapon (player_t *player, bool checkammo = false);
Size()26 	int Size () const { return (int)Weapons.Size(); }
27 	int LocateWeapon (const PClass *type);
28 
GetWeapon(int index)29 	inline const PClass *GetWeapon (int index) const
30 	{
31 		if ((unsigned)index < Weapons.Size())
32 		{
33 			return Weapons[index].Type;
34 		}
35 		else
36 		{
37 			return NULL;
38 		}
39 	}
40 
41 	friend struct FWeaponSlots;
42 
43 private:
44 	struct WeaponInfo
45 	{
46 		const PClass *Type;
47 		fixed_t Position;
48 	};
49 	void SetInitialPositions();
50 	void Sort();
51 	TArray<WeaponInfo> Weapons;
52 };
53 // FWeaponSlots::AddDefaultWeapon return codes
54 enum ESlotDef
55 {
56 	SLOTDEF_Exists,		// Weapon was already assigned a slot
57 	SLOTDEF_Added,		// Weapon was successfully added
58 	SLOTDEF_Full		// The specifed slot was full
59 };
60 
61 struct FWeaponSlots
62 {
FWeaponSlotsFWeaponSlots63 	FWeaponSlots() { Clear(); }
64 	FWeaponSlots(const FWeaponSlots &other);
65 
66 	FWeaponSlot Slots[NUM_WEAPON_SLOTS];
67 
68 	AWeapon *PickNextWeapon (player_t *player);
69 	AWeapon *PickPrevWeapon (player_t *player);
70 
71 	void Clear ();
72 	bool LocateWeapon (const PClass *type, int *const slot, int *const index);
73 	ESlotDef AddDefaultWeapon (int slot, const PClass *type);
74 	void AddExtraWeapons();
75 	void SetFromGameInfo();
76 	void SetFromPlayer(const PClass *type);
77 	void StandardSetup(const PClass *type);
78 	void LocalSetup(const PClass *type);
79 	void SendDifferences(int playernum, const FWeaponSlots &other);
80 	int RestoreSlots (FConfigFile *config, const char *section);
81 	void PrintSettings();
82 
83 	void AddSlot(int slot, const PClass *type, bool feedback);
84 	void AddSlotDefault(int slot, const PClass *type, bool feedback);
85 
86 };
87 
88 void P_PlaybackKeyConfWeapons(FWeaponSlots *slots);
89 void Net_WriteWeapon(const PClass *type);
90 const PClass *Net_ReadWeapon(BYTE **stream);
91 
92 void P_SetupWeapons_ntohton();
93 void P_WriteDemoWeaponsChunk(BYTE **demo);
94 void P_ReadDemoWeaponsChunk(BYTE **demo);
95 
96 /************************************************************************/
97 /* Class definitions													*/
98 /************************************************************************/
99 
100 // A pickup is anything the player can pickup (i.e. weapons, ammo, powerups, etc)
101 
102 enum
103 {
104 	AIMETA_BASE = 0x71000,
105 	AIMETA_PickupMessage,		// string
106 	AIMETA_GiveQuest,			// optionally give one of the quest items.
107 	AIMETA_DropAmount,			// specifies the amount for a dropped ammo item
108 	AIMETA_LowHealth,
109 	AIMETA_LowHealthMessage,
110 	AIMETA_PuzzFailMessage,
111 };
112 
113 enum
114 {
115 	IF_ACTIVATABLE		= 1<<0,		// can be activated
116 	IF_ACTIVATED		= 1<<1,		// is currently activated
117 	IF_PICKUPGOOD		= 1<<2,		// HandlePickup wants normal pickup FX to happen
118 	IF_QUIET			= 1<<3,		// Don't give feedback when picking up
119 	IF_AUTOACTIVATE		= 1<<4,		// Automatically activate item on pickup
120 	IF_UNDROPPABLE		= 1<<5,		// Item cannot be removed unless done explicitly with RemoveInventory
121 	IF_INVBAR			= 1<<6,		// Item appears in the inventory bar
122 	IF_HUBPOWER			= 1<<7,		// Powerup is kept when moving in a hub
123 	IF_UNTOSSABLE		= 1<<8,		// The player cannot manually drop the item
124 	IF_ADDITIVETIME		= 1<<9,		// when picked up while another item is active, time is added instead of replaced.
125 	IF_ALWAYSPICKUP		= 1<<10,	// For IF_AUTOACTIVATE, MaxAmount=0 items: Always "pick up", even if it doesn't do anything
126 	IF_FANCYPICKUPSOUND	= 1<<11,	// Play pickup sound in "surround" mode
127 	IF_BIGPOWERUP		= 1<<12,	// Affected by RESPAWN_SUPER dmflag
128 	IF_KEEPDEPLETED		= 1<<13,	// Items with this flag are retained even when they run out.
129 	IF_IGNORESKILL		= 1<<14,	// Ignores any skill related multiplicators when giving this item.
130 	IF_CREATECOPYMOVED	= 1<<15,	// CreateCopy changed the owner (copy's Owner field holds new owner).
131 	IF_INITEFFECTFAILED	= 1<<16,	// CreateCopy tried to activate a powerup and activation failed (can happen with PowerMorph)
132 	IF_NOATTENPICKUPSOUND = 1<<17,	// Play pickup sound with ATTN_NONE
133 	IF_PERSISTENTPOWER	= 1<<18,	// Powerup is kept when travelling between levels
134 	IF_RESTRICTABSOLUTELY = 1<<19,	// RestrictedTo and ForbiddenTo do not allow pickup in any form by other classes
135 	IF_NEVERRESPAWN		= 1<<20,	// Never, ever respawns
136 	IF_NOSCREENFLASH	= 1<<21,	// No pickup flash on the player's screen
137 	IF_TOSSED			= 1<<22,	// Was spawned by P_DropItem (i.e. as a monster drop)
138 	IF_ALWAYSRESPAWN	= 1<<23,	// Always respawn, regardless of dmflag
139 	IF_TRANSFER			= 1<<24,	// All inventory items that the inventory item contains is also transfered to the pickuper
140 	IF_NOTELEPORTFREEZE	= 1<<25,	// does not 'freeze' the player right after teleporting.
141 };
142 
143 
144 class AInventory : public AActor
145 {
146 	DECLARE_CLASS (AInventory, AActor)
147 	HAS_OBJECT_POINTERS
148 public:
149 	virtual void Touch (AActor *toucher);
150 	virtual void Serialize (FArchive &arc);
151 
152 	virtual void MarkPrecacheSounds() const;
153 	virtual void BeginPlay ();
154 	virtual void Destroy ();
155 	virtual void DepleteOrDestroy ();
156 	virtual void Tick ();
157 	virtual bool ShouldRespawn ();
158 	virtual bool ShouldStay ();
159 	virtual void Hide ();
160 	bool CallTryPickup (AActor *toucher, AActor **toucher_return = NULL);
161 	virtual void DoPickupSpecial (AActor *toucher);
162 	virtual bool SpecialDropAction (AActor *dropper);
163 	virtual bool DrawPowerup (int x, int y);
164 	virtual void DoEffect ();
165 	virtual bool Grind(bool items);
166 
167 	virtual const char *PickupMessage ();
168 	virtual void PlayPickupSound (AActor *toucher);
169 
170 	bool DoRespawn ();
171 	AInventory *PrevItem();		// Returns the item preceding this one in the list.
172 	AInventory *PrevInv();		// Returns the previous item with IF_INVBAR set.
173 	AInventory *NextInv();		// Returns the next item with IF_INVBAR set.
174 
175 	TObjPtr<AActor> Owner;		// Who owns this item? NULL if it's still a pickup.
176 	int Amount;					// Amount of item this instance has
177 	int MaxAmount;				// Max amount of item this instance can have
178 	int InterHubAmount;			// Amount of item that can be kept between hubs or levels
179 	int RespawnTics;			// Tics from pickup time to respawn time
180 	FTextureID Icon;			// Icon to show on status bar or HUD
181 	int DropTime;				// Countdown after dropping
182 	const PClass *SpawnPointClass;	// For respawning like Heretic's mace
183 
184 	DWORD ItemFlags;
185 	const PClass *PickupFlash;	// actor to spawn as pickup flash
186 
187 	FSoundIDNoInit PickupSound;
188 
189 	virtual void BecomeItem ();
190 	virtual void BecomePickup ();
191 	virtual void AttachToOwner (AActor *other);
192 	virtual void DetachFromOwner ();
193 	virtual AInventory *CreateCopy (AActor *other);
194 	virtual AInventory *CreateTossable ();
195 	virtual bool GoAway ();
196 	virtual void GoAwayAndDie ();
197 	virtual bool HandlePickup (AInventory *item);
198 	virtual bool Use (bool pickup);
199 	virtual void Travelled ();
200 	virtual void OwnerDied ();
201 
202 	virtual void AbsorbDamage (int damage, FName damageType, int &newdamage);
203 	virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive);
204 	virtual fixed_t GetSpeedFactor();
205 	virtual bool GetNoTeleportFreeze();
206 	virtual int AlterWeaponSprite (visstyle_t *vis);
207 
208 	virtual PalEntry GetBlend ();
209 
210 protected:
211 	virtual bool TryPickup (AActor *&toucher);
212 	virtual bool TryPickupRestricted (AActor *&toucher);
213 	bool CanPickup(AActor * toucher);
214 	void GiveQuest(AActor * toucher);
215 
216 private:
217 	static int StaticLastMessageTic;
218 	static const char *StaticLastMessage;
219 };
220 
221 // CustomInventory: Supports the Use, Pickup, and Drop states from 96x
222 class ACustomInventory : public AInventory
223 {
224 	DECLARE_CLASS (ACustomInventory, AInventory)
225 public:
226 
227 	// This is used when an inventory item's use state sequence is executed.
228 	bool CallStateChain (AActor *actor, FState *state);
229 
230 	bool TryPickup (AActor *&toucher);
231 	bool Use (bool pickup);
232 	bool SpecialDropAction (AActor *dropper);
233 };
234 
235 // Ammo: Something a weapon needs to operate
236 class AAmmo : public AInventory
237 {
238 	DECLARE_CLASS (AAmmo, AInventory)
239 public:
240 	void Serialize (FArchive &arc);
241 	AInventory *CreateCopy (AActor *other);
242 	bool HandlePickup (AInventory *item);
243 	const PClass *GetParentAmmo () const;
244 	AInventory *CreateTossable ();
245 
246 	int BackpackAmount, BackpackMaxAmount;
247 };
248 
249 // A weapon is just that.
250 enum
251 {
252 	AWMETA_BASE = 0x72000,
253 	AWMETA_SlotNumber,
254 	AWMETA_SlotPriority,
255 };
256 
257 class AWeapon : public AInventory
258 {
259 	DECLARE_CLASS (AWeapon, AInventory)
260 	HAS_OBJECT_POINTERS
261 public:
262 	DWORD WeaponFlags;
263 	const PClass *AmmoType1, *AmmoType2;	// Types of ammo used by this weapon
264 	int AmmoGive1, AmmoGive2;				// Amount of each ammo to get when picking up weapon
265 	int MinAmmo1, MinAmmo2;					// Minimum ammo needed to switch to this weapon
266 	int AmmoUse1, AmmoUse2;					// How much ammo to use with each shot
267 	int Kickback;
268 	fixed_t YAdjust;						// For viewing the weapon fullscreen
269 	FSoundIDNoInit UpSound, ReadySound;		// Sounds when coming up and idle
270 	const PClass *SisterWeaponType;			// Another weapon to pick up with this one
271 	const PClass *ProjectileType;			// Projectile used by primary attack
272 	const PClass *AltProjectileType;		// Projectile used by alternate attack
273 	int SelectionOrder;						// Lower-numbered weapons get picked first
274 	int MinSelAmmo1, MinSelAmmo2;			// Ignore in BestWeapon() if inadequate ammo
275 	fixed_t MoveCombatDist;					// Used by bots, but do they *really* need it?
276 	int ReloadCounter;						// For A_CheckForReload
277 	int BobStyle;							// [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha)
278 	fixed_t BobSpeed;						// [XA] Bobbing speed. Defines how quickly a weapon bobs.
279 	fixed_t BobRangeX, BobRangeY;			// [XA] Bobbing range. Defines how far a weapon bobs in either direction.
280 
281 	// In-inventory instance variables
282 	TObjPtr<AAmmo> Ammo1, Ammo2;
283 	TObjPtr<AWeapon> SisterWeapon;
284 	float FOVScale;
285 	int Crosshair;							// 0 to use player's crosshair
286 	bool GivenAsMorphWeapon;
287 
288 	bool bAltFire;	// Set when this weapon's alternate fire is used.
289 
290 	virtual void MarkPrecacheSounds() const;
291 	virtual void Serialize (FArchive &arc);
292 	virtual bool ShouldStay ();
293 	virtual void AttachToOwner (AActor *other);
294 	virtual bool HandlePickup (AInventory *item);
295 	virtual AInventory *CreateCopy (AActor *other);
296 	virtual AInventory *CreateTossable ();
297 	virtual bool TryPickup (AActor *&toucher);
298 	virtual bool TryPickupRestricted (AActor *&toucher);
299 	virtual bool PickupForAmmo (AWeapon *ownedWeapon);
300 	virtual bool Use (bool pickup);
301 	virtual void Destroy();
302 
303 	virtual FState *GetUpState ();
304 	virtual FState *GetDownState ();
305 	virtual FState *GetReadyState ();
306 	virtual FState *GetAtkState (bool hold);
307 	virtual FState *GetAltAtkState (bool hold);
308 	virtual FState *GetStateForButtonName (FName button);
309 
310 	virtual void PostMorphWeapon ();
311 	virtual void EndPowerup ();
312 
313 	enum
314 	{
315 		PrimaryFire,
316 		AltFire,
317 		EitherFire
318 	};
319 	bool CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo=false, int ammocount = -1);
320 	bool DepleteAmmo (bool altFire, bool checkEnough=true, int ammouse = -1);
321 
322 	enum
323 	{
324 		BobNormal,
325 		BobInverse,
326 		BobAlpha,
327 		BobInverseAlpha,
328 		BobSmooth,
329 		BobInverseSmooth
330 	};
331 
332 protected:
333 	AAmmo *AddAmmo (AActor *other, const PClass *ammotype, int amount);
334 	bool AddExistingAmmo (AAmmo *ammo, int amount);
335 	AWeapon *AddWeapon (const PClass *weapon);
336 };
337 
338 enum
339 {
340 	WIF_NOAUTOFIRE =		0x00000001, // weapon does not autofire
341 	WIF_READYSNDHALF =		0x00000002, // ready sound is played ~1/2 the time
342 	WIF_DONTBOB =			0x00000004, // don't bob the weapon
343 	WIF_AXEBLOOD =			0x00000008, // weapon makes axe blood on impact (Hexen only)
344 	WIF_NOALERT =			0x00000010,	// weapon does not alert monsters
345 	WIF_AMMO_OPTIONAL =		0x00000020, // weapon can use ammo but does not require it
346 	WIF_ALT_AMMO_OPTIONAL = 0x00000040, // alternate fire can use ammo but does not require it
347 	WIF_PRIMARY_USES_BOTH =	0x00000080, // primary fire uses both ammo
348 	WIF_ALT_USES_BOTH =		0x00000100, // alternate fire uses both ammo
349 	WIF_WIMPY_WEAPON =		0x00000200, // change away when ammo for another weapon is replenished
350 	WIF_POWERED_UP =		0x00000400, // this is a tome-of-power'ed version of its sister
351 	WIF_AMMO_CHECKBOTH =	0x00000800, // check for both primary and secondary fire before switching it off
352 	WIF_NO_AUTO_SWITCH =	0x00001000,	// never switch to this weapon when it's picked up
353 	WIF_STAFF2_KICKBACK =	0x00002000, // the powered-up Heretic staff has special kickback
354 	WIF_NOAUTOAIM =			0x00004000, // this weapon never uses autoaim (useful for ballistic projectiles)
355 	WIF_MELEEWEAPON =		0x00008000,	// melee weapon. Used by bots and monster AI.
356 	WIF_DEHAMMO	=			0x00010000,	// Uses Doom's original amount of ammo for the respective attack functions so that old DEHACKED patches work as intended.
357 										// AmmoUse1 will be set to the first attack's ammo use so that checking for empty weapons still works
358 	WIF_CHEATNOTWEAPON	=	0x08000000,	// Give cheat considers this not a weapon (used by Sigil)
359 
360 	// Flags used only by bot AI:
361 
362 	WIF_BOT_REACTION_SKILL_THING = 1<<31, // I don't understand this
363 	WIF_BOT_EXPLOSIVE =		1<<30,		// weapon fires an explosive
364 	WIF_BOT_BFG =			1<<28,		// this is a BFG
365 };
366 
367 class AWeaponGiver : public AWeapon
368 {
369 	DECLARE_CLASS(AWeaponGiver, AWeapon)
370 
371 public:
372 	bool TryPickup(AActor *&toucher);
373 	void Serialize(FArchive &arc);
374 
375 	fixed_t DropAmmoFactor;
376 };
377 
378 
379 // Health is some item that gives the player health when picked up.
380 class AHealth : public AInventory
381 {
382 	DECLARE_CLASS (AHealth, AInventory)
383 
384 	int PrevHealth;
385 public:
386 	virtual bool TryPickup (AActor *&other);
387 	virtual const char *PickupMessage ();
388 };
389 
390 // HealthPickup is some item that gives the player health when used.
391 class AHealthPickup : public AInventory
392 {
393 	DECLARE_CLASS (AHealthPickup, AInventory)
394 public:
395 	int autousemode;
396 
397 	virtual void Serialize (FArchive &arc);
398 	virtual AInventory *CreateCopy (AActor *other);
399 	virtual AInventory *CreateTossable ();
400 	virtual bool HandlePickup (AInventory *item);
401 	virtual bool Use (bool pickup);
402 };
403 
404 // Armor absorbs some damage for the player.
405 class AArmor : public AInventory
406 {
407 	DECLARE_CLASS (AArmor, AInventory)
408 };
409 
410 // Basic armor absorbs a specific percent of the damage. You should
411 // never pickup a BasicArmor. Instead, you pickup a BasicArmorPickup
412 // or BasicArmorBonus and those gives you BasicArmor when it activates.
413 class ABasicArmor : public AArmor
414 {
415 	DECLARE_CLASS (ABasicArmor, AArmor)
416 public:
417 	virtual void Serialize (FArchive &arc);
418 	virtual void Tick ();
419 	virtual AInventory *CreateCopy (AActor *other);
420 	virtual bool HandlePickup (AInventory *item);
421 	virtual void AbsorbDamage (int damage, FName damageType, int &newdamage);
422 
423 	int AbsorbCount;
424 	fixed_t SavePercent;
425 	int MaxAbsorb;
426 	int MaxFullAbsorb;
427 	int BonusCount;
428 	FNameNoInit ArmorType;
429 	int ActualSaveAmount;
430 };
431 
432 // BasicArmorPickup replaces the armor you have.
433 class ABasicArmorPickup : public AArmor
434 {
435 	DECLARE_CLASS (ABasicArmorPickup, AArmor)
436 public:
437 	virtual void Serialize (FArchive &arc);
438 	virtual AInventory *CreateCopy (AActor *other);
439 	virtual bool Use (bool pickup);
440 
441 	fixed_t SavePercent;
442 	int MaxAbsorb;
443 	int MaxFullAbsorb;
444 	int SaveAmount;
445 };
446 
447 // BasicArmorBonus adds to the armor you have.
448 class ABasicArmorBonus : public AArmor
449 {
450 	DECLARE_CLASS (ABasicArmorBonus, AArmor)
451 public:
452 	virtual void Serialize (FArchive &arc);
453 	virtual AInventory *CreateCopy (AActor *other);
454 	virtual bool Use (bool pickup);
455 
456 	fixed_t SavePercent;	// The default, for when you don't already have armor
457 	int MaxSaveAmount;
458 	int MaxAbsorb;
459 	int MaxFullAbsorb;
460 	int SaveAmount;
461 	int BonusCount;
462 	int BonusMax;
463 };
464 
465 // Hexen armor consists of four separate armor types plus a conceptual armor
466 // type (the player himself) that work together as a single armor.
467 class AHexenArmor : public AArmor
468 {
469 	DECLARE_CLASS (AHexenArmor, AArmor)
470 public:
471 	virtual void Serialize (FArchive &arc);
472 	virtual AInventory *CreateCopy (AActor *other);
473 	virtual AInventory *CreateTossable ();
474 	virtual bool HandlePickup (AInventory *item);
475 	virtual void AbsorbDamage (int damage, FName damageType, int &newdamage);
476 
477 	fixed_t Slots[5];
478 	fixed_t SlotsIncrement[4];
479 
480 protected:
481 	bool AddArmorToSlot (AActor *actor, int slot, int amount);
482 };
483 
484 // PuzzleItems work in conjunction with the UsePuzzleItem special
485 class APuzzleItem : public AInventory
486 {
487 	DECLARE_CLASS (APuzzleItem, AInventory)
488 public:
489 	void Serialize (FArchive &arc);
490 	bool ShouldStay ();
491 	bool Use (bool pickup);
492 	bool HandlePickup (AInventory *item);
493 
494 	int PuzzleItemNumber;
495 };
496 
497 // A MapRevealer reveals the whole map for the player who picks it up.
498 class AMapRevealer : public AInventory
499 {
500 	DECLARE_CLASS (AMapRevealer, AInventory)
501 public:
502 	bool TryPickup (AActor *&toucher);
503 };
504 
505 // A backpack gives you one clip of each ammo and doubles your
506 // normal maximum ammo amounts.
507 class ABackpackItem : public AInventory
508 {
509 	DECLARE_CLASS (ABackpackItem, AInventory)
510 public:
511 	void Serialize (FArchive &arc);
512 	bool HandlePickup (AInventory *item);
513 	AInventory *CreateCopy (AActor *other);
514 	AInventory *CreateTossable ();
515 	void DetachFromOwner ();
516 
517 	bool bDepleted;
518 };
519 
520 
521 // A score item is picked up without being added to the inventory.
522 // It differs from FakeInventory by doing nothing more than increasing the player's score.
523 class AScoreItem : public AInventory
524 {
525 	DECLARE_CLASS (AScoreItem, AInventory)
526 
527 public:
528 	bool TryPickup(AActor *&toucher);
529 };
530 
531 
532 #endif //__A_PICKUPS_H__
533