Class ShockAmmo : Ammo { Default { Tag "Shock Core"; Inventory.PickupMessage "You picked up a Shock Core."; Inventory.Amount 10; Inventory.MaxAmount 50; Ammo.BackpackAmount 20; Ammo.BackpackMaxAmount 100; Ammo.DropAmount 5; } States { Spawn: SHOA A -1; Stop; } } Class ShockAmmo2 : ShockAmmo { Default { Tag "Used Shock Core"; Inventory.PickupMessage "You picked up a used Shock Core."; Inventory.Amount 3; Ammo.DropAmount 3; } States { Spawn: SHOA A -1; Stop; } } Class ShockBeamTracer : LineTracer { Actor owner, ignore, lasthit; override ETraceStatus TraceCallback() { if ( Results.HitType == TRACE_HitActor ) { if ( (Results.HitActor == owner) || (Results.HitActor == ignore) || (Results.HitActor == lasthit) ) return TRACE_Skip; if ( Results.HitActor.bSHOOTABLE || Results.HitActor is 'ShockHitbox' ) return TRACE_Stop; return TRACE_Skip; } else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) ) { if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) ) return TRACE_Stop; return TRACE_Skip; } return TRACE_Stop; } } Class ShockRifleWave : Actor { Default { RenderStyle "Add"; Radius 0.1; Height 0; Scale 0.7; +NOBLOCKMAP; +NOGRAVITY; +DONTSPLASH; } override void Tick() { Super.Tick(); if ( globalfreeze || level.frozen ) return; alpha -= 1/50.; } States { Spawn: SWAV A 50 Bright; SWAV B 0 Bright; Stop; } } Class SuperShockRifleWave : Actor { Default { RenderStyle "Add"; Radius 0.1; Height 0; Scale 1.2; +NOBLOCKMAP; +NOGRAVITY; +DONTSPLASH; } override void Tick() { Super.Tick(); if ( globalfreeze || level.frozen ) return; alpha -= 1/50.; } States { Spawn: SWAV A 50 Bright; SWAV B 0 Bright; Stop; } } Class ShockBeamRing : Actor { Default { RenderStyle "Add"; Radius 0.1; Height 0; Scale 0.5; ReactionTime 18; +NOBLOCKMAP; +NOGRAVITY; +DONTSPLASH; } override void Tick() { Super.Tick(); if ( globalfreeze || level.frozen ) return; alpha -= 1./ReactionTime; } States { Spawn: SRNG ABCDEFGHI 2 Bright; Stop; } } Class SuperShockBeamRing : Actor { Default { RenderStyle "Add"; Radius 0.1; Height 0; Scale 0.9; ReactionTime 18; +NOBLOCKMAP; +NOGRAVITY; +DONTSPLASH; } override void Tick() { Super.Tick(); if ( globalfreeze || level.frozen ) return; alpha -= 1./ReactionTime; } States { Spawn: SRNG ABCDEFGHI 2 Bright; Stop; } } Class ShockBlastRing : ShockBeamRing { Default { Scale 3.0; ReactionTime 45; } States { Spawn: SRNG ABCDEFGHI 5 Bright; Stop; } } Class SuperShockBlastRing : ShockBeamRing { Default { Scale 5.0; ReactionTime 45; } States { Spawn: SRNG ABCDEFGHI 5 Bright; Stop; } } Class ShockSpark : Actor { Default { RenderStyle "Add"; Radius 2; Height 2; +NOBLOCKMAP; +NOGRAVITY; +MISSILE; +FORCEXYBILLBOARD; +THRUACTORS; +ROLLSPRITE; +ROLLCENTER; +NOTELEPORT; +DONTSPLASH; +CANBOUNCEWATER; -BOUNCEAUTOOFF; BounceType "Doom"; BounceFactor 1.0; WallBounceFactor 1.0; Scale 0.1; } override void PostBeginPlay() { Super.PostBeginPlay(); if ( !bAMBUSH ) { roll = FRandom[ASMD](0,360); let s = Spawn(GetClass(),pos); s.bAMBUSH = true; s.vel = vel; s.scale = scale; s.roll = roll; } } States { Spawn: ASMK A 1 Bright { A_FadeOut(FRandom[ASMD](0.0,0.1)); vel *= 0.98; } Wait; } } Class ShockSparkTrail : ShockSpark { Default { +AMBUSH; } override void PostBeginPlay() { Super.PostBeginPlay(); roll = FRandom[ASMD](0,360); } States { Spawn: ASMK A 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.2)); Wait; } } Class ShockBeam : Actor { ShockBeamTracer t; Vector3 tracedir; bool moving; double totaldist; Default { Obituary "%k inflicted mortal damage upon %o with the Shock Rifle"; DamageType 'jolted'; RenderStyle "Add"; Radius 0.1; Height 0; Scale 0.4; +NOGRAVITY; +NOCLIP; +DONTSPLASH; +FORCEXYBILLBOARD; +FORCERADIUSDMG; +NODAMAGETHRUST; } override void PostBeginPlay() { Super.PostBeginPlay(); t = new("ShockBeamTracer"); t.owner = target; t.ignore = self; moving = true; } override void Tick() { Super.Tick(); if ( globalfreeze || level.frozen ) return; if ( !moving ) return; // step trace tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); t.Trace(pos,cursector,tracedir,1000,0); totaldist += t.Results.Distance; // spawn particles for ( int i=0; i= 10000.0 ) { // reposition and explode on air SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true); ExplodeMissile(t.Results.HitLine,null); moving = false; let r = Spawn("ShockBeamRing",pos); r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x); r.pitch = asin(-t.Results.HitVector.z); } else if ( t.Results.HitType == TRACE_HitNone ) { // reposition SetOrigin(t.Results.HitPos+t.Results.HitVector,true); angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x); pitch = asin(-t.Results.HitVector.z); } else if ( t.Results.HitType == TRACE_HitActor ) { // reposition and explode on actor SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true); ExplodeMissile(null,t.Results.HitActor); if ( t.Results.HitActor is 'ShockHitbox' ) { if ( target ) { target.TakeInventory('ShockAmmo',2); UTMainHandler.DoSwing(target,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),5,-1,3,SWING_Spring,3,6); } let b = t.Results.HitActor.target; UTMainHandler.DoBlast(b,250,70000); b.ExplodeMissile(null,self); b.A_Explode(Random[ASMD](150,180),250); b.A_QuakeEx(6,6,6,60,0,1200,"",QF_RELATIVE|QF_SCALEDOWN,falloff:250,rollIntensity:0.2); b.A_SprayDecal("BigShockMark1",100); b.A_SprayDecal("BigShockMark2",100); Spawn("ShockRifleWave",b.pos); Spawn("ShockBlastLight",b.pos); let r = Spawn("ShockBlastRing",b.pos); r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x); r.pitch = asin(-t.Results.HitVector.z); A_PlaySound("shock/blast",CHAN_WEAPON,attenuation:0.5); int numpt = Random[ASMD](200,300); for ( int i=0; i= 10000.0 ) { // reposition and explode on air SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true); ExplodeMissile(t.Results.HitLine,null); moving = false; let r = Spawn("SuperShockBeamRing",pos); r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x); r.pitch = asin(-t.Results.HitVector.z); } else if ( t.Results.HitType == TRACE_HitNone ) { // reposition SetOrigin(t.Results.HitPos+t.Results.HitVector,true); angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x); pitch = asin(-t.Results.HitVector.z); } else if ( t.Results.HitType == TRACE_HitActor ) { // reposition and explode on actor SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true); ExplodeMissile(null,t.Results.HitActor); if ( t.Results.HitActor is 'ShockHitbox' ) { if ( target ) { target.TakeInventory('EnhancedShockAmmo',1); UTMainHandler.DoSwing(target,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),10,-2,3,SWING_Spring,3,6); } let b = t.Results.HitActor.target; UTMainHandler.DoBlast(b,400,70000); b.ExplodeMissile(null,self); b.A_Explode(Random[ASMD](15000,16000),400); b.A_QuakeEx(9,9,9,60,0,2400,"",QF_RELATIVE|QF_SCALEDOWN,falloff:400,rollIntensity:0.4); b.A_SprayDecal("BigShockMark1",100); b.A_SprayDecal("SBigShockMark2",100); Spawn("SuperShockRifleWave",b.pos); Spawn("SuperShockBlastLight",b.pos); let r = Spawn("SuperShockBlastRing",b.pos); r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x); r.pitch = asin(-t.Results.HitVector.z); A_PlaySound("shock/blast",CHAN_WEAPON,attenuation:0.5); A_PlaySound("sshock/blast",CHAN_6,attenuation:0.5); int numpt = Random[ASMD](200,300); for ( int i=0; i 0 ) Amount--; } Default { Tag "Enhanced Shock Core"; Inventory.PickupMessage "You picked up an Enhanced Shock Core."; Inventory.Amount 5; Inventory.MaxAmount 50; Ammo.BackpackAmount 0; Ammo.BackpackMaxAmount 50; Ammo.DropAmount 2; } States { Spawn: SHOA A -1; Stop; } } Class ViewSuperShockSpark : ViewShockSpark { States { Spawn: SSMK A 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.1)); Wait; } } Class EnhancedShockRifle : UTWeapon { override void PostBeginPlay() { Super.PostBeginPlay(); } action void A_SShockFire() { Weapon weap = Weapon(invoker); if ( !weap ) return; if ( weap.Ammo1.Amount <= 0 ) return; if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return; A_PlaySound("shock/fire",CHAN_WEAPON); invoker.FireEffect(); UTMainHandler.DoFlash(self,Color(128,255,128,0),1); UTMainHandler.DoSwing(self,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),4,-0.6,3,SWING_Spring,0,4); A_AlertMonsters(); A_QuakeEx(3,3,3,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.15); Vector3 x, y, z; [x, y, z] = Matrix4.GetAxes(pitch,angle,roll); Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+2.0*y-1.5*z; Actor p = Spawn("SuperShockBeam",origin); p.angle = angle; p.pitch = BulletSlope(); p.target = self; for ( int i=0; i<12; i++ ) { let s = Spawn("UTViewSmoke",origin); UTViewSmoke(s).ofs = (10,2,-1.5); s.scale *= 1.8; s.target = self; s.SetShade("FFC040"); s.A_SetRenderStyle(0.4,STYLE_AddShaded); UTViewSmoke(s).vvel += (FRandom[ASMD](0.2,0.6),FRandom[ASMD](-0.2,0.2),FRandom[ASMD](-0.2,0.2)); } int numpt = Random[ASMD](20,40); for ( int i=0; i