Impact Hammer fully implemented.

This commit is contained in:
Marisa the Magician 2018-05-25 20:16:37 +02:00
commit 1ddda70712
19 changed files with 428 additions and 40 deletions

View file

@ -1,14 +1,188 @@
Class ImpactHammer : UTWeapon replaces Fist
Class HammerImpact : Actor
{
Default
{
Radius 0.1;
Height 0;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_SprayDecal("ImpactMark",20);
int numpt = Random[Impact](20,40);
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Impact](-.8,.8),FRandom[Impact](-.8,.8),FRandom[Impact](-.8,.8))).unit()*FRandom[Impact](1,3);
A_SpawnParticle(Color(1,1,1)*Random[Impact](128,192),0,Random[Impact](30,60),FRandom[Impact](2,8),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0.03,0.5,-1,0.5);
}
numpt = Random[Impact](8,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Impact](-1,1),FRandom[Impact](-1,1),FRandom[Impact](-1,1)).unit()*FRandom[Impact](2,4);
A_SpawnParticle("FFA000",SPF_FULLBRIGHT,Random[Impact](10,20),FRandom[Impact](1.2,3.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,3.0,-1,-0.25);
}
Destroy();
}
}
Class ImpactHammer : UTWeapon replaces Fist
{
double chargesize, count;
action void A_ResetCharge()
{
invoker.chargesize = 0;
invoker.count = 0;
invoker.FireEffect(); // intentional UT behavior
}
action void A_ChargeUp( int amt = 1 )
{
invoker.chargesize += (0.75*amt)/TICRATE;
invoker.count += double(amt)/TICRATE;
if ( invoker.count > 0.2 )
{
invoker.count = 0;
A_AlertMonsters();
}
A_QuakeEx(clamp(invoker.chargesize*3,0,3),clamp(invoker.chargesize*3,0,3),clamp(invoker.chargesize*3,0,3),amt+1,0,96,"",QF_RELATIVE,rollIntensity:clamp(invoker.chargesize*0.3,0,0.3));
}
action void A_FireBlast()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
A_PlaySound("impact/release",CHAN_WEAPON);
invoker.FireEffect();
A_AlertMonsters();
Vector3 x, y, z;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+3.0*y-4.0*z;
double realcharge = min(1.5,invoker.chargesize);
FLineTraceData d;
LineTrace(angle,80,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
if ( d.HitType == TRACE_HitActor )
{
d.HitActor.DamageMobj(invoker,self,60*realcharge,'impact');
d.HitActor.vel += x*(1000/d.HitActor.mass)*realcharge;
if ( d.HitActor.bNOBLOOD )
{
let p = Spawn("HammerImpact",d.HitLocation-d.HitDir*4);
p.angle = atan2(d.HitDir.y,d.HitDir.x);
p.pitch = asin(-d.HitDir.z);
}
else
{
d.HitActor.TraceBleed(60*realcharge,invoker);
d.HitActor.SpawnBlood(d.HitLocation,atan2(-d.HitDir.y,-d.HitDir.x),60*realcharge);
}
}
else if ( d.HitType != TRACE_HitNone )
{
realcharge = max(1.0,invoker.chargesize);
DamageMobj(invoker,self,24*realcharge,'impact'); // It's a flat damage of 36 on UT, but I think it's more fair for it to scale
TraceBleed(24*realcharge,invoker);
vel -= x*(1200/mass)*realcharge;
let p = Spawn("HammerImpact",d.HitLocation-d.HitDir*4);
p.angle = atan2(d.HitDir.y,d.HitDir.x);
p.pitch = asin(-d.HitDir.z);
if ( d.HitType == TRACE_HitWall ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation-d.HitDir*4);
}
A_QuakeEx(realcharge*4,realcharge*4,realcharge*4,12,0,96,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:realcharge*0.2);
realcharge = max(1.0,invoker.chargesize);
int numpt = Random[Impact](20,40);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Impact](-.4,.4),FRandom[Impact](-.4,.4),FRandom[Impact](-.4,.4))).unit()*FRandom[Impact](1,3)*realcharge;
A_SpawnParticle(Color(1,1,1)*Random[Impact](128,192),0,Random[Impact](30,60),FRandom[Impact](2,8),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0.03,0.5,-1,0.5);
}
numpt = Random[Impact](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Impact](-.5,.5),FRandom[Impact](-.5,.5),FRandom[Impact](-.5,.5))).unit()*FRandom[Impact](2,4)*realcharge;
A_SpawnParticle(Color(1,1,1)*Random[Impact](16,64),0,Random[Impact](5,10),FRandom[Impact](0.3,0.8),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,-0.2,2.,-0.1);
}
}
action void A_FireAltBlast()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
A_PlaySound("impact/fire",CHAN_WEAPON);
invoker.FireEffect();
A_AlertMonsters();
A_QuakeEx(2,2,2,6,0,96,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+3.0*y-4.0*z;
FLineTraceData d;
LineTrace(angle,180,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
double dscale = d.Distance/180.;
if ( d.HitType == TRACE_HitActor )
{
d.HitActor.DamageMobj(invoker,self,20*dscale,'impact');
d.HitActor.vel += x*(500/d.HitActor.mass)*dscale;
}
else if ( d.HitType != TRACE_HitNone )
{
DamageMobj(invoker,self,24*dscale,'impact');
vel -= x*(600/mass)*dscale;
if ( d.HitType == TRACE_HitWall ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation-d.HitDir*4);
}
// push aside projectiles
let t = ThinkerIterator.Create("Actor");
Actor m;
while ( m = Actor(t.Next()) )
{
if ( !m.bMISSILE ) continue;
double rdist = level.Vec3Diff(origin,m.pos).length();
Vector3 rdir = level.Vec3Diff(origin,m.pos).unit();
if ( LineTrace(atan2(rdir.y,rdir.x),rdist,asin(-rdir.z),TRF_THRUACTORS|TRF_ABSPOSITION,origin.z,origin.x,origin.y) || (rdist > 550) || (rdir dot x < 0.9) ) continue;
m.speed = m.vel.length();
if ( m.vel dot y > 0 ) m.vel = m.speed*(m.vel+(750-rdist)*y*0.01).unit();
else m.vel = m.speed*(m.vel-(750-rdist)*y*0.01).unit();
if ( m.target == self ) continue;
if ( m.bSEEKERMISSILE ) m.tracer = m.target;
m.target = self;
}
int numpt = Random[Impact](20,40);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Impact](-.4,.4),FRandom[Impact](-.4,.4),FRandom[Impact](-.4,.4))).unit()*FRandom[Impact](1,3);
A_SpawnParticle(Color(1,1,1)*Random[Impact](128,192),0,Random[Impact](30,60),FRandom[Impact](2,8),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0.03,0.5,-1,0.5);
}
numpt = Random[Impact](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Impact](-.5,.5),FRandom[Impact](-.5,.5),FRandom[Impact](-.5,.5))).unit()*FRandom[Impact](2,4);
A_SpawnParticle(Color(1,1,1)*Random[Impact](16,64),0,Random[Impact](5,10),FRandom[Impact](0.3,0.8),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,-0.2,2.,-0.1);
}
}
action void A_ImpactRefire( statelabel flash = null )
{
FLineTraceData d;
Vector3 x, y, z;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+3.0*y-4.0*z;
LineTrace(angle,40,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
if ( (invoker.chargesize > 1) && (d.HitType == TRACE_HitActor) )
{
A_ClearRefire();
return;
}
A_Refire(flash);
}
Default
{
Tag "Impact Hammer";
Obituary "%o was smeared by %k's piston.";
Inventory.PickupMessage "You got the Impact Hammer.";
Weapon.UpSound "";
Weapon.UpSound "impact/select";
Weapon.SlotNumber 1;
Weapon.SelectionOrder 9;
+WEAPON.MELEEWEAPON;
+INVENTORY.UNTOSSABLE;
}
States
{
@ -17,5 +191,78 @@ Class ImpactHammer : UTWeapon replaces Fist
Stop;
IMPP B -1;
Stop;
Select:
IMPS A 1 A_Raise(int.max);
Wait;
Ready:
IMPS ABCDEFGHIJKLMNOPQ 1;
Idle:
IMPI A 1 A_WeaponReady();
Wait;
Fire:
IMPL A 0
{
A_ResetCharge();
A_PlaySound("impact/pull",CHAN_WEAPON);
}
IMPL A 5 A_ChargeUp(5);
IMPL B 0 A_ImpactRefire(1);
Goto Release;
IMPL B 5 A_ChargeUp(5);
IMPL C 0 A_ImpactRefire(1);
Goto Release;
IMPL C 5 A_ChargeUp(5);
IMPL D 0 A_ImpactRefire(1);
Goto Release;
IMPL D 5 A_ChargeUp(5);
IMPL E 0 A_ImpactRefire(1);
Goto Release;
IMPL E 5 A_ChargeUp(5);
IMPL E 0 A_ImpactRefire(1);
Goto Release;
IMPL E 0 A_PlaySound("impact/loop",CHAN_WEAPON,looping:true);
Hold:
IMPR A 1 A_ChargeUp();
IMPR B 0 A_ImpactRefire(1);
Goto Release;
IMPR B 1 A_ChargeUp();
IMPR C 0 A_ImpactRefire(1);
Goto Release;
IMPR C 1 A_ChargeUp();
IMPR D 0 A_ImpactRefire(1);
Goto Release;
IMPR D 1 A_ChargeUp();
IMPR E 0 A_ImpactRefire(1);
Goto Release;
IMPR E 1 A_ChargeUp();
IMPR F 0 A_ImpactRefire(1);
Goto Release;
IMPR F 1 A_ChargeUp();
IMPR G 0 A_ImpactRefire(1);
Goto Release;
IMPR G 1 A_ChargeUp();
IMPR H 0 A_ImpactRefire(1);
Goto Release;
IMPR H 1 A_ChargeUp();
IMPR I 0 A_ImpactRefire(1);
Goto Release;
IMPR I 1 A_ChargeUp();
IMPR J 0 A_ImpactRefire(1);
Goto Release;
IMPR J 1 A_ChargeUp();
IMPR A 0 A_ImpactRefire("Hold");
Goto Release;
Release:
IMPF A 0 A_FireBlast();
IMPF AABCCDEEFGGHIIJKKLMMNOOP 1;
Goto Idle;
AltFire:
IMPF A 0 A_FireAltBlast();
IMPF ABCDEFGHIJKLMNOP 1;
Goto Idle;
Deselect:
IMPD ABCDE 3;
IMPD E 1 A_Lower(int.max);
Wait;
}
}

View file

@ -6,7 +6,6 @@ Class Translocator : UTWeapon
Inventory.PickupMessage "You got the Translocator Source Module.";
Weapon.SlotNumber 1;
Weapon.SelectionOrder 10;
+INVENTORY.UNTOSSABLE;
+WEAPON.NO_AUTO_SWITCH;
}
States

View file

@ -79,7 +79,7 @@ Class UTHud : BaseStatusBar
Slots[7] = TexMan.CheckForTexture("SlotFlak",TexMan.Type_Any);
Slots[8] = TexMan.CheckForTexture("Slot8bal",TexMan.Type_Any);
Slots[9] = TexMan.CheckForTexture("SlotRifl",TexMan.Type_Any);
Icons[0] = TexMan.CheckForTexture("IconImp",TexMan.Type_Any);
Icons[0] = TexMan.CheckForTexture("IconImpH",TexMan.Type_Any);
Icons[1] = TexMan.CheckForTexture("IconAuto",TexMan.Type_Any);
Icons[2] = TexMan.CheckForTexture("IconBio",TexMan.Type_Any);
Icons[3] = TexMan.CheckForTexture("IconASMD",TexMan.Type_Any);
@ -93,7 +93,7 @@ Class UTHud : BaseStatusBar
Icons[11] = TexMan.CheckForTexture("IconTrns",TexMan.Type_Any);
Icons[12] = TexMan.CheckForTexture("IconWarH",TexMan.Type_Any);
Icons[13] = TexMan.CheckForTexture("IconASMD",TexMan.Type_Any);
Uses[0] = TexMan.CheckForTexture("UseImp",TexMan.Type_Any);
Uses[0] = TexMan.CheckForTexture("UseImpH",TexMan.Type_Any);
Uses[1] = TexMan.CheckForTexture("UseAuto",TexMan.Type_Any);
Uses[2] = TexMan.CheckForTexture("UseBio",TexMan.Type_Any);
Uses[3] = TexMan.CheckForTexture("UseASMD",TexMan.Type_Any);
@ -360,18 +360,14 @@ Class UTHud : BaseStatusBar
CurY = BaseY+4*WeapScale;
DrawColor = GoldColor;
UTDrawColorTex(BigNum[(i==9)?0:(i+1)],0.6);
if ( !wslots[i].Ammo1 ) return;
if ( !wslots[i].Ammo1 ) continue;
CurY = BaseY+52*WeapScale;
Vector2 ss = (0.6875,0.5)*WeapScale;
double dw = (Screen.GetWidth()/ss.x), dh = (Screen.GetHeight()/ss.y);
double dx = CurX/ss.x, dy = CurY/ss.y;
Vector2 bs = TexMan.GetScaledSize(AmmoBar);
double ddw = bs.x*(wslots[i].Ammo1.Amount/double(wslots[i].Ammo1.MaxAmount));
int cx, cy, cw, ch;
[cx,cy,cw,ch] = Screen.GetClipRect();
Screen.SetClipRect(CurX,CurY,ddw*ss.x,bs.y*ss.y);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true);
Screen.SetClipRect(cx,cy,cw,ch);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw);
}
}
private void DrawFragCount()