Melee is now multi-hit, have fun.
This commit is contained in:
parent
01ab2a499e
commit
c2e1497226
9 changed files with 111 additions and 60 deletions
|
|
@ -290,6 +290,12 @@ Class UseLineTracer : LineTracer
|
|||
}
|
||||
}
|
||||
|
||||
Class MHitList
|
||||
{
|
||||
Actor a;
|
||||
Vector3 dir, pos;
|
||||
}
|
||||
|
||||
extend Class SWWMWeapon
|
||||
{
|
||||
Actor pfield; // instance of parry field for current melee attack
|
||||
|
|
@ -308,65 +314,114 @@ extend Class SWWMWeapon
|
|||
if ( !FindInventory("ParryDamageChecker") )
|
||||
GiveInventory("ParryDamageChecker",1); // need this so parried projectiles deal extra damage
|
||||
}
|
||||
private action bool TryMelee( double angle, int dmg, String hitsound = "", double rangemul = 1. )
|
||||
// multi-hit cone rather than the usual one-hit arc, more fun
|
||||
private action bool TryMelee( double spread, int dmg, String hitsound = "", double rangemul = 1. )
|
||||
{
|
||||
FTranslatedLineTarget t;
|
||||
double slope = AimLineAttack(angle,1.5*DEFMELEERANGE*rangemul,t,0.,ALF_CHECK3D);
|
||||
Vector3 x, y, z, dir;
|
||||
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
|
||||
Vector3 origin = Vec2OffsetZ(0,0,player.viewz);
|
||||
Array<MHitList> hits;
|
||||
hits.Clear();
|
||||
FLineTraceData d;
|
||||
LineTrace(angle,1.5*DEFMELEERANGE*rangemul,slope,0,player.viewheight,data:d);
|
||||
int rings = 1;
|
||||
double step = spread/10.;
|
||||
double range = 1.5*DEFMELEERANGE*rangemul;
|
||||
bool raging = CountInv("RagekitPower");
|
||||
if ( (d.HitType == TRACE_HitActor) && !d.HitActor.FindInventory("ParriedBuff") )
|
||||
for ( double i=0; i<spread; i+=step )
|
||||
{
|
||||
bool bloodless = true;
|
||||
double diff = deltaangle(self.angle,AngleTo(d.HitActor));
|
||||
self.angle += clamp(diff,-5.,5.);
|
||||
SWWMUtility.DoKnockback(d.HitActor,d.HitDir+(0,0,.2),dmg*2000);
|
||||
if ( raging )
|
||||
for ( int j=0; j<360; j+=(360/rings) )
|
||||
{
|
||||
invoker.bEXTREMEDEATH = true;
|
||||
invoker.bNOEXTREMEDEATH = false;
|
||||
dir = (x+y*cos(j)*1.5*i+z*sin(j)*i).unit(); // wide ring
|
||||
LineTrace(atan2(dir.y,dir.x),range,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
|
||||
if ( d.HitType != TRACE_HitActor ) continue;
|
||||
if ( d.HitActor.FindInventory("ParriedBuff") ) continue;
|
||||
bool addme = true;
|
||||
for ( int k=0; k<hits.Size(); k++ )
|
||||
{
|
||||
if ( hits[k].a != d.HitActor ) continue;
|
||||
if ( (hits[k].dir dot x) < (dir dot x) )
|
||||
{
|
||||
// closer to centerpoint
|
||||
hits[k].dir = dir;
|
||||
hits[k].pos = d.HitLocation;
|
||||
}
|
||||
addme = false;
|
||||
break;
|
||||
}
|
||||
if ( !addme ) continue;
|
||||
let nhit = new("MHitList");
|
||||
nhit.a = d.HitActor;
|
||||
nhit.dir = dir;
|
||||
nhit.pos = d.HitLocation;
|
||||
hits.Push(nhit);
|
||||
}
|
||||
rings += 5;
|
||||
}
|
||||
// no targets
|
||||
if ( hits.Size() <= 0 ) return false;
|
||||
bool blooded = false;
|
||||
bool bloodless = false;
|
||||
if ( raging )
|
||||
{
|
||||
invoker.bEXTREMEDEATH = true;
|
||||
invoker.bNOEXTREMEDEATH = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
invoker.bEXTREMEDEATH = false;
|
||||
invoker.bNOEXTREMEDEATH = true;
|
||||
}
|
||||
int flg = DMG_USEANGLE|DMG_THRUSTLESS;
|
||||
if ( raging ) flg |= DMG_FOILINVUL;
|
||||
int quakin = raging?8:2;
|
||||
double diff = 0.;
|
||||
for ( int i=0; i<hits.Size(); i++ )
|
||||
{
|
||||
diff += deltaangle(self.angle,AngleTo(hits[i].a));
|
||||
SWWMUtility.DoKnockback(hits[i].a,hits[i].dir+(0,0,.2),dmg*2000);
|
||||
// lol oops
|
||||
if ( !hits[i].a.bDORMANT ) hits[i].a.DaggerAlert(self);
|
||||
int newdmg = hits[i].a.DamageMobj(invoker,self,dmg,'Melee',flg,atan2(hits[i].dir.y,hits[i].dir.x));
|
||||
if ( hits[i].a.player ) hits[i].a.A_QuakeEx(quakin,quakin,quakin,6,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.125*quakin);
|
||||
if ( !hits[i].a.bNOBLOOD && !hits[i].a.bDORMANT && (raging || !hits[i].a.bINVULNERABLE) )
|
||||
{
|
||||
hits[i].a.TraceBleed(newdmg,invoker);
|
||||
hits[i].a.SpawnBlood(hits[i].pos,atan2(hits[i].dir.y,hits[i].dir.x)+180,newdmg);
|
||||
blooded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
invoker.bEXTREMEDEATH = false;
|
||||
invoker.bNOEXTREMEDEATH = true;
|
||||
}
|
||||
if ( !d.HitActor.bDORMANT ) // lol oops
|
||||
d.HitActor.DaggerAlert(self);
|
||||
int flg = DMG_USEANGLE|DMG_THRUSTLESS;
|
||||
if ( raging ) flg |= DMG_FOILINVUL;
|
||||
dmg = d.HitActor.DamageMobj(invoker,self,dmg,'Melee',flg,atan2(d.HitDir.y,d.HitDir.x));
|
||||
invoker.bEXTREMEDEATH = invoker.default.bEXTREMEDEATH;
|
||||
invoker.bNOEXTREMEDEATH = invoker.default.bEXTREMEDEATH;
|
||||
int quakin = raging?8:2;
|
||||
if ( d.HitActor.player ) d.HitActor.A_QuakeEx(quakin,quakin,quakin,6,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.125*quakin);
|
||||
if ( !d.HitActor.bNOBLOOD && !d.HitActor.bDORMANT && (raging || !d.HitActor.bINVULNERABLE) )
|
||||
{
|
||||
d.HitActor.TraceBleed(dmg,invoker);
|
||||
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
|
||||
bloodless = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
let p = Spawn(raging?"BigPunchImpact":"PunchImpact",d.HitLocation);
|
||||
p.angle = atan2(-d.HitDir.y,-d.HitDir.x);
|
||||
let p = Spawn(raging?"BigPunchImpact":"PunchImpact",hits[i].pos);
|
||||
p.angle = atan2(hits[i].dir.y,hits[i].dir.x);
|
||||
bloodless = true;
|
||||
}
|
||||
if ( raging )
|
||||
{
|
||||
let ps = Spawn("BigPunchSplash",d.HitLocation);
|
||||
let ps = Spawn("BigPunchSplash",hits[i].pos);
|
||||
ps.target = self;
|
||||
ps.special1 = dmg;
|
||||
}
|
||||
A_QuakeEx(quakin/2,quakin/2,quakin/2,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.06*quakin);
|
||||
if ( raging ) A_StartSound(bloodless?"pusher/althit":"pusher/altmeat",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
else A_StartSound((hitsound!="")?hitsound:bloodless?"demolitionist/punch":"demolitionist/punchf",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_AlertMonsters(swwm_uncapalert?0:300);
|
||||
A_BumpFOV(.96);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
self.angle += clamp(diff/hits.Size(),-5.,5.); // averaged reorient
|
||||
invoker.bEXTREMEDEATH = invoker.default.bEXTREMEDEATH;
|
||||
invoker.bNOEXTREMEDEATH = invoker.default.bEXTREMEDEATH;
|
||||
A_QuakeEx(quakin/2,quakin/2,quakin/2,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.06*quakin);
|
||||
if ( raging )
|
||||
{
|
||||
if ( blooded ) A_StartSound("pusher/altmeat",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
if ( bloodless ) A_StartSound("pusher/althit",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
}
|
||||
else if ( hitsound == "" )
|
||||
{
|
||||
if ( blooded ) A_StartSound("demolitionist/punchf",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
if ( bloodless ) A_StartSound("demolitionist/punch",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
}
|
||||
else A_StartSound(hitsound,CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_AlertMonsters(swwm_uncapalert?0:300);
|
||||
A_BumpFOV(.96);
|
||||
return true;
|
||||
}
|
||||
action void A_Melee( int dmg = 40, String hitsound = "", double rangemul = 1. )
|
||||
action void A_Melee( int dmg = 40, String hitsound = "", double rangemul = 1., double spreadmul = 1. )
|
||||
{
|
||||
let raging = RagekitPower(FindInventory("RagekitPower"));
|
||||
if ( raging ) rangemul += .2;
|
||||
|
|
@ -398,12 +453,8 @@ extend Class SWWMWeapon
|
|||
invoker.wallponch = false;
|
||||
// check for shootables
|
||||
SWWMBulletTrail.DoTrail(self,origin,dir,DEFMELEERANGE*rangemul,0);
|
||||
int maxang = raging?18:12;
|
||||
for ( int i=0; i<maxang; i++ )
|
||||
{
|
||||
if ( TryMelee(angle+i*(45./16),dmg,hitsound,rangemul) || TryMelee(angle-i*(45./16),dmg,hitsound,rangemul) )
|
||||
return;
|
||||
}
|
||||
if ( TryMelee((raging?.3:.2)*spreadmul,dmg,hitsound,rangemul) )
|
||||
return;
|
||||
// check for walls instead
|
||||
FTranslatedLineTarget t;
|
||||
double slope = AimLineAttack(angle,DEFMELEERANGE*rangemul,t,0.,ALF_CHECK3D);
|
||||
|
|
|
|||
|
|
@ -1347,7 +1347,7 @@ Class Hellblazer : SWWMWeapon
|
|||
XZWQ KLM 2;
|
||||
XZWQ N 2 A_Parry(9);
|
||||
XZWQ OP 1;
|
||||
XZWQ Q 1 A_Melee(75,"demolitionist/whitl",1.05);
|
||||
XZWQ Q 1 A_Melee(75,"demolitionist/whitl",1.05,1.2);
|
||||
XZWQ RSTUV 2;
|
||||
XZWQ W 2 A_StartSound("hellblazer/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZWQ XYZ 2;
|
||||
|
|
|
|||
|
|
@ -1242,7 +1242,7 @@ Class Wallbuster : SWWMWeapon
|
|||
XZW9 GHI 2;
|
||||
XZW9 J 2 A_Parry(9);
|
||||
XZW9 KLM 1;
|
||||
XZW9 N 1 A_Melee(70,"demolitionist/whitl",1.2);
|
||||
XZW9 N 1 A_Melee(70,"demolitionist/whitl",1.2,1.4);
|
||||
XZW9 OPQRS 2;
|
||||
XZW9 T 2 A_StartSound("wallbuster/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW9 UVW 2;
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ Class Eviscerator : SWWMWeapon
|
|||
XZW9 AB 1;
|
||||
XZW9 C 1 A_Parry(9);
|
||||
XZW9 D 1;
|
||||
XZW9 E 2 A_Melee(60,"demolitionist/whitm",1.1);
|
||||
XZW9 E 2 A_Melee(60,"demolitionist/whitm",1.1,1.2);
|
||||
XZW9 FGH 2;
|
||||
XZW9 I 2 A_StartSound("eviscerator/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW9 JKL 2;
|
||||
|
|
@ -492,7 +492,7 @@ Class Eviscerator : SWWMWeapon
|
|||
XZWA QRS 1;
|
||||
XZWA T 1 A_Parry(9);
|
||||
XZWA U 1;
|
||||
XZWA V 2 A_Melee(60,"demolitionist/whitm",1.1);
|
||||
XZWA V 2 A_Melee(60,"demolitionist/whitm",1.1,1.2);
|
||||
XZWA WXY 2;
|
||||
XZWA Z 2 A_StartSound("eviscerator/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZWB ABC 2;
|
||||
|
|
|
|||
|
|
@ -515,7 +515,7 @@ Class Ynykron : SWWMWeapon
|
|||
XZW9 AB 2;
|
||||
XZW9 C 1 A_Parry(9);
|
||||
XZW9 DE 1;
|
||||
XZW9 F 1 A_Melee(100,"demolitionist/whitl",1.5);
|
||||
XZW9 F 1 A_Melee(100,"demolitionist/whitl",1.5,1.6);
|
||||
XZW9 GHIJK 1;
|
||||
XZW9 LMNO 2;
|
||||
XZW9 P 2 A_StartSound("ynykron/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ Class PusherWeapon : SWWMWeapon
|
|||
}
|
||||
if ( swwm_omnibust ) BusterWall.BustLinetrace(d,dmg,self,d.HitDir,d.HitLocation.z);
|
||||
}
|
||||
else if ( waterlevel > 2 ) SWWMUtility.DoKnockback(self,-x,18000);
|
||||
else if ( waterlevel > 2 ) SWWMUtility.DoKnockback(self,-x,50000);
|
||||
if ( swwm_extraalert || !(invoker.hitcnt%20) ) A_AlertMonsters(swwm_uncapalert?0:500);
|
||||
invoker.hitcnt++;
|
||||
}
|
||||
|
|
@ -351,7 +351,7 @@ Class PusherWeapon : SWWMWeapon
|
|||
XZW5 ABC 2;
|
||||
XZW5 D 1 A_Parry(9);
|
||||
XZW5 EFGH 1;
|
||||
XZW5 I 0 A_Melee(70,"demolitionist/whitl",1.1);
|
||||
XZW5 I 0 A_Melee(70,"demolitionist/whitl",1.1,1.2);
|
||||
XZW5 IJ 2;
|
||||
XZW5 K 2 { invoker.PlayUpSound(self); }
|
||||
XZW5 LM 2;
|
||||
|
|
|
|||
|
|
@ -540,7 +540,7 @@ Class Sparkster : SWWMWeapon
|
|||
XZW4 EFG 2;
|
||||
XZW4 H 1 A_Parry(9);
|
||||
XZW4 IJ 1;
|
||||
XZW4 K 2 A_Melee(60,"demolitionist/whitm");
|
||||
XZW4 K 2 A_Melee(60,"demolitionist/whitm",1.,1.1);
|
||||
XZW4 LMNOPQ 2;
|
||||
XZW4 R 2 A_StartSound("biospark/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW4 STUVWX 2;
|
||||
|
|
@ -550,7 +550,7 @@ Class Sparkster : SWWMWeapon
|
|||
XZW7 RST 2;
|
||||
XZW7 U 1 A_Parry(9);
|
||||
XZW7 VW 1;
|
||||
XZW7 X 2 A_Melee(60,"demolitionist/whitm");
|
||||
XZW7 X 2 A_Melee(60,"demolitionist/whitm",1.,1.1);
|
||||
XZW7 YZ 2;
|
||||
XZW8 ABCD 2;
|
||||
XZW8 E 2 A_StartSound("biospark/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
|
|
|
|||
|
|
@ -1421,7 +1421,7 @@ Class SilverBullet : SWWMWeapon
|
|||
XZW6 IJK 3;
|
||||
XZW6 L 1 A_Parry(9);
|
||||
XZW6 MN 1;
|
||||
XZW6 O 1 A_Melee(90,"demolitionist/whitl",1.6);
|
||||
XZW6 O 1 A_Melee(90,"demolitionist/whitl",1.6,2.);
|
||||
XZW6 PQ 1;
|
||||
XZW6 RST 2;
|
||||
XZW6 U 3 A_StartSound("silverbullet/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
|
|
@ -1438,7 +1438,7 @@ Class SilverBullet : SWWMWeapon
|
|||
XZWC IJK 3;
|
||||
XZWC L 1 A_Parry(9);
|
||||
XZWC MN 1;
|
||||
XZWC O 1 A_Melee(90,"demolitionist/whitl",1.6);
|
||||
XZWC O 1 A_Melee(90,"demolitionist/whitl",1.6,2.);
|
||||
XZWC PQ 1;
|
||||
XZWC RST 2;
|
||||
XZWC U 3 A_StartSound("silverbullet/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue