[ZScript resource] Non-wasteful ammo

Sprites, textures, sounds, code, and other resources belong here. Share and share-alike!
Forum rules
Before posting your Resource, please make sure you can answer YES to any of the following questions:
  • Is the resource ENTIRELY my own work?
  • If no to the previous one, do I have permission from the original author?
  • If no to the previous one, did I put a reasonable amount of work into the resource myself, such that the changes are noticeably different from the source that I could take credit for them?
If you answered no to all three, maybe you should consider taking your stuff somewhere other than the Resources forum.

Consult the Resource/Request Posting Guidelines for more information.

Please don't put requests here! They have their own forum --> here. Thank you!
User avatar
Jekyll Grim Payne
 
 
Posts: 1080
Joined: Mon Jul 21, 2008 4:08 am
Preferred Pronouns: He/Him
Graphics Processor: nVidia (Modern GZDoom)

[ZScript resource] Non-wasteful ammo

Post by Jekyll Grim Payne »

This is a new base Ammo class that functions non-wastefully. What it means is, if you already have some ammo of a specific type in your inventory and then pick up more of it, the pickup won't be completely consumed if you can't pick it up fully. Instead, the pickup will stay in the world and only the amount you've picked up will be deducted from it.

To work, all ammo have to inherit from this class. This is a resource for custom projects, not a generic utility.

For example, if you have 98 of specific ammo (based on this class) and the maxamount is 100, when you step on a pickup that is supposed to give you 10, you'll only receive 2 ammo from it, and the pickup will stay in the world, but its amount will be reduced by 2.

There's one extra feature: in case of a partial pickup, it'll modify the pickup message so that the amount you receive is printed in parentheses next to it. For example, "Pickup up pistol ammo (2)" (if the default pickupmessage is "Picked up pistol ammo").

Code: Select all

class Ammo_Base : Ammo
{
	bool processFromWorld;

	// Let this class function as a new base Ammo class:
	override Class<Ammo> GetParentAmmo ()
	{
		class<Object> type = GetClass();

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

	override void PostBeginPlay()
	{
		processFromWorld = true;
		super.PostBeginPlay();
	}

	override bool HandlePickup (Inventory item)
	{
		if (!owner)
		{
			return Super.HandlePickup(item);
		}
		let ammoitem = Ammo_Base(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
				{
					// Check difference between amount and maxamount:
					int diff = maxamount - amount;
					// Check this item is being picked up from the world, sv_unlimited_pickup is false,
					// and that the difference between amount and maxamount is smaller than
					// the amount of ammo this pickup can give us:
					if (!sv_unlimited_pickup && ammoitem.processFromWorld && diff < ammoitem.Amount)
					{
						// If passed, we don't destroy the item, but only reduce its amount
						// and DON'T set bPickupGood, to let the pickup stick around:
						ammoitem.Amount -= diff;
						// These have to be called manually, otherwise they won't be played 
						// without bPickupGood being true:
						if (!item.bQuiet)
						{
							// sound:
							ammoitem.PlayPickupSound(owner);
							// screen flash:
							if (owner.player && !item.bNoScreenFlash && owner.player.playerstate != PST_DEAD)
							{
								owner.player.bonuscount = BONUSADD;
							}
							// Pickupmessage. We customize it slightly, so that the number
							// of received ammo is appended in parentheses after the default
							// pickupmessage:
							string msg = String.Format("%s (%d)", PickupMessage(), diff);
							ammoitem.PrintPickupMessage(owner.CheckLocalView(), msg);
						}
					}
					// Otherwise set bPickupGood to true to remove the pickup:
					else
					{
						item.bPickupGood = true;
					}
					// Finally, increment the amount as usual:
					Amount += receiving;
				}
				if (!sv_unlimited_pickup)
				{
					Amount = Clamp(Amount, 0, MaxAmount);
				}

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

Return to “Resources”