Revert "Replace usage of ThinkerIterator and BlockThingsIterator in various places where we can instead loop through sector thing lists."
This reverts commit 2bd1cb0657.
This commit is contained in:
parent
2bd1cb0657
commit
3b10e684b6
17 changed files with 220 additions and 113 deletions
|
|
@ -63,12 +63,17 @@ extend Class SWWMUtility
|
|||
else brange = 1./(ExplosionRadius-FullDamageRadius);
|
||||
Actor Instigator = realsource?realsource:(flags&DE_NOTMISSILE)?Source:Source.target;
|
||||
int dflg = ((flags&DE_NONEXPLOSIVE)?0:DMG_EXPLOSION)|dmgflags;
|
||||
BlockThingsIterator bi = BlockThingsIterator.Create(Source,ExplosionRadius);
|
||||
int nhit = 0, nkill = 0;
|
||||
bool haskilled = false;
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
Array<Actor> washit;
|
||||
washit.Clear();
|
||||
while ( bi.Next() )
|
||||
{
|
||||
Actor a = bi.Thing;
|
||||
washit.Push(a);
|
||||
// early checks for self and ignored actor (usually the instigator)
|
||||
if ( (a == ignoreme) || (a == Source) )
|
||||
if ( !a || (a == ignoreme) || (a == Source) )
|
||||
continue;
|
||||
// can't be affected
|
||||
if ( !a.bSHOOTABLE && !a.bVULNERABLE )
|
||||
|
|
@ -136,6 +141,90 @@ extend Class SWWMUtility
|
|||
if ( (flags&DE_COUNTFHKILLS) && (oldhp < basehp) ) continue; // was not at full health
|
||||
if ( (!a || (a.Health <= 0)) && (!(flags&DE_COUNTENEMIES) || hostile) && (!(flags&DE_COUNTSTEALTH) || inactive) ) nkill++;
|
||||
}
|
||||
// traverse portals (needed since BlockThingsIterator can't properly cross sector portals in both vertical directions)
|
||||
int thisgroup = Source.CurSector.portalgroup;
|
||||
for ( int i=0; i<level.GetPortalGroupCount(); i++ )
|
||||
{
|
||||
if ( i == thisgroup ) continue;
|
||||
Vector2 relpos = Source.pos.xy+level.GetDisplacement(thisgroup,i);
|
||||
bi = BlockThingsIterator.CreateFromPos(relpos.x,relpos.y,Source.pos.z,Source.pos.z+Source.height,ExplosionRadius,false);
|
||||
while ( bi.Next() )
|
||||
{
|
||||
Actor a = bi.Thing;
|
||||
// early exit for already processed actors
|
||||
if ( washit.Find(a) < washit.Size() )
|
||||
continue;
|
||||
washit.Push(a);
|
||||
// early checks for self and ignored actor (usually the instigator)
|
||||
if ( !a || (a == ignoreme) || (a == Source) )
|
||||
continue;
|
||||
// can't be affected
|
||||
if ( !a.bSHOOTABLE && !a.bVULNERABLE )
|
||||
continue;
|
||||
// no blasting if no radius dmg (unless forced)
|
||||
if ( a.bNORADIUSDMG && !Source.bFORCERADIUSDMG )
|
||||
continue;
|
||||
// check the DONTHARMCLASS/DONTHARMSPECIES flags
|
||||
if ( !a.player && ((Source.bDONTHARMCLASS && (a.GetClass() == Source.GetClass())) || (Source.bDONTHARMSPECIES && (a.GetSpecies() == Source.GetSpecies()))) )
|
||||
continue;
|
||||
// check friendliness
|
||||
if ( (flags&DE_NOHURTFRIEND) && Instigator && Instigator.IsFriend(a) )
|
||||
continue;
|
||||
// can we see it
|
||||
if ( !(flags&DE_THRUWALLS) && !Source.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
|
||||
continue;
|
||||
// intersecting?
|
||||
if ( !SphereIntersect(a,Source.pos,ExplosionRadius) )
|
||||
continue;
|
||||
// calculate factor
|
||||
Vector3 dir;
|
||||
if ( flags&DE_CENTERHEIGHT ) dir = level.Vec3Diff(Source.Vec3Offset(0,0,Source.Height/2),a.Vec3Offset(0,0,a.Height/2));
|
||||
else dir = level.Vec3Diff(Source.pos,a.Vec3Offset(0,0,a.Height/2));
|
||||
double dist = dir.length();
|
||||
// intersecting, randomize direction
|
||||
if ( dir.length() <= double.epsilon )
|
||||
{
|
||||
double ang = FRandom[DoBlast](0,360);
|
||||
double pt = FRandom[DoBlast](-90,90);
|
||||
dir = Vec3FromAngles(ang,pt);
|
||||
}
|
||||
else dir /= dist;
|
||||
dist = clamp(dist-FullDamageRadius,0,min(dist,ExplosionRadius));
|
||||
double damagescale;
|
||||
if ( ExplosionRadius == FullDamageRadius ) damagescale = 1.;
|
||||
else damagescale = 1.-clamp((dist-a.Radius)*brange,0.,1.);
|
||||
double mm = MomentumTransfer*damagescale;
|
||||
// no knockback if massive/unpushable
|
||||
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,(flags&DE_EXTRAZTHRUST?.4:.1)*Momentum.length());
|
||||
Momentum /= GameTicRate*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
|
||||
bool inactive = (!a.player&&!a.target);
|
||||
bool hostile = (Instigator&&a.IsHostile(Instigator)&&(a.bISMONSTER||a.player));
|
||||
if ( (!(flags&DE_COUNTENEMIES) || hostile) && (!(flags&DE_COUNTSTEALTH) || inactive) ) nhit++;
|
||||
int dmg = int(Damage*damagescale);
|
||||
if ( flags&DE_QUADRAVOL )
|
||||
{
|
||||
OnFire.Apply(a,Instigator,dmg); // ignite
|
||||
continue;
|
||||
}
|
||||
if ( dmg <= 0 ) continue; // no harm
|
||||
int oldhp = a.Health;
|
||||
int basehp = a.GetSpawnHealth();
|
||||
int ndmg = a.DamageMobj(realinflictor?realinflictor:Source,Instigator,dmg,(DamageType=='')?Source.DamageType:DamageType,dflg,atan2(-dir.y,-dir.x));
|
||||
if ( (ndmg > 0) && a && !(flags&DE_NOBLEED) ) a.TraceBleed(ndmg,Source);
|
||||
if ( (flags&DE_HOWL) && a && (a.Health > 0) && a.bISMONSTER && !Random[DoBlast](0,3) ) a.Howl();
|
||||
if ( hostile && (!a || (a.Health <= 0)) ) haskilled = true;
|
||||
if ( (flags&DE_COUNTFHKILLS) && (oldhp < basehp) ) continue; // was not at full health
|
||||
if ( (!a || (a.Health <= 0)) && (!(flags&DE_COUNTENEMIES) || hostile) && (!(flags&DE_COUNTSTEALTH) || inactive) ) nkill++;
|
||||
}
|
||||
}
|
||||
if ( (Instigator is 'Demolitionist') && haskilled && !(flags&DE_NONEXPLOSIVE) )
|
||||
{
|
||||
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue