Need help tweaking a weapon with regenerating ammo

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

Need help tweaking a weapon with regenerating ammo

Post by Exosphere »

I currently have a sniper rifle that recharges its ammo very slowly over time, similar to the weapon from Destiny, the Ice Breaker: For those unfamiliar. I would like to change how the gun regenerates its ammo, but I am not sure how I would rewrite it.
What I would like the gun to do is to recharge its ammo only after the magazine has been fully depleted. Until the magazine is fully charged, the rifle will become unusable, and the recharge is very slow. This is how the gun is currently written.

Code: Select all

class PowerPack : Ammo
{
	Default
	{
		Inventory.MaxAmount 6;
		+INVENTORY.IGNORESKILL;
		+INVENTORY.UNDROPPABLE;
	}
}

class APR : Weapon
{
	const ammo_regen_per_tick = 1;
	protected int zoomlevel; //stores fire mode
	bool firing, depleted; 
	
	// Fire mode values: 0 = rifle, 1 = shotgun, 2 = rocket:
	enum zoomlevels
	{
		APR_Zoom1x,
		APR_Zoom7x,
		APR_Zoom12x
	}
	
	Default
	{
		Tag "APR";
		+WEAPON.AMMO_OPTIONAL
		+WEAPON.NOALERT
		Inventory.PickupSound "items/wep_pkup";
		Weapon.AmmoGive1 6;
		Weapon.AmmoUse1 1; 
		Weapon.AmmoType1 "PowerPack";
		Weapon.SlotNumber 2;
		Weapon.SlotPriority 5;
		Weapon.SelectionOrder 5;
		
		DECAL "BulletChip";
		
		+WEAPON.DONTBOB;
	}
	
	action void A_NewZoomFactor(double zoom = 1, int flgs = 0)
	{
		let plr = self.player;
		if (plr != NULL && player.ReadyWeapon != NULL)
		{
			zoom = 1 / clamp(zoom, 0.1, 100.0);
			if (flgs & 1)
			{ player.FOV = player.DesiredFOV * zoom; }
			if (flgs & 2)
			{ zoom = -zoom; }
			player.ReadyWeapon.FOVScale = zoom;
		}
	}
	
	action void A_SwitchZoom()
	{
		if (player.cmd.buttons & BT_ALTATTACK && !(player.oldbuttons & BT_ALTATTACK))
		{
			A_StartSound("weapons/zoom", CHAN_AUTO);
			invoker.zoomlevel++;
			if (invoker.zoomlevel > APR_Zoom12x)
				invoker.zoomlevel = 0;
			switch (invoker.zoomlevel)
			{
			case APR_Zoom1x:
				A_Print("Zoom: 1x"); A_NewZoomFactor(1, ZOOM_INSTANT);
				break;
			case APR_Zoom7x:
				A_Print("Zoom: 7x"); A_NewZoomFactor(7, ZOOM_INSTANT);
				break;
			case APR_Zoom12x:
				A_Print("Zoom: 12x"); A_NewZoomFactor(12, ZOOM_INSTANT);
				break;
			}
		}
	}
	
	
	States
	{
		Spawn:
			SRWM A -1;
			Loop;
			
		Deselect:
			TNT1 A 0 A_NewZoomFactor(1);
			TNT1 A 0 A_StartSound("sounds/wselect", volume: 0.8, CHAN_AUTO);
			APRV A 0 A_Lower;
			Loop;
			
		Select:
			APRV A 0 A_Raise;
			//TNT1 A 0 A_StartSound("sounds/wselect", CHAN_AUTO);
			Loop;
			
		Ready:
			APRV A 1 
			{				
				A_SwitchZoom();
				A_WeaponReady(WRF_ALLOWRELOAD);
			}
			TNT1 A 0
			{ invoker.firing = false; }
			Loop;
			
		Fire:
			TNT1 A 0
			{
				if (invoker.ammo1.amount < invoker.ammo1.maxAmount && invoker.depleted == true)
					return ResolveState("RechargeInProgress");
				invoker.depleted = false;
				A_AlertMonsters();			
				if (invoker.zoomlevel == APR_Zoom1x)
					return ResolveState("NoZoomFire");
				if (invoker.zoomlevel == APR_Zoom7x)
					return ResolveState("LowZoomFire");
				if (invoker.zoomlevel == APR_Zoom12x)
					return ResolveState("HighZoomFire");
				return ResolveState(null);
			}
			Goto Ready;
			
		FlashAPR:
			SRMF A 1 BRIGHT;
			Stop;
			
		NoZoomFire:
			APRV A 1 BRIGHT 
			{
				A_AttachLight('MuzzleFlash', DynamicLight.PointLight, "878add", 128, 0, flags: DYNAMICLIGHT.LF_ATTENUATE|DYNAMICLIGHT.LF_ATTENUATE, ofs: (32,32,player.viewheight));
				A_RailAttack(200, 0, true, "", "", flags: RGF_SILENT|RGF_FULLBRIGHT);
				A_StartSound("weapons/awp1", CHAN_AUTO, volume: 0.9);
				A_Overlay(-10, "FlashAPR");
				A_OverlayRenderstyle(-10, STYLE_Add);
			}
			TNT1 A 0 A_RemoveLight('MuzzleFlash');
			//APRV BCBA 5;
			APRV BC 3;
			APRV BAA 9;
			TNT1 A 0 A_JumpIfNoAmmo("Recharge");
			Goto Ready;
		
		LowZoomFire:
			APRV A 1 BRIGHT 
			{
				A_AttachLight('MuzzleFlash', DynamicLight.PointLight, "878add", 128, 0, flags: DYNAMICLIGHT.LF_ATTENUATE|DYNAMICLIGHT.LF_ATTENUATE, ofs: (32,32,player.viewheight));
				A_RailAttack(200, 0, true, "", "", flags: RGF_SILENT|RGF_FULLBRIGHT);
				A_StartSound("weapons/awp1", CHAN_AUTO, volume: 0.9);
				A_Overlay(-10, "FlashAPR");
				A_OverlayRenderstyle(-10, STYLE_Add);
			}
			TNT1 A 0 A_RemoveLight('MuzzleFlash');
			//APRV BCBA 5;
			APRV BC 3;
			APRV BAA 9;
			TNT1 A 0 A_JumpIfNoAmmo("Recharge");
			Goto Ready;
			
		HighZoomFire:
			APRV A 1 BRIGHT 
			{
				A_AttachLight('MuzzleFlash', DynamicLight.PointLight, "878add", 128, 0, flags: DYNAMICLIGHT.LF_ATTENUATE|DYNAMICLIGHT.LF_ATTENUATE, ofs: (32,32,player.viewheight));
				A_RailAttack(200, 0, true, "", "", flags: RGF_SILENT|RGF_FULLBRIGHT);
				A_StartSound("weapons/awp1", CHAN_AUTO, volume: 0.9);
				A_Overlay(-10, "FlashAPR");
				A_OverlayRenderstyle(-10, STYLE_Add);
			}
			TNT1 A 0 A_RemoveLight('MuzzleFlash');
			//APRV BCBA 5;
			APRV BC 3;
			APRV BAA 9;
			TNT1 A 0 A_JumpIfNoAmmo("Recharge");
			Goto Ready;
			
		Recharge:
			TNT1 A 0 
            {	
				A_Print("ENERGY DEPLETED! - WAIT FOR SHOT REGENERATION!");
				if (invoker.ammo1.amount == 0)
				{ invoker.depleted = true; }
            }
			Goto RechargeInProgress;
			
		RechargeInProgress:
			TNT1 A 0 { invoker.firing = false; }
			APRV DE 10;
			APRV FG 10;
			APRV GF 10;
			APRV EDA 10;
			TNT1 A 0 
			{ 
				A_Print("SHOT REGENERATED - READY TO FIRE.");
				A_StartSound("sounds/bell", CHAN_WEAPON);
			}
			Goto Ready;
	}
	
	override void DoEffect() 
	{
        super.DoEffect();
        if (!firing) 
		{
			if (level.time % 80 == 0) //regenerate ammo
			{ ammo1.amount = clamp(ammo1.amount + ammo_regen_per_tick, 0, ammo1.maxAmount); }
        }
    }
}
Any assistance on this is greatly appreciated.
User avatar
Virathas
Posts: 254
Joined: Thu Aug 10, 2017 9:38 am

Re: Need help tweaking a weapon with regenerating ammo

Post by Virathas »

From what i see, you nearly have all you need. Simply changing the condition to the regeneration should suffice.
Something like

Code: Select all

        if (depleted) 
	{
		if (level.time % 80 == 0) //regenerate ammo
		{ ammo1.amount = clamp(ammo1.amount + ammo_regen_per_tick, 0, ammo1.maxAmount); }
        }
Since it can only recharge when empty, you no longer need the check for "do not recharge when firing" and we can check for "the weapon was depleted"
User avatar
Exosphere
Posts: 168
Joined: Sun Jun 11, 2017 11:42 am
Location: New England, US

Re: Need help tweaking a weapon with regenerating ammo

Post by Exosphere »

Virathas wrote: Sun Oct 02, 2022 1:17 am From what i see, you nearly have all you need. Simply changing the condition to the regeneration should suffice.
Something like

Code: Select all

        if (depleted) 
	{
		if (level.time % 80 == 0) //regenerate ammo
		{ ammo1.amount = clamp(ammo1.amount + ammo_regen_per_tick, 0, ammo1.maxAmount); }
        }
Since it can only recharge when empty, you no longer need the check for "do not recharge when firing" and we can check for "the weapon was depleted"
So, good news: After I made the changes you recommended, the gun appeared to work, only recharging after the entire magazine was depleted.

Bad news: It will only allow for a full recharge only once, and then every time I fire a shot (with 5 shots still remain in the magazine), it will say the gun needs to be recharged.

I am not sure why the gun would only allow for one full recharge and then not anymore.
User avatar
Virathas
Posts: 254
Joined: Thu Aug 10, 2017 9:38 am

Re: Need help tweaking a weapon with regenerating ammo

Post by Virathas »

I wager that the "depleted" value is not reset properly. You could try adding a check in regen to set the depleted back to false like this:

Code: Select all

        if (depleted) 
	{
		if (level.time % 80 == 0) //regenerate ammo
		{ 
			ammo1.amount = clamp(ammo1.amount + ammo_regen_per_tick, 0, ammo1.maxAmount); 
			if (ammo1.amount == ammo1.maxamount)
				depleted = false;
		}
        }
Post Reply

Return to “Scripting”