Itamex Hammer fully implemented.

This commit is contained in:
Mari the Deer 2022-08-12 14:48:33 +02:00
commit b6138aa396
263 changed files with 241 additions and 25 deletions

View file

@ -30,6 +30,21 @@ Class ItamexHammer : SWWMWeapon
A_QuakeEx(1,1,1,15,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:.1);
return ResolveState(null);
}
action void A_HammerAltHit()
{
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
SWWMUtility.DoKnockback(self,x,3000.*invoker.charge);
if ( A_Melee(int(100+invoker.charge*2),"itamex/hit",1.8,1.1,3.,MELEE_Rip|MELEE_FleshSound|MELEE_HammerHit|MELEE_Vertical|MELEE_ExtraWide|MELEE_ForceBust) )
{
A_BumpFOV(.9);
A_QuakeEx(5,5,5,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:.35);
A_AlertMonsters(swwm_uncapalert?0:800);
return;
}
A_BumpFOV(.95);
A_QuakeEx(1,1,1,15,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:.1);
}
override void DoEffect()
{
@ -113,15 +128,66 @@ Class ItamexHammer : SWWMWeapon
if ( invoker.charge <= 0 ) A_StopSound(CHAN_WEAPONEXTRA);
}
action void A_AltCharge()
{
invoker.charge = min(100.,invoker.charge*1.02+1.);
double vibe = (invoker.charge/100.)**2.;
A_WeaponOffset(FRandom[Hammer](-.5,.5)*vibe,32+FRandom[Hammer](-.5,.5)*vibe,WOF_INTERPOLATE);
}
action State A_AltHold()
{
invoker.charge = min(100.,invoker.charge*1.02+1.);
double vibe = (invoker.charge/100.)**2.;
A_WeaponOffset(FRandom[Hammer](-.5,.5)*vibe,32+FRandom[Hammer](-.5,.5)*vibe,WOF_INTERPOLATE);
if ( !(player.cmd.buttons&BT_ALTATTACK) )
{
A_WeaponOffset(0,32,WOF_INTERPOLATE);
return ResolveState("AltRelease");
}
return ResolveState(null);
}
action void A_AltRelease()
{
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
SWWMUtility.DoKnockback(self,x-(0,0,3.),120000.);
A_BumpFOV(.9);
A_StartSound("itamex/drop",CHAN_WEAPONEXTRA2);
A_StartSound("itamex/drop",CHAN_WEAPONEXTRA3);
}
action void A_AltHit()
{
if ( (pos.z <= floorz+16) && (pitch > -15) )
{
A_StopSound(CHAN_WEAPONEXTRA2);
A_StopSound(CHAN_WEAPONEXTRA3);
A_StartSound("itamex/slam",CHAN_WEAPON,CHANF_OVERLAP);
A_StartSound("itamex/slam",CHAN_WEAPON,CHANF_OVERLAP);
vel.z += invoker.charge*.03;
A_BumpFOV(.85);
A_QuakeEx(8,8,8,10,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
A_AlertMonsters(swwm_uncapalert?0:2500);
let s = Spawn("HammerShockwave",(pos.x,pos.y,floorz));
s.target = self;
s.special1 = int(invoker.charge*3);
}
invoker.charge = 0.;
}
override void OwnerDied()
{
Super.OwnerDied();
A_StopSound(CHAN_WEAPONEXTRA);
charge = 0.;
}
override void Travelled()
{
Super.Travelled();
A_StopSound(CHAN_WEAPONEXTRA);
charge = 0.;
}
Default
@ -152,7 +218,11 @@ Class ItamexHammer : SWWMWeapon
XZW2 PQRST 3;
Goto Ready;
Ready:
XZW2 A 1 A_WeaponReady(WRF_ALLOWRELOAD|WRF_ALLOWZOOM|WRF_ALLOWUSER1);
XZW2 A 1
{
A_WeaponOffset(0,32,WOF_INTERPOLATE); // ensure we're back to normal offsets just in case
A_WeaponReady(WRF_ALLOWRELOAD|WRF_ALLOWZOOM|WRF_ALLOWUSER1);
}
Wait;
Fire:
XZW2 A 2 A_StartSound("itamex/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
@ -169,15 +239,34 @@ Class ItamexHammer : SWWMWeapon
XZW3 MNOPQR 2;
Goto Ready;
FireHit:
XZW3 FF 2;
XZW3 STU 2;
XZW3 VWXYZ 1;
XZW3 F 2;
XZW3 STUVW 2;
XZW3 XYZ 1;
XZW4 A 2;
XZW4 B 2 A_StartSound("itamex/meleeend",CHAN_WEAPON,CHANF_OVERLAP,starttime:.42);
XZW4 C 2;
Goto Ready;
AltFire:
XZW2 A 1; // TODO
XZW2 A 2 A_StartSound("itamex/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
XZW4 DEFG 2 A_AltCharge();
XZW4 HIJKLMNOPQRSTU 1 A_AltCharge();
XZW4 V 1 A_AltHold();
Wait;
AltRelease:
XZW4 V 1 A_AltRelease();
XZW4 WXYZ 1 A_BumpPitch(2.);
XZW5 A 1 A_BumpPitch(3.);
XZW5 B 1
{
A_BumpPitch(3.);
A_HammerAltHit();
}
XZW5 CD 1 A_BumpPitch(4.);
XZW5 E 1 A_AltHit();
XZW5 FGHIJKLMN 2;
XZW5 O 2 A_StartSound("itamex/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 PQRS 2;
XZW5 TUVW 3;
Goto Ready;
Zoom:
XZW2 A 2 A_StartSound("itamex/meleestart",CHAN_WEAPON,CHANF_OVERLAP);

View file

@ -1 +1,100 @@
// Itamex Hammer projectiles and effects
// akin to the land shockwave, but with sliiiiightly different behavior
Class HammerShockwave : Actor
{
Default
{
Obituary "$O_HAMMER";
+NOGRAVITY;
+NOBLOCKMAP;
+NOTELEPORT;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
+NOINTERACTION;
Radius .1;
Height 0.;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_QuakeEx(5,5,5,20,0,300+special1*4,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:200,rollIntensity:.8);
SWWMUtility.DoExplosion(self,30+special1/2,100000+special1*2000,80+special1/2,40,DE_BLAST|DE_EXTRAZTHRUST,'HammerShockwave',target);
for ( int i=0; i<360; i+=5 )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,3);
let s = Spawn("SWWMSmoke",Vec3Angle(4,i,8));
s.vel = pvel+(cos(i),sin(i),0)*7.;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,4);
s.scale *= 1.5;
s.alpha *= .4;
}
for ( int i=0; i<360; i+=5 )
{
let r = Spawn("HammerRadiusShockwave",Vec3Angle(5,i));
r.target = target;
r.angle = i;
r.vel.xy = (cos(i),sin(i))*(r.speed+special1*.1);
r.alpha *= .3+special1*.0005;
}
int numpt = Random[ExploS](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
let raging = RagekitPower(target.FindInventory("RagekitPower"));
// bust the floor
let tempme = new("LineTracer"); // gross hack to pass needed data
int dmg = 300+special1*4;
if ( raging ) dmg *= 8;
F3DFloor ff;
for ( int i=0; i<FloorSector.Get3DFloorCount(); i++ )
{
if ( !(FloorSector.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
ff = FloorSector.Get3DFloor(i);
break;
}
if ( ff ) tempme.Results.ffloor = ff;
tempme.Results.HitSector = FloorSector;
tempme.Results.HitType = TRACE_HitFloor;
BusterWall.Bust(tempme.Results,dmg,target,(0,0,-1),pos.z);
if ( raging )
{
let ps = Spawn("BigPunchSplash",pos);
ps.damagetype = 'GroundPound';
ps.target = target;
ps.special1 = dmg;
raging.DoHitFX();
}
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
TNT1 A 140;
Stop;
}
}
Class HammerRadiusShockwave : DemolitionistRadiusShockwave
{
Default
{
Obituary "$O_HAMMER";
DamageType 'HammerShockwave';
DamageFunction int(100*alpha);
}
}

View file

@ -1137,7 +1137,7 @@ Class RagekitPower : Powerup
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags )
{
if ( passive ) return;
if ( (damageType == 'Melee') || (damageType == 'Jump') || (damageType == 'Dash') || (damageType == 'Buttslam') || (damageType == 'GroundPound') )
if ( (damageType == 'Melee') || (damageType == 'Jump') || (damageType == 'Dash') || (damageType == 'Buttslam') || (damageType == 'GroundPound') || (damageType == 'HammerShockwave') )
{
newdamage = damage*8;
DoHitFX();

View file

@ -166,6 +166,7 @@ Class SWWMStats : SWWMStaticThinker
if ( inflictor && inflictor.FindInventory("ParriedBuff") ) which = 'DoomWeapon'; // gross hack
// properly credit some projectiles to their respective gun
else if ( inflictor is 'AirBullet' ) which = 'DeepImpact';
else if ( (inflictor is 'HammerShockwave') || (inflictor is 'HammerRadiusShockwave') ) which = 'ItamexHammer';
else if ( (inflictor is 'ExplodiumMagArm') || (inflictor is 'ExplodiumMagProj') || (inflictor is 'ExplodiumBulletImpact') ) which = 'ExplodiumGun';
else if ( ((inflictor is 'SaltImpact') && !inflictor.Args[0]) || ((inflictor is 'SaltBeam') && !inflictor.Args[1]) || (inflictor is 'CorrodeDebuff') || (inflictor is 'CorrosiveFlechette') || ((inflictor is 'TheBall') && !inflictor.special1) || (inflictor is 'GoldenImpact') || (inflictor is 'GoldenSubImpact') || (inflictor is 'GoldenSubSubImpact') ) which = 'Spreadgun';
else if ( ((inflictor is 'SaltImpact') && inflictor.Args[0]) || ((inflictor is 'SaltBeam') && inflictor.Args[1]) || ((inflictor is 'TheBall') && inflictor.special1) ) which = 'Wallbuster';

View file

@ -1145,6 +1145,7 @@ Class SWWMUtility
static bool IsExplosiveSource( Actor s )
{
if ( s is 'DemolitionistShockwave' ) return false;
if ( s is 'HammerShockwave' ) return false;
if ( s is 'BigPunchSplash' ) return false;
if ( s is 'AirBullet' ) return false;
if ( s is 'SaltBeam' ) return false;

View file

@ -183,6 +183,13 @@ Class SWWMWeapon : Weapon abstract
Demolitionist(self).lastbump *= factor;
}
action void A_BumpPitch( double factor )
{
if ( !(self is 'Demolitionist') ) return;
Demolitionist(self).bumppitch.Push(factor);
A_SetPitch(pitch+factor,SPF_INTERPOLATE);
}
// subtracts given ammo from price, drops excess
virtual bool PickupForAmmoSWWM( SWWMWeapon ownedWeapon )
{

View file

@ -529,14 +529,14 @@ extend Class SWWMWeapon
invoker.wallponch = false;
// check for shootables
SWWMBulletTrail.DoTrail(self,origin,dir,DEFMELEERANGE*rangemul,0);
if ( TryMelee((raging?.3:.2)*spreadmul,dmg,hitsound,rangemul,kickmul,flags) )
return true;
bool res = TryMelee((raging?.3:.2)*spreadmul,dmg,hitsound,rangemul,kickmul,flags);
if ( !flags&MELEE_Rip ) return res;
// check for walls instead
FTranslatedLineTarget t;
double slope = AimLineAttack(angle,DEFMELEERANGE*rangemul,t,0.,ALF_CHECK3D);
FLineTraceData d;
LineTrace(angle,DEFMELEERANGE*rangemul,slope,TRF_THRUACTORS,player.viewheight,data:d);
if ( d.HitType == TRACE_HitNone ) return false;
if ( d.HitType == TRACE_HitNone ) return res;
Vector3 HitNormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
{
@ -570,7 +570,11 @@ extend Class SWWMWeapon
A_StartSound((raging&&!(flags&MELEE_ForceSound))?"demolitionist/xpunch":(hitsound!="")?hitsound:"demolitionist/punch",CHAN_WEAPON,CHANF_OVERLAP);
A_AlertMonsters(swwm_uncapalert?0:100);
if ( raging ) raging.DoHitFX();
if ( (flags&MELEE_ForceBust) || swwm_omnibust ) BusterWall.BustLinetrace(d,raging?(dmg*8):dmg,self,d.HitDir,d.HitLocation.z);
if ( (flags&MELEE_ForceBust) || swwm_omnibust )
{
if ( flags&MELEE_HammerHit ) dmg = dmg*2+200; // extra bust damage if it's the hammer
BusterWall.BustLinetrace(d,raging?(dmg*8):dmg,self,d.HitDir,d.HitLocation.z);
}
return true;
}
}