Classes:BackpackItem

From ZDoom Wiki
Jump to navigation Jump to search
Note: Wait! Stop! You do not need to copy this actor's code into your project! Here's why:
  1. This actor is already defined in GZDoom, there's no reason to define it again.
  2. In fact, trying to define an actor with the same name will cause an error (because it already exists).
  3. If you want to make your own version of this actor, use inheritance.
  4. Definitions for existing actors are put on the wiki for reference purpose only.
Backpack item
Actor type Internal Game MiniZDoomLogoIcon.png (ZDoom)
DoomEd Number None Class Name BackpackItem


Classes: InventoryBackpackItem
 →AmmoSatchel
 →Backpack
 →BagOfHolding

BackpackItem is the base class for all backpack-like items. This class itself is never used directly. Its only purpose is to be a base class for other items.

Upon pickup, any BackpackItem will iterate over all existing ammo classes in the player's inventory and increase their MaxAmount to their backPackMaxAmount. The backpack will also give the player some ammo—that amount is defined in every ammo class, through the Ammo.BackpackAmount property. Note, the changes to amount and maxamount are properties of the ammo classes, NOT the backpack.

Creating multiple types of backpack (for example, one that would double ammo capacity and another that would triple it) is not possible directly. Doing that would require significantly modifying the logic and modifying ammo capacity manually, through the SetAmmoCapacity function. As is, BackpackItem functions like any Inventory item: only the first instance of it you receive is picked up in your inventory; all further instances are intercepted by that first instance (using the HandlePickup virtual) and are only allowed to give you extra ammo, not modify its maxamount further.

ZScript definition

Note: The ZScript definition below is for reference and may be different in the current version of GZDoom.The most up-to-date version of this code can be found on GZDoom GitHub.
class BackpackItem : Inventory
{
	bool 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.
	//
	//===========================================================================

	override Inventory CreateCopy (Actor other)
	{
		// Find every unique type of ammoitem. Give it to the player if
		// he doesn't have it already, and double its maximum capacity.
		uint end = AllActorClasses.Size();
		for (uint i = 0; i < end; ++i)
		{
			let ammotype = (class<Ammo>)(AllActorClasses[i]);

			if (ammotype && GetDefaultByType(ammotype).GetParentAmmo() == ammotype)
			{
				let ammoitem = Ammo(other.FindInventory(ammotype));
				int amount = GetDefaultByType(ammotype).BackpackAmount;
				// extra ammo in baby mode and nightmare mode
				if (!bIgnoreSkill)
				{
					amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
				}
				if (amount < 0) amount = 0;
				if (ammoitem == NULL)
				{ // The player did not have the ammoitem. Add it.
					ammoitem = Ammo(Spawn(ammotype));
					ammoitem.Amount = bDepleted ? 0 : amount;
					if (ammoitem.BackpackMaxAmount > ammoitem.MaxAmount)
					{
						ammoitem.MaxAmount = ammoitem.BackpackMaxAmount;
					}
					if (ammoitem.Amount > ammoitem.MaxAmount)
					{
						ammoitem.Amount = ammoitem.MaxAmount;
					}
					ammoitem.AttachToOwner (other);
				}
				else
				{ // The player had the ammoitem. Give some more.
					if (ammoitem.MaxAmount < ammoitem.BackpackMaxAmount)
					{
						ammoitem.MaxAmount = ammoitem.BackpackMaxAmount;
					}
					if (!bDepleted && ammoitem.Amount < ammoitem.MaxAmount)
					{
						ammoitem.Amount += amount;
						if (ammoitem.Amount > ammoitem.MaxAmount)
						{
							ammoitem.Amount = ammoitem.MaxAmount;
						}
					}
				}
			}
		}
		return Super.CreateCopy (other);
	}

	//===========================================================================
	//
	// ABackpackItem :: HandlePickup
	//
	// When the player picks up another backpack, just give them more ammoitem.
	//
	//===========================================================================

	override bool HandlePickup (Inventory 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 is 'BackpackItem')
		{
			for (let probe = Owner.Inv; probe != NULL; probe = probe.Inv)
			{
				let ammoitem = Ammo(probe);

				if (ammoitem && ammoitem.GetParentAmmo() == ammoitem.GetClass())
				{
					if (ammoitem.Amount < ammoitem.MaxAmount || sv_unlimited_pickup)
					{
						int amount = ammoitem.Default.BackpackAmount;
						// extra ammo in baby mode and nightmare mode
						if (!bIgnoreSkill)
						{
							amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
						}
						ammoitem.Amount += amount;
						if (ammoitem.Amount > ammoitem.MaxAmount && !sv_unlimited_pickup)
						{
							ammoitem.Amount = ammoitem.MaxAmount;
						}
					}
				}
			}
			// The pickup always succeeds, even if you didn't get anything
			item.bPickupGood = true;
			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 ammoitem.
	//
	//===========================================================================

	override Inventory CreateTossable (int amount)
	{
		let pack = BackpackItem(Super.CreateTossable(-1));
		if (pack != NULL)
		{
			pack.bDepleted = true;
		}
		return pack;
	}

	//===========================================================================
	//
	// ABackpackItem :: DetachFromOwner
	//
	//===========================================================================

	override void DetachFromOwner ()
	{
		// When removing a backpack, drop the player's ammo maximums to normal

		for (let item = Owner.Inv; item != NULL; item = item.Inv)
		{
			if (item is 'Ammo' && item.MaxAmount == Ammo(item).BackpackMaxAmount)
			{
				item.MaxAmount = item.Default.MaxAmount;
				if (item.Amount > item.MaxAmount)
				{
					item.Amount = item.MaxAmount;
				}
			}
		}
	}
}

DECORATE definition

Note: This is legacy code, kept for archival purposes only. DECORATE is deprecated in GZDoom and is completely superseded by ZScript. GZDoom internally uses the ZScript definition above.
ACTOR BackpackItem : Inventory native {}