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
|
|
@ -1,3 +1,3 @@
|
|||
[default]
|
||||
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r835 \cu(Sat 29 Jul 13:15:34 CEST 2023)\c-";
|
||||
SWWM_SHORTVER="\cw1.3pre r835 \cu(2023-07-29 13:15:34)\c-";
|
||||
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r834 \cu(Sat 29 Jul 12:25:53 CEST 2023)\c-";
|
||||
SWWM_SHORTVER="\cw1.3pre r834 \cu(2023-07-29 12:25:53)\c-";
|
||||
|
|
|
|||
|
|
@ -1036,18 +1036,14 @@ Class MisterGrenade : Actor
|
|||
if ( bNoProx ) return;
|
||||
// "safe delay" for main grenade
|
||||
if ( !bAMBUSH && (ReactionTime > default.ReactionTime-20) ) return;
|
||||
bool breakout = false;
|
||||
foreach ( s:level.Sectors )
|
||||
let bt = BlockThingsIterator.Create(self,120);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1133,11 +1129,13 @@ Class MisterGrenade : Actor
|
|||
}
|
||||
// gather seekable targets
|
||||
Array<Actor> candidates;
|
||||
let bt = BlockThingsIterator.Create(self,2000);
|
||||
let tt = new("TargetTracer");
|
||||
tt.target = target;
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
while ( bt.Next() )
|
||||
{
|
||||
if ( (t == tracer) || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
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;
|
||||
// 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,6 +3,7 @@
|
|||
extend Class SWWMHandler
|
||||
{
|
||||
ui SWWMProjectionData projdata;
|
||||
transient ui ThinkerIterator dbgti;
|
||||
|
||||
private ui void DrawWorldLine( RenderEvent e, Vector3 apos, Vector3 bpos, Color col )
|
||||
{
|
||||
|
|
@ -102,7 +103,10 @@ 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);
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
if ( !dbgti ) dbgti = ThinkerIterator.Create("Actor");
|
||||
else dbgti.Reinit();
|
||||
Actor a;
|
||||
while ( a = Actor(dbgti.Next()) )
|
||||
{
|
||||
if ( (a == players[consoleplayer].Camera) && !(players[consoleplayer].cheats&CF_CHASECAM) ) continue;
|
||||
if ( a.bINVISIBLE && !(a is 'DynamicLight') ) continue;
|
||||
|
|
|
|||
|
|
@ -178,18 +178,14 @@ extend Class SWWMHandler
|
|||
// copies the floatbob of overlapping identical items, so it doesn't look weird
|
||||
private void CopyFloatBob( Actor a )
|
||||
{
|
||||
bool breakout = false;
|
||||
foreach ( s:level.Sectors )
|
||||
let bt = BlockThingsIterator.Create(a,16);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,9 +98,11 @@ 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;
|
||||
// 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 )
|
||||
while ( a = Actor(cti.Next()) )
|
||||
{
|
||||
if ( !a.player && !a.bISMONSTER ) continue;
|
||||
// ignore the dead
|
||||
|
|
@ -204,12 +206,12 @@ extend Class SWWMHandler
|
|||
}
|
||||
mapclearagain++;
|
||||
if ( !iwantdie ) return;
|
||||
for ( int i=0; i<MAXPLAYERS; i++ )
|
||||
let ti = ThinkerIterator.Create("SWWMStats",Thinker.STAT_STATIC);
|
||||
SWWMStats s;
|
||||
while ( s = SWWMStats(ti.Next()) )
|
||||
{
|
||||
if ( !playeringame[i] ) continue;
|
||||
let demo = Demolitionist(players[i].mo);
|
||||
if ( !demo || !demo.mystats ) continue;
|
||||
if ( demo.mystats.deaths > 0 ) return;
|
||||
if ( s.deaths > 0 )
|
||||
return;
|
||||
}
|
||||
SWWMUtility.MarkAchievement("wantdie",players[consoleplayer]);
|
||||
}
|
||||
|
|
@ -277,9 +279,11 @@ extend Class SWWMHandler
|
|||
}
|
||||
// update trackers for anything around the player
|
||||
double viewdist = SWWMStatusBar.MAPVIEWDIST*swwm_mm_zoom;
|
||||
// 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 )
|
||||
BlockThingsIterator bt = BlockThingsIterator.Create(players[consoleplayer].Camera,viewdist);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
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;
|
||||
|
|
@ -321,15 +325,19 @@ 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);
|
||||
// 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 )
|
||||
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() )
|
||||
{
|
||||
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,19 +523,15 @@ 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;
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; )
|
||||
while ( bt.Next() )
|
||||
{
|
||||
let next = t.snext;
|
||||
if ( (t == self) || !(t is 'HammerspaceEmbiggener') || !(t.spawnpoint ~== spawnpoint) )
|
||||
{
|
||||
t = next;
|
||||
continue;
|
||||
}
|
||||
let t = bt.Thing;
|
||||
if ( !t || (t == self) || !(t is 'HammerspaceEmbiggener') || !(t.spawnpoint ~== spawnpoint) ) continue;
|
||||
tamount += HammerspaceEmbiggener(t).Amount;
|
||||
t.ClearCounters();
|
||||
t.Destroy();
|
||||
t = next;
|
||||
}
|
||||
if ( tamount <= 1 ) return;
|
||||
tamount -= tamount%2; // always even numbered
|
||||
|
|
|
|||
|
|
@ -58,10 +58,12 @@ Class LampMoth : Actor
|
|||
if ( !lamp )
|
||||
{
|
||||
// look for nearby lamps
|
||||
let bi = BlockThingsIterator.Create(self,250);
|
||||
double mindist = 62500.;
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
while ( bi.Next() )
|
||||
{
|
||||
if ( !(a is 'CompanionLamp') ) continue;
|
||||
if ( !bi.Thing || !(bi.Thing is 'CompanionLamp') ) continue;
|
||||
Actor a = bi.Thing;
|
||||
double dist = Distance3DSquared(a);
|
||||
if ( (a.frame == 0) || (dist > mindist) && !CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
||||
mindist = dist;
|
||||
|
|
|
|||
|
|
@ -310,9 +310,11 @@ Class GhostTarget : Actor
|
|||
}
|
||||
if ( isFrozen() ) return;
|
||||
if ( diedie ) A_FadeOut(.05);
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
let bt = BlockThingsIterator.Create(self,300);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
if ( !t.bIsMonster || t.player || !t.IsHostile(master) || (t.target != self) ) continue;
|
||||
let t = bt.Thing;
|
||||
if ( !t || !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,7 +510,9 @@ Class Mykradvo : Inventory
|
|||
{
|
||||
targets.Clear();
|
||||
// search all actively hostile enemies within 50m
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
let ti = ThinkerIterator.Create("Actor");
|
||||
Actor a;
|
||||
while ( a=Actor(ti.Next()) )
|
||||
{
|
||||
// must be an active, shootable live monster
|
||||
if ( !a.bISMONSTER || !a.bSHOOTABLE || a.bDORMANT || (a.Health <= 0) ) continue;
|
||||
|
|
|
|||
|
|
@ -5,15 +5,18 @@ extend Class Demolitionist
|
|||
{
|
||||
if ( player.cmd.buttons&BT_USER3 )
|
||||
{
|
||||
foreach ( s:level.Sectors ) for ( Actor i=s.thinglist; i; i=i.snext )
|
||||
let bt = BlockThingsIterator.Create(self,800);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
if ( !(i is 'Inventory') && !(i is 'Chancebox') && !(i is 'SWWMRespawnTimer') ) continue;
|
||||
let i = bt.Thing;
|
||||
if ( !i || (!(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;
|
||||
|
|
@ -50,9 +53,11 @@ extend Class Demolitionist
|
|||
}
|
||||
if ( (magitem_cnt < 8) && !swwm_usetopickup )
|
||||
{
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
let bt = BlockThingsIterator.Create(self,500);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
if ( !(t is 'Inventory') || !t.bSPECIAL || !t.bDROPPED || t.bINVISIBLE || Inventory(t).Owner || !SWWMUtility.SphereIntersect(t,pos,500) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
|
||||
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) )
|
||||
continue;
|
||||
let i = Inventory(t);
|
||||
Class<Inventory> cls = i.GetClass();
|
||||
|
|
@ -82,6 +87,7 @@ extend Class Demolitionist
|
|||
magitem = nmi;
|
||||
magitem_cnt++;
|
||||
}
|
||||
bt.Destroy();
|
||||
}
|
||||
SWWMMagItem itm = magitem;
|
||||
SWWMMagItem prev = null, next;
|
||||
|
|
@ -523,13 +529,14 @@ 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;
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
while ( (spd > 0) && bi.Next() )
|
||||
{
|
||||
if ( spd <= 0 ) break;
|
||||
if ( (a == self) || (!a.bSOLID && !a.bSHOOTABLE) || a.bTHRUACTORS || a.bCORPSE || !CanCollideWith(a,false) || !a.CanCollideWith(self,true) ) continue;
|
||||
a = bi.Thing;
|
||||
if ( !a || (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,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"));
|
||||
|
|
|
|||
|
|
@ -111,9 +111,11 @@ Class ParryField : SWWMNonInteractiveActor
|
|||
}
|
||||
SetOrigin(SWWMUtility.GetFireOffset(master,20,0,0),false);
|
||||
let raging = RagekitPower(master.FindInventory("RagekitPower"));
|
||||
let st = Demolitionist(master).mystats;
|
||||
let s = Demolitionist(master).mystats;
|
||||
// check for projectiles to deflect
|
||||
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
|
||||
let ti = ThinkerIterator.Create("Actor");
|
||||
Actor a;
|
||||
while ( a = Actor(ti.Next()) )
|
||||
{
|
||||
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);
|
||||
|
|
@ -177,13 +179,13 @@ Class ParryField : SWWMNonInteractiveActor
|
|||
if ( !critsnd )
|
||||
{
|
||||
A_StartSound("misc/soulsparry",CHAN_ITEM,CHANF_OVERLAP,1.,.5);
|
||||
if ( st ) st.pparries++;
|
||||
if ( s ) s.pparries++;
|
||||
}
|
||||
critsnd = true;
|
||||
if ( (a is 'LostSoul') && (master.player.ReadyWeapon is 'SilverBullet') )
|
||||
SWWMUtility.MarkAchievement("baseball",master.player);
|
||||
}
|
||||
if ( st ) st.parries++;
|
||||
if ( s ) s.parries++;
|
||||
SWWMUtility.AchievementProgressInc("parry",1,master.player);
|
||||
}
|
||||
if ( --special1 <= 0 ) Destroy();
|
||||
|
|
|
|||
|
|
@ -266,18 +266,14 @@ Class HellblazerMissile : Actor
|
|||
return;
|
||||
}
|
||||
// proximity check
|
||||
bool checked = false;
|
||||
foreach ( s:level.Sectors )
|
||||
let bt = BlockThingsIterator.Create(self,200);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -465,11 +465,13 @@ Class YnykronImpact : SWWMNonInteractiveActor
|
|||
let s = Spawn("YnykronImpactArm",pos);
|
||||
s.target = target;
|
||||
}
|
||||
let bt = BlockThingsIterator.Create(self,rad+200);
|
||||
Array<Actor> candidates;
|
||||
candidates.Clear();
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
while ( bt.Next() )
|
||||
{
|
||||
if ( !t.bSHOOTABLE || !SWWMUtility.SphereIntersect(t,pos,rad) || (!SWWMUtility.SphereIntersect(t,pos,100) && !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY)) ) continue;
|
||||
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 ( 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,8 +211,10 @@ 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 st = Demolitionist(self).mystats;
|
||||
foreach ( s:level.Sectors ) for ( Actor m=s.thinglist; m; m=m.snext )
|
||||
let ti = ThinkerIterator.Create("Actor");
|
||||
Actor m;
|
||||
let s = Demolitionist(self).mystats;
|
||||
while ( m = Actor(ti.Next()) )
|
||||
{
|
||||
if ( !SWWMUtility.ValidProjectile(m) ) continue;
|
||||
Vector3 rdir = level.Vec3Diff(origin,m.pos);
|
||||
|
|
@ -233,7 +235,7 @@ Class DeepImpact : SWWMWeapon
|
|||
pb.AttachToOwner(m);
|
||||
pb.bAMBUSH = true;
|
||||
}
|
||||
if ( st ) st.parries++;
|
||||
if ( s ) s.parries++;
|
||||
SWWMUtility.AchievementProgressInc("parry",1,player);
|
||||
}
|
||||
int numpt = Random[Impact](7,12);
|
||||
|
|
|
|||
|
|
@ -192,10 +192,12 @@ Class BigBiospark : Actor
|
|||
if ( !(special2%5) )
|
||||
{
|
||||
double closest = double.infinity;
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
let bt = BlockThingsIterator.Create(self,8000);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
double dist;
|
||||
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;
|
||||
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;
|
||||
Vector3 dirto = level.Vec3Diff(pos,t.Vec3Offset(0,0,t.height/2)).unit();
|
||||
if ( dist > closest ) continue;
|
||||
closest = dist;
|
||||
|
|
@ -220,9 +222,11 @@ Class BigBiospark : Actor
|
|||
angle = atan2(dir.y,dir.x);
|
||||
pitch = asin(-dir.z);
|
||||
// deal (proper) radius damage
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
let bt2 = BlockThingsIterator.Create(self,500);
|
||||
while ( bt2.Next() )
|
||||
{
|
||||
if ( !t.bSHOOTABLE ) continue;
|
||||
let t = bt2.Thing;
|
||||
if ( !t || !t.bSHOOTABLE ) continue;
|
||||
if ( SWWMUtility.SphereIntersect(t,pos,40) )
|
||||
{
|
||||
t.DamageMobj(self,target,4+special1,'Biospark');
|
||||
|
|
@ -461,10 +465,12 @@ Class BiosparkBall : Actor
|
|||
if ( !(special2%5) )
|
||||
{
|
||||
double closest = double.infinity;
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
let bt = BlockThingsIterator.Create(self,500);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
double dist;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
|
@ -491,17 +497,13 @@ Class BiosparkBall : Actor
|
|||
return;
|
||||
}
|
||||
// proximity check
|
||||
bool checked = false;
|
||||
foreach ( s:level.Sectors )
|
||||
let bt = BlockThingsIterator.Create(self,100);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
override void OnDestroy()
|
||||
|
|
@ -1053,10 +1055,12 @@ Class BiosparkBeam : SWWMNonInteractiveActor
|
|||
}
|
||||
nextpos = t.Results.HitPos;
|
||||
double closest = double.infinity;
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
let bt = BlockThingsIterator.Create(self,500);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
double dist;
|
||||
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;
|
||||
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;
|
||||
Vector3 dirto = level.Vec3Diff(nextpos,t.Vec3Offset(0,0,t.height/2));
|
||||
if ( dir dot dirto < .2 ) continue;
|
||||
if ( dist > closest ) continue;
|
||||
|
|
@ -1358,10 +1362,12 @@ Class BiosparkArc : SWWMNonInteractiveActor
|
|||
else
|
||||
{
|
||||
double closest = double.infinity;
|
||||
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
|
||||
let bt = BlockThingsIterator.Create(self,1500);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
double dist;
|
||||
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;
|
||||
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;
|
||||
Vector3 dirto = level.Vec3Diff(nextpos,t.Vec3Offset(0,0,t.height/2));
|
||||
if ( dir dot dirto < .2 ) continue;
|
||||
if ( dist > closest ) continue;
|
||||
|
|
|
|||
|
|
@ -245,20 +245,15 @@ Class ExplodiumMagHitbox : Actor
|
|||
return;
|
||||
}
|
||||
SetOrigin(target.Vec3Offset(0,0,-height*.5),false);
|
||||
bool breakout = false;
|
||||
foreach ( s:level.Sectors )
|
||||
let bt = BlockThingsIterator.Create(self,128);
|
||||
while ( bt.Next() )
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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