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