##  Alternate Fire/Reload/Zoom/...States on Weapons

 Thanks to WildWeasel for teaching me a non-ACS way of doing this. I've been meaning to write this for ages, but never got around to it.

One of the more obscure tricks with weapons is the ability to add a new firing state (a state that can be activated aside from primary and alternate fire). This is usually used to have a key that specifically zooms or reloads. However, this is actually quite a simple trick.

For reference, here are three wiki pages:

- [KeyConf](http://www.zdoom.org/wiki/KEYCONF)
- [Adding Keysections](http://zdoom.org/wiki/Adding_keysections)
- [CustomInventory](http://www.zdoom.org/wiki/Classes:CustomInventory)
- [A\_JumpIfInventory](http://www.zdoom.org/wiki/A_JumpIfInventory)

 I'll put it in basic terms, then explain each part further. Essentially, you have a dummy inventory item as a flag for the weapon to check for in the Ready state, and this item is given and taken away by a pair of CustomInventory items which are bound to a key.

I'll use a third Fire state as an example. To explain further, we start with our fake inventory item; an item that literally has
no use besides A_JumpIfInventory to check for:

Actor IsFiring : Inventory
{
 Inventory.Amount 1 //This doesn't technically need to be here but it's better to make sure
 Inventory.MaxAmount 1
 -INVBAR //Keeps it from displaying in the inventory bar, but you don't have to worry
 States
 {
 Spawn:
 TNT1 A 1
 Fail //Keeps it from really doing anything in the world
 }

All this will do is sit in your inventory. Now we have an alternate pistol checking for this:

Actor Pistol2 : DoomWeapon 5010 //Named differently so it won't conflict with Doom's
 {
 Game Doom
 Weapon.SelectionOrder 1900
 Weapon.AmmoUse 1
 Weapon.AmmoGive 20
 Weapon.AmmoType "Clip"
 AttackSound "weapons/pistol"
 Obituary "$OB_MPPISTOL"
 +WEAPON.WIMPY_WEAPON
 Inventory.Pickupmessage "$PICKUP_PISTOL_DROPPED"
 Decal BulletChip
 States
 {
 Ready:
 PISG A 0 A_JumpIfInventory("IsFiring", 1, "AltAltFire") //We're checking for the fake inventory item
 PISG A 1 A_WeaponReady
 Loop
 Deselect:
 PISG A 1 A_Lower
 Loop
 Select:
 PISG A 1 A_Raise
 Loop
 Fire:
 PISG A 4
 PISG B 6 A_FirePistol
 PISG C 4
 PISG B 5 A_ReFire
 Goto Ready
 AltFire: //Because why not, we're already using altfire!
 PISG A 4
 PISG B 6 A_FirePistol
 PISG C 4
 PISG B 5 A_ReFire
 Goto Ready
 AltAltFire:
 PISG A 4
 PISG BBB 0 A_FirePistol
 PISG B 6 A_FirePistol //Fires four times so we know it's working
 PISG C 4
 PISG B 5 A_ReFire
 Goto Ready
 Flash:
 PISF A 7 Bright A_Light1
 Goto LightDone
 PISF A 7 Bright A_Light0
 Goto LightDone
 Spawn:
 PIST A -1
 Stop
 }
}

There! Our pistol is checking for that item, and has a new firing state. Now we just need those two CustomInventory items:

Actor Action_Fire : CustomInventory
{
 Inventory.Amount 1
 Inventory.MaxAmount 1
 -INVBAR
 States
 {
 Use:
 TNT1 A 0 A_GiveInventory("IsFiring", 1)
 Fail // It's important that these items end in "Fail" instead of "Stop" or else they are removed from inventory as soon as they are used. Fail will keep them in your inventory.
 }
}

Actor Action_FireCancel : CustomInventory
{
 Inventory.Amount 1
 Inventory.MaxAmount 1
 -INVBAR
 States
 {
 Use:
 TNT1 A 0 A_TakeInventory("IsFiring", 1)
 Fail
 }
}

When Action_Fire is used, it will give the fake item, but when Action_FireCancel is used, it will take it away again. Thus, using one will make the pistol fire, and the other will make it stop. **It is important that both of these are given to the player at the start with Player.StartItem, or this will not work.**

Now to bind these two items to a key:

AddKeySection "Your Section Name" YourSectionsName
AddMenuKey "Alternate AltFire" +altaltfire
Alias +altaltfire "Use Action_Fire" // + events occur when the key is pressed.
Alias -altaltfire "Use Action_FireCancel" // - events occur when the key is released.
DefaultBind x +altaltfire // only the + event needs to be bound.

Check the wiki link above about adding keysections for explanations of what these do. Now, when the key is pressed it will give the item (activating AltAltFire), and when the key is released, it will take the item away (making it stop firing).

And it's that simple! If you want to test it out, here's a full Decorate and KeyConf:

Actor Pistol2 : DoomWeapon 5010 //Named differently so it won't conflict with Doom's
 {
 Game Doom
 Weapon.SelectionOrder 1900
 Weapon.AmmoUse 1
 Weapon.AmmoGive 20
 Weapon.AmmoType "Clip"
 AttackSound "weapons/pistol"
 Obituary "$OB_MPPISTOL"
 +WEAPON.WIMPY_WEAPON
 Inventory.Pickupmessage "$PICKUP_PISTOL_DROPPED"
 Decal BulletChip
 States
 {
 Ready:
 PISG A 0 A_JumpIfInventory("IsFiring", 1, "AltAltFire") //We're checking for the fake inventory item
 PISG A 1 A_WeaponReady
 Loop
 Deselect:
 PISG A 1 A_Lower
 Loop
 Select:
 PISG A 1 A_Raise
 Loop
 Fire:
 PISG A 4
 PISG B 6 A_FirePistol
 PISG C 4
 PISG B 5 A_ReFire
 Goto Ready
 AltFire: //Because why not, we're already using altfire!
 PISG A 4
 PISG B 6 A_FirePistol
 PISG C 4
 PISG B 5 A_ReFire
 Goto Ready
 AltAltFire:
 PISG A 4
 PISG BBB 0 A_FirePistol
 PISG B 6 A_FirePistol //Fires four times so we know it's working
 PISG C 4
 PISG B 5 A_ReFire
 Goto Ready
 Flash:
 PISF A 7 Bright A_Light1
 Goto LightDone
 PISF A 7 Bright A_Light0
 Goto LightDone
 Spawn:
 PIST A -1
 Stop
 }
}

Actor IsFiring : Inventory
{
 Inventory.Amount 1 //This doesn't technically need to be here but it's better to make sure
 Inventory.MaxAmount 1
 -INVBAR //Keeps it from displaying in the inventory bar, but you don't have to worry
 States
 {
 Spawn:
 TNT1 A 1
 Fail //Keeps it from really doing anything in the world
 }
}

Actor Action_Fire : CustomInventory
{
 Inventory.Amount 1
 Inventory.MaxAmount 1
 -INVBAR
 States
 {
 Use:
 TNT1 A 0 A_GiveInventory("IsFiring", 1)
 Fail // It's important that these items end in "Fail" instead of "Stop" or else they are removed from inventory as soon as they are used. Fail will keep them in your inventory.
 }
}

Actor Action_FireCancel : CustomInventory
{
 Inventory.Amount 1
 Inventory.MaxAmount 1
 -INVBAR
 States
 {
 Use:
 TNT1 A 0 A_TakeInventory("IsFiring", 1)
 Fail
 }
}

Actor DoomPlayer2 : DoomPlayer
{
 Player.StartItem "Pistol2", 1
 Player.StartItem "Clip", 50
 Player.StartItem "Fist"
 Player.StartItem "Action_Fire", 1
 Player.StartItem "Action_FireCancel", 1
}

KeyConf:

ClearPlayerClasses
AddPlayerClass DoomPlayer2

AddKeySection "Your Section Name" YourSectionsName
AddMenuKey "Alternate AltFire" +altaltfire
Alias +altaltfire "Use Action_Fire" // + events occur when the key is pressed.
Alias -altaltfire "Use Action_FireCancel" // - events occur when the key is released.
DefaultBind x +altaltfire // only the + event needs to be bound.

Keep in mind, by the way, Fire and AltFire have some special behavior that alerts monsters, and A_Refire only works for Fire/Hold and AltFire/AltHold. Here's another AltAltFire that emulates that behavior:

AltAltFire:
 PISG A 4 A_AlertMonsters //Because it alerts monsters as soon as the state is entered.
 PISG BBB 0 A_FirePistol
 PISG B 6 A_FirePistol //Fires four times so we know it's working
 PISG C 4
 PISG B 5 A_JumpIfInventory("IsFiring", 1, "AltAltFire") //Fire again if the button is still pressed, like A_Refire.
 Goto Ready
<div data-id="7" 
	class="eb-inst eb-hide eb-custom eb-7 "
	data-options='{"trigger":"onPageLoad","trigger_selector":"","delay":0,"early_trigger":false,"scroll_depth":"percentage","scroll_depth_value":80,"firing_frequency":1,"reverse_scroll_close":false,"threshold":0,"close_out_viewport":false,"exit_timer":1000,"idle_time":10000,"close_on_esc":false,"animation_open":"fadeInUp","animation_close":"fadeOut","animation_duration":300,"disable_page_scroll":false,"test_mode":false,"debug":false,"ga_tracking":false,"ga_tracking_id":0,"ga_tracking_event_category":"EngageBox","ga_tracking_event_label":"Box #7 - Realm667 | Relaunch Beta Phase","auto_focus":false}'
	data-type='popup'
	>

	<button type="button" data-ebox-cmd="close" class="eb-close placement-outside" aria-label="Close">
	<img alt="close popup button" />
	<span aria-hidden="true">&times;</span>
</button>
	<div class="eb-dialog " role="dialog" aria-modal="true" id="dialog7" aria-label="dialog7">
		
		<button type="button" data-ebox-cmd="close" class="eb-close placement-inside" aria-label="Close">
	<img alt="close popup button" />
	<span aria-hidden="true">&times;</span>
</button>	
		<div class="eb-container">
						<div class="eb-content">
				<h3>Welcome Back</h3>
<p>Dear visitors, the Realm667 is back online with an upgraded system, a new framework and updated plugins. It's not perfectly finished yet but you are able to access your primary source for anything related to Doom modding.</p>
<p>If you encounter some bugs - visual or partical ones - please take the time to post them in our "<strong>Let us know</strong>" <a href="/kunena/let-us-know">forum</a>, so we can take care of it.</p>
<p>Thanks kindly, and enjoy your visit!</p>			</div>
		</div>
	</div>	
</div>
