Replace usage of ThinkerIterator and BlockThingsIterator in various places where we can instead loop through sector thing lists.
While in the latter case this may result in longer loops, it also reduces GC thrashing by not needing to allocate an iterator every time. This also simplifies the DoBlast code as there is no longer a need to manually traverse portals vertically.
This commit is contained in:
parent
ea86ab99d0
commit
2bd1cb0657
17 changed files with 113 additions and 220 deletions
|
|
@ -1036,14 +1036,18 @@ Class MisterGrenade : Actor
|
|||
if ( bNoProx ) return;
|
||||
// "safe delay" for main grenade
|
||||
if ( !bAMBUSH && (ReactionTime > default.ReactionTime-20) ) return;
|
||||
let bt = BlockThingsIterator.Create(self,120);
|
||||
while ( bt.Next() )
|
||||
bool breakout = false;
|
||||
foreach ( s:level.Sectors )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),bAMBUSH?80:120) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
special1++;
|
||||
tracer = t;
|
||||
break;
|
||||
for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
if ( !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),bAMBUSH?80:120) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
special1++;
|
||||
tracer = t;
|
||||
breakout = true;
|
||||
break;
|
||||
}
|
||||
if ( breakout ) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1129,13 +1133,11 @@ Class MisterGrenade : Actor
|
|||
}
|
||||
// gather seekable targets
|
||||
Array<Actor> candidates;
|
||||
let bt = BlockThingsIterator.Create(self,2000);
|
||||
let tt = new("TargetTracer");
|
||||
tt.target = target;
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || (t == tracer) || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
if ( (t == tracer) || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
// don't seek if enemy is too close to shooter
|
||||
if ( target && SWWMUtility.SphereIntersect(t,target.pos,250) ) continue;
|
||||
// don't seek if shooter is between us and the enemy
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
extend Class SWWMHandler
|
||||
{
|
||||
ui SWWMProjectionData projdata;
|
||||
transient ui ThinkerIterator dbgti;
|
||||
|
||||
private ui void DrawWorldLine( RenderEvent e, Vector3 apos, Vector3 bpos, Color col )
|
||||
{
|
||||
|
|
@ -103,10 +102,7 @@ extend Class SWWMHandler
|
|||
if ( !swwm_debugview ) return;
|
||||
// prepare projection data, we're going to need this
|
||||
SWWMUtility.PrepareProjData(projdata,e.ViewPos,e.ViewAngle,e.ViewPitch,e.ViewRoll,players[consoleplayer].fov);
|
||||
if ( !dbgti ) dbgti = ThinkerIterator.Create("Actor");
|
||||
else dbgti.Reinit();
|
||||
Actor a;
|
||||
while ( a = Actor(dbgti.Next()) )
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
if ( (a == players[consoleplayer].Camera) && !(players[consoleplayer].cheats&CF_CHASECAM) ) continue;
|
||||
if ( a.bINVISIBLE && !(a is 'DynamicLight') ) continue;
|
||||
|
|
|
|||
|
|
@ -178,14 +178,18 @@ extend Class SWWMHandler
|
|||
// copies the floatbob of overlapping identical items, so it doesn't look weird
|
||||
private void CopyFloatBob( Actor a )
|
||||
{
|
||||
let bt = BlockThingsIterator.Create(a,16);
|
||||
while ( bt.Next() )
|
||||
bool breakout = false;
|
||||
foreach ( s:level.Sectors )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || (t == a) || !(t is 'Inventory') || !(t.spawnpoint ~== a.spawnpoint) ) continue;
|
||||
a.floatbobphase = t.floatbobphase;
|
||||
a.angle = t.angle; // also copy angle
|
||||
break;
|
||||
for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
if ( (t == a) || !(t is 'Inventory') || !(t.spawnpoint ~== a.spawnpoint) ) continue;
|
||||
a.floatbobphase = t.floatbobphase;
|
||||
a.angle = t.angle; // also copy angle
|
||||
breakout = true;
|
||||
break;
|
||||
}
|
||||
if ( breakout ) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,11 +98,9 @@ extend Class SWWMHandler
|
|||
}
|
||||
bool enteredcombat = false;
|
||||
// add new entries
|
||||
if ( !cti ) cti = ThinkerIterator.Create("Actor");
|
||||
else cti.Reinit();
|
||||
Actor a, keyactor = null;
|
||||
bool bossfound = false;
|
||||
while ( a = Actor(cti.Next()) )
|
||||
// we can use this instead of a thinker iterator as only actors that EXIST physically could count as combatants
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
if ( !a.player && !a.bISMONSTER ) continue;
|
||||
// ignore the dead
|
||||
|
|
@ -206,12 +204,12 @@ extend Class SWWMHandler
|
|||
}
|
||||
mapclearagain++;
|
||||
if ( !iwantdie ) return;
|
||||
let ti = ThinkerIterator.Create("SWWMStats",Thinker.STAT_STATIC);
|
||||
SWWMStats s;
|
||||
while ( s = SWWMStats(ti.Next()) )
|
||||
for ( int i=0; i<MAXPLAYERS; i++ )
|
||||
{
|
||||
if ( s.deaths > 0 )
|
||||
return;
|
||||
if ( !playeringame[i] ) continue;
|
||||
let demo = Demolitionist(players[i].mo);
|
||||
if ( !demo || !demo.mystats ) continue;
|
||||
if ( demo.mystats.deaths > 0 ) return;
|
||||
}
|
||||
SWWMUtility.MarkAchievement("wantdie",players[consoleplayer]);
|
||||
}
|
||||
|
|
@ -279,11 +277,9 @@ extend Class SWWMHandler
|
|||
}
|
||||
// update trackers for anything around the player
|
||||
double viewdist = SWWMStatusBar.MAPVIEWDIST*swwm_mm_zoom;
|
||||
BlockThingsIterator bt = BlockThingsIterator.Create(players[consoleplayer].Camera,viewdist);
|
||||
while ( bt.Next() )
|
||||
// still about as expensive as using a BlockThingsIterator, but without the need to allocate one every tic
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
let a = bt.Thing;
|
||||
if ( !a ) continue;
|
||||
Vector2 rv = a.pos.xy-players[consoleplayer].Camera.pos.xy;
|
||||
if ( max(abs(rv.x)-a.radius,abs(rv.y)-a.radius) > viewdist )
|
||||
continue;
|
||||
|
|
@ -325,19 +321,15 @@ extend Class SWWMHandler
|
|||
continue;
|
||||
SWWMSimpleTracker.Track(self,a);
|
||||
}
|
||||
bt.Destroy();
|
||||
// oh boy here we go
|
||||
int thisgroup = players[consoleplayer].Camera.CurSector.portalgroup;
|
||||
for ( int i=0; i<level.GetPortalGroupCount(); i++ )
|
||||
{
|
||||
if ( i == thisgroup ) continue;
|
||||
Vector2 relpos = players[consoleplayer].Camera.pos.xy+level.GetDisplacement(thisgroup,i);
|
||||
if ( bt ) bt.Destroy();
|
||||
bt = BlockThingsIterator.CreateFromPos(relpos.x,relpos.y,players[consoleplayer].Camera.pos.z,players[consoleplayer].Camera.pos.z+players[consoleplayer].Camera.height,viewdist,false);
|
||||
while ( bt.Next() )
|
||||
// still about as expensive as using a BlockThingsIterator, but without the need to allocate one every tic
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
let a = bt.Thing;
|
||||
if ( !a ) continue;
|
||||
Vector2 rv = a.pos.xy-relpos;
|
||||
if ( max(abs(rv.x)-a.radius,abs(rv.y)-a.radius) > viewdist )
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -523,15 +523,19 @@ Class HammerspaceEmbiggener : Inventory
|
|||
// since backpacks are taller in Doom
|
||||
if ( gameinfo.gametype&GAME_DoomChex )
|
||||
A_SetSize(-1,26);
|
||||
let bt = BlockThingsIterator.Create(self,16);
|
||||
int tamount = Amount;
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || (t == self) || !(t is 'HammerspaceEmbiggener') || !(t.spawnpoint ~== spawnpoint) ) continue;
|
||||
let next = t.snext;
|
||||
if ( (t == self) || !(t is 'HammerspaceEmbiggener') || !(t.spawnpoint ~== spawnpoint) )
|
||||
{
|
||||
t = next;
|
||||
continue;
|
||||
}
|
||||
tamount += HammerspaceEmbiggener(t).Amount;
|
||||
t.ClearCounters();
|
||||
t.Destroy();
|
||||
t = next;
|
||||
}
|
||||
if ( tamount <= 1 ) return;
|
||||
tamount -= tamount%2; // always even numbered
|
||||
|
|
|
|||
|
|
@ -58,12 +58,10 @@ Class LampMoth : Actor
|
|||
if ( !lamp )
|
||||
{
|
||||
// look for nearby lamps
|
||||
let bi = BlockThingsIterator.Create(self,250);
|
||||
double mindist = 62500.;
|
||||
while ( bi.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
if ( !bi.Thing || !(bi.Thing is 'CompanionLamp') ) continue;
|
||||
Actor a = bi.Thing;
|
||||
if ( !(a is 'CompanionLamp') ) continue;
|
||||
double dist = Distance3DSquared(a);
|
||||
if ( (a.frame == 0) || (dist > mindist) && !CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
mindist = dist;
|
||||
|
|
|
|||
|
|
@ -310,11 +310,9 @@ Class GhostTarget : Actor
|
|||
}
|
||||
if ( isFrozen() ) return;
|
||||
if ( diedie ) A_FadeOut(.05);
|
||||
let bt = BlockThingsIterator.Create(self,300);
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || !t.bIsMonster || t.player || !t.IsHostile(master) || (t.target != self) ) continue;
|
||||
if ( !t.bIsMonster || t.player || !t.IsHostile(master) || (t.target != self) ) continue;
|
||||
if ( SWWMUtility.BoxIntersect(self,t,pad:16) || t.CheckMeleeRange() )
|
||||
{
|
||||
// they found out, there's no one here
|
||||
|
|
|
|||
|
|
@ -510,9 +510,7 @@ Class Mykradvo : Inventory
|
|||
{
|
||||
targets.Clear();
|
||||
// search all actively hostile enemies within 50m
|
||||
let ti = ThinkerIterator.Create("Actor");
|
||||
Actor a;
|
||||
while ( a=Actor(ti.Next()) )
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
// must be an active, shootable live monster
|
||||
if ( !a.bISMONSTER || !a.bSHOOTABLE || a.bDORMANT || (a.Health <= 0) ) continue;
|
||||
|
|
|
|||
|
|
@ -5,18 +5,15 @@ extend Class Demolitionist
|
|||
{
|
||||
if ( player.cmd.buttons&BT_USER3 )
|
||||
{
|
||||
let bt = BlockThingsIterator.Create(self,800);
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor i=s.thinglist; i; i=i.snext )
|
||||
{
|
||||
let i = bt.Thing;
|
||||
if ( !i || (!(i is 'Inventory') && !(i is 'Chancebox') && !(i is 'SWWMRespawnTimer')) ) continue;
|
||||
if ( !(i is 'Inventory') && !(i is 'Chancebox') && !(i is 'SWWMRespawnTimer') ) continue;
|
||||
if ( (i is 'Inventory') && (i.bINVISIBLE || !i.bSPECIAL || Inventory(i).Owner) ) continue;
|
||||
if ( (i is 'Chancebox') && (i.CurState != i.SpawnState) ) continue;
|
||||
if ( !SWWMUtility.SphereIntersect(i,pos,800) ) continue;
|
||||
if ( !level.allmap && !i.CheckSight(self,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
SWWMItemSense.Spawn(self,i);
|
||||
}
|
||||
bt.Destroy();
|
||||
}
|
||||
SWWMItemsense itm = itemsense;
|
||||
SWWMItemsense prev = null, next;
|
||||
|
|
@ -53,11 +50,9 @@ extend Class Demolitionist
|
|||
}
|
||||
if ( (magitem_cnt < 8) && !swwm_usetopickup )
|
||||
{
|
||||
let bt = BlockThingsIterator.Create(self,500);
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || !(t is 'Inventory') || !t.bSPECIAL || !t.bDROPPED || t.bINVISIBLE || Inventory(t).Owner || !SWWMUtility.SphereIntersect(t,pos,500) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
|
||||
if ( !(t is 'Inventory') || !t.bSPECIAL || !t.bDROPPED || t.bINVISIBLE || Inventory(t).Owner || !SWWMUtility.SphereIntersect(t,pos,500) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
|
||||
continue;
|
||||
let i = Inventory(t);
|
||||
Class<Inventory> cls = i.GetClass();
|
||||
|
|
@ -87,7 +82,6 @@ extend Class Demolitionist
|
|||
magitem = nmi;
|
||||
magitem_cnt++;
|
||||
}
|
||||
bt.Destroy();
|
||||
}
|
||||
SWWMMagItem itm = magitem;
|
||||
SWWMMagItem prev = null, next;
|
||||
|
|
@ -529,14 +523,13 @@ extend Class Demolitionist
|
|||
Vector3 viewdir = SWWMUtility.Vec3FromAngles(angle,pitch);
|
||||
// look for things we could potentially bump into
|
||||
bool bumped = false;
|
||||
let bi = BlockThingsIterator.Create(self,500);
|
||||
let raging = RagekitPower(FindInventory("RagekitPower"));
|
||||
double maxmass = max(mass*spd/40.,200);
|
||||
if ( raging ) maxmass *= 2;
|
||||
while ( (spd > 0) && bi.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
a = bi.Thing;
|
||||
if ( !a || (a == self) || (!a.bSOLID && !a.bSHOOTABLE) || a.bTHRUACTORS || a.bCORPSE || !CanCollideWith(a,false) || !a.CanCollideWith(self,true) ) continue;
|
||||
if ( spd <= 0 ) break;
|
||||
if ( (a == self) || (!a.bSOLID && !a.bSHOOTABLE) || a.bTHRUACTORS || a.bCORPSE || !CanCollideWith(a,false) || !a.CanCollideWith(self,true) ) continue;
|
||||
if ( !SWWMUtility.ExtrudeIntersect(self,a,dir*(spd+radius),8) ) continue;
|
||||
if ( (a.pos.z <= a.floorz) && (a.height <= MaxStepHeight) ) continue;
|
||||
Vector3 diff = level.Vec3Diff(pos,a.pos);
|
||||
|
|
|
|||
|
|
@ -63,17 +63,12 @@ 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;
|
||||
Array<Actor> washit;
|
||||
washit.Clear();
|
||||
while ( bi.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
Actor a = bi.Thing;
|
||||
washit.Push(a);
|
||||
// early checks for self and ignored actor (usually the instigator)
|
||||
if ( !a || (a == ignoreme) || (a == Source) )
|
||||
if ( (a == ignoreme) || (a == Source) )
|
||||
continue;
|
||||
// can't be affected
|
||||
if ( !a.bSHOOTABLE && !a.bVULNERABLE )
|
||||
|
|
@ -141,90 +136,6 @@ 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"));
|
||||
|
|
|
|||
|
|
@ -111,11 +111,9 @@ Class ParryField : SWWMNonInteractiveActor
|
|||
}
|
||||
SetOrigin(SWWMUtility.GetFireOffset(master,20,0,0),false);
|
||||
let raging = RagekitPower(master.FindInventory("RagekitPower"));
|
||||
let s = Demolitionist(master).mystats;
|
||||
let st = Demolitionist(master).mystats;
|
||||
// check for projectiles to deflect
|
||||
let ti = ThinkerIterator.Create("Actor");
|
||||
Actor a;
|
||||
while ( a = Actor(ti.Next()) )
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
{
|
||||
if ( (justparried.Find(a) < justparried.Size()) || !(SWWMUtility.ValidProjectile(a) || a.bSKULLFLY) || a.bTHRUACTORS || (level.Vec3Diff(a.pos,pos).length() > 80) ) continue;
|
||||
if ( a is 'Whirlwind' ) SWWMUtility.MarkAchievement("tornado",master.player);
|
||||
|
|
@ -179,13 +177,13 @@ Class ParryField : SWWMNonInteractiveActor
|
|||
if ( !critsnd )
|
||||
{
|
||||
A_StartSound("misc/soulsparry",CHAN_ITEM,CHANF_OVERLAP,1.,.5);
|
||||
if ( s ) s.pparries++;
|
||||
if ( st ) st.pparries++;
|
||||
}
|
||||
critsnd = true;
|
||||
if ( (a is 'LostSoul') && (master.player.ReadyWeapon is 'SilverBullet') )
|
||||
SWWMUtility.MarkAchievement("baseball",master.player);
|
||||
}
|
||||
if ( s ) s.parries++;
|
||||
if ( st ) st.parries++;
|
||||
SWWMUtility.AchievementProgressInc("parry",1,master.player);
|
||||
}
|
||||
if ( --special1 <= 0 ) Destroy();
|
||||
|
|
|
|||
|
|
@ -266,14 +266,18 @@ Class HellblazerMissile : Actor
|
|||
return;
|
||||
}
|
||||
// proximity check
|
||||
let bt = BlockThingsIterator.Create(self,200);
|
||||
while ( bt.Next() )
|
||||
bool checked = false;
|
||||
foreach ( s:level.Sectors )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),bNOGRAVITY?50:90) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
deto++;
|
||||
tracer = t;
|
||||
break;
|
||||
for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
if ( !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),bNOGRAVITY?50:90) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
deto++;
|
||||
tracer = t;
|
||||
checked = true;
|
||||
break;
|
||||
}
|
||||
if ( checked ) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -465,13 +465,11 @@ Class YnykronImpact : SWWMNonInteractiveActor
|
|||
let s = Spawn("YnykronImpactArm",pos);
|
||||
s.target = target;
|
||||
}
|
||||
let bt = BlockThingsIterator.Create(self,rad+200);
|
||||
Array<Actor> candidates;
|
||||
candidates.Clear();
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || !t.bSHOOTABLE || !SWWMUtility.SphereIntersect(t,pos,rad) || (!SWWMUtility.SphereIntersect(t,pos,100) && !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY)) ) continue;
|
||||
if ( !t.bSHOOTABLE || !SWWMUtility.SphereIntersect(t,pos,rad) || (!SWWMUtility.SphereIntersect(t,pos,100) && !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY)) ) continue;
|
||||
if ( YnykronShot(master) && (YnykronShot(master).hitlist.Find(t) < YnykronShot(master).hitlist.Size()) )
|
||||
continue;
|
||||
Vector3 dirto = level.Vec3Diff(pos,t.Vec3Offset(0,0,t.Height/2));
|
||||
|
|
|
|||
|
|
@ -211,10 +211,8 @@ Class DeepImpact : SWWMWeapon
|
|||
let p = SWWMPuff.Setup(avgpos,avgdir,invoker,self,l.a);
|
||||
l.a.DamageMobj(p,self,int(dmg/250.),'Push',DMG_THRUSTLESS|DMG_INFLICTOR_IS_PUFF);
|
||||
}
|
||||
let ti = ThinkerIterator.Create("Actor");
|
||||
Actor m;
|
||||
let s = Demolitionist(self).mystats;
|
||||
while ( m = Actor(ti.Next()) )
|
||||
let st = Demolitionist(self).mystats;
|
||||
foreach ( s:level.Sectors ) for ( Actor m=s.thinglist; m; m=m.snext )
|
||||
{
|
||||
if ( !SWWMUtility.ValidProjectile(m) ) continue;
|
||||
Vector3 rdir = level.Vec3Diff(origin,m.pos);
|
||||
|
|
@ -235,7 +233,7 @@ Class DeepImpact : SWWMWeapon
|
|||
pb.AttachToOwner(m);
|
||||
pb.bAMBUSH = true;
|
||||
}
|
||||
if ( s ) s.parries++;
|
||||
if ( st ) st.parries++;
|
||||
SWWMUtility.AchievementProgressInc("parry",1,player);
|
||||
}
|
||||
int numpt = Random[Impact](7,12);
|
||||
|
|
|
|||
|
|
@ -192,12 +192,10 @@ Class BigBiospark : Actor
|
|||
if ( !(special2%5) )
|
||||
{
|
||||
double closest = double.infinity;
|
||||
let bt = BlockThingsIterator.Create(self,8000);
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
double dist;
|
||||
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || ((dist=Distance3DSquared(t)) > 64000000) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
if ( !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || ((dist=Distance3DSquared(t)) > 64000000) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
Vector3 dirto = level.Vec3Diff(pos,t.Vec3Offset(0,0,t.height/2)).unit();
|
||||
if ( dist > closest ) continue;
|
||||
closest = dist;
|
||||
|
|
@ -222,11 +220,9 @@ Class BigBiospark : Actor
|
|||
angle = atan2(dir.y,dir.x);
|
||||
pitch = asin(-dir.z);
|
||||
// deal (proper) radius damage
|
||||
let bt2 = BlockThingsIterator.Create(self,500);
|
||||
while ( bt2.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt2.Thing;
|
||||
if ( !t || !t.bSHOOTABLE ) continue;
|
||||
if ( !t.bSHOOTABLE ) continue;
|
||||
if ( SWWMUtility.SphereIntersect(t,pos,40) )
|
||||
{
|
||||
t.DamageMobj(self,target,4+special1,'Biospark');
|
||||
|
|
@ -465,12 +461,10 @@ Class BiosparkBall : Actor
|
|||
if ( !(special2%5) )
|
||||
{
|
||||
double closest = double.infinity;
|
||||
let bt = BlockThingsIterator.Create(self,500);
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
double dist;
|
||||
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || ((dist=Distance3DSquared(t)) > 250000) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
if ( !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || ((dist=Distance3DSquared(t)) > 250000) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
Vector3 dirto = level.Vec3Diff(pos,t.Vec3Offset(0,0,t.height/2)).unit();
|
||||
if ( dir dot dirto < .5 ) continue; // don't seek stuff that's behind us
|
||||
if ( dist > closest ) continue;
|
||||
|
|
@ -497,13 +491,17 @@ Class BiosparkBall : Actor
|
|||
return;
|
||||
}
|
||||
// proximity check
|
||||
let bt = BlockThingsIterator.Create(self,100);
|
||||
while ( bt.Next() )
|
||||
bool checked = false;
|
||||
foreach ( s:level.Sectors )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),16) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
deto++;
|
||||
break;
|
||||
for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
if ( !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),16) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
deto++;
|
||||
checked = true;
|
||||
break;
|
||||
}
|
||||
if ( checked ) break;
|
||||
}
|
||||
}
|
||||
override void OnDestroy()
|
||||
|
|
@ -1055,12 +1053,10 @@ Class BiosparkBeam : SWWMNonInteractiveActor
|
|||
}
|
||||
nextpos = t.Results.HitPos;
|
||||
double closest = double.infinity;
|
||||
let bt = BlockThingsIterator.Create(self,500);
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
double dist;
|
||||
if ( !t || (!(t is 'BiosparkHitbox') && (!t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)))) || ((dist=Distance3DSquared(t)) > 250000) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
if ( (!(t is 'BiosparkHitbox') && (!t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)))) || ((dist=Distance3DSquared(t)) > 250000) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
Vector3 dirto = level.Vec3Diff(nextpos,t.Vec3Offset(0,0,t.height/2));
|
||||
if ( dir dot dirto < .2 ) continue;
|
||||
if ( dist > closest ) continue;
|
||||
|
|
@ -1362,12 +1358,10 @@ Class BiosparkArc : SWWMNonInteractiveActor
|
|||
else
|
||||
{
|
||||
double closest = double.infinity;
|
||||
let bt = BlockThingsIterator.Create(self,1500);
|
||||
while ( bt.Next() )
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
double dist;
|
||||
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || ((dist=Distance3DSquared(t)) > 2250000) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
if ( !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || ((dist=Distance3DSquared(t)) > 2250000) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
Vector3 dirto = level.Vec3Diff(nextpos,t.Vec3Offset(0,0,t.height/2));
|
||||
if ( dir dot dirto < .2 ) continue;
|
||||
if ( dist > closest ) continue;
|
||||
|
|
|
|||
|
|
@ -245,15 +245,20 @@ Class ExplodiumMagHitbox : Actor
|
|||
return;
|
||||
}
|
||||
SetOrigin(target.Vec3Offset(0,0,-height*.5),false);
|
||||
let bt = BlockThingsIterator.Create(self,128);
|
||||
while ( bt.Next() )
|
||||
bool breakout = false;
|
||||
foreach ( s:level.Sectors )
|
||||
{
|
||||
if ( !bt.Thing || (bt.Thing == self) || !bt.Thing.bSHOOTABLE || (bt.Thing == target.target) || bt.Thing.IsFriend(target.target) || !SWWMUtility.BoxIntersect(self,bt.Thing) )
|
||||
continue;
|
||||
target.bKILLED = true;
|
||||
target.SetStateLabel("Detonate");
|
||||
Destroy();
|
||||
break;
|
||||
for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
{
|
||||
if ( (t == self) || !t.bSHOOTABLE || (t == target.target) || t.IsFriend(target.target) || !SWWMUtility.BoxIntersect(self,t) )
|
||||
continue;
|
||||
target.bKILLED = true;
|
||||
target.SetStateLabel("Detonate");
|
||||
Destroy();
|
||||
breakout = true;
|
||||
break;
|
||||
}
|
||||
if ( breakout ) break;
|
||||
}
|
||||
}
|
||||
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue