#pragma once #include "a_ammo.h" class PClassWeapon; class AWeapon; class FWeaponSlot { public: FWeaponSlot() { Clear(); } FWeaponSlot(const FWeaponSlot &other) { Weapons = other.Weapons; } FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; } void Clear() { Weapons.Clear(); } bool AddWeapon (const char *type); bool AddWeapon (PClassWeapon *type); void AddWeaponList (const char *list, bool clear); AWeapon *PickWeapon (player_t *player, bool checkammo = false); int Size () const { return (int)Weapons.Size(); } int LocateWeapon (PClassWeapon *type); inline PClassWeapon *GetWeapon (int index) const { if ((unsigned)index < Weapons.Size()) { return Weapons[index].Type; } else { return NULL; } } friend struct FWeaponSlots; private: struct WeaponInfo { PClassWeapon *Type; int Position; }; void SetInitialPositions(); void Sort(); TArray Weapons; }; // FWeaponSlots::AddDefaultWeapon return codes enum ESlotDef { SLOTDEF_Exists, // Weapon was already assigned a slot SLOTDEF_Added, // Weapon was successfully added SLOTDEF_Full // The specifed slot was full }; struct FWeaponSlots { FWeaponSlots() { Clear(); } FWeaponSlots(const FWeaponSlots &other); FWeaponSlot Slots[NUM_WEAPON_SLOTS]; AWeapon *PickNextWeapon (player_t *player); AWeapon *PickPrevWeapon (player_t *player); void Clear (); bool LocateWeapon (PClassWeapon *type, int *const slot, int *const index); ESlotDef AddDefaultWeapon (int slot, PClassWeapon *type); void AddExtraWeapons(); void SetFromGameInfo(); void SetFromPlayer(PClassPlayerPawn *type); void StandardSetup(PClassPlayerPawn *type); void LocalSetup(PClassActor *type); void SendDifferences(int playernum, const FWeaponSlots &other); int RestoreSlots (FConfigFile *config, const char *section); void PrintSettings(); void AddSlot(int slot, PClassWeapon *type, bool feedback); void AddSlotDefault(int slot, PClassWeapon *type, bool feedback); }; void P_PlaybackKeyConfWeapons(FWeaponSlots *slots); void Net_WriteWeapon(PClassWeapon *type); PClassWeapon *Net_ReadWeapon(BYTE **stream); void P_SetupWeapons_ntohton(); void P_WriteDemoWeaponsChunk(BYTE **demo); void P_ReadDemoWeaponsChunk(BYTE **demo); // A weapon is just that. class PClassWeapon : public PClassInventory { DECLARE_CLASS(PClassWeapon, PClassInventory); protected: virtual void DeriveData(PClass *newclass); public: PClassWeapon(); virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); void Finalize(FStateDefinitions &statedef); int SlotNumber; int SlotPriority; }; class AWeapon : public AStateProvider { DECLARE_CLASS_WITH_META(AWeapon, AStateProvider, PClassWeapon) HAS_OBJECT_POINTERS public: DWORD WeaponFlags; PClassAmmo *AmmoType1, *AmmoType2; // Types of ammo used by this weapon int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon int AmmoUse1, AmmoUse2; // How much ammo to use with each shot int Kickback; float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) FSoundIDNoInit UpSound, ReadySound; // Sounds when coming up and idle PClassWeapon *SisterWeaponType; // Another weapon to pick up with this one PClassActor *ProjectileType; // Projectile used by primary attack PClassActor *AltProjectileType; // Projectile used by alternate attack int SelectionOrder; // Lower-numbered weapons get picked first int MinSelAmmo1, MinSelAmmo2; // Ignore in BestWeapon() if inadequate ammo double MoveCombatDist; // Used by bots, but do they *really* need it? int ReloadCounter; // For A_CheckForReload int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double) float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs. float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction. // In-inventory instance variables TObjPtr Ammo1, Ammo2; TObjPtr SisterWeapon; float FOVScale; int Crosshair; // 0 to use player's crosshair bool GivenAsMorphWeapon; bool bAltFire; // Set when this weapon's alternate fire is used. virtual void MarkPrecacheSounds() const; virtual void Serialize(FSerializer &arc); virtual bool ShouldStay (); virtual void AttachToOwner (AActor *other); virtual bool HandlePickup (AInventory *item); virtual AInventory *CreateCopy (AActor *other); virtual AInventory *CreateTossable (); virtual bool TryPickup (AActor *&toucher); virtual bool TryPickupRestricted (AActor *&toucher); virtual bool PickupForAmmo (AWeapon *ownedWeapon); virtual bool Use (bool pickup); virtual void Destroy() override; FState *GetUpState (); FState *GetDownState (); FState *GetReadyState (); FState *GetAtkState (bool hold); FState *GetAltAtkState (bool hold); FState *GetStateForButtonName (FName button); virtual void PostMorphWeapon (); virtual void EndPowerup (); void CallEndPowerup(); enum { PrimaryFire, AltFire, EitherFire }; bool CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo=false, int ammocount = -1); bool DepleteAmmo (bool altFire, bool checkEnough=true, int ammouse = -1); enum { BobNormal, BobInverse, BobAlpha, BobInverseAlpha, BobSmooth, BobInverseSmooth }; protected: AAmmo *AddAmmo (AActor *other, PClassActor *ammotype, int amount); bool AddExistingAmmo (AAmmo *ammo, int amount); AWeapon *AddWeapon (PClassWeapon *weapon); }; enum { WIF_NOAUTOFIRE = 0x00000001, // weapon does not autofire WIF_READYSNDHALF = 0x00000002, // ready sound is played ~1/2 the time WIF_DONTBOB = 0x00000004, // don't bob the weapon WIF_AXEBLOOD = 0x00000008, // weapon makes axe blood on impact (Hexen only) WIF_NOALERT = 0x00000010, // weapon does not alert monsters WIF_AMMO_OPTIONAL = 0x00000020, // weapon can use ammo but does not require it WIF_ALT_AMMO_OPTIONAL = 0x00000040, // alternate fire can use ammo but does not require it WIF_PRIMARY_USES_BOTH = 0x00000080, // primary fire uses both ammo WIF_ALT_USES_BOTH = 0x00000100, // alternate fire uses both ammo WIF_WIMPY_WEAPON = 0x00000200, // change away when ammo for another weapon is replenished WIF_POWERED_UP = 0x00000400, // this is a tome-of-power'ed version of its sister WIF_AMMO_CHECKBOTH = 0x00000800, // check for both primary and secondary fire before switching it off WIF_NO_AUTO_SWITCH = 0x00001000, // never switch to this weapon when it's picked up WIF_STAFF2_KICKBACK = 0x00002000, // the powered-up Heretic staff has special kickback WIF_NOAUTOAIM = 0x00004000, // this weapon never uses autoaim (useful for ballistic projectiles) WIF_MELEEWEAPON = 0x00008000, // melee weapon. Used by bots and monster AI. WIF_DEHAMMO = 0x00010000, // Uses Doom's original amount of ammo for the respective attack functions so that old DEHACKED patches work as intended. // AmmoUse1 will be set to the first attack's ammo use so that checking for empty weapons still works WIF_NODEATHDESELECT = 0x00020000, // Don't jump to the Deselect state when the player dies WIF_NODEATHINPUT = 0x00040000, // The weapon cannot be fired/reloaded/whatever when the player is dead WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil) // Flags used only by bot AI: WIF_BOT_REACTION_SKILL_THING = 1<<31, // I don't understand this WIF_BOT_EXPLOSIVE = 1<<30, // weapon fires an explosive WIF_BOT_BFG = 1<<28, // this is a BFG }; class AWeaponGiver : public AWeapon { DECLARE_CLASS(AWeaponGiver, AWeapon) public: bool TryPickup(AActor *&toucher); void Serialize(FSerializer &arc); double DropAmmoFactor; };