flak_m/zscript/impacthammer.zsc
Marisa Kirisame 72eb6ca8d1 Impact Hammer fully implemented. Began working on Chainsaw.
Tweaked the shake effect on all weapons.
Covered up some seams on redeemer texture. Moved the model slightly to cover up a gap.
Corrected the chainsaw and translocator HUD icons.
2018-05-26 00:10:31 +02:00

268 lines
8.6 KiB
Text

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,realcharge);
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*6,realcharge*6,realcharge*6,16,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:realcharge*0.2);
realcharge = max(1.0,realcharge);
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,1,"",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 "impact/select";
Weapon.SlotNumber 1;
Weapon.SelectionOrder 9;
+WEAPON.MELEEWEAPON;
}
States
{
Spawn:
IMPP A -1;
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;
}
}