Classes:Ammo

From ZDoom Wiki
Jump to navigation Jump to search
Note: Wait! Stop! Before you copy this actor's definition into your mod, remember the following things:
  1. You do not need to copy that actor, since it is already defined.
  2. In fact, it's not just useless, it's actually harmful as it can cause problems.
  3. If you want to modify it, or use a modified version, using inheritance is the way to go.
  4. The actor definitions here are put on the wiki for reference purpose only. Learn from them, don't copy them.
  5. There is only one exception: if what you want is changing Ammo capacity, you need to create a new type from Ammo.
Ammo
Actor type Internal Game MiniZDoomLogoIcon.png (ZDoom)
DoomEd Number None Class Name Ammo


Classes: InventoryAmmo
 →BlasterAmmo
 →Cell
 →Clip
 →ClipOfBullets
 →CrossbowAmmo
 →ElectricBolts
 →EnergyPod
 →GoldWandAmmo
 →HEGrenadeRounds
 →MaceAmmo
 →Mana1
 →Mana2
 →MiniMissiles
 →PhoenixRodAmmo
 →PhosphorusGrenadeRounds
 →PoisonBolts
 →RocketAmmo
 →Shell
 →SkullRodAmmo

An Ammo item defines ammunition for use by weapons. For the most part ammo acts like a normal inventory item but there are some differences:

  • Only items that inherit directly from Ammo are separate types. All items that inherit from a subclass of Ammo define new pickup items for that ammo type.
  • The amount of ammo the player can carry can be affected by picking up a subclass of BackpackItem.
  • The amount of ammo each item gives the player can be increased for the easiest and hardest skill level in the game.
  • Ammunition is never placed in the inventory bar. Instead, it is shown in its own place on the HUD or status bar.

Using in ZScript and DECORATE

Ammo items support all the basic Inventory properties. In addition they define:

  • Ammo.BackpackAmount amount
The amount of this ammo type received from a backpack.
  • Ammo.BackpackMaxAmount amount
The maximum amount of this ammo type that can be carried with a backpack.
  • Ammo.DropAmount amount
Specifies the amount of ammo a dropped item without any explicit amount given contains. By default ammo amount is reduced by half when it's dropped by enemies, but this property can override that. Note that dropped amount can also be explicitly set in the DropItem property.

Note that ammo capacity (Inventory.MaxAmount, Ammo.BackpackAmount and Ammo.BackpackMaxAmount) are only relevant for a type derived directly from Ammo, such as Clip. Types with further derivation (such as ClipBox which is derived from Clip) use their parent class's amounts.

Creating a new custom base ammo class that isn't Ammo can be done by overriding GetParentAmmo.

Fields

  • int BackpackAmount
The value for the Ammo.BackpackAmount property.
  • int BackpackMaxAmount
The value for the Ammo.BackpackMaxAmount property.
  • meta int DropAmount
The value for the Ammo.DropAmount property.

Methods

NOTE: Ammo supports all Inventory methods.

Virtual

Examples

This defines a new ammo type:

// ZScript:
class LaserRecharge : Ammo
{
  Default
  {
    Inventory.PickupMessage "Laser recharge unit";
    Inventory.Amount 10;
    Inventory.MaxAmount 200;
    Inventory.Icon "AAMOA0";
    Ammo.BackpackAmount 10;
    Ammo.BackpackMaxAmount 400;
  }
  States
  {
  Spawn:
    ZCLP A -1;
    stop;
  }
}
// DECORATE:
actor LaserRecharge : Ammo
{
  Inventory.PickupMessage "Laser recharge unit"
  Inventory.Amount 10
  Inventory.MaxAmount 200
  Inventory.Icon "AAMOA0"
  Ammo.BackpackAmount 10
  Ammo.BackpackMaxAmount 400
  states
  {
  Spawn:
    ZCLP A -1
    stop
  }
}

This defines a second pickup item for the same ammo type:

//ZScript:
class LargeLaserRecharge : LaserRecharge
{
  Default
  {
    Inventory.PickupMessage "Large laser recharge unit";
    Inventory.Amount 50;
  }
  States
  {
  Spawn:
    AAMO A -1;
    stop;
  }
}
//DECORATE:
actor LargeLaserRecharge : LaserRecharge
{
  Inventory.PickupMessage "Large laser recharge unit"
  Inventory.Amount 50
  states
  {
  Spawn:
    AAMO A -1
    stop
  }
}

NOTE: In order to be able to place the items on the map, you will need to give your ammo items DoomEdNums.

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 Ammo : Inventory
{
	int BackpackAmount;
	int BackpackMaxAmount;
	meta int DropAmount;
	
	property BackpackAmount: BackpackAmount;
	property BackpackMaxAmount: BackpackMaxAmount;
	property DropAmount: DropAmount;

	Default
	{
		+INVENTORY.KEEPDEPLETED
		Inventory.PickupSound "misc/ammo_pkup";
	}

	//===========================================================================
	//
	// 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.
	//
	//===========================================================================

	virtual Class<Ammo> GetParentAmmo ()
	{
		class<Object> type = GetClass();

		while (type.GetParentClass() != "Ammo" && type.GetParentClass() != NULL)
		{
			type = type.GetParentClass();
		}
		return (class<Ammo>)(type);
	}

	//===========================================================================
	//
	// AAmmo :: HandlePickup
	//
	//===========================================================================

	override bool HandlePickup (Inventory item)
	{
		let ammoitem = Ammo(item);
		if (ammoitem != null && ammoitem.GetParentAmmo() == GetClass())
		{
			if (Amount < MaxAmount || sv_unlimited_pickup)
			{
				int receiving = item.Amount;

				if (!item.bIgnoreSkill)
				{ // extra ammo in baby mode and nightmare mode
					receiving = int(receiving * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
				}
				int oldamount = Amount;

				if (Amount > 0 && Amount + receiving < 0)
				{
					Amount = 0x7fffffff;
				}
				else
				{
					Amount += receiving;
				}
				if (Amount > MaxAmount && !sv_unlimited_pickup)
				{
					Amount = MaxAmount;
				}
				item.bPickupGood = true;

				// 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.

				if (oldamount == 0 && Owner != null && Owner.player != null)
				{
					PlayerPawn(Owner).CheckWeaponSwitch(GetClass());
				}
			}
			return true;
		}
		return false;
	}

	//===========================================================================
	//
	// AAmmo :: CreateCopy
	//
	//===========================================================================

	override Inventory CreateCopy (Actor other)
	{
		Inventory copy;
		int amount = Amount;

		// extra ammo in baby mode and nightmare mode
		if (!bIgnoreSkill)
		{
			amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
		}

		let type = GetParentAmmo();
		if (GetClass() != type && type != null)
		{
			if (!GoAway ())
			{
				Destroy ();
			}

			copy = Inventory(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
	//
	//===========================================================================

	override Inventory CreateTossable(int amt)
	{
		Inventory copy = Super.CreateTossable(amt);
		if (copy != null)
		{ // Do not increase ammo by dropping it and picking it back up at
		  // certain skill levels.
			copy.bIgnoreSkill = true;
		}
		return copy;
	}

	//---------------------------------------------------------------------------
	//
	// Modifies the drop amount of this item according to the current skill's
	// settings (also called by ADehackedPickup::TryPickup)
	//
	//---------------------------------------------------------------------------
	
	override void ModifyDropAmount(int dropamount)
	{
		bool ignoreskill = true;
		double dropammofactor = G_SkillPropertyFloat(SKILLP_DropAmmoFactor);
		// Default drop amount is half of regular amount * regular ammo multiplication
		if (dropammofactor == -1) 
		{
			dropammofactor = 0.5;
			ignoreskill = false;
		}

		if (dropamount > 0)
		{
			if (ignoreskill)
			{
				self.Amount = int(dropamount * dropammofactor);
				bIgnoreSkill = true;
			}
			else
			{
				self.Amount = dropamount;
			}
		}
		else
		{
			// Half ammo when dropped by bad guys.
			int amount = self.DropAmount;
			if (amount <= 0)
			{
				amount = MAX(1, int(self.Amount * dropammofactor));
			}
			self.Amount = amount;
			bIgnoreSkill = ignoreskill;
		}
	}
	
}

DECORATE definition

Note: This is legacy code, kept here for reference only. DECORATE is still supported but no longer used by GZDoom. GZDoom internally uses the ZScript definition above.
ACTOR Ammo : Inventory native
{
  +INVENTORY.KEEPDEPLETED
  Inventory.PickupSound "misc/ammo_pkup"
}

See also