Convert Quadravol fire debuff to inventory item.
Copy over spread code from black shell debuff (lower hard lock risk).
This commit is contained in:
parent
794fe23c2c
commit
78dc1bb453
4 changed files with 92 additions and 85 deletions
|
|
@ -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-";
|
||||
|
|
|
|||
|
|
@ -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<numpt; i++ )
|
||||
{
|
||||
Vector3 pos = victim.Vec3Offset(FRandom[FlameT](-victim.radius,victim.radius)*.8,FRandom[FlameT](-victim.radius,victim.radius)*.8,FRandom[FlameT](victim.height*.2,victim.height*.8));
|
||||
Vector3 tpos = Owner.Vec3Offset(FRandom[FlameT](-Owner.radius,Owner.radius)*.8,FRandom[FlameT](-Owner.radius,Owner.radius)*.8,FRandom[FlameT](Owner.height*.2,Owner.height*.8));
|
||||
double ang = FRandom[FlameT](0,360);
|
||||
double pt = FRandom[FlameT](-90,90);
|
||||
if ( amount > 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue