[Zscript] Manual reload for akimbo pistols

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
JUSSOMONE
Posts: 41
Joined: Fri Oct 07, 2022 8:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia (Modern GZDoom)

[Zscript] Manual reload for akimbo pistols

Post by JUSSOMONE »

Good afternoon, firstly, sorry to bother you people so much with my questions but programming is not something I have a talent for and time to study, so I apologize if I being annoying these days.

Now for the problem:

I've been having headaches with this "little" thing about my mod, the manual reload for akimbo pistols, I've been trying for 2 days straight to implement it, but to no avail...It's a very tricky code with a lot of Hackyness so I apologize for it, but since gzdoom dosen't support a realistic akimbo function this was the only way of doing it, I will be really grateful for anyone capable of solving this issue for me.

Code: Select all

actor Magnum : Weapon// replaces Pistol
{
    Decal                   BulletChip
    Weapon.BobRangeX        0
    Weapon.BobStyle         Smooth
    Weapon.SlotNumber       2
    Weapon.SelectionOrder   1900
    Weapon.AmmoType		    "MagnumBullet"
    Weapon.AmmoGive		    0
    Weapon.AmmoUse		    1
    Inventory.PickupMessage "You picked up a .44 Magnum Mega Class A1!"
    Scale                   0.14
    +AMMO_OPTIONAL
    +NOALERT
    +INVENTORY.UNDROPPABLE
    Radius				    12
    Height				    12
    States
    {
      Spawn:
        PSTL A -1
        STOP

      Ready:
        TNT1 A 0 A_JumpIfInventory("SynthFireActive",1,"Ready2")
        PIST A 1 A_WeaponReady(WRF_ALLOWRELOAD) --> RELOAD MANUALLY IF ONE WISHES
        TNT1 A 0 A_JumpIfNoAmmo("SingleReload") --> OR WAITS FOR EMPTYING THE CLIP
        LOOP
		
      NothingFire:
	TNT1 A 0
	Goto Ready	

      SingleReload: --> AUTOMATIC RELOAD
        TNT1 A 0 A_JumpIfInventory("MagnumClip",1,1)
	Goto Ready
        PIST F 11 A_PlaySound("weapons/pistol/reload", 0, 1.0, 0, 1.0)
        PIST G 11
        PIST H 11
        TNT1 A 0 A_TakeInventory("MagnumBullet",8)
	TNT1 A 0 A_TakeInventory("MagnumClip",1)
	TNT1 A 0 A_GiveInventory("MagnumBullet",8)
        Goto Ready
	  
      Reload:  --> MANUAL RELOAD
	TNT1 A 0 A_JumpIfInventory("SynthFireActive",1,"ReloadSynth") --> IF DUAL WIELDED, RELOAD BOTH
	TNT1 A 0 A_JumpIfInventory("MagnumBullet",8, "Ready")
	TNT1 A 0 A_JumpIfInventory("MagnumClip",1,1)
	Goto Ready
        PIST F 11 A_PlaySound("weapons/pistol/reload", 0, 1.0, 0, 1.0)
        PIST G 11
        PIST H 11
        TNT1 A 0 A_TakeInventory("MagnumBullet",8)
	TNT1 A 0 A_TakeInventory("MagnumClip",1)
	TNT1 A 0 A_GiveInventory("MagnumBullet",8)
        Goto Ready
      
      ReloadSynth:
        TNT1 A 0 A_JumpIfInventory("MagnumBullet",8,1) --> RELOAD THE "LEFT" FIRST
	Goto LReload
	TNT1 A 0 A_JumpIfInventory("MagnumBulletRight",8,2)  --> THEN RELOAD THE "RIGHT"
	TNT1 A 0 A_GiveInventory("IsManualReload",1)  --> DUMMY, SO THE GHOST PISTOL WON'T APPEAR
	Goto ReloadRight
	TNT1 A 0 --> OTHWERWISE, FORGET AND GO TO IDLE
	Goto LIdle
	  

      Deselect:
        TNT1 A 0 A_JumpIfInventory("SynthFireActive",1,"Deselect2")
        TNT1 A 0 A_Lower
        PIST A 1 A_Lower
        LOOP

      Select:
        TNT1 A 0 A_SetCrosshair (8)
        TNT1 A 0 A_Raise
        PIST A 1 A_Raise
        LOOP
	
      Fire:
        TNT1 A 0 A_JumpIf(waterlevel == 3, "NothingFire")
	TNT1 A 0 A_JumpIfInventory("SynthFireActive",1,"LFire") --> IS DUAL-WIELDED, THEN FIRE THE "LEFT" PISTOL
        TNT1 A 0 A_JumpIfNoAmmo(13)
        TNT1 A 0 A_AlertMonsters
	TNT1 A 0 A_TakeInventory("MagnumBullet",1)
        TNT1 A 0 A_FireBullets(1.0, 1.0, -1, random(20,28), "MarathonPuff", FBF_NORANDOM)
        TNT1 A 0 A_PlaySound("weapons/pistol/fire", 0, 1.0, 0, 1.0)
        TNT1 A 0 A_FireProjectile("44mmCasingSpawner", 0, 0, 8, 0)//A_SpawnItemEx("44mmCasing", 20, 5, 35, 0, 10, 0, 0, SXF_NOCHECKPOSITION)
	TNT1 A 0 A_Recoil(0.2)
	PIST A 3 A_Light2 //Offset(0, 32)
	PIST B 3 Bright A_Light1
	PIST C 3 Bright A_Light0 
        PIST D 3 
        PIST E 4 
        TNT1 A 0 A_Refire
        Goto Ready
        PIST A 1
        Goto SingleReload

      AltFire:
        TNT1 A 0 A_JumpIfInventory("SynthFireActive",1,"RFire") --> IS DUAL-WIELDED, THEN FIRE THE "RIGHT" PISTOL
        TNT1 A 0 A_JumpIfInventory("CanDualPistols",1,1) --> IF FOUND ANOTHER PISTOL, CHECKS FOR IT THEN PLAY ANIMATION
        goto Ready
        PIS3 A 1 A_GiveInventory("SynthFireActive",1) --> THE ANIMATION AND DUMMY INVENTORY FOR DUAL-WIELD SYTNH CHECK
        PIS3 B 1 
        PIS3 C 1 
        PIS3 DEFGHIJ 1 //ABCDEFGHIJKLMNOPQ 1
        TNT1 A 0 A_GunFlash  --> HACKY WAY TO IMPLEMENT A DUMMY FUNCTIONAL SECONDARY WEAPON SPRITE ALONGSIDE THE FIRST WHILST THE FRAMES ARE BEING PLAYED
        PIS3 K 1 A_GiveInventory("SynthFireActive",1)
        goto Ready2
       
      Deselect2:
        TNT1 A 0 A_TakeInventory("SynthFireActive",1)
        TNT1 A 0 A_TakeInventory("SynthFireLeft",1)
        TNT1 A 0 A_TakeInventory("SynthFireRight",1)
        TNT1 A 0 A_TakeInventory("LeftReload",1)
        TNT1 A 0 A_TakeInventory("RightReload",1)

      DS:
        TNT1 A 0 A_Lower
        PIS1 A 1 A_Lower
        Goto DS

      Ready2:
        PIS1 A 1 A_GunFlash
        TNT1 A 0 A_GiveInventory("SynthFireActive",1)
	TNT1 A 0 ACS_NamedExecuteAlways("ActivateLeft",0,0,0,0) //act.synth-fire LEFT(pri)
	TNT1 A 0 ACS_NamedExecuteAlways("ActivateRight",0,0,0,0) //act.synth-fire RIGHT(sec)
        // Left Magnum
      LIdle:
        TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
        PIS1 A 1 A_WeaponReady(12) --> THE ONLY TRUE WEAPON CHECK
        TNT1 A 0 A_JumpIf(GetPlayerInput(INPUT_BUTTONS, AAPTR_PLAYER1) & BT_RELOAD,"Reload")
	TNT1 A 0 A_JumpIfInventory("MagnumBullet",1,1)
        Goto LReload
        TNT1 A 0 A_JumpIfInventory("SynthFireLeft",1,"LFire")
        Loop

      LInvisible:
        TNT1 A 33
        TNT1 A 0 A_TakeInventory("RightReload",1)
        Goto LIdle

      LReload:
        TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
	TNT1 A 0 A_JumpIfInventory("MagnumClip",1,1) //
	Goto LIdle
        TNT1 A 0
        TNT1 A 0 A_Light0
        TNT1 A 0 A_GiveInventory("LeftReload",1)
        PIS1 F 11 A_PlaySound("weapons/pistol/reload", 0, 1.0, 0, 1.0)
        PIS1 G 11
        PIS1 H 11
        TNT1 A 0 A_TakeInventory("MagnumBullet",8) //
        TNT1 A 0 A_TakeInventory("MagnumClip",1) //
        TNT1 A 0 A_GiveInventory("MagnumBullet",8)
        Goto LIdle
	  
      ReloadLeft:
        TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
	TNT1 A 0 A_JumpIfInventory("MagnumBullet",8, "LIdle")
	TNT1 A 0 A_JumpIfInventory("MagnumClip",1,1) //
	Goto LIdle
        TNT1 A 0
        TNT1 A 0 A_Light0
        TNT1 A 0 A_GiveInventory("LeftReload",1)
        PIS1 F 11 A_PlaySound("weapons/pistol/reload", 0, 1.0, 0, 1.0)
        PIS1 G 11
        PIS1 H 11
        TNT1 A 0 A_TakeInventory("MagnumBullet",8) //
        TNT1 A 0 A_TakeInventory("MagnumClip",1) //
        TNT1 A 0 A_GiveInventory("MagnumBullet",8)
        Goto LIdle
	  
	  //CheckRightToReload:
	    //TNT1 A 0 A_JumpIfInventory("MagnumBulletRight", 8, "LIdle")
	    //Goto ReloadRight
	    

      LFire:
        TNT1 A 0 A_JumpIf(waterlevel == 3, "NothingFire")
	TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
        TNT1 A 0 A_JumpIfInventory("MagnumBullet",1,1)
        Goto LReload//LIdle
        TNT1 A 0 A_AlertMonsters//,0,0,0,0)
        TNT1 A 0 A_TakeInventory("MagnumBullet",1)
        TNT1 A 0 A_FireBullets(1.0, 1.0, -1, random(20,28), "MarathonPuff", FBF_NORANDOM)
        TNT1 A 0 A_PlaySound("weapons/pistol/fire", 0, 1.0, 0, 1.0)
        TNT1 A 0 A_FireProjectile("44mmCasingSpawnerLeft", 0, 0, 8, 0)
        TNT1 A 0 A_Recoil(0.2)
	TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
	PIS1 A 3 A_Light2
        TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
	PIS1 B 3 Bright A_Light1
        TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
	PIS1 C 3 Bright A_Light0
        TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
        PIS1 D 3 
        TNT1 A 0 A_JumpIfInventory("RightReload",1,"LInvisible")
        PIS1 E 4 
        TNT1 A 0 A_JumpIfInventory("SynthFireLeft",1,"LFire")
        Goto LIdle

      Flash: //--> THE DUMMY USED TO SIMULATE THE SECOND WEAPON AT HAND BY SIMULTANEOUSLY WITH THE FIRST
        PIS2 A 8 --> TEMPORARILY, UNTIL THE "LEFT" IS UP AND RUNNING

      RIdle:
        TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
        PIS2 A 1 A_JumpIfInventory("IsManualReload", 1, "RInvisibleManual") --> WHEN THE PLAYER MANUALLY RELOADS THE "RIGHT" PISTOL,IT DISAPPEARS TEMPORARILY UNTIL THE RELOAD ENDS
        TNT1 A 0 A_JumpIfInventory("MagnumBulletRight",1,1)
        Goto RReload
        TNT1 A 0 A_JumpIfInventory("SynthFireRight",1,"RFire")
        Loop
      
      RInvisibleManual: --> THE STATE WHERE THE  "RIGHT" PISTOL DISAPPEARS
	TNT1 A 33
        TNT1 A 0 A_TakeInventory("IsManualReload",1)
	Goto RIdle
	  
      RInvisible:
        TNT1 A 33
        TNT1 A 0 A_TakeInventory("LeftReload",1)
        Goto RIdle

      RReload:
        TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
        TNT1 A 0 A_JumpIfInventory("MagnumClip",1,1) //
        Goto RIdle //
        TNT1 A 0 A_Light0
        TNT1 A 0 A_GiveInventory("RightReload",1)
        PIS2 F 11 A_PlaySound("weapons/pistol/reload", 0, 1.0, 0, 1.0)
        PIS2 G 11
        PIS2 H 11
        TNT1 A 0 A_TakeInventory("MagnumBulletRight",8) //
        TNT1 A 0 A_TakeInventory("MagnumClip",1) //
        TNT1 A 0 A_GiveInventory("MagnumBulletRight",8)
        Goto RIdle
	  
      ReloadRight:
        TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
	TNT1 A 0 A_JumpIfInventory("MagnumClip",1,1) //
        Goto RIdle //
        TNT1 A 0 A_Light0
        TNT1 A 0 A_GiveInventory("RightReload",1)
        PIS2 F 11 A_PlaySound("weapons/pistol/reload", 0, 1.0, 0, 1.0)
        PIS2 G 11
        PIS2 H 11
        TNT1 A 0 A_TakeInventory("MagnumBulletRight",8) //
        TNT1 A 0 A_TakeInventory("MagnumClip",1) //
        TNT1 A 0 A_GiveInventory("MagnumBulletRight",8)
	Goto RIdle

      RFire:
        TNT1 A 0 A_JumpIf(waterlevel == 3, "RIdle")
	TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
        TNT1 A 0 A_JumpIfInventory("MagnumBulletRight",1,1)
        Goto RReload//RIdle
        TNT1 A 0 A_AlertMonsters//,0,0,0,0)
        TNT1 A 0 A_TakeInventory("MagnumBulletRight",1)
        TNT1 A 0 A_FireBullets(1.0, 1.0, -1, random(20,28), "MarathonPuff", FBF_NORANDOM)
        TNT1 A 0 A_PlaySound("weapons/pistol/fire", 0, 1.0, 0, 1.0)
        TNT1 A 0 A_FireProjectile("44mmCasingSpawnerRight", 0, 0, -8, 0)
	TNT1 A 0 A_Recoil(0.2)
	TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
	PIS2 A 3 A_Light2
        TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
	PIS2 B 3 Bright A_Light1
        TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
	PIS2 C 3 Bright A_Light0
        TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
        PIS2 D 3 
        TNT1 A 0 A_JumpIfInventory("LeftReload",1,"RInvisible")
        PIS2 E 4 
        TNT1 A 0 A_JumpIfInventory("SynthFireRight",1,"RFire")
        Goto RIdle
		
    }
}

actor MagnumBullet : Ammo
{
    Inventory.MaxAmount 8
}

actor MagnumBulletRight : Ammo
{
    Inventory.MaxAmount 8
}
The ACS Code:

Code: Select all

#library "MARATHON"
#include "zcommon.acs"

// Synthetic-Fire system. Uses ACS and GetPlayerInput to 'simulate' the use of
// fire buttons. This effectively allows for true dual-wielded weapons. Nifty!

// Left (primary) weapon.
script "ActivateLeft" (void) //891
{
	while(checkinventory("SynthFireActive")>0)
	{
		if(getplayerinput(-1, INPUT_BUTTONS) & BT_ATTACK)
		{
			giveinventory("SynthFireLeft",1);
			while(getplayerinput(-1, INPUT_BUTTONS) & BT_ATTACK) 
			{ 
			      delay(1); 
			}
			takeinventory("SynthFireLeft",1);
		}
		delay(1);
	}
}

// Right (secondary) weapon.
script "ActivateRight" (void) //892
{
	while(CheckInventory("SynthFireActive")>0)
	{
		if(GetPlayerInput(-1, INPUT_BUTTONS) & BT_ALTATTACK)
		{
			GiveInventory("SynthFireRight",1);
			while(GetPlayerInput(-1, INPUT_BUTTONS) & BT_ALTATTACK) 
			{ 
			     delay(1); 
			}
			TakeInventory("SynthFireRight",1);
		}
		delay(1);
	}
}
The Dummy inventory checks:

Code: Select all

actor Boolean: Inventory //True or false checks
{
    + IGNORESKILL
    Inventory.MaxAmount 1
}

ACTOR SynthFireActive : Boolean {} // enables synthetic-fire system.
ACTOR SynthFireLeft   : Boolean {} // special refire-trackers for
ACTOR SynthFireRight  : Boolean {} // synthetic-fire dual-wielding.

ACTOR LeftReload : Boolean {}
ACTOR RightReload : Boolean {}
ACTOR IsManualReload : Boolean {}

actor CanDualPistols: Boolean {} //Check if can Akimbo
The PIST frames is when the player is with only a pistol in hand
The PIS2 frames is the left side of the screen, but working as the "right" technically in the codes
The PIS1 frames is the right side of the screen, but working as the "left" technically in the codes
The PIS3 frames is the animation for bringing up the second pistol on screen

I did some notes on the code so you can understand parts of it...The thing is, the single and "left" side works reloading manually but when I try with the second("right"), it bugs out with a ghost pistol and then the same "right" pistol transforms into two and the "left" disappears and stops working.

I've tried by giving a dummy "IsManualReloading" in the Reload State when the player wants to manually reload the "right" pistol so in the RIdle function, the ghost one would disappear temporarily by using a JumpIf function and then removing the dummy inventory...but as said before, it bugs out. I will understand if it's too much asking, especially because it's my first mod. So I don't mind waiting even if it's for a long time. Thanks anyway.

Here is the video for further analysis: https://www.youtube.com/watch?v=h7hsgELnJBQ
Post Reply

Return to “Scripting”