From 78dc1bb453239eb287bbc2530b8ac37cf196061e Mon Sep 17 00:00:00 2001 From: Marisa the Magician Date: Sat, 3 Sep 2022 18:28:13 +0200 Subject: [PATCH] Convert Quadravol fire debuff to inventory item. Copy over spread code from black shell debuff (lower hard lock risk). --- language.version | 4 +- zscript/dlc1/swwm_notashotgun_fx.zsc | 164 ++++++++++++++------------- zscript/swwm_thinkers_player.zsc | 2 +- zscript/weapons/swwm_shot_fx.zsc | 7 +- 4 files changed, 92 insertions(+), 85 deletions(-) diff --git a/language.version b/language.version index a24f7d57a..321a259bc 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r398 \cu(Sat 3 Sep 09:33:23 CEST 2022)\c-"; -SWWM_SHORTVER="\cw1.3pre r398 \cu(2022-09-03 09:33:23)\c-"; +SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r399 \cu(Sat 3 Sep 18:28:13 CEST 2022)\c-"; +SWWM_SHORTVER="\cw1.3pre r399 \cu(2022-09-03 18:28:13)\c-"; diff --git a/zscript/dlc1/swwm_notashotgun_fx.zsc b/zscript/dlc1/swwm_notashotgun_fx.zsc index 1a6111277..50fdce85d 100644 --- a/zscript/dlc1/swwm_notashotgun_fx.zsc +++ b/zscript/dlc1/swwm_notashotgun_fx.zsc @@ -929,7 +929,7 @@ Class OnFireLight : PointLightFlickerRandomAttenuated override void Tick() { Super.Tick(); - if ( !of || !of.victim ) + if ( !of || !of.Owner ) { A_StopSound(CHAN_VOICE); Destroy(); @@ -938,32 +938,78 @@ Class OnFireLight : PointLightFlickerRandomAttenuated Args[0] = clamp(of.Amount*4,0,255); Args[1] = clamp(of.Amount*2,0,160); Args[2] = clamp(of.Amount/2,0,24); - Args[3] = int(max(of.victim.radius,of.victim.height)*2.5+40+clamp(of.amount/4,0,120)); + Args[3] = int(max(of.Owner.radius,of.Owner.height)*2.5+40+clamp(of.Amount/4,0,120)); Args[4] = args[3]+8; - SetOrigin(of.Victim.Vec3Offset(0,0,of.Victim.Height/2),true); + SetOrigin(of.Owner.Vec3Offset(0,0,of.Owner.Height/2),true); } } -Class OnFire : Thinker +Class OnFire : Inventory { - Actor victim, instigator, lite; - int amount, cnt; + Actor instigator, lite; + int cnt; double oangle; - override void Tick() + Default { - if ( level.isFrozen() ) return; - if ( !victim ) + Obituary "$O_QUADRAVOL"; + Inventory.Amount 1; + Inventory.MaxAmount 500; + +INVENTORY.KEEPDEPLETED; // since our amount can go below 0, we need special cleanup + +INVENTORY.UNDROPPABLE; + +INVENTORY.UNTOSSABLE; + } + + override void AttachToOwner( Actor other ) + { + Super.AttachToOwner(other); + cnt = 1; + lite = Spawn("OnFireLight",other.pos); + lite.specialf1 = 3; + OnFireLight(lite).of = self; + } + + override void OwnerDied() + { + Super.OwnerDied(); + amount = min(amount,100); + } + + override void PreTravelled() + { + Super.PreTravelled(); + // debuff disappears between levels + Destroy(); + } + + override int DoSpecialDamage( Actor target, int Damage, Name DamageType ) + { + if ( target == Owner ) return Damage; + // spread ourselves + let t = OnFire(target.FindInventory("OnFire")); + if ( !t ) + { + t = Apply(target,instigator,min(Damage,int(Amount*.6))); // prevent "escalating" spread + t.cnt = 15; // long delay + } + else if ( t.Amount < int(Amount*.6) ) t.Amount = min(t.Amount+Damage,int(Amount*.6)); // prevent "escalating" spread + t.instigator = instigator; + return clamp(int(Damage*.15),1,50); // reduced direct damage + } + + override void DoEffect() + { + Super.DoEffect(); + if ( !Owner ) { Destroy(); return; } - if ( victim is 'Demolitionist' ) amount = min(amount-1,200); // Demo's body puts out fire faster - if ( victim.Health <= 0 ) amount = min(amount,100); + if ( Owner is 'Demolitionist' ) amount = min(amount-1,200); // Demo's body puts out fire faster if ( !(level.maptime%3) ) amount--; - if ( victim.player ) amount -= int(abs(actor.deltaangle(victim.angle,oangle))/30); - oangle = victim.angle; + if ( Owner.player ) amount -= int(abs(actor.deltaangle(Owner.angle,oangle))/30); + oangle = Owner.angle; if ( amount < -30 ) { Destroy(); @@ -973,101 +1019,62 @@ Class OnFire : Thinker else { cnt = 10; - if ( victim.bSHOOTABLE && (victim.Health > 0) && (amount > 0) ) + if ( Owner.bSHOOTABLE && (Owner.Health > 0) && (amount > 0) ) { int flg = DMG_THRUSTLESS; - if ( victim is 'Centaur' ) flg |= DMG_FOILINVUL; // you're on fire, that shield is worthless - Actor inflictor = instigator; - if ( instigator ) - { - let q = instigator.FindInventory("Quadravol"); - if ( q ) inflictor = q; - } - victim.DamageMobj(inflictor,instigator,clamp(int(amount*.15),1,50),'Fire',flg); - if ( victim.bISMONSTER && !Random[FlameT](0,3) ) - victim.Howl(); + if ( Owner is 'Centaur' ) flg |= DMG_FOILINVUL; // you're on fire, that shield is worthless + Owner.DamageMobj(self,instigator,clamp(int(amount*.15),1,50),'Fire',flg); + if ( Owner.bISMONSTER && !Random[FlameT](0,3) ) + Owner.Howl(); } - if ( !victim ) + if ( !Owner ) { Destroy(); return; } + // damage nearby actors + SWWMUtility.DoExplosion(Owner,amount,0,Owner.radius+40+amount/5,0,DE_NOBLEED|DE_NOSPLASH|DE_HOWL|DE_CENTERHEIGHT|DE_NONEXPLOSIVE,'Fire',null,DMG_THRUSTLESS,instigator,self); } - double mult = max(victim.radius,victim.height)/30.; + double mult = max(Owner.radius,Owner.height)/30.; if ( lite ) lite.A_SoundVolume(CHAN_VOICE,min(1.,mult*amount/80.)); if ( level.maptime%5 ) return; int numpt = clamp(int(Random[FlameT](2,4)*amount*.02),1,4); numpt = int(clamp(numpt*mult**.5,1,5)); for ( int i=0; i 0 ) { - let c = victim.Spawn("OnFireTrail",pos); + let c = Spawn("OnFireTrail",tpos); c.scale *= max(.35,mult*.6); - c.vel = victim.vel*.5+SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[FlameT](.5,2.)*c.scale.x; + c.vel = Owner.vel*.5+SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[FlameT](.5,2.)*c.scale.x; } if ( Random[FlameT](0,2) ) continue; - let s = victim.Spawn("SWWMHalfSmoke",pos); + let s = Spawn("SWWMHalfSmoke",tpos); s.scale *= max(.5,mult*.75); s.alpha *= min(amount+30,100)*.005; - s.vel = victim.vel*.5+SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[FlameT](.2,.6)*s.scale.x; + s.vel = Owner.vel*.5+SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[FlameT](.2,.6)*s.scale.x; } - // this is too expensive, it has to go - /*let bt = BlockThingsIterator.Create(victim); - while ( bt.Next() ) - { - let t = bt.Thing; - if ( !t || !t.bSHOOTABLE || (t.Health <= 0) || (t == victim) ) - continue; - double maxdist = (victim.radius+t.radius+20); - if ( (victim.Distance3DSquared(t) > maxdist*maxdist) || !victim.CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) - continue; - int amt = max(1,amount/10); - let of = IsOnFire(t); - if ( of ) - { - amt = min(5,amt); - of.amount = min(500,of.amount+amt); - of.cnt = min(of.cnt,5); - } - else Apply(t,instigator,amt); - } - bt.Destroy();*/ - // damage nearby actors instead - Actor inflictor = instigator; - if ( instigator ) - { - let q = instigator.FindInventory("Quadravol"); - if ( q ) inflictor = q; - } - SWWMUtility.DoExplosion(victim,clamp(int(amount*.15),1,50),0,victim.radius+40+amount/5,0,DE_NOBLEED|DE_NOSPLASH|DE_HOWL|DE_CENTERHEIGHT|DE_NONEXPLOSIVE,'Fire',null,DMG_THRUSTLESS,instigator,inflictor); } static OnFire Apply( Actor victim, Actor instigator, int amount ) { if ( amount <= 0 ) return null; - let ti = ThinkerIterator.Create("OnFire",STAT_USER); - OnFire t; - while ( t = OnFire(ti.Next()) ) + let t = OnFire(victim.FindInventory("OnFire")); + if ( t ) { - if ( t.victim != victim ) continue; - if ( instigator ) t.instigator = instigator; - t.amount = min(500,t.amount+amount); + t.instigator = instigator; + t.amount = min(t.maxamount,t.amount+amount); t.cnt = min(t.cnt,5); return t; } - t = new("ONFire"); - t.ChangeStatNum(STAT_USER); - t.victim = victim; + t = OnFire(Spawn("ONFire")); + t.AttachToOwner(victim); t.instigator = instigator; - t.amount = min(500,amount); + t.amount = min(t.maxamount,amount); t.cnt = 1; - t.lite = Actor.Spawn("OnFireLight",victim.pos); - t.lite.specialf1 = 3; - OnFireLight(t.lite).of = t; t.oangle = victim.angle; double mult = max(victim.radius,victim.height)/30.; t.lite.A_StartSound("misc/flame",CHAN_VOICE,CHANF_LOOP); @@ -1075,15 +1082,10 @@ Class OnFire : Thinker return t; } - static OnFire IsOnFire( Actor victim ) + static clearscope OnFire IsOnFire( Actor victim ) { - let ti = ThinkerIterator.Create("OnFire",STAT_USER); - OnFire t; - while ( t = OnFire(ti.Next()) ) - { - if ( (t.victim != victim) || (t.amount <= 0) ) continue; - return t; - } + let t = OnFire(victim.FindInventory("OnFire")); + if ( t && (t.amount > 0) ) return t; return null; } } diff --git a/zscript/swwm_thinkers_player.zsc b/zscript/swwm_thinkers_player.zsc index 3f7d9b27e..0c11df71c 100644 --- a/zscript/swwm_thinkers_player.zsc +++ b/zscript/swwm_thinkers_player.zsc @@ -173,7 +173,7 @@ Class SWWMStats : SWWMStaticThinker else if ( (inflictor is 'EvisceratorChunk') || (inflictor is 'EvisceratorProj') ) which = 'Eviscerator'; else if ( inflictor is 'SheenTrail' ) which = 'HeavyMahSheenGun'; else if ( (inflictor is 'HellblazerMissile') || (inflictor is 'HellblazerRavagerArm') || (inflictor is 'HellblazerWarheadArm') ) which = 'Hellblazer'; - else if ( (inflictor is 'QuadProj') || (inflictor is 'QuadExplArm') || ((inflictor is 'Demolitionist') && (DamageType == 'Fire')) ) which = 'Quadravol'; // last one is a hack for fire effects + else if ( (inflictor is 'QuadProj') || (inflictor is 'QuadExplArm') || (inflictor is 'OnFire') ) which = 'Quadravol'; else if ( (inflictor is 'BigBiospark') || (inflictor is 'BiosparkBall') || (inflictor is 'BiosparkBeamImpact') || (inflictor is 'BiosparkComboImpact') || (inflictor is 'BiosparkComboImpactSub') || (inflictor is 'BiosparkBeam') || (inflictor is 'BiosparkArc') || (inflictor is 'BiosparkCore') ) which = 'Sparkster'; else if ( (inflictor is 'SilverAirRip') || (inflictor is 'SilverAirRip2') || (inflictor is 'SilverImpact') || (inflictor is 'FatChodeImpact') || (inflictor is 'FatChodeExplosionArm') ) which = 'SilverBullet'; else if ( (inflictor is 'CandyBeam') || (inflictor is 'CandyPop') || (inflictor is 'CandyMagArm') || (inflictor is 'CandyGunProj') || (inflictor is 'CandyMagProj') || (inflictor is 'CandyBulletImpact') ) which = 'CandyGun'; diff --git a/zscript/weapons/swwm_shot_fx.zsc b/zscript/weapons/swwm_shot_fx.zsc index b96df0a4e..a824d4a04 100644 --- a/zscript/weapons/swwm_shot_fx.zsc +++ b/zscript/weapons/swwm_shot_fx.zsc @@ -571,7 +571,6 @@ Class CorrodeDebuff : Inventory Obituary "$O_SPREADGUN_BLACK_DEBUFF"; Inventory.Amount 1; Inventory.MaxAmount 1000; - Inventory.InterHubAmount 0; +INVENTORY.UNDROPPABLE; +INVENTORY.UNTOSSABLE; } @@ -605,6 +604,12 @@ Class CorrodeDebuff : Inventory cnt = -1; if ( instigator ) SWWMUtility.AchievementProgressInc("acid",1,instigator.player); } + override void PreTravelled() + { + Super.PreTravelled(); + // debuff disappears between levels + Destroy(); + } override void DoEffect() { Super.DoEffect();