Charged SHotgun?

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
Okgo5555
Posts: 89
Joined: Thu Mar 23, 2017 11:18 am

Charged SHotgun?

Post by Okgo5555 »

I am trying to make a shotgun that needs the user to hold primary fire to "charge" the attack and then utlilizes different fire states depending on how long the player holds the trigger down. I can get the thing to shoot, like an autoshotty, or I can get it to not shoot at all. Can someone tell me why this isn't working?

Code: Select all

ACTOR ChargeSPAS : DoomWeapon
{
  Weapon.BobStyle Alpha
  Weapon.BobRangeX .05
  Weapon.BobRangeY .85
  Weapon.BobSpeed 1.75
  Inventory.PickupMessage "You got the Charge SPAS!"
    Weapon.AmmoType "Shell"
    Weapon.AmmoGive 8
    Weapon.AmmoUse 1
    Weapon.AmmoType2 "ChargePower"
    Weapon.AmmoGive2 0
    Weapon.AmmoUse2 0
  Weapon.SlotNumber 3
  Weapon.SelectionOrder 399
  +INVENTORY.ALWAYSPICKUP
  +WEAPON.NOAUTOFIRE
  Inventory.PickupSound "weapons/get"
  AttackSound "DSQKGN"
  Scale 1.25
States
    {
    Spawn:
        SHOT A -1
        Loop
    Ready:
        SPAS A 1 A_WeaponReady
        Loop

Select:
SPAS A 1 A_Raise
Loop
Deselect:
SPAS A 1 A_Lower
Loop
    Fire:
        TNT1 A 0 A_GiveInventory("ChargePower", 1)
		SPAS A 0 A_JumpIfInventory("ChargePower", 1, "ChargedFire")
        SPAS A 2 
        SPAS A 2 
        TNT1 A 0 A_Refire
        Goto FireRelease
    
    ChargedFire:
        TNT1 A 0 A_JumpIfInventory("ChargePower", 30, "Fire30")
        TNT1 A 0 A_JumpIfInventory("ChargePower", 25, "Fire25")
        TNT1 A 0 A_JumpIfInventory("ChargePower", 20, "Fire20")
        TNT1 A 0 A_JumpIfInventory("ChargePower", 15, "Fire15")
        TNT1 A 0 A_JumpIfInventory("ChargePower", 10, "Fire10")
        TNT1 A 0 A_JumpIfInventory("ChargePower", 5, "Fire5")
    
    Fire5:
        SPSF A 2 A_PlaySound("weapons/sgfire")
        SPSF B 3 A_FireBullets(5, 5, 7, 6)
		Goto FireRelease
    Fire10:
        SPSF A 2 A_PlaySound("weapons/sgfire")
        SPSF B 3 A_FireBullets(5, 5, 7, 6)
		Goto FireRelease
    Fire15:
        SPSF A 2 A_PlaySound("weapons/sgfire")
        SPSF B 3 A_FireBullets(5, 5, 7, 6)
		Goto FireRelease
    Fire20:
        SPSF C 2 A_PlaySound("weapons/sgfire")
        SPSF D 3 A_FireBullets(5, 5, 7, 6)
		Goto FireRelease
    Fire25:
        SPSF C 2 A_PlaySound("weapons/sgfire")
        SPSF D 3 A_FireBullets(5, 5, 7, 6)
		Goto FireRelease
    Fire30:
        SPSF E 2 A_PlaySound("weapons/sgfire")
		SPSF F 3 A_FireBullets(10, 10, 17, 16)
        Goto FireRelease
    
    FireRelease:
        SPAS C 2 
        SPAS B 4
		SPAS A 1
		NULL A 0 A_TakeInventory("ChargePower", 999)
        NULL A 0 A_Refire
        Goto Ready
    }
}


ACTOR ChargePower : Ammo
{
  Inventory.MaxAmount 30
  Inventory.Amount 0
  +INVENTORY.UNDROPPABLE
}
Jarewill
 
 
Posts: 1853
Joined: Sun Jul 21, 2019 8:54 am

Re: Charged SHotgun?

Post by Jarewill »

On first glance, an error appears here:

Code: Select all

    Fire:
        TNT1 A 0 A_GiveInventory("ChargePower", 1)
		SPAS A 0 A_JumpIfInventory("ChargePower", 1, "ChargedFire") //<----
        SPAS A 2 
        SPAS A 2 
        TNT1 A 0 A_Refire
        Goto FireRelease
The Fire state starts with giving the player the token item, then in the next frame it jumps if the item has at least one.
That entire line can be removed because the player is guaranteed to have at least one item upon starting the state.
And also I would say to end the state with Goto ChargedFire instead of FireRelease.
Okgo5555
Posts: 89
Joined: Thu Mar 23, 2017 11:18 am

Re: Charged SHotgun?

Post by Okgo5555 »

ok, yes, I am aware this is a mess, but bare with me because it actually works as intended as a weapon now. There is only one problem remaining:

When the weapon is in the Hold state, the weapon sprite jumps up and down the vertical axis wildly if the player is moving and holding down the trigger simultaneously.

Code: Select all

ACTOR DooMSPAS : DoomWeapon
{
  Weapon.BobStyle Alpha
  Weapon.BobRangeX .05
  Weapon.BobRangeY .85
  Weapon.BobSpeed 1.775
  Inventory.PickupMessage "You got the Charger!"
  Weapon.AmmoType "Shell"
  Weapon.AmmoGive 8
  Weapon.AmmoUse 1
  Weapon.SlotNumber 3
  Weapon.SelectionOrder 397
  +INVENTORY.ALWAYSPICKUP
  +WEAPON.NOAUTOFIRE
  Inventory.PickupSound "weapons/get"
  AttackSound "SSG_SHOO" // Fallback sound
  Scale 1.25

  States
  {
  Ready:
    SPAS AAAAAAAAAAAA 0 A_WeaponReady
	SPAS A 1 A_WeaponReady // Bobbing happens here
    Loop

  Select:
    SPAS A 1 A_Raise
    Loop

  Deselect:
    SPAS A 1 A_Lower
    Loop

  // State entered when fire button is first pressed
  Fire:
    SPAS A 0 A_TakeInventory("ChargeCounter", 10)// Reset charge counter
    SPAS A 1 A_WeaponReady//A_TakeInventory("ChargeCounter", 10) // Use a tick here too
    Goto Hold

  // State loops while the fire button is held down
 Hold:
	SPAS A 2 A_GiveInventory("ChargeCounter", 1)
    // Check if max charge reached ONLY to play the sound cue (instant check is fine)
    TNT1 A 0 A_JumpIfInventory("ChargeCounter", 6, "FireCharged")
    // Fall through to the main hold loop
    SPAS A 1 
    SPAS A 0 A_WeaponReady//Small Delay before first A_WeaponReady
HoldLoop:
  SPAS A 1 A_WeaponReady(WRF_NOFIRE | WRF_NOSWITCH) // Keep bobbing but prevent switching/firing
  TNT1 A 0 A_JumpIfInventory("ChargeCounter", 6, "FireCharged")
  TNT1 A 0 A_Refire

  // State entered when the fire button is released (instant decision is fine)
  ReleaseFire:
    // Check if the counter reached the maximum charge
	SPSF A 1 
    TNT1 A 0 A_JumpIfInventory("ChargeCounter", 6, "FireCharged")
    // If not fully charged, jump to the normal firing sequence
    Goto FireNormal

  // Normal firing sequence (not fully charged)
  FireNormal:
    // Combine sound and flash on the first visible frame of the firing animation
	SPSF A 1 Bright A_GunFlash
    SHTG A 0 Bright A_RailAttack (15, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ARPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (10, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ARPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
	SPSF A 1 Bright 
    TNT1 A 0 A_TakeInventory("ChargeCounter", 6)
	TNT1 A 0 A_PlaySound ("SSG_SHOO", CHAN_WEAPON)
    // --- Standard Shot Pellet Pattern (these can likely remain 0-tick) ---
    SHTG A 0 Bright A_RailAttack (15, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (10, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    // --- Continue Animation ---
    SPSF B 2 Bright // Second frame of flash/firing
    SPAS C 4       // Start recovery/pump animation
    SPAS C 3
    SPAS C 4
    SPAS B 3
    SPAS B 3
    SPAS B 3 A_WeaponReady
    Goto PostFireCleanup

  // Charged firing sequence (fully charged)
  FireCharged:
    // Combine sound and *custom* flash on the first visible frame
    TNT1 A 0 A_TakeInventory("ChargeCounter", 6)
	SPSF E 3 Bright A_GunFlash("FlashCharged")
   TNT1 A 0 A_PlaySound("LIFEWARN", CHAN_BODY)
	TNT1 A 0 A_PlaySound ("SSG_SHOO", CHAN_WEAPON)
    // --- Charged Shot Pellet Pattern (Restored) ---
    SHTG A 0 Bright A_RailAttack (15, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ARPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (10, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ARPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (15, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (10, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (15, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ARPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (10, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ARPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (15, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (10, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (15, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ARPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (10, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ARPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (15, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (10, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    SHTG A 0 Bright A_RailAttack (5, 0, 0, none, "Gold" , RGF_NOPIERCING|RGF_EXPLICITANGLE|RGF_FULLBRIGHT|RGF_SILENT, 0, "ArPuff", random (-6,5),random (-4,3), 0, 8, 12, 3, none, 4)
    // --- Continue Animation ---
    SPSF F 3 Bright // Second frame of charged flash/firing
    SPAS C 4       // Start recovery/pump animation
    SPAS C 3
    SPAS C 4
    SPAS B 3
    SPAS B 3
    SPAS B 3 A_WeaponReady
    Goto PostFireCleanup

  // Common state after firing either normal or charged shot
  PostFireCleanup:
    // Resetting the counter here instantly should be fine
    SPAS B 1 A_TakeInventory("ChargeCounter", 6)
    Goto Ready // Return to ready state
  Flash:
    TNT1 A 4 // Default flash duration if state is used
    Goto LightDone

  // Custom muzzle flash state (Not strictly needed now, but good for A_GunFlash fallback)
  FlashCharged:
    TNT1 A 6 // Custom flash duration if state is used
    Goto LightDone

  Spawn:
    SHOT A -1 Bright // Assuming SHOT A is your pickup sprite
    Stop
  }
}

// Inventory item to track the charge level (no changes needed here)
ACTOR ChargeCounter : Inventory
{
  Inventory.MaxAmount 6
  Inventory.Amount 0
  +INVENTORY.UNDROPPABLE
  +INVENTORY.NOSCREENFLASH
}
Jarewill
 
 
Posts: 1853
Joined: Sun Jul 21, 2019 8:54 am

Re: Charged SHotgun?

Post by Jarewill »

A_WeaponReady is responsible for making the gun bob while frames without it will snap the gun to the default offsets.
And you are calling A_WeaponReady a lot in places where it generally shouldn't be called.
Okgo5555
Posts: 89
Joined: Thu Mar 23, 2017 11:18 am

Re: Charged SHotgun?

Post by Okgo5555 »

Ya. I figured it out. Thanks.

So, I must admit that I have a bit of a concern with preservation. I understand that DECORATE is no longer the thing, but I find it to be useful because it constrains someone like me to a framework that is more era appropriate. Like, with DECORATE, you're constrained to calling functions and actions that are predefined. With ZScript, u can essentially do anything- which is cool, bit it's not the same thing, you know? When it comes to preservation, I don't think it's constructive to just abandon the documentation. It's like if someone started burning up copues of BASIC for dummies. Haha
Post Reply

Return to “Scripting”