From e571fccc4d03e30852e8402057038730cc2ff6b6 Mon Sep 17 00:00:00 2001 From: Marisa the Magician Date: Wed, 28 Sep 2022 21:00:24 +0200 Subject: [PATCH] Mortal Rifle fully implemented (oh my). --- FuturePlans.md | 4 +- language.def_base | 2 +- language.es_base | 2 +- language.version | 4 +- modeldef.mortalrifle | 31 ++ models/extra/MRBoltS.png | Bin 4363 -> 4015 bytes palettes/Cyanblu.pal | Bin 768 -> 1536 bytes zscript/dlc1/swwm_dlcweapons_hud.zsc | 2 - zscript/dlc1/swwm_mister.zsc | 370 ++++++++++++++++++++- zscript/dlc1/swwm_mister_fx.zsc | 291 +++++++++++++++- zscript/handler/swwm_handler_worldtick.zsc | 4 +- zscript/hud/swwm_hud.zsc | 2 +- zscript/hud/swwm_hudobjects.zsc | 5 +- zscript/swwm_common_fx.zsc | 2 +- zscript/utility/swwm_utility.zsc | 7 + zscript/weapons/swwm_thiccboolet.zsc | 1 + 16 files changed, 700 insertions(+), 27 deletions(-) diff --git a/FuturePlans.md b/FuturePlans.md index 6ea26fe1c..5f74bcb17 100644 --- a/FuturePlans.md +++ b/FuturePlans.md @@ -22,8 +22,8 @@ More weapons, because we need 'em. In addition, all the "easy to implement" mini - [8] Ray-Khom *(UnSX)* - The Most Silent Takedown *(Kill 40 enemies with the Ray-Khom primary without alerting them)* - John Romero's Curse *(Fry yourself by discharging an electric weapon in water)* - - [9] Mortal Rifle *(UnSX 2)* - - Railed Hard *(Shoot through 44 enemies with a single Mortal Rifle overpressure shot)* + - ✓ [9] Mortal Rifle *(UnSX 2)* + - ✓ Railed Hard *(Kill 44 enemies with a single Mortal Rifle overpressure shot)* - [0] Rafan-Kos *(UnSX 4)* - Blasting Ropes *(Melt a grand total of 5000 enemies with the Rafan-Kos)* * ☑ **Additional Voice Acting:** diff --git a/language.def_base b/language.def_base index 2fca323ef..e345e7c45 100644 --- a/language.def_base +++ b/language.def_base @@ -1304,7 +1304,7 @@ SWWM_ACHIEVEMENT_PUZZLE_TXT = "Solve all fractions of \"puzzles\" in the same sa SWWM_ACHIEVEMENT_RAGE_TAG = "No Talk me Angy"; SWWM_ACHIEVEMENT_RAGE_TXT = "Use %s Ragekits"; SWWM_ACHIEVEMENT_RAIL_TAG = "Railed Hard"; -SWWM_ACHIEVEMENT_RAIL_TXT = "Shoot through %s enemies with a single Mortal Rifle overpressure shot"; +SWWM_ACHIEVEMENT_RAIL_TXT = "Kill %s enemies with a single Mortal Rifle overpressure shot"; SWWM_ACHIEVEMENT_REFLECT_TAG = "Return to Sender"; SWWM_ACHIEVEMENT_REFLECT_TXT = "Kill %s enemies with parried projectiles"; SWWM_ACHIEVEMENT_REFRESH_TAG = "Stay Fresh"; diff --git a/language.es_base b/language.es_base index 995b0cc5e..31a635381 100644 --- a/language.es_base +++ b/language.es_base @@ -1151,7 +1151,7 @@ SWWM_ACHIEVEMENT_PUZZLE_TXT = "Resuelve todas las partes de \"puzzles\" en la mi SWWM_ACHIEVEMENT_RAGE_TAG = "No Hablo me Enfado"; SWWM_ACHIEVEMENT_RAGE_TXT = "Usa %s Ragekits"; SWWM_ACHIEVEMENT_RAIL_TAG = "Metida de Través"; -SWWM_ACHIEVEMENT_RAIL_TXT = "Atraviesa %s enemigos con un solo disparo a presión del Rifle Mortal"; +SWWM_ACHIEVEMENT_RAIL_TXT = "Mata %s enemigos con un solo disparo a presión del Rifle Mortal"; SWWM_ACHIEVEMENT_REFLECT_TAG = "Devuelto a Remitente"; SWWM_ACHIEVEMENT_REFLECT_TXT = "Mata %s enemigos con proyectiles desviados"; SWWM_ACHIEVEMENT_REFRESH_TAG = "Siempre Fresco"; diff --git a/language.version b/language.version index d49f6a3f2..4b2fca2a6 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r523 \cu(Wed 28 Sep 17:58:30 CEST 2022)\c-"; -SWWM_SHORTVER="\cw1.3pre r523 \cu(2022-09-28 17:58:30)\c-"; +SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r524 \cu(Wed 28 Sep 21:00:24 CEST 2022)\c-"; +SWWM_SHORTVER="\cw1.3pre r524 \cu(2022-09-28 21:00:24)\c-"; diff --git a/modeldef.mortalrifle b/modeldef.mortalrifle index 7680ef7a4..71e659836 100644 --- a/modeldef.mortalrifle +++ b/modeldef.mortalrifle @@ -80,6 +80,37 @@ Model "MisterSubGrenade" FrameIndex XZW1 A 0 0 } +Model "MisterRailBeam" +{ + Path "models/extra" + + Model 0 "YBeam.obj" + Skin 0 "MRBolt.png" + Scale 1 1 0.6 + USEACTORPITCH + USEACTORROLL + DONTCULLBACKFACES + + FrameIndex XZW1 A 0 0 + Skin 0 "MRBoltS.png" + FrameIndex XZW1 B 0 0 +} +Model "MisterRailChildBeam" +{ + Path "models/extra" + + Model 0 "YBeam.obj" + Skin 0 "MRBolt.png" + Scale 1 1 0.6 + USEACTORPITCH + USEACTORROLL + DONTCULLBACKFACES + + FrameIndex XZW1 A 0 0 + Skin 0 "MRBoltS.png" + FrameIndex XZW1 B 0 0 +} + Model "MisterRifle" { Path "models" diff --git a/models/extra/MRBoltS.png b/models/extra/MRBoltS.png index d90a9b2953d5422f5e30912d33a0199d51ea6d27..bbc833d14487e0c48a33fa0bffe3c205a6ce2feb 100644 GIT binary patch literal 4015 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 RVPIfj@O1TaS?83{1ORR&9bo_f diff --git a/palettes/Cyanblu.pal b/palettes/Cyanblu.pal index 725b1e3506946a3db46759acbb61e965088d349c..95128d9170f60ecaef0d992271778bbad47fb94c 100644 GIT binary patch delta 781 zcmZo*Yv5VHTwhyTTLVVbwYAkXHPtmWRn^s%U{q0ET~Sq4UR70ASy@(DSz1|HT2WB~ zM#U8s#pUJ2<>f`?<%Q+tg=J+0V3c20mS0+$S6Z4|T9R7=LOI37*~P_K#YI^~MVUoK znT3Vvg#{o~P>@zokXoOgpOT-Sl9!i~mzSKEmz0;AlnX+Mxw#3sIUtmi6Q7e4my;cr z4MMS5Sut5z(OH?%nIIIIkrA1Z5s{G|o}M0_mKK(p8k(9KlA02nk`kPp9F&|Kn3x!l znCPFF;Fpl#7a#8v7v~)p>lGX86%*qT9qk@nALSMq=^7E?91-pm7UmEdY9AVE8ysvC z6l4_`XyNZ~=I3YR<743Mt?TKj?&hZCbm0Ux?*ZDq^ctZLfT>~P$a6X4MSR@N?M{ynxaaYB8p(7pdq55E+VfkEUzvs zrv^r>67>oK67u}w^8Dg*{9>~FVzPXqG9V-( z%_}0!D=Y;PS3d?K8@!koN9oIHXY+yWfj{Onx( z>|A_ooV;utJZv1?tnA#Z>|88toGh#yEUfIzEbPq8tjx@;Od!O<#Kg?V#LULX$i&FV F1OS!Mw~zn; delta 6 NcmZqRX<%Ex3;+g~0k!}D diff --git a/zscript/dlc1/swwm_dlcweapons_hud.zsc b/zscript/dlc1/swwm_dlcweapons_hud.zsc index 05e66c795..99ecd94f1 100644 --- a/zscript/dlc1/swwm_dlcweapons_hud.zsc +++ b/zscript/dlc1/swwm_dlcweapons_hud.zsc @@ -163,8 +163,6 @@ extend Class MisterRifle for ( int i=0; i hitlist; + Array hitlist; Array shootthroughlist; Array waterhitlist; + Array portalseg; - double RealMaxDist; + double maxdist; bool pastwall, fullstop; Array WallPenetrateList; @@ -34,16 +47,35 @@ Class MisterRailTracer : LineTracer hl.hitpos = Results.Crossed3DWaterPos; WaterHitList.Push(hl); } - if ( Results.HitType == TRACE_HitActor ) + if ( Results.HitType == TRACE_CrossingPortal ) + { + let seg = new("MRRailSeg"); + seg.enter = Results.HitPos; + seg.exit = Results.SrcFromTarget; + portalseg.Push(seg); + } + else if ( Results.HitType == TRACE_HitActor ) { if ( Results.HitActor == ignoreme ) return TRACE_Skip; if ( Results.HitActor.bSHOOTABLE ) { - let ent = new("HitListEntry"); + let ent = new("MRHitListEntry"); ent.hitactor = Results.HitActor; ent.hitlocation = Results.HitPos; ent.x = Results.HitVector; ent.pastwall = pastwall; + ent.bExit = false; + hitlist.Push(ent); + // also include exit point if we can reach it + Vector3 exit = SWWMUtility.TraceExit(Results.HitActor,Results.HitPos,Results.HitVector); + if ( level.Vec3Diff(Results.HitPos,exit).length() > (maxdist-Results.Distance) ) + return TRACE_Skip; // exit point is beyond our max distance + ent = new("MRHitListEntry"); + ent.hitactor = Results.HitActor; + ent.hitlocation = exit; + ent.x = Results.HitVector; + ent.pastwall = pastwall; + ent.bExit = true; hitlist.Push(ent); return TRACE_Skip; } @@ -62,7 +94,7 @@ Class MisterRailTracer : LineTracer if ( (Results.Tier == TIER_Middle) && Results.HitLine.sidedef[1] && !(Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) ) return TRACE_Skip; } - int maxstep = int(RealMaxDist-Results.Distance); + int maxstep = int(maxdist-Results.Distance); for ( int i=1; i<=maxstep; i++ ) { Vector3 ofs = Results.HitPos+Results.HitVector*i; @@ -144,6 +176,26 @@ Class MisterRailTracer : LineTracer } } +Class MisterRailCounter : Thinker +{ + PlayerInfo player; + Array effectors; + int nkill; + + override void Tick() + { + int neff = 0; + for ( int i=0; i 0 ) return; + SWWMUtility.AchievementProgress("rail",nkill,player); + Destroy(); + } +} + Class MisterRifle : SWWMWeapon { int clipcount; @@ -152,7 +204,7 @@ Class MisterRifle : SWWMWeapon bool boltlock; bool waschambered; bool wasgchambered; - int prefirecnt; + double prefirecnt; transient int holdtic; int firemode; ui int lastfiremode; @@ -165,8 +217,6 @@ Class MisterRifle : SWWMWeapon Property ClipCount : clipcount; - transient MisterRailTracer mrt; // I pity the fool - override void InitializeWeapon() { // no round in the chamber @@ -694,8 +744,15 @@ Class MisterRifle : SWWMWeapon A_StartSound("mister/cancelover",CHAN_WEAPON,CHANF_OVERLAP); return ResolveState("FireOverpressureCancel"); } - if ( invoker.prefirecnt == 99 ) invoker.holdtic = gametic; - invoker.prefirecnt = min(100,int(invoker.prefirecnt+1)); + if ( invoker.prefirecnt < 100 ) + { + invoker.prefirecnt += 1.5; + if ( invoker.prefirecnt >= 100 ) + { + invoker.prefirecnt = 100; + invoker.holdtic = gametic; + } + } A_SoundVolume(CHAN_WEAPONEXTRA,clamp(invoker.prefirecnt*.01,.01,1.)); A_SoundPitch(CHAN_WEAPONEXTRA,clamp(.5+invoker.prefirecnt*.005,.5,1.)**.5); if ( (invoker.prefirecnt >= 100) && !((gametic-invoker.holdtic)%32) && CheckLocalView() ) @@ -719,6 +776,299 @@ Class MisterRifle : SWWMWeapon A_QuakeEx(8,8,8,12,0,10,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:2.); A_BumpFOV(.85); A_AlertMonsters(swwm_uncapalert?0:12000); + for ( int i=0; i<12; i++ ) + { + let s = Spawn("SWWMSmoke",origin); + s.scale *= .4; + s.alpha *= .1; + s.vel += vel*.5+x*FRandom[Mister](1.,12.); + s.SetShade(Color(0,3,4)*Random[ExploS](48,63)); + } + Vector3 dir, startdir; + startdir = dir = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll); + let mrt = new("MisterRailTracer"); // I pity the fool + mrt.ignoreme = self; + mrt.hitlist.Clear(); + mrt.shootthroughlist.Clear(); + mrt.waterhitlist.Clear(); + mrt.wallpenetratelist.Clear(); + mrt.ffloors.Clear(); + mrt.portalseg.Clear(); + for ( int i=0; i 32 ) + { + b = Spawn("MisterRailBeam",sstart); + b.frame = 1; + b.scale.y = 32; + b.angle = atan2(sdir.y,sdir.x); + b.pitch = asin(-sdir.z)+90; + MisterRailBeam(b).mrc = mrc; + mrc.effectors.Push(b); + sstart += sdir*32; + sdist -= 32; + b = Spawn("MisterRailBeam",sstart); + } + else + { + b = Spawn("MisterRailBeam",sstart); + b.frame = 1; + } + b.scale.y = sdist; + b.angle = atan2(sdir.y,sdir.x); + b.pitch = asin(-sdir.z)+90; + MisterRailBeam(b).mrc = mrc; + mrc.effectors.Push(b); + } + else for ( int i=0; i 32 ) + { + b = Spawn("MisterRailBeam",sstart); + b.target = self; + b.frame = 1; + b.scale.y = 32; + b.angle = atan2(sdir.y,sdir.x); + b.pitch = asin(-sdir.z)+90; + MisterRailBeam(b).mrc = mrc; + mrc.effectors.Push(b); + sstart += sdir*32; + sdist -= 32; + b = Spawn("MisterRailBeam",sstart); + } + else + { + b = Spawn("MisterRailBeam",sstart); + b.frame = 1; + } + } + else b = Spawn("MisterRailBeam",sstart); + b.target = self; + b.scale.y = sdist; + b.angle = atan2(sdir.y,sdir.x); + b.pitch = asin(-sdir.z)+90; + MisterRailBeam(b).mrc = mrc; + mrc.effectors.Push(b); + sstart = mrt.portalseg[i].exit; + if ( i == (mrt.portalseg.Size()-1) ) + { + sdir = mrt.Results.HitPos-sstart; + sdist = sdir.length(); + sdir /= sdist; + b = Spawn("MisterRailBeam",sstart); + b.target = self; + b.scale.y = sdist; + b.angle = atan2(sdir.y,sdir.x); + b.pitch = asin(-sdir.z)+90; + MisterRailBeam(b).mrc = mrc; + mrc.effectors.Push(b); + } + } + for ( int i=0; i bi; // so we can ignite them all at once after main contact damage + for ( int i=0; i 0 ) + { + Vector3 start = origin; + Vector3 end = mrt.WallPenetrateList[0].hitpos; + Vector3 tdir = level.Vec3Diff(start,end); + double dist = tdir.length(); + tdir /= dist; + for ( double d=4.; d<=dist; d+=8. ) + { + if ( !Random[ExploS](0,1) ) continue; + Vector3 ofs = level.Vec3Offset(start,tdir*d); + if ( !level.IsPointInLevel(ofs) ) continue; + let b = Spawn("SWWMHalfSmoke",ofs); + b.Scale *= FRandom[ExploS](.7,1.4); + b.alpha *= .2; + b.special1 = Random[ExploS](1,3); + b.SetShade(Color(2,3,4)*Random[ExploS](48,63)); + } + for ( int i=1; i= mrt.WallPenetrateList.Size()-1 ) end = mrt.Results.HitPos; + else end = mrt.WallPenetrateList[i+1].hitpos; + tdir = level.Vec3Diff(start,end); + dist = tdir.length(); + tdir /= dist; + for ( double d=4.; d<=dist; d+=8. ) + { + if ( !Random[ExploS](0,1) ) continue; + Vector3 ofs = level.Vec3Offset(start,tdir*d); + if ( !level.IsPointInLevel(ofs) ) continue; + let b = Spawn("SWWMHalfSmoke",ofs); + b.Scale *= FRandom[ExploS](.7,1.4); + b.alpha *= .2; + b.special1 = Random[ExploS](1,3); + b.SetShade(Color(2,3,4)*Random[ExploS](48,63)); + } + } + } + else + { + for ( double d=4.; d<=mrt.Results.Distance; d+=8. ) + { + if ( !Random[ExploS](0,1) ) continue; + Vector3 ofs = level.Vec3Offset(origin,startdir*d); + if ( !level.IsPointInLevel(ofs) ) continue; + let b = Spawn("SWWMHalfSmoke",ofs); + b.Scale *= FRandom[ExploS](.7,1.4); + b.alpha *= .2; + b.special1 = Random[ExploS](1,3); + b.SetShade(Color(2,3,4)*Random[ExploS](48,63)); + } + } } action void A_MisterFireGrenade() diff --git a/zscript/dlc1/swwm_mister_fx.zsc b/zscript/dlc1/swwm_mister_fx.zsc index 037b4ca6f..32684b350 100644 --- a/zscript/dlc1/swwm_mister_fx.zsc +++ b/zscript/dlc1/swwm_mister_fx.zsc @@ -191,6 +191,7 @@ Class MisterBulletImpactPop : Actor Class MisterFuzzy : Actor { + MisterRailCounter mrc; Default { Obituary "$O_MORTALRIFLE"; @@ -215,7 +216,9 @@ Class MisterFuzzy : Actor override void Tick() { if ( isFrozen() ) return; - SWWMUtility.DoExplosion(self,(special2<0)?4:44,3000,80,80,DE_EXTRAZTHRUST); + int nhit, nkill; + [nhit, nkill] = SWWMUtility.DoExplosion(self,(special2<0)?4:44,3000,80,80,DE_EXTRAZTHRUST|DE_COUNTENEMIES); + if ( mrc ) mrc.nkill += nkill; special1--; if ( special1 <= 0 ) { @@ -332,6 +335,7 @@ Class MisterFuzzyTrail : Actor Class MisterPop : Actor { + MisterRailCounter mrc; Default { Obituary "$O_MORTALRIFLE"; @@ -368,13 +372,18 @@ Class MisterPop : Actor Spawn: TNT1 A 1 NoDelay { - A_SetTics(Random[ExploS](1,5)); + A_SetTics(Random[ExploS](1,15)); Scale *= FRandom[ExploS](.5,1.5); Scale.x *= RandomPick[ExploS](-1,1); Scale.y *= RandomPick[ExploS](-1,1); roll = FRandom[ExploS](0,360); } - BLPF C 2 Bright { SWWMUtility.DoExplosion(self,4,2000,50,50,DE_EXTRAZTHRUST); } + BLPF C 2 Bright + { + int nhit, nkill; + [nhit, nkill] = SWWMUtility.DoExplosion(self,4,2000,50,50,DE_EXTRAZTHRUST|DE_COUNTENEMIES); + if ( mrc ) mrc.nkill += nkill; + } TNT1 A 1 { let p = Spawn("MisterFuzzyTrail",pos); @@ -387,6 +396,7 @@ Class MisterPop : Actor Class MisterBulletImpact : Actor { + MisterRailCounter mrc; // simplify code by putting this here Default { Obituary "$O_MORTALRIFLE"; @@ -648,6 +658,280 @@ Class MisterStreamImpact : MisterBulletImpact } } +Class MisterRailEntryImpact : MisterBulletImpact +{ + Default + { + Scale 1.2; + } + override void A_BulletExplode() + { + A_AlertMonsters(swwm_uncapalert?0:4000); + int nhit, nkill; + [nhit, nkill] = SWWMUtility.DoExplosion(self,444,200000,100,100,DE_EXTRAZTHRUST|DE_COUNTENEMIES); + if ( mrc ) mrc.nkill += nkill; + A_QuakeEx(6,6,6,10,0,400,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:150,rollintensity:.8); + A_StartSound("mister/hitover",CHAN_VOICE,attenuation:.35); + A_SprayDecal("SmallRocketBlast",-172); + Scale *= FRandom[ExploS](0.8,1.1); + Scale.x *= RandomPick[ExploS](-1,1); + Scale.y *= RandomPick[ExploS](-1,1); + int numpt = Random[ExploS](8,12); + for ( int i=0; i viewdist ) continue; if ( !level.allmap && !(a.target && a.target.IsFriend(players[consoleplayer].mo)) && !a.CheckSight(players[consoleplayer].Camera,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) @@ -380,7 +380,7 @@ extend Class SWWMHandler let a = beams[i]; if ( !a ) continue; Vector2 rv = a.pos.xy-relpos; - double rad = a.speed*cos(a.pitch); + double rad = SWWMUtility.IsYBeam(a)?(a.scale.y*cos(a.pitch-90)):(a.speed*cos(a.pitch)); if ( max(abs(rv.x)-rad,abs(rv.y)-rad) > viewdist ) continue; if ( !level.allmap && !(a.target && a.target.IsFriend(players[consoleplayer].mo)) && !a.CheckSight(players[consoleplayer].Camera,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) diff --git a/zscript/hud/swwm_hud.zsc b/zscript/hud/swwm_hud.zsc index 41d8e7137..c212b25cb 100644 --- a/zscript/hud/swwm_hud.zsc +++ b/zscript/hud/swwm_hud.zsc @@ -2198,7 +2198,7 @@ Class SWWMStatusBar : BaseStatusBar { pos = SWWMUtility.LerpVector2(t.target.prev.xy,t.target.pos.xy,FracTic); angle = t.target.angle; - radius = t.isbeam?(t.target.speed*cos(t.target.pitch)):t.target.radius; + radius = t.isybeam?(t.target.scale.y*cos(t.target.pitch-90)):t.isbeam?(t.target.speed*cos(t.target.pitch)):t.target.radius; } else { diff --git a/zscript/hud/swwm_hudobjects.zsc b/zscript/hud/swwm_hudobjects.zsc index 4b73c04e7..e11beffa6 100644 --- a/zscript/hud/swwm_hudobjects.zsc +++ b/zscript/hud/swwm_hudobjects.zsc @@ -265,7 +265,7 @@ Class SWWMSimpleTracker play bool vipitem; bool expired; bool ismissile; - bool isbeam; + bool isbeam, isybeam; int lastupdate; ui double smoothalpha; // smoothened alpha, for ui SWWMSimpleTracker next; @@ -274,7 +274,8 @@ Class SWWMSimpleTracker play { if ( !target ) return; isbeam = SWWMUtility.IsBeamProj(target); - radius = isbeam?(target.speed*cos(target.pitch)):target.radius; + isybeam = isbeam&&SWWMUtility.IsYBeam(target); + radius = isybeam?(target.scale.y*cos(target.pitch+90)):isbeam?(target.speed*cos(target.pitch)):target.radius; angle = target.angle; pos = target.pos; isplayer = target.player; diff --git a/zscript/swwm_common_fx.zsc b/zscript/swwm_common_fx.zsc index 1bcad9df0..ae64b8117 100644 --- a/zscript/swwm_common_fx.zsc +++ b/zscript/swwm_common_fx.zsc @@ -939,7 +939,7 @@ Class SWWMTeleportLine : Actor override void Tick() { - if ( !tline ) + if ( !tline || !tline.special ) { Destroy(); return; diff --git a/zscript/utility/swwm_utility.zsc b/zscript/utility/swwm_utility.zsc index de7d7424c..104d627da 100644 --- a/zscript/utility/swwm_utility.zsc +++ b/zscript/utility/swwm_utility.zsc @@ -1466,6 +1466,13 @@ Class SWWMUtility if ( a is 'YnykronLightningArc' ) return true; if ( a is 'YnykronAltBeam' ) return true; if ( a is 'MykradvoTendril' ) return true; + if ( a is 'MisterRailBeam' ) return true; + return false; + } + // is this a YBeam type? (real pitch is pitch-90, scale.y == length) + static play bool IsYBeam( Actor a ) + { + if ( a is 'MisterRailBeam' ) return true; return false; } diff --git a/zscript/weapons/swwm_thiccboolet.zsc b/zscript/weapons/swwm_thiccboolet.zsc index 79c60a78a..f5bb5df49 100644 --- a/zscript/weapons/swwm_thiccboolet.zsc +++ b/zscript/weapons/swwm_thiccboolet.zsc @@ -674,6 +674,7 @@ Class SilverBullet : SWWMWeapon sst.Trace(norigin,level.PointInSector(norigin.xy),x2,maxdist,TRACE_HitSky); maxdist -= (sst.exitpoint-norigin).length(); norigin = sst.exitpoint; + x2 = sst.Results.HitVector; } while ( !sst.fullstop ); invoker.nkills = 0;