diff --git a/graphics/Achievements/MxWorldwide.png b/graphics/Achievements/MxWorldwide.png index c92b53487..5816f7406 100644 Binary files a/graphics/Achievements/MxWorldwide.png and b/graphics/Achievements/MxWorldwide.png differ diff --git a/language.version b/language.version index e6d68e347..e12de9248 100644 --- a/language.version +++ b/language.version @@ -1,2 +1,2 @@ [default] -SWWM_MODVER="\chSWWM \cwGZ\c- r441 (Thu 30 Jul 17:35:20 CEST 2020)"; +SWWM_MODVER="\chSWWM \cwGZ\c- r442 (Fri 31 Jul 16:14:00 CEST 2020)"; diff --git a/zscript/swwm_common.zsc b/zscript/swwm_common.zsc index c7c7c5e14..6f32397af 100644 --- a/zscript/swwm_common.zsc +++ b/zscript/swwm_common.zsc @@ -15,6 +15,16 @@ enum ESWWMGZChannels CHAN_AMBEXTRA = 63211 // player ambience when submerged }; +enum EDoExplosionFlags +{ + DE_BLAST = 1, // sets BLASTED flag on pushed actors + DE_NOBLEED = 2, // does not spawn blood decals on hit + DE_NOSPLASH = 4, // like XF_NOSPLASH + DE_THRUWALLS = 8, // damages through geometry (no sight check) + DE_NOTMISSILE = 16, // instigator is the source itself (normally it'd be its target pointer) + DE_EXTRAZTHRUST = 32, // applies a higher Z thrust to enemies on ground +}; + // Misc. Utility code Class SWWMUtility { @@ -368,8 +378,8 @@ Class SWWMStats : Thinker { PlayerInfo myplayer; int lastspawn, dashcount, boostcount, stompcount, airtime, kills, - deaths, damagedealt, damagetaken, mkill, hiscore, hhiscore, - topdealt, toptaken, skill; + deaths, damagedealt, hdamagedealt, damagetaken, hdamagetaken, + mkill, hiscore, hhiscore, topdealt, toptaken, skill; double grounddist, airdist, fuelusage, topspeed; Array wstats; Array > alreadygot; @@ -385,6 +395,39 @@ Class SWWMStats : Thinker return false; } + void AddDamageDealt( int dmg ) + { + int upper = dmg/1000000000; + int lower = dmg%1000000000; + if ( hdamagedealt+upper < hdamagedealt ) hdamagedealt = 999999999; + else hdamagedealt += upper; + damagedealt += lower; + if ( damagedealt > 999999999 ) + { + upper = damagedealt/1000000000; + lower = damagedealt%1000000000; + if ( hdamagedealt+upper < hdamagedealt ) hdamagedealt = 999999999; + else hdamagedealt += upper; + damagedealt = lower; + } + } + void AddDamageTaken( int dmg ) + { + int upper = dmg/1000000000; + int lower = dmg%1000000000; + if ( hdamagetaken+upper < hdamagetaken ) hdamagetaken = 999999999; + else hdamagetaken += upper; + damagetaken += lower; + if ( damagetaken > 999999999 ) + { + upper = damagetaken/1000000000; + lower = damagetaken%1000000000; + if ( hdamagetaken+upper < hdamagetaken ) hdamagetaken = 999999999; + else hdamagetaken += upper; + damagetaken = lower; + } + } + void AddWeaponKill( Actor inflictor ) { Class which = myplayer.ReadyWeapon?myplayer.ReadyWeapon.GetClass():null; @@ -829,6 +872,8 @@ Class SWWMScoreObj : Thinker static SWWMScoreObj Spawn( int score, Vector3 pos, int tcolor = Font.CR_GOLD, Actor acc = null ) { + let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); + if ( !hnd ) return null; let o = new("SWWMScoreObj"); o.ChangeStatNum(STAT_USER); o.score = score; @@ -841,23 +886,19 @@ Class SWWMScoreObj : Thinker o.damnum = (tcolor == Font.CR_RED) || (tcolor == Font.CR_GREEN) || (tcolor == Font.CR_BLUE); o.xcnt = 0; o.acc = acc; - let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); - if ( hnd ) + if ( o.damnum ) { - if ( o.damnum ) - { - o.next = hnd.damnums; - if ( hnd.damnums ) hnd.damnums.prev = o; - hnd.damnums = o; - hnd.damnums_cnt++; - } - else - { - o.next = hnd.scorenums; - if ( hnd.scorenums ) hnd.scorenums.prev = o; - hnd.scorenums = o; - hnd.scorenums_cnt++; - } + o.next = hnd.damnums; + if ( hnd.damnums ) hnd.damnums.prev = o; + hnd.damnums = o; + hnd.damnums_cnt++; + } + else + { + o.next = hnd.scorenums; + if ( hnd.scorenums ) hnd.scorenums.prev = o; + hnd.scorenums = o; + hnd.scorenums_cnt++; } return o; } @@ -914,6 +955,8 @@ Class SWWMInterest : Thinker static SWWMInterest Spawn( Vector3 pos = (0,0,0), Key thekey = null, Line theline = null ) { + let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); + if ( !hnd ) return null; if ( (!thekey && !theline) || (thekey && theline) ) return null; let i = new("SWWMInterest"); i.ChangeStatNum(STAT_USER); @@ -931,14 +974,10 @@ Class SWWMInterest : Thinker return null; } i.pos = thekey?thekey.Vec3Offset(0,0,thekey.height/2):pos; - let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); - if ( hnd ) - { - i.next = hnd.intpoints; - if ( hnd.intpoints ) hnd.intpoints.prev = i; - hnd.intpoints = i; - hnd.intpoints_cnt++; - } + i.next = hnd.intpoints; + if ( hnd.intpoints ) hnd.intpoints.prev = i; + hnd.intpoints = i; + hnd.intpoints_cnt++; return i; } @@ -993,9 +1032,10 @@ Class SWWMCombatTracker : Thinker static SWWMCombatTracker Spawn( Actor target ) { - let ti = ThinkerIterator.Create("SWWMCombatTracker",STAT_USER); + let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); + if ( !hnd ) return null; SWWMCombatTracker t; - while ( t = SWWMCombatTracker(ti.Next()) ) + for ( t=hnd.trackers; t; t=t.next ) { if ( t.mytarget != target ) continue; return t; @@ -1018,14 +1058,10 @@ Class SWWMCombatTracker : Thinker t.oldprev = target.prev; t.intp = DynamicValueInterpolator.Create(t.lasthealth,.5,1,100); t.myplayer = target.player; - let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); - if ( hnd ) - { - t.next = hnd.trackers; - if ( hnd.trackers ) hnd.trackers.prev = t; - hnd.trackers = t; - hnd.trackers_cnt++; - } + t.next = hnd.trackers; + if ( hnd.trackers ) hnd.trackers.prev = t; + hnd.trackers = t; + hnd.trackers_cnt++; return t; } @@ -2202,6 +2238,10 @@ Class SWWMHandler : EventHandler transient CVar lang; transient String curlang; + // optimization + OnFire fires; + int fires_cnt; + static void HealthFlash( int p ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); @@ -2825,15 +2865,13 @@ Class SWWMHandler : EventHandler { tookdamage[e.Thing.PlayerNumber()] = true; let s = SWWMStats.Find(e.Thing.player); - if ( s.damagetaken+e.Damage < s.damagetaken ) s.damagetaken = int.max; - else s.damagetaken += e.Damage; + s.AddDamageTaken(e.Damage); if ( e.Damage > s.toptaken ) s.toptaken = e.Damage; } if ( e.DamageSource && e.DamageSource.player ) { let s = SWWMStats.Find(e.DamageSource.player); - if ( s.damagedealt+e.Damage < s.damagedealt ) s.damagedealt = int.max; - else s.damagedealt += e.Damage; + s.AddDamageDealt(e.Damage); if ( e.Damage > s.topdealt ) s.topdealt = e.Damage; } } @@ -2966,7 +3004,7 @@ Class SWWMHandler : EventHandler SWWMScoreObj.Spawn(2000,e.DamageSource.Vec3Offset(0,0,e.DamageSource.Height/2)); } spreecount[pnum]++; - if ( s && spreecount[pnum] > s.skill ) + if ( s && (spreecount[pnum] > s.skill) && !tookdamage[pnum] ) s.skill = spreecount[pnum]; } } @@ -3084,7 +3122,9 @@ Class SWWMHandler : EventHandler if ( e.KeyScan == 33 ) // assuming that's the F key on all keyboards (hopefully) { let demo = Demolitionist(players[consoleplayer].mo); - if ( demo && (demo.Health <= 0) && (demo.deadtimer > 40) ) + let gone = PlayerGone(players[consoleplayer].mo); + if ( (demo && (demo.Health <= 0) && (demo.deadtimer > 40)) + || (gone && (gone.Health <= 0) && (gone.deadtimer > 40)) ) { // pay respects int numf = Random[FInTheChat](1,6); @@ -3660,7 +3700,7 @@ Class SWWMHandler : EventHandler if ( a.bNORADIUSDMG && !Source.bFORCERADIUSDMG && !forceblast ) continue; // massive, no knockback - if ( a.bCANNOTPUSH || (a.Mass >= 10000000) ) + if ( a.bDONTTHRUST || (a.Mass >= Actor.LARGE_MASS) ) continue; // check the DONTHARMCLASS/DONTHARMSPECIES flags if ( !a.player && ((Source.bDONTHARMCLASS && (a.GetClass() == Source.GetClass())) || (Source.bDONTHARMSPECIES && (a.GetSpecies() == Source.GetSpecies()))) ) @@ -3695,7 +3735,7 @@ Class SWWMHandler : EventHandler return; if ( !Victim.bSHOOTABLE && !Victim.bVULNERABLE ) return; - if ( Victim.bCANNOTPUSH || (Victim.Mass >= 10000000) ) + if ( Victim.bDONTTHRUST || (Victim.Mass >= Actor.LARGE_MASS) ) return; Vector3 Momentum = HitDirection*MomentumTransfer; if ( (Victim.pos.z <= Victim.floorz) || !Victim.TestMobjZ() ) @@ -3706,7 +3746,7 @@ Class SWWMHandler : EventHandler // complete spherical and more accurate replacement of A_Explode // 100% free of the buggery GZDoom's own splash damage has - static void DoExplosion( Actor Source, double Damage, double MomentumTransfer, double ExplosionRadius, double FullDamageRadius = 0., Name DamageType = '', Actor ignoreme = null ) + static void DoExplosion( Actor Source, double Damage, double MomentumTransfer, double ExplosionRadius, double FullDamageRadius = 0., int flags = 0, Name DamageType = '', Actor ignoreme = null ) { // debug, display radius sphere if ( swwm_explosiondebug ) @@ -3721,8 +3761,9 @@ Class SWWMHandler : EventHandler s.SetShade("Red"); } } + if ( !(flags&DE_NOSPLASH) ) Source.CheckSplash(ExplosionRadius); double brange = 1./(ExplosionRadius-FullDamageRadius); - Actor Instigator = Source.bMISSILE?Source.target:Source; + Actor Instigator = (flags&DE_NOTMISSILE)?Source:Source.target; BlockThingsIterator bi = BlockThingsIterator.Create(Source,ExplosionRadius*2); // test with doubled radius, just to be sure while ( bi.Next() ) { @@ -3740,7 +3781,7 @@ Class SWWMHandler : EventHandler if ( !a.player && ((Source.bDONTHARMCLASS && (a.GetClass() == Source.GetClass())) || (Source.bDONTHARMSPECIES && (a.GetSpecies() == Source.GetSpecies()))) ) continue; // can we see it - if ( !Source.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) + if ( !(flags&DE_THRUWALLS) && !Source.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue; // intersecting? if ( !SWWMUtility.SphereIntersect(a,Source.pos,ExplosionRadius) ) @@ -3760,19 +3801,20 @@ Class SWWMHandler : EventHandler double damagescale = 1.-clamp((dist-a.Radius)*brange,0.,1.); double mm = MomentumTransfer*damagescale; // no knockback if massive/unpushable - if ( (abs(mm) > 0.) && !a.bCANNOTPUSH && (a.Mass < 10000000) ) + if ( (abs(mm) > 0.) && !a.bDORMANT && !a.bDONTTHRUST && (a.Mass < Actor.LARGE_MASS) ) { Vector3 Momentum = dir*mm; if ( (a.pos.z <= a.floorz) || !a.TestMobjZ() ) - Momentum.z = max(Momentum.z,.1*Momentum.length()); + Momentum.z = max(Momentum.z,(flags&DE_EXTRAZTHRUST?.4:.1)*Momentum.length()); Momentum /= Thinker.TICRATE*max(50,a.Mass); // prevent tiny things from getting yeeted at warp speed a.vel += Momentum; + if ( (flags&DE_BLAST) && a.bCANBLAST && !a.bDONTBLAST ) a.bBLASTED = true; } // hit it int dmg = int(Damage*damagescale); if ( dmg <= 0 ) continue; // no harm - int ndmg = a.DamageMobj(Instigator,Source,dmg,(DamageType=='')?Source.DamageType:DamageType,DMG_EXPLOSION,atan2(-dir.y,-dir.x)); - a.TraceBleed((ndmg>0)?ndmg:dmg,Source); + int ndmg = a.DamageMobj(Instigator,Source,dmg,(DamageType!='')?Source.DamageType:DamageType,DMG_EXPLOSION,atan2(-dir.y,-dir.x)); + if ( !(flags&DE_NOBLEED) ) a.TraceBleed((ndmg>0)?ndmg:dmg,Source); } // TODO destructible geometry support } diff --git a/zscript/swwm_deepdarkimpact.zsc b/zscript/swwm_deepdarkimpact.zsc index 5da35c1a2..70488b591 100644 --- a/zscript/swwm_deepdarkimpact.zsc +++ b/zscript/swwm_deepdarkimpact.zsc @@ -355,7 +355,7 @@ Class DeepImpact : SWWMWeapon Vector3 avgdir = list[i].avgdir/list[i].nhits; double avgdist = list[i].avgdist/list[i].nhits; double dmg = 4000.*(1.-clamp(avgdist/300.,0.,1.)); - if ( !list[i].a.bCANNOTPUSH && (list[i].a.mass < LARGE_MASS) ) + if ( !list[i].a.bDONTTHRUST && (list[i].a.mass < LARGE_MASS) ) list[i].a.vel += ((avgdir+(0,0,.35))*dmg/max(50,list[i].a.mass)); list[i].a.DamageMobj(self,self,int(dmg/500.),'Push',DMG_THRUSTLESS); } diff --git a/zscript/swwm_inventory.zsc b/zscript/swwm_inventory.zsc index 871923a6b..a909df559 100644 --- a/zscript/swwm_inventory.zsc +++ b/zscript/swwm_inventory.zsc @@ -572,7 +572,7 @@ Class BigPunchSplash : Actor override void PostBeginPlay() { Super.PostBeginPlay(); - SWWMHandler.DoExplosion(self,special1,40000,120,ignoreme:target); + SWWMHandler.DoExplosion(self,special1,40000,120,60,ignoreme:target); Destroy(); } } diff --git a/zscript/swwm_menu.zsc b/zscript/swwm_menu.zsc index 2123d10f1..2ea861139 100644 --- a/zscript/swwm_menu.zsc +++ b/zscript/swwm_menu.zsc @@ -1959,10 +1959,12 @@ Class SWWMKnowledgeBaseMenu : GenericMenu str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDEATHS"),stats.deaths); Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); yy += 16; - str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDDEALT"),stats.damagedealt); + if ( stats.hdamagedealt > 0 ) str = str = String.Format("\cx%s\c-%d%09d",StringTable.Localize("$SWWM_STATDDEALT"),stats.hdamagedealt,stats.damagedealt); + else str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDDEALT"),stats.damagedealt); Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); yy += 16; - str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDTAKEN"),stats.damagetaken); + if ( stats.hdamagetaken > 0 ) str = String.Format("\cx%s\c-%d%09d",StringTable.Localize("$SWWM_STATDTAKEN"),stats.hdamagetaken,stats.damagetaken); + else str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDTAKEN"),stats.damagetaken); Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); yy += 16; str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATTDEALT"),stats.topdealt); diff --git a/zscript/swwm_player.zsc b/zscript/swwm_player.zsc index a508d0eff..ea5797500 100644 --- a/zscript/swwm_player.zsc +++ b/zscript/swwm_player.zsc @@ -555,7 +555,8 @@ Class Demolitionist : PlayerPawn else { // launch in movement direction (useful for moving platforms) - if ( oldencroached && (dashboost <= 0.) && (lastvelz >= -25) ) vel += oldencroached.vel+level.Vec3Diff(oldencroachedpos,oldencroached.pos); + // make sure we're not getting launched because an enemy just died under our feet, because that can cause some issues + if ( oldencroached && (dashboost <= 0.) && (lastvelz >= -25) && (!oldencroached.bISMONSTER || (oldencroached.Health > 0)) ) vel += oldencroached.vel+level.Vec3Diff(oldencroachedpos,oldencroached.pos); oldencroached = null; } if ( encroached && encroached.bSHOOTABLE && !encroached.bNODAMAGE && (lastvelz <= 0) && !(encroached is 'Demolitionist') ) @@ -614,7 +615,7 @@ Class Demolitionist : PlayerPawn } Vector3 dir = vel+dashdir*dashboost; double spd = dir.length(); - dir = dir.unit(); + dir = dir/spd; Vector3 viewdir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); // look for things we could potentially bump into let bi = BlockThingsIterator.Create(self,500); @@ -623,9 +624,11 @@ Class Demolitionist : PlayerPawn { a = bi.Thing; if ( !a || (a == self) || !a.bSHOOTABLE || a.bTHRUACTORS ) continue; - Vector3 diff = level.Vec3Diff(pos,a.pos); if ( !SWWMUtility.ExtrudeIntersect(self,a,dir*spd,8,16) ) continue; if ( !CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue; + Vector3 diff = level.Vec3Diff(pos,a.pos); + Vector3 dirto = diff.unit(); + if ( dir dot dirto < 0 ) continue; // large monsters will stop the player (unless hit from above if we're going at ground pound speed) A_QuakeEx(4,4,4,10,0,128,"",QF_RELATIVE|QF_SCALEDOWN); A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP); @@ -640,15 +643,16 @@ Class Demolitionist : PlayerPawn vel.z += 5+(spd*(10/mass)); dashboost *= .3; } - Vector3 pushdir = Vec3To(a).unit()*.1+dir*.9; + Vector3 pushdir = dirto*.1+dir*.9; if ( !a.bDONTTHRUST && (a.Mass < Mass*1.5) ) { a.vel += pushdir*(15+(spd*20/max(50,a.mass))); - a.vel.z += 5+(spd*(5/max(50,a.mass))); + if ( (a.pos.z <= a.floorz) || !a.TestMobjZ() ) + a.vel.z += 5+(spd*(5/max(50,a.mass))); } int flg = DMG_THRUSTLESS; if ( FindInventory("RagekitPower") ) flg |= DMG_FOILINVUL; - if ( !a.player ) a.bBLASTED = true; + if ( !a.player && !a.bDONTBLAST ) a.bBLASTED = true; int dmg = int(15+spd*2.5); if ( dir dot viewdir < -.3 ) dmg *= 2; // BUTTSLAM dmg = a.DamageMobj(self,self,dmg,'Dash',flg); @@ -1861,7 +1865,7 @@ Class DemolitionistRadiusShockwaveTail : Actor Spawn: SDST A 1 { - A_FadeOut(0.08); + A_FadeOut(.02); A_SetScale(scale.x,scale.y*0.98); } Wait; @@ -1898,8 +1902,9 @@ Class DemolitionistRadiusShockwave : Actor if ( damage <= 0 ) return damage; if ( (target.mass < LARGE_MASS) && !target.bDONTTHRUST ) { - target.vel.xy += vel.xy.unit()*(7000./max(50,target.mass))*alpha; - target.vel.z += (800./max(50,target.mass))*alpha; + target.vel.xy += vel.xy.unit()*(14000./max(50,target.mass))*alpha; + if ( (target.pos.z <= floorz) || !target.TestMobjZ() ) + target.vel.z += (1500./max(50,target.mass))*alpha; } return damage; } @@ -1911,7 +1916,7 @@ Class DemolitionistRadiusShockwave : Actor SetZ(floorz); Spawn("InvisibleSplasher",Vec3Offset(0,0,2)); let s = Spawn("DemolitionistRadiusShockwaveTail",pos); - s.vel = vel*.2; + s.vel = vel*.1; s.scale = scale; s.alpha = alpha; s.angle = angle; @@ -1951,16 +1956,7 @@ Class DemolitionistShockwave : Actor A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,attenuation:.2,pitch:.7); A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,attenuation:.1,pitch:.4); } - target.A_Blast(BF_AFFECTBOSSES,200+min(special1*3,100),100+min(special1*2,130),10+min(special1/10,20),"SWWMNothing",""); - A_Explode(40+min(special1,120),100+min(special1*2,130),XF_EXPLICITDAMAGETYPE,damagetype:'GroundPound'); - for ( int i=0; i<360; i+=5 ) - { - let r = Spawn("DemolitionistRadiusShockwave",Vec3Angle(10,i)); - r.target = target; - r.angle = i; - r.vel.xy = (cos(i),sin(i))*(r.speed+min(special1*.15,20)); - r.alpha *= .1+min(special1*.03,.9); - } + SWWMHandler.DoExplosion(self,40+min(special1,120),100000+min(special1*2000,150000),100+min(special1*2,130),80,DE_BLAST|DE_EXTRAZTHRUST,'GroundPound',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); @@ -1971,6 +1967,15 @@ Class DemolitionistShockwave : Actor s.scale *= 1.5; s.alpha *= .4; } + if ( pos.z > floorz+16 ) return; + for ( int i=0; i<360; i+=5 ) + { + let r = Spawn("DemolitionistRadiusShockwave",Vec3Angle(10,i)); + r.target = target; + r.angle = i; + r.vel.xy = (cos(i),sin(i))*(r.speed+min(special1*.15,20)); + r.alpha *= .1+min(special1*.03,.9); + } int numpt = Random[ExploS](10,20); for ( int i=0; i 0)) || (victim.Distance3D(t) > victim.radius+t.radius+40) || !victim.CheckSight(t) ) continue; int amt = max(1,amount/10); - if ( IsOnFire(t) ) amt = min(5,amt); - Apply(t,instigator,amt); + OnFire of = IsOnFire(t); + if ( of ) + { + amt = min(5,amt); + if ( instigator ) of.instigator = instigator; + of.amount = min(500,of.amount+amt); + of.cnt = min(of.cnt,5); + } + else Apply(t,instigator,amt); } } static OnFire Apply( Actor victim, Actor instigator, int amount, int delay = 0 ) { if ( amount <= 0 ) return null; - let ti = ThinkerIterator.Create("OnFire"); + let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); + if ( !hnd ) return null; OnFire t; - while ( t = OnFire(ti.Next()) ) + for ( t=hnd.fires; t; t=t.nextfire ) { if ( t.victim != victim ) continue; if ( instigator ) t.instigator = instigator; @@ -1000,19 +1029,26 @@ Class OnFire : Actor t.lite = Actor.Spawn("OnFireLight",victim.pos); OnFireLight(t.lite).of = t; t.oangle = victim.angle; + // append + t.nextfire = hnd.fires; + if ( hnd.fires ) hnd.fires.prevfire = t; + hnd.fires = t; + hnd.fires_cnt++; return t; } - static bool IsOnFire( Actor victim ) + static OnFire IsOnFire( Actor victim ) { - let ti = ThinkerIterator.Create("OnFire"); + let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); + if ( !hnd ) return null; OnFire t; - while ( t = OnFire(ti.Next()) ) + for ( t=hnd.fires; t; t=t.nextfire ) { if ( t.victim != victim ) continue; - return (t.amount>0); + if ( t.amount <= 0 ) return null; + return t; } - return false; + return null; } Default @@ -1619,7 +1655,7 @@ Class GoldenImpact : Actor { Super.PostBeginPlay(); A_AlertMonsters(40000); - SWWMHandler.DoExplosion(self,7777,40000,600,500); + SWWMHandler.DoExplosion(self,7777,40000,600,500,DE_EXTRAZTHRUST); A_QuakeEx(9,9,9,40,0,5000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollintensity:1.5); A_StartSound("spreadgun/goldexpl",CHAN_VOICE,attenuation:.3); A_StartSound("spreadgun/goldexpl",CHAN_WEAPON,attenuation:.15); @@ -1746,7 +1782,7 @@ Class GoldenSubImpact : Actor override void PostBeginPlay() { Super.PostBeginPlay(); - SWWMHandler.DoExplosion(self,777,30000,400,300); + SWWMHandler.DoExplosion(self,777,30000,400,300,DE_EXTRAZTHRUST); A_QuakeEx(7,7,7,20,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollintensity:.8); A_SprayDecal("BigScorch",-172); Scale *= FRandom[ExploS](0.8,1.1); @@ -1871,7 +1907,7 @@ Class GoldenSubSubImpact : Actor override void PostBeginPlay() { Super.PostBeginPlay(); - SWWMHandler.DoExplosion(self,77,20000,200,100); + SWWMHandler.DoExplosion(self,77,20000,200,100,DE_EXTRAZTHRUST); A_QuakeEx(4,4,4,15,0,1000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:100,rollintensity:.4); A_SprayDecal("Scorch",-172); Scale *= FRandom[ExploS](0.8,1.1); diff --git a/zscript/swwm_splode.zsc b/zscript/swwm_splode.zsc index 6cffc1fc5..4a338d27b 100644 --- a/zscript/swwm_splode.zsc +++ b/zscript/swwm_splode.zsc @@ -135,7 +135,7 @@ Class ExplodiumMagProj : Actor A_SetRenderStyle(1.,STYLE_Add); Scale *= 2.+.2*special1; A_AlertMonsters(6000); - SWWMHandler.DoExplosion(self,20+15*special1,80000+8000*special1,90+10*special1,60); + SWWMHandler.DoExplosion(self,20+15*special1,80000+8000*special1,90+10*special1,60,DE_EXTRAZTHRUST); A_QuakeEx(9,9,9,30,0,400+80*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollintensity:2.); A_StartSound("explodium/maghit",CHAN_VOICE,attenuation:.35); A_StartSound("explodium/maghit",CHAN_WEAPON,attenuation:.2); @@ -229,7 +229,7 @@ Class ExplodiumBulletImpact : Actor { Super.PostBeginPlay(); A_AlertMonsters(3000); - SWWMHandler.DoExplosion(self,25,80000,90,40); + SWWMHandler.DoExplosion(self,25,80000,90,40,DE_EXTRAZTHRUST); A_QuakeEx(4,4,4,10,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:150,rollintensity:0.2); A_StartSound("explodium/hit",CHAN_VOICE,attenuation:.6); A_StartSound("explodium/hit",CHAN_WEAPON,attenuation:.3); diff --git a/zscript/swwm_tastytreat.zsc b/zscript/swwm_tastytreat.zsc index ee7eefc9f..634b21265 100644 --- a/zscript/swwm_tastytreat.zsc +++ b/zscript/swwm_tastytreat.zsc @@ -529,7 +529,7 @@ Class CandyGunProj : Actor A_SetRenderStyle(1.,STYLE_Add); Scale *= 6.+.2*special1; A_AlertMonsters(40000); - SWWMHandler.DoExplosion(self,3500+500*special1,80000+8000*special1,300+20*special1,120); + SWWMHandler.DoExplosion(self,3500+500*special1,80000+8000*special1,300+20*special1,120,DE_EXTRAZTHRUST); A_QuakeEx(9,9,9,70,0,1500+100*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:1200,rollintensity:2.); A_StartSound("candygun/gunhit",CHAN_VOICE,attenuation:.24); A_StartSound("candygun/gunhit",CHAN_WEAPON,attenuation:.12); @@ -639,7 +639,7 @@ Class CandyMagProj : Actor A_SetRenderStyle(1.,STYLE_Add); Scale *= 3.+.2*special1; A_AlertMonsters(20000); - SWWMHandler.DoExplosion(self,700+600*special1,80000+8000*special1,150+15*special1,90); + SWWMHandler.DoExplosion(self,700+600*special1,80000+8000*special1,150+15*special1,90,DE_EXTRAZTHRUST); A_QuakeEx(9,9,9,30,0,500+80*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollintensity:2.); A_StartSound("candygun/maghit",CHAN_VOICE,attenuation:.24); A_StartSound("candygun/maghit",CHAN_WEAPON,attenuation:.12); @@ -733,7 +733,7 @@ Class CandyBulletImpact : Actor { Super.PostBeginPlay(); A_AlertMonsters(9000); - SWWMHandler.DoExplosion(self,700,48000,200,80); + SWWMHandler.DoExplosion(self,700,48000,200,80,DE_EXTRAZTHRUST); A_QuakeEx(6,6,6,15,0,300,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollintensity:0.2); A_StartSound("candygun/hit",CHAN_VOICE,attenuation:.25); A_StartSound("candygun/hit",CHAN_WEAPON,attenuation:.5);