[solved] emulate hexen arch melee attacks

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!)

[solved] emulate hexen arch melee attacks

Postby Lagi » Sat Dec 12, 2020 7:11 am

Hexen melee attacks search for target in the cone of 90deg. which is very good.

Did someone write any function so i can use similar behavior with my weapons? (zscript is fine)

im too stupid to wrtie the func from here on my own:
https://github.com/coelckers/gzdoom/blo ... terfist.zs

but what excactly do you want?


TNT1 a A_meleeAsHexenAttack9326(dmg, range, pufftype*)

search arch can be hardcoded

*if i dont ask too much :D
Last edited by Lagi on Sat Dec 12, 2020 10:07 am, edited 1 time in total.
User avatar
Lagi
 
Joined: 23 Jun 2018
Location: Thou shalt alter thy beliefs with new evidence

Re: emulate hexen arch melee attacks

Postby Player701 » Sat Dec 12, 2020 7:59 am

The following code implements a generalized version of the fighter's fist attack. I've taken the original code and removed the parts specific to the fist's implementation. It seems to work fine on my end, please tell me if you have any problems with it.

Code: Select allExpand view
class HexenMeleeWeapon : Weapon
{
    private action bool TryPunch(double angle, int damage, int power, int range, class<Actor> pufftype)
    {
        Class<Actor> pufftype;
        FTranslatedLineTarget t;

        double slope = AimLineAttack (angle, 2*range, t, 0., ALF_CHECK3D);
        if (t.linetarget != null)
        {
            LineAttack (angle, 2*range, slope, damage, 'Melee', pufftype, true, t);
            if (t.linetarget != null)
            {
                // The mass threshold has been changed to CommanderKeen's value which has been used most often for 'unmovable' stuff.
                if (t.linetarget.player != null || (t.linetarget.Mass < 10000000 && (t.linetarget.bIsMonster)))
                {
                    if (!t.linetarget.bDontThrust)
                    {
                        t.linetarget.Thrust(power, t.attackAngleFromSource);
                    }
                }
                AdjustPlayerAngle(t);
                return true;
            }
        }
        return false;
    }

    action void A_HexenPunch(int damage, int range = 0, class<Actor> pufftype = 'BulletPuff', sound hitsound = "", sound misssound = "")
    {
        if (player == null)
        {
            return;
        }

        if (range == 0)
        {
            range = DEFMELEERANGE;
        }

        if (pufftype == null)
        {
            pufftype = 'BulletPuff';
        }

        for (int i = 0; i < 16; i++)
        {
            if (TryPunch(angle + i*(45./16), damage, 2, range, pufftype) || TryPunch(angle - i*(45./16), damage, 2, range, pufftype))
            {
                // hit something           
                A_StartSound (hitsound, CHAN_WEAPON);
                return;
            }
        }

        A_StartSound (misssound, CHAN_WEAPON);
        double slope = AimLineAttack (angle, range, null, 0., ALF_CHECK3D);
        LineAttack (angle, range, slope, damage, 'Melee', pufftype, true);
    }
}
User avatar
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: emulate hexen arch melee attacks

Postby Lagi » Sat Dec 12, 2020 9:09 am

that was quick, thanks
User avatar
Lagi
 
Joined: 23 Jun 2018
Location: Thou shalt alter thy beliefs with new evidence

Re: emulate hexen arch melee attacks

Postby Lagi » Sat Dec 12, 2020 10:06 am

works good, very as it should 8-)

is there a way to use the function A_hexenPunch without inheriting from HexenMeleeWeapon ?

edit: suggest change default puff to staffpuff (heretic) of punchpuff *hexen
pufftype = 'BulletPuff';

======================================

create ZSCRIPT.zs in your mod file:
Code: Select allExpand view
class HexenMeleeWeapon  : Weapon
{
 


    private action bool TryPunch(double angle, int damage, int power, int range, class<Actor> pufftype)
    {
        Class<Actor> pufftype;
        FTranslatedLineTarget t;

        double slope = AimLineAttack (angle, 2*range, t, 0., ALF_CHECK3D);
        if (t.linetarget != null)
        {
            LineAttack (angle, 2*range, slope, damage, 'Melee', pufftype, true, t);
            if (t.linetarget != null)
            {
                // The mass threshold has been changed to CommanderKeen's value which has been used most often for 'unmovable' stuff.
                if (t.linetarget.player != null || (t.linetarget.Mass < 10000000 && (t.linetarget.bIsMonster)))
                {
                    if (!t.linetarget.bDontThrust)
                    {
                        t.linetarget.Thrust(power, t.attackAngleFromSource);
                    }
                }
                AdjustPlayerAngle(t);
                return true;
            }
        }
        return false;
    }

    action void A_HexenPunch(int damage, int range = 0, class<Actor> pufftype = 'BulletPuff', sound hitsound = "", sound misssound = "")
    {
        if (player == null)
        {
            return;
        }

        if (range == 0)
        {
            range = DEFMELEERANGE;
        }

        if (pufftype == null)
        {
            pufftype = 'BulletPuff';
        }

        for (int i = 0; i < 16; i++)
        {
            if (TryPunch(angle + i*(45./16), damage, 2, range, pufftype) || TryPunch(angle - i*(45./16), damage, 2, range, pufftype))
            {
                // hit something           
                A_StartSound (hitsound, CHAN_WEAPON);
                return;
            }
        }

        A_StartSound (misssound, CHAN_WEAPON);
        double slope = AimLineAttack (angle, range, null, 0., ALF_CHECK3D);
        LineAttack (angle, range, slope, damage, 'Melee', pufftype, true);
    }
}


use A_hexenPunch in decorate weapon, but it need to inherit from HexenMeleeWeapon (yes, copy paste of wiki is necessary)

DECORATE:
Code: Select allExpand view
ACTOR Mace2 :HexenMeleeWeapon
{
  Weapon.SelectionOrder 1400
  Weapon.AmmoUse 1
  Weapon.AmmoGive1 50
  Weapon.YAdjust 15
  Weapon.AmmoType "MaceAmmo"
  Weapon.SisterWeapon "MacePowered"
  Inventory.PickupMessage "$TXT_WPNMACE"
  Tag "$TAG_MACE"

   
  States
  {
  Spawn:
    WMCE A -1
    Stop
  Ready:
    MACE A 1 A_WeaponReady
    Loop
  Deselect:
    MACE A 1 A_Lower
    Loop
  Select:
    MACE A 1 A_Raise
    Loop
  Fire:
   TNT1 A 0  A_JumpIfInventory("Backhand", 1, "BackSWING")
    MACE H 2   
   MACE I 2
    MACE J 2 A_HEXENPUNCH(RANDOM(20,60))  //<<<<<<===================================================================HERE
    MACE KL 2
     
   TNT1 A 5 A_GiveInventory("Backhand", 1)
   TNT1 A 7 A_WeaponReady
   TNT1 A 1 A_TakeInventory("Backhand", 1)
   
   MACE A 1 Offset(0, 60)
    MACE A 1 Offset(0, 52)
    MACE A 1 Offset(0, 44)
    MACE A 1 Offset(0, 36)
    MACE A 1
   Goto ready


BackSWING:
      MACE M 2  Offset(0,8)     
      MACE N 2 A_PlaySound("WHOP")      
      MACE O 2 A_Custompunch(random(45, 85), 1, CPF_NORANDOMPUFFZ, "STAFFPuff", 110)
      MACE PQ 2
      
      TNT1 A 9 A_TakeInventory("Backhand", 1)
      TNT1 A 7 A_WeaponReady
      MACE A 1 Offset(0, 60)
      MACE A 1 Offset(0, 52)
      MACE A 1 Offset(0, 44)
      MACE A 1 Offset(0, 36)
      MACE A 1

      Goto Ready
  }
}
User avatar
Lagi
 
Joined: 23 Jun 2018
Location: Thou shalt alter thy beliefs with new evidence

Re: [solved] emulate hexen arch melee attacks

Postby Player701 » Sat Dec 12, 2020 11:05 am

If you're using DECORATE, inheritance is likely the only option. With ZScript, you can use mixins. Simply add the keyword "mixin" to HexenMeleeWeapon so that it reads "mixin class HexenMeleeWeapon", and then in your actual weapon code, add this line:

Code: Select allExpand view
mixin HexenMeleeWeapon;

Then you will be able to call A_HexenPunch from your weapon code. Note that HexenMeleeWeapon is no longer a class, so you cannot inherit from it anymore.

Another ZScript-only solution is to implement the attack as a static method. You will then be able to call it from anywhere regardless of inheritance. However, this requires modifying the code so that the actor who initiates the attack is passed as an argument:

Code: Select allExpand view
class HexenMelee
{
    private static bool TryPunch(Actor originator, double angle, int damage, int power, int range, class<Actor> pufftype)
    {
        Class<Actor> pufftype;
        FTranslatedLineTarget t;

        double slope = originator.AimLineAttack (angle, 2*range, t, 0., ALF_CHECK3D);
        if (t.linetarget != null)
        {
            originator.LineAttack (angle, 2*range, slope, damage, 'Melee', pufftype, true, t);
            if (t.linetarget != null)
            {
                // The mass threshold has been changed to CommanderKeen's value which has been used most often for 'unmovable' stuff.
                if (t.linetarget.player != null || (t.linetarget.Mass < 10000000 && (t.linetarget.bIsMonster)))
                {
                    if (!t.linetarget.bDontThrust)
                    {
                        t.linetarget.Thrust(power, t.attackAngleFromSource);
                    }
                }
                originator.AdjustPlayerAngle(t);
                return true;
            }
        }
        return false;
    }

    static void A_HexenPunch(Actor originator, int damage, int range = 0, class<Actor> pufftype = 'StaffPuff', sound hitsound = "", sound misssound = "")
    {
        if (originator == null)
        {
            return;
        }

        if (range == 0)
        {
            range = DEFMELEERANGE;
        }

        if (pufftype == null)
        {
            pufftype = 'StaffPuff';
        }
       
        double ang = originator.Angle;

        for (int i = 0; i < 16; i++)
        {
            if (TryPunch(originator, ang + i*(45./16), damage, 2, range, pufftype) || TryPunch(originator, ang - i*(45./16), damage, 2, range, pufftype))
            {
                // hit something           
                originator.A_StartSound (hitsound, CHAN_WEAPON);
                return;
            }
        }

        originator.A_StartSound (misssound, CHAN_WEAPON);
        double slope = originator.AimLineAttack (ang, range, null, 0., ALF_CHECK3D);
        originator.LineAttack (ang, range, slope, damage, 'Melee', pufftype, true);
    }
}

To call this attack from your weapon code, use the following code:

Code: Select allExpand view
MACE J 2 { HexenMelee.A_HexenPunch(self, random(20, 60)); }
User avatar
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: [solved] emulate hexen arch melee attacks

Postby neoworm » Mon Dec 14, 2020 4:04 am

I was already using generalized HeXen style melee attack before. Based on Cleric's mace instead of fighter's fist. I wanted to make variants that scan from center, from left and from right and a cleave variant that damages all enemies in the cone. But I didn't know that I could use Mixins to add these calls into other classes without inheritance. Time to rewrite the code. It will also be useful for adding my improved shields to other monsters without the need to redefine the whole creature with different parents just to inherit the right code.
User avatar
neoworm
 
Joined: 23 Sep 2005
Location: Czech Republic

Re: [solved] emulate hexen arch melee attacks

Postby Lagi » Mon Dec 14, 2020 11:59 am

can you give link to your improved centaur shield?
User avatar
Lagi
 
Joined: 23 Jun 2018
Location: Thou shalt alter thy beliefs with new evidence

Re: [solved] emulate hexen arch melee attacks

Postby neoworm » Mon Dec 14, 2020 12:36 pm

Not done yet. The core is already working, but I still didn't create all the exceptions and have some problems with sounds. The code is still pretty messy too. If I have some time to work on it during weekend I will do some kind of release and ask people around to help me with reviewing it.
User avatar
neoworm
 
Joined: 23 Sep 2005
Location: Czech Republic

Re: [solved] emulate hexen arch melee attacks

Postby Woolie Wool » Sun Dec 27, 2020 5:53 pm

Player701 wrote:If you're using DECORATE, inheritance is likely the only option. With ZScript, you can use mixins. Simply add the keyword "mixin" to HexenMeleeWeapon so that it reads "mixin class HexenMeleeWeapon", and then in your actual weapon code, add this line:

Code: Select allExpand view
mixin HexenMeleeWeapon;

Then you will be able to call A_HexenPunch from your weapon code. Note that HexenMeleeWeapon is no longer a class, so you cannot inherit from it anymore.


This sounds awesome, but could you do a version of HexenMeleeWeapon that A_HexenPunch has the equivalent of CPF_USEAMMO, lifesteal, and lifestealmax?

Note I am working towards doing this myself, and I've already added useammo as a bool (and passed power from the base TryPunch function to A_HexenPunch as a parameter so I can customize that), but I'd like to see someone else do it so I can check my own work against someone who actually knows ZScript because I am totally new to ZScript or really any scripting more complex than DECORATE.
User avatar
Woolie Wool
Call Apogee Say "Snappity!"
 
Joined: 15 Dec 2003
Discord: Woolie Wool#9878
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: [solved] emulate hexen arch melee attacks

Postby Player701 » Mon Dec 28, 2020 12:25 am

Try this out:

Code: Select allExpand view
mixin class HexenMeleeWeapon
{
    private action bool TryPunch(double angle, int damage, int power, int range, class<Actor> pufftype, bool useammo, double lifesteal, int lifestealmax)
    {
        Class<Actor> pufftype;
        FTranslatedLineTarget t;

        double slope = AimLineAttack (angle, 2*range, t, 0., ALF_CHECK3D);
        if (t.linetarget != null)
        {
            // deplete ammo
            let weap = player.ReadyWeapon;

            if (useammo && weap != null && stateinfo != null && stateinfo.mStateType == STATE_Psprite)
            {
                if (!weap.DepleteAmmo(weap.bAltFire, true))
                {
                    // out of ammo
                    return true;
                }
            }

            Actor puff;
            int actualdamage;

            [puff, actualdamage] = LineAttack (angle, 2*range, slope, damage, 'Melee', pufftype, true, t);

            if (t.linetarget != null)
            {
                if (lifesteal > 0 && !t.linetarget.bDontDrain)
                {
                    GiveBody (int(actualdamage * lifesteal), lifestealmax);
                }

                // The mass threshold has been changed to CommanderKeen's value which has been used most often for 'unmovable' stuff.
                if (t.linetarget.player != null || (t.linetarget.Mass < 10000000 && (t.linetarget.bIsMonster)))
                {
                    if (!t.linetarget.bDontThrust)
                    {
                        t.linetarget.Thrust(power, t.attackAngleFromSource);
                    }
                }
                AdjustPlayerAngle(t);
                return true;
            }
        }
        return false;
    }

    action void A_HexenPunch(int damage, int range = 0, class<Actor> pufftype = 'BulletPuff', sound hitsound = "", sound misssound = "", bool useammo = false, double lifesteal = 0, int lifestealmax = 0)
    {
        if (player == null)
        {
            return;
        }

        if (range == 0)
        {
            range = DEFMELEERANGE;
        }

        if (pufftype == null)
        {
            pufftype = 'BulletPuff';
        }

        for (int i = 0; i < 16; i++)
        {
            if (TryPunch(angle + i*(45./16), damage, 2, range, pufftype, useammo, lifesteal, lifestealmax) || TryPunch(angle - i*(45./16), damage, 2, range, pufftype, useammo, lifesteal, lifestealmax))
            {
                // hit something           
                A_StartSound (hitsound, CHAN_WEAPON);
                return;
            }
        }

        A_StartSound (misssound, CHAN_WEAPON);
        double slope = AimLineAttack (angle, range, null, 0., ALF_CHECK3D);
        LineAttack (angle, range, slope, damage, 'Melee', pufftype, true);
    }
}
User avatar
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: [solved] emulate hexen arch melee attacks

Postby Woolie Wool » Mon Dec 28, 2020 9:16 am

It's got everything I need except that its attacks don't respect +PUFFONACTORS like the existing melee attacks, which is a problem e.g. for Timon's Axe.
User avatar
Woolie Wool
Call Apogee Say "Snappity!"
 
Joined: 15 Dec 2003
Discord: Woolie Wool#9878
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: [solved] emulate hexen arch melee attacks

Postby Player701 » Mon Dec 28, 2020 9:30 am

Ouch. There's a typo in that code. Remove this line from TryPunch (right after the opening brace):

Code: Select allExpand view
Class<Actor> pufftype;

(Too bad the ZScript compiler doesn't report cases of uninitialized variable usage... perhaps I should try to implement it myself?)
User avatar
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: [solved] emulate hexen arch melee attacks

Postby Woolie Wool » Mon Dec 28, 2020 9:34 am

Perfect! Thank you! :D
User avatar
Woolie Wool
Call Apogee Say "Snappity!"
 
Joined: 15 Dec 2003
Discord: Woolie Wool#9878
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: [solved] emulate hexen arch melee attacks

Postby Lagi » Sun Jan 24, 2021 9:37 am

i think there is bug with attack range here:

Code: Select allExpand view
        double slope = AimLineAttack (angle, 2*range, t, 0., ALF_CHECK3D);
        if (t.linetarget != null)
        {
            LineAttack (angle, 2*range, slope, damage, 'Melee', pufftype, true, t);
            if (t.linetarget != null)


all weapons using hexenpunch are reach much further. So i remove this 2*range, and all seems to be more intact.

Code: Select allExpand view
        double slope = AimLineAttack (angle, range, t, 0., ALF_CHECK3D);
        if (t.linetarget != null)
        {
            LineAttack (angle, range, slope, damage, 'Melee', pufftype, true, t);
            if (t.linetarget != null)
User avatar
Lagi
 
Joined: 23 Jun 2018
Location: Thou shalt alter thy beliefs with new evidence

Re: [solved] emulate hexen arch melee attacks

Postby Player701 » Sun Jan 24, 2021 10:04 am

The default range for Hexen fist attack when it hits an object is 2*DEFMELEERANGE, and just DEFMELEERANGE otherwise. That code was taken directly from gzdoom.pk3 (I only replaced the DEFMELEERANGE constant with an argument), but you're of course free to adjust the values to your own liking. :)
User avatar
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support


Return to Scripting

Who is online

Users browsing this forum: No registered users and 1 guest