Weapon with with charge and un-charge actions

Mon Feb 07, 2022 9:06 am

I've got a weapon with charge, the usual thing where you hold fire to charge and release to actually fire. While holding fire it builds the charge until the charge hit the maximum limit.
I would also like to add a minimum charge value. If the fire button is released before the charge reaches the minimum charge level, then it doesn't fire and instead walks backwards through the charge animation frames to un-charge the weapon.
Right now I have this:
Code:
   Fire:
      TNT1 A 0 {invoker.PowerAmount = 0;}
      TNT1 A 0 A_Jump(256,"Charge1","Charge2","Charge3");
      
   Charge1:
      UWAA B 4;
      UWAA C 4;
      UWAA D 4;
      TNT1 A 4;
   Hold1:
      TNT1 A 1 IncreasePower();
      TNT1 A 0 A_ReFire("Hold1");
   Attack1:
      UWAA D 4;
      UWAA E 4;
      UWAA F 4 A_CustomPunch(2 * random(1, 10), TRUE);
      UWAA G 4;
      TNT1 A 4;
      TNT1 A 0 A_ReFire("Fire");
      Goto Ready;

There are 3 charge, hold, and attack states, all basically the same, just different sprite sets for variety.
The CustomPunch is just a placeholder for now.

The way I think I should do this is on each frame in the charge animation is add a function like A_JumpIfNotRefire(256,-1) to walk backwards through the animation if the fire isn't being held.
Then at the end of the hold state add a 0-tic frame with a function that checks if invoker.PowerMinimum <= invoker.PowerAmount and if not, it jumps back to the end of the charge animation. From there the charge animation will handle walking back through the rest.

Is this the best way to do this? If so, how to write those custom jump functions? If not, what's the better way?

EDIT: 2 more small questions:
I look at my weapon HUD sprites in Slade with Hud offsets and they're perfect. But in-game they're too low. If I put Weapon.YAdjust -32; in defaults then they're perfect in fullscreen but still too low with the status bar. What am I doing wrong?
Is there an easy way to set and swap out the base sprite? In this example I'm using UWAA, but I have UWAB, UWAC, UWAD, etc for when the player is left handed or right handed, and what color gloves they are wearing. Is there an easy way to swap that base value out or do I have to define a ton of states for each sprite set?

Re: Weapon with with charge and un-charge actions

Mon Feb 07, 2022 9:18 am

Looks like I can do that minimum check with a A_JumpIf call.

For detecting fire key no longer pressed, I find this post but it's from 2009 and not sure if that's still relevant.

Re: Weapon with with charge and un-charge actions

Mon Feb 07, 2022 9:23 pm

Thinking about this, I think I could do it like this:
Code:
   Charge1:
      UWAA B 4 A_JumpIf(NoRefire,"Ready");
      UWAA C 4 A_JumpIf(NoRefire,"Charge+1");
      UWAA D 4 A_JumpIf(NoRefire,"Charge+2");
      TNT1 A 4 A_JumpIf(NoRefire,"Charge+3");
   Hold1:
      TNT1 A 1 IncreasePower();
      TNT1 A 0 A_ReFire("Hold1");
      TNT1 A 0 A_JumpIf(Power<PowerMin,"Charge1+4");

And then I still need to find a NoRefire() function. Would this work or is there a better way?

Re: Weapon with with charge and un-charge actions

Mon Feb 07, 2022 10:10 pm

This was easy enough:
Code:
   action bool A_IsNotRefire()
   {
      return !(player.cmd.buttons & BT_ATTACK);
   }

It doesn't handle altrefire but I'm not using that right now.

That jump to "Label+Offset" doesn't seem to work. I'll have to find something else.

I try this:
Code:
   Charge1:
      UWAA B 4 A_JumpIf(A_IsNotRefire(),"Ready");
      UWAA C 4 A_JumpIf(A_IsNotRefire(),-1);
      UWAA D 4 A_JumpIf(A_IsNotRefire(),-1);
      TNT1 ] 4 A_JumpIf(A_IsNotRefire(),-1);
   Hold1:
      TNT1 ] 1 A_IncreasePower;
      TNT1 ] 0 A_ReFire("Hold1");
      TNT1 ] 0 A_JumpIf(A_IsPowerLow(),-3);

but Jump doesn't like negative numbers

So I've got to try something else

Re: Weapon with with charge and un-charge actions

Tue Feb 08, 2022 1:49 am

Even if jump did take negative numbers, that wouldn't work because functions are executed before the frames are drawn, not after.

I go something to work, it's a little messy but I ended up keeping track of my own frame counter and increasing it or decreasing it based on whether the fire key was held or not:
Code:
//FUNCTIONS
   action bool A_IsPowerLow(){
      return invoker.PowerAmount<invoker.PowerMinAmount;
   }
   
   action bool A_IsNotRefire(){
      return !(player.cmd.buttons & BT_ATTACK);
   }
   
   action state A_JumpCharge1(){
      if (A_IsNotRefire()){
         invoker.ChargeFrame--;
      } else {
         invoker.ChargeFrame++;
      }
      if (invoker.ChargeFrame<=0){
         return A_Jump(256,"Ready");
      } else {
         return A_Jump(256,"Charge1");
      }
   }
   action state A_JumpIfPowerLow(){
      if (A_IsPowerLow()){
         invoker.ChargeFrame--;
         return A_Jump(256,"Charge1");
      }
      return A_Jump(256,'Attack1');
   }

Code:
//STATES
   Charge1:
      TNT1 ] 0 A_Jump(256,invoker.ChargeFrame*2+1);
      UWAA B 4;
      TNT1 ] 0 A_JumpCharge1;
      UWAA C 4;
      TNT1 ] 0 A_JumpCharge1;
      UWAA D 4;
      TNT1 ] 0 A_JumpCharge1;
      TNT1 ] 4;
      TNT1 ] 0 A_JumpCharge1;
   Hold1:
      TNT1 ] 1 A_IncreasePower;
      TNT1 ] 0 A_ReFire("Hold1");
      TNT1 ] 0 A_JumpIfPowerLow();

Re: Weapon with with charge and un-charge actions

Tue Feb 08, 2022 8:36 am

Trying to clean this up like this:
Code:
   action state A_JumpCharge(string ChargeLabel, string ReadyLabel){
      if (A_IsNotRefire()){
         invoker.ChargeFrame--;
      } else {
         invoker.ChargeFrame++;
      }
      if (invoker.ChargeFrame<=0){
         return A_Jump(256,ReadyLabel);
      } else {
         return A_Jump(256,ChargeLabel);
      }
   }
   action state A_JumpCharge1(){
      return A_JumpCharge1("Charge1","Ready");
   }

but his doesn't work. It seems that A_Jump can take a string in the states block but not in the actual function definition. What a pain in the ass.

Re: Weapon with with charge and un-charge actions

Tue Feb 08, 2022 9:28 am

easy fix - change the "string" to "statelabel" and it's all good