Various things here and there:

- Allow total damage dealt/taken stat to go beyond int.max.
- Reduce thinker iterator usage in some places (most notably for fire debuffs).
- Fix untouchable spree stat tracking.
- Allow paying respects when erased by Ynykron.
- Correct use of wrong flag (CANNOTPUSH instead of DONTTHRUST) in several spots.
- Use LARGE_MASS const instead of its value where needed.
- Add flags to DoExplosion, for various things.
- Fix missing splashes on DoExplosion.
- Allow DoExplosion to set the BLASTED flag, used by ground pound shockwaves.
- Add flag to re-enable the higher Z thrust on DoExplosion knockback.
- Added a "sweet spot" to berserk shockwaves.
- Explodium splash deals more Z thrust, allowing it to send enemies flying when aiming at the feet, as intended.
- Adjust a couple things related to player dashing.
- Fix player being yeeted when killing a large enemy by stomping.
- Tweaked ground pound shockwaves. The ring shockwave only spawns on solid ground now.
This commit is contained in:
Mari the Deer 2020-07-31 16:14:00 +02:00
commit e422da7cc8
10 changed files with 178 additions and 93 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Before After
Before After

View file

@ -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)";

View file

@ -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<WeaponUsage> wstats;
Array<Class<Weapon> > 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<Weapon> 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
}

View file

@ -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);
}

View file

@ -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();
}
}

View file

@ -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);

View file

@ -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<numpt; i++ )
{

View file

@ -886,10 +886,31 @@ Class OnFireLight : DynamicLight
Class OnFire : Actor
{
OnFire prevfire, nextfire;
Actor victim, instigator, lite;
int amount, cnt, delay;
double oangle;
override void OnDestroy()
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd )
{
hnd.fires_cnt--;
if ( !prevfire )
{
hnd.fires = nextfire;
if ( nextfire ) nextfire.prevfire = null;
}
else
{
prevfire.nextfire = nextfire;
if ( nextfire ) nextfire.prevfire = prevfire;
}
}
Super.OnDestroy();
}
override void Tick()
{
if ( !victim )
@ -967,17 +988,25 @@ Class OnFire : Actor
let t = bt.Thing;
if ( !t || !t.bSHOOTABLE || (t.Health <= 0) || (t == victim) || ((t == instigator) && (delay > 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);

View file

@ -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);

View file

@ -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);