Example of a Gun That Actually Reloads

Forum rules
Please don't start threads here asking for help. This forum is not for requesting guides, only for posting them. If you need help, the Editing forum is for you.

Post a reply

Smilies
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :geek: :ugeek: :!: :?: :idea: :arrow: :| :mrgreen: :3: :wub: >:( :blergh:
View more smilies

BBCode is OFF
Smilies are ON

Topic review
   

Expand view Topic review: Example of a Gun That Actually Reloads

Re: Example of a Gun That Actually Reloads

by ramon.dexter » Sun Jan 07, 2018 3:53 am

phantombeta wrote:Here's something way better for ZScript, although it shouldn't be impossible to port to DECORATE.

Code: Select all

    Reload:
        TNT1 A 0 {
            if (CheckInventory (invoker.ammoType1, 0) || !CheckInventory (invoker.ammoType2, 1))
                return ResolveState ("Ready");

            int ammoAmount = min (FindInventory (invoker.ammoType1).maxAmount - CountInv (invoker.ammoType1), CountInv (invoker.ammoType2));
            if (ammoAmount <= 0)
                return ResolveState ("Ready");

            GiveInventory (invoker.ammoType1, ammoAmount);
            TakeInventory (invoker.ammoType2, ammoAmount);

            return ResolveState ("ReloadFinish");
        }
With this you don't even need to change anything in the code for different weapons. You could even just shove it into a base weapon class and use the same code for every weapon.
This is just sweet! Thank you! :wub:

Re: Example of a Gun That Actually Reloads

by Matt » Fri Jan 05, 2018 7:42 pm

I don't think FindInventory would be available in Decorate, given neither variables nor even "invoker" are, so the counter item and manually inserting the correct ammo class names would still be required.

(but that is an excellent solution and anyone using ZScript should use that instead - I would, however, call an A_SetInventory or whatever to make sure that the FindInventory...maxAmount wouldn't crash)

Re: Example of a Gun That Actually Reloads

by phantombeta » Fri Jan 05, 2018 7:02 pm

Here's something way better for ZScript, although it shouldn't be impossible to port to DECORATE.

Code: Select all

    Reload:
        TNT1 A 0 {
            if (CheckInventory (invoker.ammoType1, 0) || !CheckInventory (invoker.ammoType2, 1))
                return ResolveState ("Ready");

            int ammoAmount = min (FindInventory (invoker.ammoType1).maxAmount - CountInv (invoker.ammoType1), CountInv (invoker.ammoType2));
            if (ammoAmount <= 0)
                return ResolveState ("Ready");

            GiveInventory (invoker.ammoType1, ammoAmount);
            TakeInventory (invoker.ammoType2, ammoAmount);

            return ResolveState ("ReloadFinish");
        }
With this you don't even need to change anything in the code for different weapons. You could even just shove it into a base weapon class and use the same code for every weapon.

Re: Example of a Gun That Actually Reloads

by Matt » Fri Jan 05, 2018 6:24 pm

If we're going to have a reloading tutorial on the first page of this forum can we update it to use countinv and min instead of those loops?

Those 45 lines could be replaced with the following 23:

Code: Select all

      Reload:
         TNT1 A 0 A_JumpIfInventory("PistolLoad", 20, "Full")
         TNT1 A 0 A_JumpIfInventory("PowerInfiniteAmmo", 1, "ReallyReload")
         TNT1 A 0 A_JumpIfInventory("Clip", 1, "ReallyReload")
         Goto NoAmmo
      ReallyReload:
         TNT1 A 35 //Reload Animation
         TNT1 A 0
         {
            //you can replace this with "int tempammocounter..." in zscript
            A_SetInventory("TempAmmoCounter",
                min(
                    20-countinv("PistolLoad"),
                    countinv("Clip")
                )
            );
            A_GiveInventory("PistolLoad", countinv("TempAmmoCounter"));
            if (!countinv("PowerInfiniteAmmo"))
            {
                A_TakeInventory("Clip", countinv("TempAmmoCounter"), TIF_NOTAKEINFINITE);
            }
         }
         Goto Ready
plus 5 lines for the following counter which could be reused for other weapons:

Code: Select all

actor TempAmmoCounter : Inventory
{
    inventory.maxamount 1000000
    //or whatever the highest number is that you need
}

Re: Example of a Gun That Actually Reloads

by FluorescentGreen5 » Sat Apr 29, 2017 12:57 am

wildweasel wrote:
FluorescentGreen5 wrote:Gunlabs' tutorial of weapon reloading demonstrates a weapon that takes from both the main ammo supply and the dummy ammo. Personally I find that a bit crude. Brutal Doom (and other big mods) has a proper reload system, where is only takes from the gun's 'internal' ammo supply and then transfers ammo from the main ammo supply to the gun's 'internal' ammo supply
With due respect, I wonder if you read the entire tutorial? While I do Duke style reloads at first, the Gunlabs code does eventually have a proper per-bullet reload system by the end of the tutorial. Unless you meant something else?
It seems I have dun goofed. But then again, the GunLabs tutorial wasn't exactly the cleanest. I will replace what I have with a refined version of their code.

Re: Example of a Gun That Actually Reloads

by wildweasel » Fri Apr 28, 2017 11:40 pm

FluorescentGreen5 wrote:Gunlabs' tutorial of weapon reloading demonstrates a weapon that takes from both the main ammo supply and the dummy ammo. Personally I find that a bit crude. Brutal Doom (and other big mods) has a proper reload system, where is only takes from the gun's 'internal' ammo supply and then transfers ammo from the main ammo supply to the gun's 'internal' ammo supply
With due respect, I wonder if you read the entire tutorial? While I do Duke style reloads at first, the Gunlabs code does eventually have a proper per-bullet reload system by the end of the tutorial. Unless you meant something else?

Example of a Gun That Actually Reloads

by FluorescentGreen5 » Fri Apr 28, 2017 11:25 pm

Gunlabs' tutorial of weapon reloading demonstrates a weapon that takes from both the main ammo supply and the dummy ammo. Personally I find that a bit crude. Brutal Doom (and other big mods) has a proper reload system, where is only takes from the gun's 'internal' ammo supply and then transfers ammo from the main ammo supply to the gun's 'internal' ammo supply. I have written my own code that does that, and even incorporated the "TIF_NOTAKEINFINITE" flag to allow infinite ammo power-ups to take effect, something that mods with reload don't usually do.

Didn't read the whole tutorial, how silly of me. Anyway, this is just a refined version of GunLab's Weapon Reload Tutorial.

I can understand why some mod makers went with the "count the shots and then inconvenience the player" method, I mean, just look at how complicated this code is:

Here's my code:

Code: Select all

Actor Pistol2 : Pistol //Note that you should use "Pistol2PickUp" for obtaining the weapon.
{
	Weapon.SlotNumber 0 //To make it easier to differentiate it from the original pistol.
	Weapon.AmmoType1 "PistolLoad"
	Weapon.AmmoGive1 20
	Weapon.AmmoUse1 1
	Weapon.AmmoType2 "Clip"
	AttackSound "weapons/pistol"
	
	+WEAPON.AMMO_OPTIONAL //Prevent the weapon from deselecting when running out of ammo, allowing the player to reload it.
	
	States
	{
		Ready:
			PISG A 1 A_WeaponReady(WRF_ALLOWRELOAD)
		Loop
		
		Fire:
			PISG A 0 A_JumpIfNoAmmo("Reload")
			PISG A 4
			PISG B 0 A_FireBullets(5.6, 0, 1, 5, "BulletPuff")
			PISG B 6 A_GunFlash
			PISG C 4
			PISG B 5 A_ReFire
		Goto Ready
		
		Reload:
			TNT1 A 0 A_JumpIfInventory("PistolLoad", 20, "Full")
			TNT1 A 0 A_JumpIfInventory("PowerInfiniteAmmo", 1, "InfiniteReload")
			TNT1 A 0 A_JumpIfInventory("PistolLoad", 1, "TopUpReload")
			TNT1 A 0 A_JumpIfInventory("Clip", 20, 1)
		Goto IncompleteReload
			TNT1 A 35 //Reload Animation
			TNT1 A 0 A_TakeInventory("Clip", 20)
			TNT1 A 0 A_GiveInventory("PistolLoad", 20)
		Goto Ready
		
		TopUpReload:
			TNT1 A 0 A_JumpIfInventory("Clip", 20, 1)
		Goto IncompleteTopUpReload
			TNT1 A 35 //Reload Animation
		UnitTopUpReload:
			TNT1 A 0 A_TakeInventory("Clip", 1)
			TNT1 A 0 A_GiveInventory("PistolLoad", 1)
			TNT1 A 0 A_JumpIfInventory("PistolLoad", 20, "Ready")
		Goto UnitTopUpReload
		
		IncompleteTopUpReload:
			TNT1 A 0 A_JumpIfInventory("Clip", 1, 1)
		Goto NoAmmo
			TNT1 A 35 //Reload Animation
		UnitIncompleteTopUpReload:
			TNT1 A 0 A_TakeInventory("Clip", 1)
			TNT1 A 0 A_GiveInventory("PistolLoad", 1)
			TNT1 A 0 A_JumpIfInventory("Clip", 1, "UnitIncompleteTopUpReload")
		Goto Ready
		
		IncompleteReload:
			TNT1 A 0 A_JumpIfInventory("Clip", 1, 1)
		Goto NoAmmo
			TNT1 A 35 //Reload Animation
		UnitIncompleteReload:
			TNT1 A 0 A_TakeInventory("Clip", 1)
			TNT1 A 0 A_GiveInventory("PistolLoad", 1)
			TNT1 A 0 A_JumpIfInventory("Clip", 1, "UnitIncompleteReload")
		Goto Ready
		
		InfiniteReload:
			TNT1 A 35 //Reload Animation
			TNT1 A 0 A_GiveInventory("PistolLoad", 20)
		Goto Ready
		
		Full:
			PISG A 1 A_Print("No need to reload.")
		Goto Ready
		
		NoAmmo:
			PISG A 1 A_Print("No Ammo")
		Goto Ready
	}
}

Actor PistolLoad : Ammo
{
	Inventory.MaxAmount 20
}

/*
The specialised pickup for "Pistol2". Will give you the gun's internal ammo when you don't have the
gun already, and will give you the main ammo when you already have the gun. Maybe I should rename
the gun to "Pistol2Weapon" and "Pistol2PickUp" to "Pistol2".
*/
Actor Pistol2PickUp : CustomInventory 
{
	Tag "Pistol"
	Inventory.PickupSound "misc/w_pkup"
	Inventory.PickupMessage "$PICKUP_PISTOL_DROPPED"
	
	+INVENTORY.AUTOACTIVATE
	
	States
	{
		Spawn:
			PIST A 1
		Loop
		
		Pickup:
			TNT1 A 0 A_JumpIfInventory("Pistol2", 1, 2) //You could use a state label instead.
			TNT1 A 0 A_GiveInventory("Pistol2")
		Stop
			TNT1 A 0 A_GiveInventory("Clip", 20)
		Stop
	}
}
This code can be simplified, but doing so will create overhead (if you're learning actual programming you'll know that it means it will requires more processing power). But if you don't care, here you go:

Code: Select all

Actor Pistol2 : Pistol //Note that you should use "Pistol2PickUp" for obtaining the weapon.
{
	Weapon.SlotNumber 0 //To make it easier to differentiate it from the original pistol.
	Weapon.AmmoType1 "PistolLoad"
	Weapon.AmmoGive1 20
	Weapon.AmmoUse1 1
	Weapon.AmmoType2 "Clip"
	AttackSound "weapons/pistol"
	
	+WEAPON.AMMO_OPTIONAL //Prevent the weapon from deselecting when running out of ammo, allowing the player to reload it.
	
	States
	{
		Ready:
			PISG A 1 A_WeaponReady(WRF_ALLOWRELOAD)
		Loop
		
		Fire:
			PISG A 0 A_JumpIfNoAmmo("Reload")
			PISG A 4
			PISG B 0 A_FireBullets(5.6, 0, 1, 5, "BulletPuff")
			PISG B 6 A_GunFlash
			PISG C 4
			PISG B 5 A_ReFire
		Goto Ready
		
		Reload:
			TNT1 A 0 A_JumpIfInventory("PistolLoad", 20, "Full")
			TNT1 A 35 //Reload Animation
		UnitReload:
			TNT1 A 0 A_JumpIfInventory("Clip", 1, 1)
		Goto Ready
			TNT1 A 0 A_JumpIfInventory("PistolLoad", 20, "Ready")
			
			TNT1 A 0 A_TakeInventory("Clip", 1, TIF_NOTAKEINFINITE)
			TNT1 A 0 A_GiveInventory("PistolLoad", 1)
		Goto UnitReload
		
		Full:
			PISG A 1 A_Print("No need to reload.")
		Goto Ready
		
		NoAmmo:
			PISG A 1 A_Print("No Ammo")
		Goto Ready
	}
}

Actor PistolLoad : Ammo
{
	Inventory.MaxAmount 20
}

/*
The specialised pickup for "Pistol2". Will give you the gun's internal ammo when you don't have the
gun already, and will give you the main ammo when you already have the gun. Maybe I should rename
the gun to "Pistol2Weapon" and "Pistol2PickUp" to "Pistol2".
*/
Actor Pistol2PickUp : CustomInventory 
{
	Tag "Pistol"
	Inventory.PickupSound "misc/w_pkup"
	Inventory.PickupMessage "$PICKUP_PISTOL_DROPPED"
	
	+INVENTORY.AUTOACTIVATE
	
	States
	{
		Spawn:
			PIST A 1
		Loop
		
		Pickup:
			TNT1 A 0 A_JumpIfInventory("Pistol2", 1, 2) //You could use a state label instead.
			TNT1 A 0 A_GiveInventory("Pistol2")
		Stop
			TNT1 A 0 A_GiveInventory("Clip", 20)
		Stop
	}
}
You will need to change a lot of things in the code to suit your needs.
Let me know if I should add anything to the tutorial.

Top