From 229c55ce61b5be24fc7d2a489017d988c711d67d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 12:24:50 +0100 Subject: [PATCH] - moved ammo to its own file, including the backpack. - moved weapon declarations to their own header. --- src/CMakeLists.txt | 1 + src/b_think.cpp | 1 + src/d_dehacked.cpp | 1 + src/d_player.h | 1 + src/fragglescript/t_func.cpp | 1 + src/g_inventory/a_ammo.cpp | 381 ++++++++++++++++++++++++++ src/g_inventory/a_ammo.h | 47 ++++ src/g_inventory/a_pickups.cpp | 343 +---------------------- src/g_inventory/a_pickups.h | 268 ------------------ src/g_inventory/a_puzzleitems.cpp | 64 ++++- src/g_inventory/a_weaponpiece.cpp | 63 +++++ src/g_inventory/a_weaponpiece.h | 1 + src/g_inventory/a_weapons.cpp | 36 +++ src/g_inventory/a_weapons.h | 230 ++++++++++++++++ src/g_shared/sbarinfo.cpp | 1 + src/g_shared/shared_hud.cpp | 1 + src/g_strife/strife_sbar.cpp | 1 + src/m_cheat.cpp | 1 + src/p_acs.cpp | 1 + src/p_enemy.cpp | 1 + src/p_mobj.cpp | 1 + src/p_user.cpp | 1 + src/scripting/thingdef_properties.cpp | 1 + 23 files changed, 836 insertions(+), 611 deletions(-) create mode 100644 src/g_inventory/a_ammo.cpp create mode 100644 src/g_inventory/a_ammo.h create mode 100644 src/g_inventory/a_weapons.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be6c0ac730..1265544963 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1107,6 +1107,7 @@ set (PCH_SOURCES w_wad.cpp wi_stuff.cpp zstrformat.cpp + g_inventory/a_ammo.cpp g_inventory/a_armor.cpp g_inventory/a_artifacts.cpp g_inventory/a_keys.cpp diff --git a/src/b_think.cpp b/src/b_think.cpp index d097db8640..7dd196622b 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -21,6 +21,7 @@ #include "d_event.h" #include "d_player.h" #include "vectors.h" +#include "a_ammo.h" static FRandom pr_botmove ("BotMove"); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 630586b0d3..62daefcaa9 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -75,6 +75,7 @@ #include "v_text.h" #include "vmbuilder.h" #include "a_armor.h" +#include "a_ammo.h" // [SO] Just the way Randy said to do it :) // [RH] Made this CVAR_SERVERINFO diff --git a/src/d_player.h b/src/d_player.h index 95a288ebdf..4cdfb8b793 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -30,6 +30,7 @@ #include "doomstat.h" #include "a_artifacts.h" +#include "a_weapons.h" // The player data structure depends on a number // of other structs: items (internal inventory), diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 7266daf40a..6b0059981e 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -69,6 +69,7 @@ #include "p_setup.h" #include "p_spec.h" #include "r_utility.h" +#include "a_ammo.h" #include "math/cmath.h" static FRandom pr_script("FScript"); diff --git a/src/g_inventory/a_ammo.cpp b/src/g_inventory/a_ammo.cpp new file mode 100644 index 0000000000..23a9221874 --- /dev/null +++ b/src/g_inventory/a_ammo.cpp @@ -0,0 +1,381 @@ +/* +** a_ammo.cpp +** Implements ammo and backpack items. +** +**--------------------------------------------------------------------------- +** Copyright 2000-2016 Randy Heit +** Copyright 2006-2016 Cheistoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "c_dispatch.h" +#include "d_player.h" +#include "serializer.h" + +IMPLEMENT_CLASS(PClassAmmo, false, false) + +PClassAmmo::PClassAmmo() +{ + DropAmount = 0; +} + +void PClassAmmo::DeriveData(PClass *newclass) +{ + assert(newclass->IsKindOf(RUNTIME_CLASS(PClassAmmo))); + Super::DeriveData(newclass); + PClassAmmo *newc = static_cast(newclass); + + newc->DropAmount = DropAmount; +} + +IMPLEMENT_CLASS(AAmmo, false, false) + +DEFINE_FIELD(AAmmo, BackpackAmount) +DEFINE_FIELD(AAmmo, BackpackMaxAmount) + +//=========================================================================== +// +// AAmmo :: Serialize +// +//=========================================================================== + +void AAmmo::Serialize(FSerializer &arc) +{ + Super::Serialize (arc); + auto def = (AAmmo*)GetDefault(); + arc("backpackamount", BackpackAmount, def->BackpackAmount) + ("backpackmaxamount", BackpackMaxAmount, def->BackpackMaxAmount); +} + +//=========================================================================== +// +// AAmmo :: GetParentAmmo +// +// Returns the least-derived ammo type that this ammo is a descendant of. +// That is, if this ammo is an immediate subclass of Ammo, then this ammo's +// type is returned. If this ammo's superclass is not Ammo, then this +// function travels up the inheritance chain until it finds a type that is +// an immediate subclass of Ammo and returns that. +// +// The intent of this is that all unique ammo types will be immediate +// subclasses of Ammo. To make different pickups with different ammo amounts, +// you subclass the type of ammo you want a different amount for and edit +// that. +// +//=========================================================================== + +PClassActor *AAmmo::GetParentAmmo () const +{ + PClass *type = GetClass(); + + while (type->ParentClass != RUNTIME_CLASS(AAmmo) && type->ParentClass != NULL) + { + type = type->ParentClass; + } + return static_cast(type); +} + +//=========================================================================== +// +// AAmmo :: HandlePickup +// +//=========================================================================== +EXTERN_CVAR(Bool, sv_unlimited_pickup) + +bool AAmmo::HandlePickup (AInventory *item) +{ + if (GetClass() == item->GetClass() || + (item->IsKindOf (RUNTIME_CLASS(AAmmo)) && static_cast(item)->GetParentAmmo() == GetClass())) + { + if (Amount < MaxAmount || sv_unlimited_pickup) + { + int receiving = item->Amount; + + if (!(item->ItemFlags & IF_IGNORESKILL)) + { // extra ammo in baby mode and nightmare mode + receiving = int(receiving * G_SkillProperty(SKILLP_AmmoFactor)); + } + int oldamount = Amount; + + if (Amount > 0 && Amount + receiving < 0) + { + Amount = 0x7fffffff; + } + else + { + Amount += receiving; + } + if (Amount > MaxAmount && !sv_unlimited_pickup) + { + Amount = MaxAmount; + } + item->ItemFlags |= IF_PICKUPGOOD; + + // If the player previously had this ammo but ran out, possibly switch + // to a weapon that uses it, but only if the player doesn't already + // have a weapon pending. + + assert (Owner != NULL); + + if (oldamount == 0 && Owner != NULL && Owner->player != NULL) + { + barrier_cast(Owner)->CheckWeaponSwitch(GetClass()); + } + } + return true; + } + return false; +} + +//=========================================================================== +// +// AAmmo :: CreateCopy +// +//=========================================================================== + +AInventory *AAmmo::CreateCopy (AActor *other) +{ + AInventory *copy; + int amount = Amount; + + // extra ammo in baby mode and nightmare mode + if (!(ItemFlags&IF_IGNORESKILL)) + { + amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); + } + + if (GetClass()->ParentClass != RUNTIME_CLASS(AAmmo) && GetClass() != RUNTIME_CLASS(AAmmo)) + { + PClassActor *type = GetParentAmmo(); + if (!GoAway ()) + { + Destroy (); + } + + copy = static_cast(Spawn (type)); + copy->Amount = amount; + copy->BecomeItem (); + } + else + { + copy = Super::CreateCopy (other); + copy->Amount = amount; + } + if (copy->Amount > copy->MaxAmount) + { // Don't pick up more ammo than you're supposed to be able to carry. + copy->Amount = copy->MaxAmount; + } + return copy; +} + +//=========================================================================== +// +// AAmmo :: CreateTossable +// +//=========================================================================== + +AInventory *AAmmo::CreateTossable() +{ + AInventory *copy = Super::CreateTossable(); + if (copy != NULL) + { // Do not increase ammo by dropping it and picking it back up at + // certain skill levels. + copy->ItemFlags |= IF_IGNORESKILL; + } + return copy; +} + + +// Backpack ----------------------------------------------------------------- + +IMPLEMENT_CLASS(ABackpackItem, false, false) + +DEFINE_FIELD(ABackpackItem, bDepleted) + +//=========================================================================== +// +// ABackpackItem :: Serialize +// +//=========================================================================== + +void ABackpackItem::Serialize(FSerializer &arc) +{ + Super::Serialize (arc); + auto def = (ABackpackItem*)GetDefault(); + arc("bdepleted", bDepleted, def->bDepleted); +} + +//=========================================================================== +// +// ABackpackItem :: CreateCopy +// +// A backpack is being added to a player who doesn't yet have one. Give them +// every kind of ammo, and increase their max amounts. +// +//=========================================================================== + +AInventory *ABackpackItem::CreateCopy (AActor *other) +{ + // Find every unique type of ammo. Give it to the player if + // he doesn't have it already, and double its maximum capacity. + for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) + { + PClass *type = PClassActor::AllActorClasses[i]; + + if (type->ParentClass == RUNTIME_CLASS(AAmmo)) + { + PClassActor *atype = static_cast(type); + AAmmo *ammo = static_cast(other->FindInventory(atype)); + int amount = static_cast(GetDefaultByType(type))->BackpackAmount; + // extra ammo in baby mode and nightmare mode + if (!(ItemFlags&IF_IGNORESKILL)) + { + amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); + } + if (amount < 0) amount = 0; + if (ammo == NULL) + { // The player did not have the ammo. Add it. + ammo = static_cast(Spawn(atype)); + ammo->Amount = bDepleted ? 0 : amount; + if (ammo->BackpackMaxAmount > ammo->MaxAmount) + { + ammo->MaxAmount = ammo->BackpackMaxAmount; + } + if (ammo->Amount > ammo->MaxAmount) + { + ammo->Amount = ammo->MaxAmount; + } + ammo->AttachToOwner (other); + } + else + { // The player had the ammo. Give some more. + if (ammo->MaxAmount < ammo->BackpackMaxAmount) + { + ammo->MaxAmount = ammo->BackpackMaxAmount; + } + if (!bDepleted && ammo->Amount < ammo->MaxAmount) + { + ammo->Amount += amount; + if (ammo->Amount > ammo->MaxAmount) + { + ammo->Amount = ammo->MaxAmount; + } + } + } + } + } + return Super::CreateCopy (other); +} + +//=========================================================================== +// +// ABackpackItem :: HandlePickup +// +// When the player picks up another backpack, just give them more ammo. +// +//=========================================================================== + +bool ABackpackItem::HandlePickup (AInventory *item) +{ + // Since you already have a backpack, that means you already have every + // kind of ammo in your inventory, so we don't need to look at the + // entire PClass list to discover what kinds of ammo exist, and we don't + // have to alter the MaxAmount either. + if (item->IsKindOf (RUNTIME_CLASS(ABackpackItem))) + { + for (AInventory *probe = Owner->Inventory; probe != NULL; probe = probe->Inventory) + { + if (probe->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo)) + { + if (probe->Amount < probe->MaxAmount || sv_unlimited_pickup) + { + int amount = static_cast(probe->GetDefault())->BackpackAmount; + // extra ammo in baby mode and nightmare mode + if (!(item->ItemFlags&IF_IGNORESKILL)) + { + amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); + } + probe->Amount += amount; + if (probe->Amount > probe->MaxAmount && !sv_unlimited_pickup) + { + probe->Amount = probe->MaxAmount; + } + } + } + } + // The pickup always succeeds, even if you didn't get anything + item->ItemFlags |= IF_PICKUPGOOD; + return true; + } + return false; +} + +//=========================================================================== +// +// ABackpackItem :: CreateTossable +// +// The tossed backpack must not give out any more ammo, otherwise a player +// could cheat by dropping their backpack and picking it up for more ammo. +// +//=========================================================================== + +AInventory *ABackpackItem::CreateTossable () +{ + ABackpackItem *pack = static_cast(Super::CreateTossable()); + if (pack != NULL) + { + pack->bDepleted = true; + } + return pack; +} + +//=========================================================================== +// +// ABackpackItem :: DetachFromOwner +// +//=========================================================================== + +void ABackpackItem::DetachFromOwner () +{ + // When removing a backpack, drop the player's ammo maximums to normal + AInventory *item; + + for (item = Owner->Inventory; item != NULL; item = item->Inventory) + { + if (item->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo) && + item->MaxAmount == static_cast(item)->BackpackMaxAmount) + { + item->MaxAmount = static_cast(item->GetDefault())->MaxAmount; + if (item->Amount > item->MaxAmount) + { + item->Amount = item->MaxAmount; + } + } + } +} + diff --git a/src/g_inventory/a_ammo.h b/src/g_inventory/a_ammo.h new file mode 100644 index 0000000000..fe5e1759e8 --- /dev/null +++ b/src/g_inventory/a_ammo.h @@ -0,0 +1,47 @@ +#pragma once +#include "a_pickups.h" + +// Ammo: Something a weapon needs to operate +class PClassAmmo : public PClassInventory +{ + DECLARE_CLASS(PClassAmmo, PClassInventory) +protected: + virtual void DeriveData(PClass *newclass); +public: + PClassAmmo(); + + int DropAmount; // Specifies the amount for a dropped ammo item. +}; + +class AAmmo : public AInventory +{ + DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo) +public: + + void Serialize(FSerializer &arc); + AInventory *CreateCopy (AActor *other); + bool HandlePickup (AInventory *item); + PClassActor *GetParentAmmo () const; + AInventory *CreateTossable (); + + int BackpackAmount, BackpackMaxAmount; +}; + + +// A backpack gives you one clip of each ammo and doubles your +// normal maximum ammo amounts. +class ABackpackItem : public AInventory +{ + DECLARE_CLASS (ABackpackItem, AInventory) +public: + + void Serialize(FSerializer &arc); + bool HandlePickup (AInventory *item); + AInventory *CreateCopy (AActor *other); + AInventory *CreateTossable (); + void DetachFromOwner (); + + bool bDepleted; +}; + + diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index ad843667a5..84b8b366fe 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -20,8 +20,10 @@ #include "p_spec.h" #include "serializer.h" #include "virtual.h" +#include "a_ammo.h" static FRandom pr_restore ("RestorePos"); +EXTERN_CVAR(Bool, sv_unlimited_pickup) IMPLEMENT_CLASS(PClassInventory, false, false) @@ -70,179 +72,6 @@ void PClassInventory::Finalize(FStateDefinitions &statedef) ((AActor*)Defaults)->flags |= MF_SPECIAL; } -IMPLEMENT_CLASS(PClassAmmo, false, false) - -PClassAmmo::PClassAmmo() -{ - DropAmount = 0; -} - -void PClassAmmo::DeriveData(PClass *newclass) -{ - assert(newclass->IsKindOf(RUNTIME_CLASS(PClassAmmo))); - Super::DeriveData(newclass); - PClassAmmo *newc = static_cast(newclass); - - newc->DropAmount = DropAmount; -} - -IMPLEMENT_CLASS(AAmmo, false, false) - -DEFINE_FIELD(AAmmo, BackpackAmount) -DEFINE_FIELD(AAmmo, BackpackMaxAmount) - -//=========================================================================== -// -// AAmmo :: Serialize -// -//=========================================================================== - -void AAmmo::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - auto def = (AAmmo*)GetDefault(); - arc("backpackamount", BackpackAmount, def->BackpackAmount) - ("backpackmaxamount", BackpackMaxAmount, def->BackpackMaxAmount); -} - -//=========================================================================== -// -// AAmmo :: GetParentAmmo -// -// Returns the least-derived ammo type that this ammo is a descendant of. -// That is, if this ammo is an immediate subclass of Ammo, then this ammo's -// type is returned. If this ammo's superclass is not Ammo, then this -// function travels up the inheritance chain until it finds a type that is -// an immediate subclass of Ammo and returns that. -// -// The intent of this is that all unique ammo types will be immediate -// subclasses of Ammo. To make different pickups with different ammo amounts, -// you subclass the type of ammo you want a different amount for and edit -// that. -// -//=========================================================================== - -PClassActor *AAmmo::GetParentAmmo () const -{ - PClass *type = GetClass(); - - while (type->ParentClass != RUNTIME_CLASS(AAmmo) && type->ParentClass != NULL) - { - type = type->ParentClass; - } - return static_cast(type); -} - -//=========================================================================== -// -// AAmmo :: HandlePickup -// -//=========================================================================== -EXTERN_CVAR(Bool, sv_unlimited_pickup) - -bool AAmmo::HandlePickup (AInventory *item) -{ - if (GetClass() == item->GetClass() || - (item->IsKindOf (RUNTIME_CLASS(AAmmo)) && static_cast(item)->GetParentAmmo() == GetClass())) - { - if (Amount < MaxAmount || sv_unlimited_pickup) - { - int receiving = item->Amount; - - if (!(item->ItemFlags & IF_IGNORESKILL)) - { // extra ammo in baby mode and nightmare mode - receiving = int(receiving * G_SkillProperty(SKILLP_AmmoFactor)); - } - int oldamount = Amount; - - if (Amount > 0 && Amount + receiving < 0) - { - Amount = 0x7fffffff; - } - else - { - Amount += receiving; - } - if (Amount > MaxAmount && !sv_unlimited_pickup) - { - Amount = MaxAmount; - } - item->ItemFlags |= IF_PICKUPGOOD; - - // If the player previously had this ammo but ran out, possibly switch - // to a weapon that uses it, but only if the player doesn't already - // have a weapon pending. - - assert (Owner != NULL); - - if (oldamount == 0 && Owner != NULL && Owner->player != NULL) - { - barrier_cast(Owner)->CheckWeaponSwitch(GetClass()); - } - } - return true; - } - return false; -} - -//=========================================================================== -// -// AAmmo :: CreateCopy -// -//=========================================================================== - -AInventory *AAmmo::CreateCopy (AActor *other) -{ - AInventory *copy; - int amount = Amount; - - // extra ammo in baby mode and nightmare mode - if (!(ItemFlags&IF_IGNORESKILL)) - { - amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); - } - - if (GetClass()->ParentClass != RUNTIME_CLASS(AAmmo) && GetClass() != RUNTIME_CLASS(AAmmo)) - { - PClassActor *type = GetParentAmmo(); - if (!GoAway ()) - { - Destroy (); - } - - copy = static_cast(Spawn (type)); - copy->Amount = amount; - copy->BecomeItem (); - } - else - { - copy = Super::CreateCopy (other); - copy->Amount = amount; - } - if (copy->Amount > copy->MaxAmount) - { // Don't pick up more ammo than you're supposed to be able to carry. - copy->Amount = copy->MaxAmount; - } - return copy; -} - -//=========================================================================== -// -// AAmmo :: CreateTossable -// -//=========================================================================== - -AInventory *AAmmo::CreateTossable() -{ - AInventory *copy = Super::CreateTossable(); - if (copy != NULL) - { // Do not increase ammo by dropping it and picking it back up at - // certain skill levels. - copy->ItemFlags |= IF_IGNORESKILL; - } - return copy; -} - //--------------------------------------------------------------------------- // // FUNC P_GiveBody @@ -2068,174 +1897,6 @@ void AHealthPickup::Serialize(FSerializer &arc) arc("autousemode", autousemode, def->autousemode); } -// Backpack ----------------------------------------------------------------- - -IMPLEMENT_CLASS(ABackpackItem, false, false) - -DEFINE_FIELD(ABackpackItem, bDepleted) - -//=========================================================================== -// -// ABackpackItem :: Serialize -// -//=========================================================================== - -void ABackpackItem::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - auto def = (ABackpackItem*)GetDefault(); - arc("bdepleted", bDepleted, def->bDepleted); -} - -//=========================================================================== -// -// ABackpackItem :: CreateCopy -// -// A backpack is being added to a player who doesn't yet have one. Give them -// every kind of ammo, and increase their max amounts. -// -//=========================================================================== - -AInventory *ABackpackItem::CreateCopy (AActor *other) -{ - // Find every unique type of ammo. Give it to the player if - // he doesn't have it already, and double its maximum capacity. - for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) - { - PClass *type = PClassActor::AllActorClasses[i]; - - if (type->ParentClass == RUNTIME_CLASS(AAmmo)) - { - PClassActor *atype = static_cast(type); - AAmmo *ammo = static_cast(other->FindInventory(atype)); - int amount = static_cast(GetDefaultByType(type))->BackpackAmount; - // extra ammo in baby mode and nightmare mode - if (!(ItemFlags&IF_IGNORESKILL)) - { - amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); - } - if (amount < 0) amount = 0; - if (ammo == NULL) - { // The player did not have the ammo. Add it. - ammo = static_cast(Spawn(atype)); - ammo->Amount = bDepleted ? 0 : amount; - if (ammo->BackpackMaxAmount > ammo->MaxAmount) - { - ammo->MaxAmount = ammo->BackpackMaxAmount; - } - if (ammo->Amount > ammo->MaxAmount) - { - ammo->Amount = ammo->MaxAmount; - } - ammo->AttachToOwner (other); - } - else - { // The player had the ammo. Give some more. - if (ammo->MaxAmount < ammo->BackpackMaxAmount) - { - ammo->MaxAmount = ammo->BackpackMaxAmount; - } - if (!bDepleted && ammo->Amount < ammo->MaxAmount) - { - ammo->Amount += amount; - if (ammo->Amount > ammo->MaxAmount) - { - ammo->Amount = ammo->MaxAmount; - } - } - } - } - } - return Super::CreateCopy (other); -} - -//=========================================================================== -// -// ABackpackItem :: HandlePickup -// -// When the player picks up another backpack, just give them more ammo. -// -//=========================================================================== - -bool ABackpackItem::HandlePickup (AInventory *item) -{ - // Since you already have a backpack, that means you already have every - // kind of ammo in your inventory, so we don't need to look at the - // entire PClass list to discover what kinds of ammo exist, and we don't - // have to alter the MaxAmount either. - if (item->IsKindOf (RUNTIME_CLASS(ABackpackItem))) - { - for (AInventory *probe = Owner->Inventory; probe != NULL; probe = probe->Inventory) - { - if (probe->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo)) - { - if (probe->Amount < probe->MaxAmount || sv_unlimited_pickup) - { - int amount = static_cast(probe->GetDefault())->BackpackAmount; - // extra ammo in baby mode and nightmare mode - if (!(item->ItemFlags&IF_IGNORESKILL)) - { - amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); - } - probe->Amount += amount; - if (probe->Amount > probe->MaxAmount && !sv_unlimited_pickup) - { - probe->Amount = probe->MaxAmount; - } - } - } - } - // The pickup always succeeds, even if you didn't get anything - item->ItemFlags |= IF_PICKUPGOOD; - return true; - } - return false; -} - -//=========================================================================== -// -// ABackpackItem :: CreateTossable -// -// The tossed backpack must not give out any more ammo, otherwise a player -// could cheat by dropping their backpack and picking it up for more ammo. -// -//=========================================================================== - -AInventory *ABackpackItem::CreateTossable () -{ - ABackpackItem *pack = static_cast(Super::CreateTossable()); - if (pack != NULL) - { - pack->bDepleted = true; - } - return pack; -} - -//=========================================================================== -// -// ABackpackItem :: DetachFromOwner -// -//=========================================================================== - -void ABackpackItem::DetachFromOwner () -{ - // When removing a backpack, drop the player's ammo maximums to normal - AInventory *item; - - for (item = Owner->Inventory; item != NULL; item = item->Inventory) - { - if (item->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo) && - item->MaxAmount == static_cast(item)->BackpackMaxAmount) - { - item->MaxAmount = static_cast(item->GetDefault())->MaxAmount; - if (item->Amount > item->MaxAmount) - { - item->Amount = item->MaxAmount; - } - } - } -} - //=========================================================================== // // ABackpack diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 56caabf3cb..00a8e6546d 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -9,92 +9,9 @@ class player_t; class FConfigFile; -class AWeapon; -class PClassWeapon; class PClassPlayerPawn; struct visstyle_t; -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); - /************************************************************************/ /* Class definitions */ /************************************************************************/ @@ -252,174 +169,6 @@ public: bool SpecialDropAction (AActor *dropper); }; -// Ammo: Something a weapon needs to operate -class PClassAmmo : public PClassInventory -{ - DECLARE_CLASS(PClassAmmo, PClassInventory) -protected: - virtual void DeriveData(PClass *newclass); -public: - PClassAmmo(); - - int DropAmount; // Specifies the amount for a dropped ammo item. -}; - -class AAmmo : public AInventory -{ - DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo) -public: - - void Serialize(FSerializer &arc); - AInventory *CreateCopy (AActor *other); - bool HandlePickup (AInventory *item); - PClassActor *GetParentAmmo () const; - AInventory *CreateTossable (); - - int BackpackAmount, BackpackMaxAmount; -}; - -// 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; -}; - - // Health is some item that gives the player health when picked up. class PClassHealth : public PClassInventory { @@ -488,23 +237,6 @@ public: bool TryPickup (AActor *&toucher); }; -// A backpack gives you one clip of each ammo and doubles your -// normal maximum ammo amounts. -class ABackpackItem : public AInventory -{ - DECLARE_CLASS (ABackpackItem, AInventory) -public: - - void Serialize(FSerializer &arc); - bool HandlePickup (AInventory *item); - AInventory *CreateCopy (AActor *other); - AInventory *CreateTossable (); - void DetachFromOwner (); - - bool bDepleted; -}; - - // A score item is picked up without being added to the inventory. // It differs from FakeInventory by doing nothing more than increasing the player's score. class AScoreItem : public AInventory diff --git a/src/g_inventory/a_puzzleitems.cpp b/src/g_inventory/a_puzzleitems.cpp index 0d63bb00c3..e2a538387d 100644 --- a/src/g_inventory/a_puzzleitems.cpp +++ b/src/g_inventory/a_puzzleitems.cpp @@ -1,3 +1,38 @@ +/* +** a_puzzleitems.cpp +** Implements Hexen's puzzle items. +** +**--------------------------------------------------------------------------- +** Copyright 2002-2016 Randy Heit +** Copyright 2006-2016 Cheistoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include "info.h" #include "a_pickups.h" #include "a_artifacts.h" @@ -8,7 +43,17 @@ #include "doomstat.h" #include "v_font.h" + IMPLEMENT_CLASS(PClassPuzzleItem, false, false) +IMPLEMENT_CLASS(APuzzleItem, false, false) + +DEFINE_FIELD(APuzzleItem, PuzzleItemNumber) + +//=========================================================================== +// +// +// +//=========================================================================== void PClassPuzzleItem::DeriveData(PClass *newclass) { @@ -17,9 +62,12 @@ void PClassPuzzleItem::DeriveData(PClass *newclass) static_cast(newclass)->PuzzFailMessage = PuzzFailMessage; } -IMPLEMENT_CLASS(APuzzleItem, false, false) -DEFINE_FIELD(APuzzleItem, PuzzleItemNumber) +//=========================================================================== +// +// +// +//=========================================================================== bool APuzzleItem::HandlePickup (AInventory *item) { @@ -31,6 +79,12 @@ bool APuzzleItem::HandlePickup (AInventory *item) return Super::HandlePickup (item); } +//=========================================================================== +// +// +// +//=========================================================================== + bool APuzzleItem::Use (bool pickup) { if (P_UsePuzzleItem (Owner, PuzzleItemNumber)) @@ -49,6 +103,12 @@ bool APuzzleItem::Use (bool pickup) return false; } +//=========================================================================== +// +// +// +//=========================================================================== + bool APuzzleItem::ShouldStay () { return !!multiplayer; diff --git a/src/g_inventory/a_weaponpiece.cpp b/src/g_inventory/a_weaponpiece.cpp index bb98415fca..b504559bd1 100644 --- a/src/g_inventory/a_weaponpiece.cpp +++ b/src/g_inventory/a_weaponpiece.cpp @@ -1,3 +1,38 @@ +/* +** a_weaponpieces.cpp +** Implements generic weapon pieces +** +**--------------------------------------------------------------------------- +** Copyright 2006-2016 Cheistoph Oelckers +** Copyright 2006-2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include "a_pickups.h" #include "a_weaponpiece.h" #include "doomstat.h" @@ -9,6 +44,12 @@ IMPLEMENT_CLASS(AWeaponHolder, false, false) DEFINE_FIELD(AWeaponHolder, PieceMask); DEFINE_FIELD(AWeaponHolder, PieceWeapon); +//=========================================================================== +// +// +// +//=========================================================================== + void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) { Super::ReplaceClassRef(oldclass, newclass); @@ -19,6 +60,11 @@ void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) } } +//=========================================================================== +// +// +// +//=========================================================================== void AWeaponHolder::Serialize(FSerializer &arc) { @@ -33,6 +79,11 @@ IMPLEMENT_POINTERS_START(AWeaponPiece) IMPLEMENT_POINTER(FullWeapon) IMPLEMENT_POINTERS_END +//=========================================================================== +// +// +// +//=========================================================================== void AWeaponPiece::Serialize(FSerializer &arc) { @@ -151,11 +202,23 @@ bool AWeaponPiece::TryPickup (AActor *&toucher) return true; } +//=========================================================================== +// +// +// +//=========================================================================== + bool AWeaponPiece::ShouldStay () { return PrivateShouldStay (); } +//=========================================================================== +// +// +// +//=========================================================================== + bool AWeaponPiece::PrivateShouldStay () { // We want a weapon piece to behave like a weapon, so follow the exact diff --git a/src/g_inventory/a_weaponpiece.h b/src/g_inventory/a_weaponpiece.h index e293637cf9..bcaa261cbd 100644 --- a/src/g_inventory/a_weaponpiece.h +++ b/src/g_inventory/a_weaponpiece.h @@ -1,5 +1,6 @@ #pragma once #include "a_pickups.h" +#include "a_weapons.h" // class PClassWeaponPiece : public PClassInventory diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 4f49ecd6f6..90a217495a 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -1,3 +1,38 @@ +/* +** a_weapons.cpp +** Implements weapon handling +** +**--------------------------------------------------------------------------- +** Copyright 2000-2016 Randy Heit +** Copyright 2006-2016 Cheistoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include #include "a_pickups.h" @@ -19,6 +54,7 @@ #include "serializer.h" #include "thingdef.h" #include "virtual.h" +#include "a_ammo.h" #define BONUSADD 6 diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h new file mode 100644 index 0000000000..786f6189b6 --- /dev/null +++ b/src/g_inventory/a_weapons.h @@ -0,0 +1,230 @@ +#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; +}; + diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index f2852919d8..8ca8d68163 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -59,6 +59,7 @@ #include "gstrings.h" #include "version.h" #include "cmdlib.h" +#include "a_ammo.h" #define ARTIFLASH_OFFSET (statusBar->invBarOffset+6) enum diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index c6e12918d5..a061dbf59a 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -44,6 +44,7 @@ #include "w_wad.h" #include "a_keys.h" #include "a_armor.h" +#include "a_ammo.h" #include "sbar.h" #include "sc_man.h" #include "templates.h" diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 3a242f80c3..973364cf7d 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -13,6 +13,7 @@ #include "templates.h" #include "a_keys.h" #include "a_armor.h" +#include "a_ammo.h" #include "gi.h" #include "g_level.h" #include "colormatcher.h" diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 6bd6b3862a..53405017ac 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -48,6 +48,7 @@ #include "r_utility.h" #include "a_morph.h" #include "a_armor.h" +#include "a_ammo.h" // [RH] Actually handle the cheat. The cheat code in st_stuff.c now just // writes some bytes to the network data stream, and the network code diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 93d0cd45b3..ba086da3ad 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -84,6 +84,7 @@ #include "thingdef.h" #include "a_pickups.h" #include "a_armor.h" +#include "a_ammo.h" extern FILE *Logfile; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 5b2ba6d655..29128c8b71 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -51,6 +51,7 @@ #include "p_spec.h" #include "p_checkposition.h" #include "math/cmath.h" +#include "a_ammo.h" #include "gi.h" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7c7d97cf2c..2d36136f34 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -70,6 +70,7 @@ #include "d_player.h" #include "virtual.h" #include "a_armor.h" +#include "a_ammo.h" // MACROS ------------------------------------------------------------------ diff --git a/src/p_user.cpp b/src/p_user.cpp index e92b560db3..11857631ab 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -60,6 +60,7 @@ #include "p_spec.h" #include "virtual.h" #include "a_armor.h" +#include "a_ammo.h" static FRandom pr_skullpop ("SkullPop"); diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index e85b6a1d9f..e87602114b 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -70,6 +70,7 @@ #include "r_data/colormaps.h" #include "a_weaponpiece.h" #include "vmbuilder.h" +#include "a_ammo.h" extern TArray OptionalClassPtrs;