Need help with custom melee ideas <solved>

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.

Need help with custom melee ideas <solved>

Postby deathzero021 » Sun Nov 17, 2019 10:18 pm

I am having some trouble thinking of an approach to creating a custom melee attack for the player that allows for the weapon to hit multiple enemies in one strike, as well as having a wide sweeping arc to it's attack.

The most obvious approach is to use a projectile with RIPPER flag and that despawn after 1 tic. The issue with this is that they don't leave a lot of choices for the shape of the attack. As far as I can tell, we're limited to circle collision masks for projectiles, based on the radius and height properties. To counter that limitation, I could spawn multiple projectiles that form an arc. This could work but has one major flaw.

Multiple projectiles could cause an enemy to receive damage from 2 or more projectiles at once, which isn't the intended effect and would lead to inconsistent results.

The only other approach I can think of is a zscript function that replaces the standard player melee attack. However, I can't think of a solution there either because melee attacks require a target to deal damage and since this attack should be able to hit multiple enemies, potentially enemies you aren't directly facing, you can't rely on a single target variable to deal out the damage.

Perhaps there is an approach utilizing how projectiles deal damage to enemies that can be used to create a custom melee script, but I just don't know enough about zscript to know how possible that is. I've tried digging around in the attacks.zs file but there are few examples in there. RadiusDamage? Not sure how it works but maybe that's a possibility.

If anyone can offer some advice or ideas, I'd greatly appreciate it.

Edit: there are a handful of possible solutions found below.
Last edited by deathzero021 on Mon Nov 18, 2019 3:52 pm, edited 1 time in total.
User avatar
deathzero021
 
Joined: 24 Apr 2019
Operating System: Windows 10/8.1/8 64-bit
Graphics Processor: nVidia with Vulkan support

Re: Need help with custom melee ideas

Postby Cherno » Sun Nov 17, 2019 10:25 pm

You could use a ThinkerIterator to get all monsters in teh vincinity, and then damage them with DamageMobj if they are withing a certain angle.
Not the most elegant solution but one that would work.
Take a look at the GutsRipper mod which has pretty much exactly what you describe.
User avatar
Cherno
 
Joined: 06 Dec 2016

Re: Need help with custom melee ideas

Postby Void Weaver » Sun Nov 17, 2019 10:55 pm

Another very simple way is to call a fan volley of short-range A_FireBullets within specified angle, and it will be more smooth if it will be called from your weapon overlay.
By that way I've made a blade with the same effect; and in addition could write a some check for each puff to make sure that any puff hit its target only once.
User avatar
Void Weaver
Keeper of the Diablo bestiary storage Also amateur DECORATE-spaghetti weaver ಠ_ಠ
 
Joined: 18 Dec 2014

Re: Need help with custom melee ideas

Postby deathzero021 » Mon Nov 18, 2019 2:15 am

Cherno wrote:You could use a ThinkerIterator to get all monsters in teh vincinity, and then damage them with DamageMobj if they are withing a certain angle.
Not the most elegant solution but one that would work.
Take a look at the GutsRipper mod which has pretty much exactly what you describe.

Thanks for the suggestions. I'll have to look into Thinkers more. As for that mod, looks like the developer used a series of Rail Attacks which I suppose works but as that mod shows, it's super OP. There's no way to prevent enemies from getting hit by multiple "rails" at once, so it isn't easy to balance.

Void Weaver wrote:Another very simple way is to call a fan volley of short-range A_FireBullets within specified angle, and it will be more smooth if it will be called from your weapon overlay.
By that way I've made a blade with the same effect; and in addition could write a some check for each puff to make sure that any puff hit its target only once.
I'm pretty sure that runs into the same problem, getting hit by multiple bullets resulting in inconsistent damage. Although I guess you could write some kind of check for the bullets, if you give the attack a unique ID every time you use the weapon, than you could have the enemy check the ID of the bullet before receiving damage, and ensure that the same ID can't hurt the enemy twice in a row. That would certainly overly complicate receiving damage though. That's likely too much decorate hackery for my liking. I'd prefer thinking of a cleaner solution that can work for any situation.
User avatar
deathzero021
 
Joined: 24 Apr 2019
Operating System: Windows 10/8.1/8 64-bit
Graphics Processor: nVidia with Vulkan support

Re: Need help with custom melee ideas

Postby D2JK » Mon Nov 18, 2019 4:20 am

This could work but has one major flaw. Multiple projectiles could cause an enemy to receive damage from 2 or more projectiles at once, which isn't the intended effect and would lead to inconsistent results.


For this approach: you could create a dummy powerup of a short duration (powerups count down on their own and then vanish), and make the projectile give this to the victim (blockingMObj). The projectile would have a short duration, and maybe overridden SpecialMissileHit function which checks for the victim's inventory for this item. Or just nullify the DamageFunction(), check for the item in Death state, dealing damage to the victim only if item is found.

Maybe you could even modify the DamageFunction itself, checking for item there...
D2JK
 
Joined: 30 Aug 2014

Re: Need help with custom melee ideas

Postby deathzero021 » Mon Nov 18, 2019 4:46 am

D2JK wrote:
This could work but has one major flaw. Multiple projectiles could cause an enemy to receive damage from 2 or more projectiles at once, which isn't the intended effect and would lead to inconsistent results.


For this approach: you could create a dummy powerup of a short duration (powerups count down on their own and then vanish), and make the projectile give this to the victim (blockingMObj). The projectile would have a short duration, and maybe overridden SpecialMissileHit function which checks for the victim's inventory for this item. Or just nullify the DamageFunction(), check for the item in Death state, dealing damage to the victim only if item is found.

Maybe you could even modify the DamageFunction itself, checking for item there...

I think i get what you are saying. So, we can remove the powerup after damaging the enemy, so it only gets hit once. Well, in theory. Since there are multiple projectiles still, there's always a chance that a projectile gives the enemy the powerup, dies, damages enemy, removes powerup, but another projectile is still alive and repeats the process. But assuming that they all die at precisely the same moment, this might work. It'd be messy but it could work. Not ideal though as it still leads to the weird shape attacks and relying on projectiles.

I was messing around with A_RailAttack and got a half-decent shape going. Of course the multi-hit is an issue though. Does anyone know how thick a rail attack is? Is it like a thin line? It appears that way if you look at the particles. Close range, it'd still likely hit more than once. For now, it's the easiest option to fall back on, if no other approach works.

I also looked into ThinkerIterator, and i think it would likely be a bit slow. It would have to check every single damageable actor in the entire map, and check distances, angles, etc. Not a very optimized approach.

Edit: also, for the powerup idea, it would require checking all actors for the powerup too, right? Which is going to be a problem if a map has a lot of enemies...
User avatar
deathzero021
 
Joined: 24 Apr 2019
Operating System: Windows 10/8.1/8 64-bit
Graphics Processor: nVidia with Vulkan support

Re: Need help with custom melee ideas

Postby D2JK » Mon Nov 18, 2019 6:42 am

The point about powerups was that you can create a powerup that lasts for X tics only, after which it will automatically expire and remove itself from the owner's inventory. That is, you wouldn't manually remove it, but you would check for its existence in order to decide whether to deal damage to the victim/item owner. There will be no costly thinker iteration involved.

Rail attacks are a "thin line" indeed. You can also disable the penetration property, which I guess is what was troubling you.
D2JK
 
Joined: 30 Aug 2014

Re: Need help with custom melee ideas

Postby Void Weaver » Mon Nov 18, 2019 7:02 am

Oh, of course! A_RailAttack is much suitable for this goal indeed! Thank you for the tip deathzero021! ^_^

A some example for test:
Code: Select allExpand view
ACTOR SwipeBlade : FWeapQuietus
{
Weapon.SlotNumber 2
Weapon.SlotPriority 1
States
{
Fire:
FSRD DE 3 Bright Offset(5, 36)
FSRD F 2 Bright Offset(5, 36) A_Overlay(1001,"SwipeAttack")
FSRD G 3 Bright Offset(5, 36)
Goto Super::Fire+4

SwipeAttack:
TNT1 A 1 A_RailAttack(10,15,0,None,None,RGF_SILENT|RGF_NOPIERCING|RGF_NORANDOMPUFFZ,0,"SwipePuff",0,0,64,1,1,1,None,15)
TNT1 A 1 A_RailAttack(10,10,0,None,None,RGF_SILENT|RGF_NOPIERCING|RGF_NORANDOMPUFFZ,0,"SwipePuff",0,0,64,1,1,1,None,10)
TNT1 A 1 A_RailAttack(10,5,0,None,None,RGF_SILENT|RGF_NOPIERCING|RGF_NORANDOMPUFFZ,0,"SwipePuff",0,0,64,1,1,1,None,5)
TNT1 A 1 A_RailAttack(10,0,0,None,None,RGF_SILENT|RGF_NOPIERCING|RGF_NORANDOMPUFFZ,0,"SwipePuff",0,0,64,1,1,1,None,0)
TNT1 A 1 A_RailAttack(10,-5,0,None,None,RGF_SILENT|RGF_NOPIERCING|RGF_NORANDOMPUFFZ,0,"SwipePuff",0,0,64,1,1,1,None,-5)
TNT1 A 1 A_RailAttack(10,-10,0,None,None,RGF_SILENT|RGF_NOPIERCING|RGF_NORANDOMPUFFZ,0,"SwipePuff",0,0,64,1,1,1,None,-10)
TNT1 A 1 A_RailAttack(10,-15,0,None,None,RGF_SILENT|RGF_NOPIERCING|RGF_NORANDOMPUFFZ,0,"SwipePuff",0,0,64,1,1,1,None,-15)
Stop
}
}

ACTOR SwipePuff : BulletPuff
{
+ALWAYSPUFF
+HITTRACER
+PUFFONACTORS
DamageType "SwingPuff"
States
{
XDeath:
TNT1 A 0 {bALLOWPARTICLES=0;}
TNT1 A 0 A_JumpIfInventory("PuffTimer",1,"Failed",AAPTR_TRACER)
TNT1 A 0 A_GiveInventory("PuffTimer",1,AAPTR_TRACER)
Stop
Failed:
TNT1 A 0 A_GiveInventory("PuffProtect",1,AAPTR_TRACER)
Stop
}
}

ACTOR PuffProtect : PowerProtection
{
DamageFactor "SwingPuff",0
Powerup.Duration 5
Inventory.MaxAmount 1
}

ACTOR PuffTimer : Powerup
{
Powerup.Duration 2
Inventory.MaxAmount 1
}

*Goes to rework his blade via rails.*
User avatar
Void Weaver
Keeper of the Diablo bestiary storage Also amateur DECORATE-spaghetti weaver ಠ_ಠ
 
Joined: 18 Dec 2014

Re: Need help with custom melee ideas

Postby deathzero021 » Mon Nov 18, 2019 8:18 am

Ahh I see what was meant now by the powerups concept. That is a pretty easy way to implement this. I'll give it a try. Void Weaver is definitely on the right path, although I don't see why you have two powerups. Looking at that code, it appears the enemy will take damage twice before becoming invulnerable to the damage. (though i'm probably not understanding it properly haha)
User avatar
deathzero021
 
Joined: 24 Apr 2019
Operating System: Windows 10/8.1/8 64-bit
Graphics Processor: nVidia with Vulkan support

Re: Need help with custom melee ideas

Postby Tartlman » Mon Nov 18, 2019 8:20 am

take a look at GMOTA's code for doomslayer's longsword. I think this is what you want.
User avatar
Tartlman
shitposting with zscript
 
Joined: 11 Oct 2018
Location: meme hell
Discord: bogus#2947

Re: Need help with custom melee ideas

Postby Void Weaver » Mon Nov 18, 2019 10:37 am

Yeah, GMOTA's longsword a really cool, but IIRC its mechanics compiled into ACS... not sure.

deathzero021 wrote:although I don't see why you have two powerups. Looking at that code, it appears the enemy will take damage twice before becoming invulnerable to the damage. (though i'm probably not understanding it properly haha)
You understand it correct... almost. :)

The overlay deals a row of the same damage hitscans with a some delay, to make it looks like a slash prolonged in time. Since we are want to make sure that any target will take only one hit at 10 dmg we just define a special DamageType "SwingPuff" for puffs.
Then each puff do check for presence of "PuffTimer" (just timer powerup-token) in its TRACER inventory, if it presented, then it immediately gives a some protection ("PuffProtect") vs "SwingPuff" damage. But if TRACER haven't "PuffTimer" yet (and it haven't at a first hit) then timer will be placed into TRACER's inv, to make sure that a next possible puff wouldn't damages the same TRACER (player's foe).

So, the 1st hit mark TRACER as already hitted, and the 2nd hit for the same TRACER will no inflict damage because it immediately will protect TRACER from 2nd puff hit itself. For next blade swing all timers (include protection powerup) will fall. So each blade swing will inflict no more than 10 damage for each foe.
If you remove any powerup from this sequence then zombieman will fall from 1 hit, but now he dies only with 2 swings.

P. S.
For a some reason in this case giving of protection powerup takes into account before damage infliction from puff itself, so 2nd hit will always harmless.
User avatar
Void Weaver
Keeper of the Diablo bestiary storage Also amateur DECORATE-spaghetti weaver ಠ_ಠ
 
Joined: 18 Dec 2014

Re: Need help with custom melee ideas

Postby deathzero021 » Mon Nov 18, 2019 3:52 pm

Void Weaver wrote:
deathzero021 wrote:although I don't see why you have two powerups. Looking at that code, it appears the enemy will take damage twice before becoming invulnerable to the damage. (though i'm probably not understanding it properly haha)
You understand it correct... almost. :)

The overlay deals a row of the same damage hitscans with a some delay, to make it looks like a slash prolonged in time. Since we are want to make sure that any target will take only one hit at 10 dmg we just define a special DamageType "SwingPuff" for puffs.
Then each puff do check for presence of "PuffTimer" (just timer powerup-token) in its TRACER inventory, if it presented, then it immediately gives a some protection ("PuffProtect") vs "SwingPuff" damage. But if TRACER haven't "PuffTimer" yet (and it haven't at a first hit) then timer will be placed into TRACER's inv, to make sure that a next possible puff wouldn't damages the same TRACER (player's foe).

So, the 1st hit mark TRACER as already hitted, and the 2nd hit for the same TRACER will no inflict damage because it immediately will protect TRACER from 2nd puff hit itself. For next blade swing all timers (include protection powerup) will fall. So each blade swing will inflict no more than 10 damage for each foe.
If you remove any powerup from this sequence then zombieman will fall from 1 hit, but now he dies only with 2 swings.

P. S.
For a some reason in this case giving of protection powerup takes into account before damage infliction from puff itself, so 2nd hit will always harmless.
Ahh okay now it makes more sense. I'll have to try this approach. I'm thinking not every weapon should need this approach but for wide sweeping attacks, this could do the trick. Thanks for the help. 8-)
User avatar
deathzero021
 
Joined: 24 Apr 2019
Operating System: Windows 10/8.1/8 64-bit
Graphics Processor: nVidia with Vulkan support


Return to Scripting

Who is online

Users browsing this forum: No registered users and 2 guests