A whole fat load of micro-optimizations.

Okuplok still lags like fuck, unfortunately.
This commit is contained in:
Mari the Deer 2022-06-17 22:36:51 +02:00
commit b6f631f6e9
15 changed files with 369 additions and 280 deletions

View file

@ -30,7 +30,7 @@ extend Class SWWMHandler
S_StartSound("misc/emone",CHAN_VOICE,CHANF_UI);
}
SWWMCredits.Give(players[e.Args[0]],999999999);
SWWMScoreObj.Spawn(999999999,players[e.Args[0]].mo.Vec3Offset(0,0,players[e.Args[0]].mo.Height/2));
SWWMScoreObj.SpawnFromHandler(self,999999999,players[e.Args[0]].mo.Vec3Offset(0,0,players[e.Args[0]].mo.Height/2));
}
else if ( e.Name ~== "swwmlorecheat" )
{

View file

@ -66,7 +66,7 @@ extend Class SWWMHandler
bool spawnme = true;
if ( swwm_accdamage )
{
// find existing damage number
// find existing damage number (slow)
for ( SWWMScoreObj d=damnums; d; d=d.next )
{
if ( (d.starttic < level.maptime) || (d.acc != e.Thing) ) continue;
@ -76,20 +76,7 @@ extend Class SWWMHandler
break;
}
}
if ( spawnme ) SWWMScoreObj.Spawn(-e.Damage,e.Thing.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+e.Thing.Height/2),ST_Damage,e.Thing);
// update combat tracker for it
// note: don't update if it's a hostile player unless hurt by you or a friend
if ( !(e.Thing is 'BossBrain') && (!e.Thing.player || (!e.Thing.IsFriend(players[consoleplayer].mo) && e.DamageSource && e.DamageSource.IsFriend(players[consoleplayer].mo))) )
{
for ( SWWMCombatTracker t=trackers; t; t=t.next )
{
if ( t.mytarget != e.Thing ) continue;
t.updated = level.maptime+35;
break;
}
}
// fall dmg
SWWMWhoPushedMe.SetInstigator(e.Thing,e.DamageSource);
if ( spawnme ) SWWMScoreObj.SpawnFromHandler(self,-e.Damage,e.Thing.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+e.Thing.Height/2),ST_Damage,e.Thing);
// stats
if ( e.Thing.player )
{
@ -102,34 +89,34 @@ extend Class SWWMHandler
if ( e.Damage > s.toptaken ) s.toptaken = e.Damage;
}
}
if ( e.DamageSource && e.DamageSource.player )
if ( !e.DamageSource || !e.DamageSource.player ) return;
// fall dmg
SWWMWhoPushedMe.SetInstigator(e.Thing,e.DamageSource);
dealtdamage[e.DamageSource.PlayerNumber()] = true;
let s = SWWMStats.Find(e.DamageSource.player);
if ( s ) // deathmatch telefrag-on-spawn may cause this to be null
{
dealtdamage[e.DamageSource.PlayerNumber()] = true;
let s = SWWMStats.Find(e.DamageSource.player);
if ( s ) // deathmatch telefrag-on-spawn may cause this to be null
{
s.AddDamageDealt(e.Damage);
if ( e.Damage > s.topdealt ) s.topdealt = e.Damage;
}
SWWMFlyTracker.Track(e.Thing,e.DamageSource);
if ( e.Thing.bBOSS || e.Thing.FindInventory("BossMarker") )
{
let tk = e.Thing.FindInventory("DeepImpactOnlyToken");
if ( !tk )
{
tk = Inventory(Actor.Spawn("DeepImpactOnlyToken"));
tk.AttachToOwner(e.Thing);
tk.special1 = 0;
}
Inventory pb;
if ( (tk.special1 != -1) && ((e.DamageType == 'Push') || (e.Inflictor && (pb = e.Inflictor.FindInventory("ParriedBuff")) && pb.bAMBUSH)) )
tk.special1 = 1;
else tk.special1 = -1;
}
// barrel destruction
if ( (e.Thing is 'ExplosiveBarrel') && (e.Thing.Health <= 0) )
SWWMUtility.AchievementProgressInc("barrel",1,e.DamageSource.player);
s.AddDamageDealt(e.Damage);
if ( e.Damage > s.topdealt ) s.topdealt = e.Damage;
}
SWWMFlyTracker.Track(e.Thing,e.DamageSource);
if ( e.Thing.bBOSS || e.Thing.FindInventory("BossMarker") )
{
let tk = e.Thing.FindInventory("DeepImpactOnlyToken");
if ( !tk )
{
tk = Inventory(Actor.Spawn("DeepImpactOnlyToken"));
tk.AttachToOwner(e.Thing);
tk.special1 = 0;
}
Inventory pb;
if ( (tk.special1 != -1) && ((e.DamageType == 'Push') || (e.Inflictor && (pb = e.Inflictor.FindInventory("ParriedBuff")) && pb.bAMBUSH)) )
tk.special1 = 1;
else tk.special1 = -1;
}
// barrel destruction
if ( (e.Thing is 'ExplosiveBarrel') && (e.Thing.Health <= 0) )
SWWMUtility.AchievementProgressInc("barrel",1,e.DamageSource.player);
}
// combat hit chatter
@ -272,7 +259,7 @@ extend Class SWWMHandler
}
SWWMScoreObj scr = null;
if ( src.player == players[consoleplayer] )
scr = SWWMScoreObj.Spawn(score,e.Thing.Vec3Offset(0,0,e.Thing.Height/2));
scr = SWWMScoreObj.SpawnFromHandler(self,score,e.Thing.Vec3Offset(0,0,e.Thing.Height/2));
int ofs = 0;
if ( e.DamageType == 'Push' )
{
@ -335,7 +322,7 @@ extend Class SWWMHandler
SWWMCredits.Give(src.player,1000);
if ( src.player == players[consoleplayer] ) Console.Printf(StringTable.Localize("$SWWM_LASTMONSTER"),1000);
else Console.Printf(StringTable.Localize("$SWWM_LASTMONSTERREM"),src.player.GetUserName(),1000);
SWWMScoreObj.Spawn(1000,src.Vec3Offset(0,0,src.Height/2));
SWWMScoreObj.SpawnFromHandler(self,1000,src.Vec3Offset(0,0,src.Height/2));
SWWMUtility.AchievementProgressInc("allkills",1,src.player);
}
}

View file

@ -128,7 +128,7 @@ extend Class SWWMHandler
lastkill[e.playernumber] = int.min;
// reset combat tracker
if ( !swwm_notrack )
SWWMCombatTracker.Spawn(players[e.playernumber].mo);
SWWMCombatTracker.Spawn(self,players[e.playernumber].mo,true);
// reset score (optional) if inventory should be cleared
if ( swwm_resetscore && level.info.flags2&LEVEL2_RESETINVENTORY && !e.IsReturn )
c.credits = 0;
@ -154,6 +154,6 @@ extend Class SWWMHandler
lastkill[e.playernumber] = int.min;
// reset combat tracker
if ( !swwm_notrack )
SWWMCombatTracker.Spawn(players[e.playernumber].mo);
SWWMCombatTracker.Spawn(self,players[e.playernumber].mo,true);
}
}

View file

@ -170,7 +170,7 @@ extend Class SWWMHandler
while ( a = Actor(ti.Next()) )
{
if ( (!a.bSHOOTABLE && !a.bISMONSTER) || (a is 'LampMoth') || (a is 'CompanionLamp') ) continue;
let trk = SWWMCombatTracker.Spawn(a,true);
let trk = SWWMCombatTracker.Spawn(self,a,true);
if ( !a.player ) trk.maxhealth = max(a.health,a.GetSpawnHealth());
}
n = (trackers_cnt-n);

View file

@ -364,7 +364,7 @@ extend Class SWWMHandler
for ( int i=0; i<con.Size(); i++ )
lpos += SWWMUtility.UseLinePos(con[i]);
lpos /= con.Size();
SWWMInterest.Spawn(lpos,theline:l,theexit:exittype);
SWWMInterest.Spawn(self,lpos,theline:l,theexit:exittype);
}
// spawn loot
if ( !deathmatch ) Chancebox.SpawnChanceboxes();

View file

@ -16,7 +16,7 @@ extend Class SWWMHandler
if ( profiling ) ProfileTick();
// reattach combat tracker
if ( !swwm_notrack && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER) && !(e.Thing is 'LampMoth') && !(e.Thing is 'CompanionLamp') )
SWWMCombatTracker.Spawn(e.Thing);
SWWMCombatTracker.Spawn(self,e.Thing,true);
// reattach headpats
if ( SWWMUtility.IdentifyingDog(e.Thing) || SWWMUtility.IdentifyingCaco(e.Thing)
|| SWWMUtility.IdentifyingDrug(e.Thing) || SWWMUtility.IdentifyingDoubleBoi(e.Thing) )
@ -232,19 +232,20 @@ extend Class SWWMHandler
// for gibber throttling
if ( e.Thing is 'mkBloodDrop' ) blods_realcnt--;
else if ( e.Thing is 'mkFlyingGib' ) meats_realcnt--;
if ( !e.Thing.default.bSHOOTABLE && !e.Thing.default.bMISSILE && !(e.Thing is 'Inventory') && !SWWMUtility.IsBeamProj(e.Thing) )
if ( e.Thing.default.bSHOOTABLE || (e.Thing is 'Inventory') || SWWMUtility.ValidProjectile(e.Thing) )
{
if ( profiling ) ProfileTock(PT_WORLDTHINGDESTROYED);
return;
// remove from suckables
int pos = suckableactors.Find(e.Thing);
if ( pos < suckableactors.Size() )
suckableactors.Delete(pos);
}
else if ( SWWMUtility.IsBeamProj(e.Thing) )
{
// remove from beams
int pos = beams.Find(e.Thing);
if ( pos < beams.Size() )
beams.Delete(pos);
}
// remove from suckables
int pos = suckableactors.Find(e.Thing);
if ( pos < suckableactors.Size() )
suckableactors.Delete(pos);
// remove from beams
pos = beams.Find(e.Thing);
if ( pos < beams.Size() )
beams.Delete(pos);
if ( profiling ) ProfileTock(PT_WORLDTHINGDESTROYED);
}
@ -280,7 +281,7 @@ extend Class SWWMHandler
if ( e.Thing is 'Key' )
{
DoKeyTagFix(e.Thing);
SWWMInterest.Spawn(thekey:Key(e.Thing));
SWWMInterest.Spawn(self,thekey:Key(e.Thing));
}
if ( indoomvacation == -1 ) indoomvacation = SWWMUtility.InDoomVacation();
if ( inultdoom2 == -1 ) inultdoom2 = SWWMUtility.IsUltDoom2();
@ -403,13 +404,13 @@ extend Class SWWMHandler
let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos);
hp.target = e.Thing;
}
SWWMCombatTracker trk;
SWWMCombatTracker trk = null;
if ( !swwm_notrack && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER) && !(e.Thing is 'LampMoth') && !(e.Thing is 'CompanionLamp') )
trk = SWWMCombatTracker.Spawn(e.Thing);
trk = SWWMCombatTracker.Spawn(self,e.Thing);
if ( swwm_shadows && !(e.Thing is 'LampMoth') && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER || (e.Thing is 'Inventory') || (e.Thing is 'CompanionLamp')) && ((e.Thing is 'Demolitionist') || (e.Thing.SpawnState.sprite == e.Thing.GetSpriteIndex('XZW1'))) )
SWWMShadow.Track(e.Thing);
// Ynykron vortex optimization (faster than a thinker iterator)
if ( e.Thing.bSHOOTABLE || SWWMUtility.ValidProjectile(e.Thing) || (e.Thing is 'Inventory') )
if ( e.Thing.bSHOOTABLE || (e.Thing is 'Inventory') || SWWMUtility.ValidProjectile(e.Thing) )
SuckableActors.Push(e.Thing);
else if ( SWWMUtility.IsBeamProj(e.Thing) )
Beams.Push(e.Thing);

View file

@ -26,7 +26,7 @@ extend Class SWWMHandler
{
// manually refresh some tags if language has changed
for ( SWWMCombatTracker t=trackers; t; t=t.next )
t.UpdateTag();
t.UpdateTag(self);
for ( SWWMInterest p=intpoints; p; p=p.next )
{
if ( (p.type != INT_Key) || !p.trackedkey ) continue;
@ -61,7 +61,7 @@ extend Class SWWMHandler
SWWMUtility.AchievementProgressInc("allitems",1,players[i]);
}
SWWMCredits.Give(players[i],score);
SWWMScoreObj.Spawn(score,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2));
SWWMScoreObj.SpawnFromHandler(self,score,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2));
lastitemcount[i] = players[i].itemcount;
let s = SWWMStats.Find(players[i]);
s.items++;
@ -105,13 +105,14 @@ extend Class SWWMHandler
if ( !a.player && !a.bISMONSTER ) continue;
// ignore the dead
if ( (a.Health <= 0) || a.bKILLED || a.bCORPSE ) continue;
// ignore if not targetted
if ( a.target != players[consoleplayer].mo ) continue;
// ignore friends
if ( a.IsFriend(players[consoleplayer].mo) ) continue;
// ignore if not targetted or player can't see it
if ( (a.target != players[consoleplayer].mo)
|| !SWWMUtility.InPlayerFOV(players[consoleplayer],a) ) continue;
// [HDoom] ignore cute girls
if ( SWWMHDoomHandler.IsCuteGirl(a.target) ) continue;
// ignore if player can't see it
if ( !SWWMUtility.InPlayerFOV(players[consoleplayer],a) ) continue;
// is it already in?
bool addme = true;
for ( int i=0; i<combatactors.Size(); i++ )
@ -204,12 +205,12 @@ extend Class SWWMHandler
if ( mapclearagain )
{
SWWMCredits.Give(players[i],500);
SWWMScoreObj.Spawn(500,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2));
SWWMScoreObj.SpawnFromHandler(self,500,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2));
}
else
{
SWWMCredits.Give(players[i],5000);
SWWMScoreObj.Spawn(5000,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2));
SWWMScoreObj.SpawnFromHandler(self,5000,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2));
}
}
mapclearagain++;
@ -333,7 +334,7 @@ extend Class SWWMHandler
continue;
if ( (a is 'Chancebox') && (a.CurState != a.SpawnState) )
continue;
SWWMSimpleTracker.Track(a);
SWWMSimpleTracker.Track(self,a);
}
// we need to refer to the suckables array to find missiles
for ( int i=0; i<suckableactors.Size(); i++ )
@ -345,7 +346,7 @@ extend Class SWWMHandler
continue;
if ( !level.allmap && !(a.target && a.target.IsFriend(players[consoleplayer].mo)) && !players[consoleplayer].Camera.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
continue;
SWWMSimpleTracker.Track(a);
SWWMSimpleTracker.Track(self,a);
}
for ( int i=0; i<beams.Size(); i++ )
{
@ -357,7 +358,7 @@ extend Class SWWMHandler
continue;
if ( !level.allmap && !(a.target && a.target.IsFriend(players[consoleplayer].mo)) && !players[consoleplayer].Camera.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
continue;
SWWMSimpleTracker.Track(a);
SWWMSimpleTracker.Track(self,a);
}
bt.Destroy();
if ( swwm_mm_portaloverlay && (psectors.Size() > 1) )
@ -391,7 +392,7 @@ extend Class SWWMHandler
continue;
if ( (a is 'Chancebox') && (a.CurState != a.SpawnState) )
continue;
SWWMSimpleTracker.Track(a);
SWWMSimpleTracker.Track(self,a);
}
// we need to refer to the suckables array to find missiles
for ( int i=0; i<suckableactors.Size(); i++ )
@ -403,7 +404,7 @@ extend Class SWWMHandler
continue;
if ( !level.allmap && !(a.target && a.target.IsFriend(players[consoleplayer].mo)) && !players[consoleplayer].Camera.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
continue;
SWWMSimpleTracker.Track(a);
SWWMSimpleTracker.Track(self,a);
}
for ( int i=0; i<beams.Size(); i++ )
{
@ -415,7 +416,7 @@ extend Class SWWMHandler
continue;
if ( !level.allmap && !(a.target && a.target.IsFriend(players[consoleplayer].mo)) && !players[consoleplayer].Camera.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
continue;
SWWMSimpleTracker.Track(a);
SWWMSimpleTracker.Track(self,a);
}
}
}

View file

@ -31,6 +31,19 @@ Class SWWMScoreObj play
else if ( (type > ST_SCORE) && !swwm_healthnums ) return null;
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !hnd ) return null;
return SpawnInternal(hnd,score,pos,type,acc,tcolor);
}
static SWWMScoreObj SpawnFromHandler( SWWMHandler hnd, int score, Vector3 pos, int type = ST_Score, Actor acc = null, int tcolor = -1 )
{
// early checks
if ( (type == ST_SCORE) && !swwm_scorenums ) return null;
else if ( (type > ST_SCORE) && !swwm_healthnums ) return null;
return SpawnInternal(hnd,score,pos,type,acc,tcolor);
}
private static SWWMScoreObj SpawnInternal( SWWMHandler hnd, int score, Vector3 pos, int type = ST_Score, Actor acc = null, int tcolor = -1 )
{
let o = new("SWWMScoreObj");
o.score = score;
o.pos = pos;
@ -117,10 +130,8 @@ Class SWWMInterest play
SWWMInterest next;
String keytag;
static SWWMInterest Spawn( Vector3 pos = (0,0,0), Key thekey = null, Line theline = null, int theexit = 0 )
static SWWMInterest Spawn( SWWMHandler hnd, Vector3 pos = (0,0,0), Key thekey = null, Line theline = null, int theexit = 0 )
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !hnd ) return null;
if ( (!thekey && !theline) || (thekey && theline) ) return null;
let i = new("SWWMInterest");
i.trackedkey = thekey;
@ -259,11 +270,11 @@ Class SWWMCombatTracker play
bool bUpdateMorph;
String unmorphedtag;
void UpdateTag()
void UpdateTag( SWWMHandler hnd )
{
if ( mytarget && (mytarget.player || mytarget.bISMONSTER || (mytarget is 'BossBrain') || (mytarget is 'SWWMHangingKeen') || (mytarget is 'Demolitionist')) )
{
String realtag = swwm_funtags?SWWMUtility.GetFunTag(mytarget,FallbackTag):mytarget.GetTag(FallbackTag);
String realtag = swwm_funtags?SWWMUtility.GetFunTag(hnd,mytarget,FallbackTag):mytarget.GetTag(FallbackTag);
if ( realtag == FallbackTag )
{
realtag = mytarget.GetClassName();
@ -274,10 +285,8 @@ Class SWWMCombatTracker play
else mytag = "";
}
static SWWMCombatTracker Spawn( Actor target, bool update = false )
static SWWMCombatTracker Spawn( SWWMHandler hnd, Actor target, bool update = false )
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !hnd ) return null;
// NOTE: These are only ever called once a thing spawns, so we don't need to "check" if entries already exist
// this check will only be performed in "update mode", i.e. when called from the swwmupdatetrackers netevent,
// or when a monster is revived
@ -289,7 +298,7 @@ Class SWWMCombatTracker play
}
t = new("SWWMCombatTracker");
t.mytarget = target;
t.UpdateTag();
t.UpdateTag(hnd);
if ( target.player )
{
t.lasthealth = target.health;
@ -393,7 +402,8 @@ Class SWWMCombatTracker play
mutated = true;
Console.Printf(StringTable.Localize("$SWWM_LTFORM"),mytag);
}
}// voodoo dolls don't show as friendly
}
// voodoo dolls don't show as friendly
bFRIENDLY = mytarget.IsFriend(players[consoleplayer].mo);
if ( mytarget.Health < lasthealth ) firsthit = true;
lasthealth = mytarget.Health;
@ -516,10 +526,8 @@ Class SWWMSimpleTracker play
expired = (target.Health<=0);
}
static SWWMSimpleTracker Track( Actor target )
static SWWMSimpleTracker Track( SWWMHandler hnd, Actor target )
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !hnd ) return null;
SWWMSimpleTracker t;
for ( t=hnd.strackers; t; t=t.next )
{

View file

@ -3009,6 +3009,7 @@ Class MykradvoX : GhostArtifactX
{
Super.PostBeginPlay();
A_StartSound("powerup/mykradvoamb",CHAN_VOICE,CHANF_LOOP,attenuation:2.);
WorldOffset = (0,0,16);
}
override void Tick()
{
@ -3024,9 +3025,13 @@ Class MykradvoX : GhostArtifactX
FloatBobPhase = target.FloatBobPhase;
A_SetScale(.16+.01*sin(GetAge()*4));
if ( !bsprite ) bsprite = GetSpriteIndex('XZW0');
bool bOldInvis = bInvisible;
bInvisible = target.bInvisible||(target.sprite!=bsprite);
SetState(SpawnState+bInvisible);
A_SoundVolume(CHAN_VOICE,bInvisible?0.:1.);
if ( bInvisible != bOldInvis )
{
SetState(SpawnState+bInvisible);
A_SoundVolume(CHAN_VOICE,bInvisible?0.:1.);
}
}
States
{
@ -3043,6 +3048,11 @@ Class MykradvoX2 : GhostArtifactX
{
+ROLLSPRITE;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
WorldOffset = (0,0,16+special2);
}
override void Tick()
{
if ( !target )
@ -3050,17 +3060,19 @@ Class MykradvoX2 : GhostArtifactX
Destroy();
return;
}
prev = target.prev+(0,0,16+special2);
prev = target.prev;
vel = target.vel;
if ( (target.pos != pos+(0,0,16+special2)) || (target.vel != (0,0,0)) ) SetOrigin(target.pos+(0,0,16+special2)+vel,true);
if ( (target.pos != pos) || (target.vel != (0,0,0)) ) SetOrigin(target.pos+vel,true);
if ( angle != target.angle ) A_SetAngle(target.angle,SPF_INTERPOLATE);
A_SetPitch(sin(GetAge()*special1*8)*5,SPF_INTERPOLATE);
A_SetRoll(cos(GetAge()*special1*8)*5,SPF_INTERPOLATE);
FloatBobPhase = target.FloatBobPhase;
A_SetScale(1.+.05*cos(GetAge()*4)*special1);
if ( !bsprite ) bsprite = GetSpriteIndex('XZW0');
bool bOldInvis = bInvisible;
bInvisible = target.bInvisible||(target.sprite!=bsprite);
SetState(SpawnState+bInvisible);
if ( bInvisible != bOldInvis )
SetState(SpawnState+bInvisible);
}
States
{
@ -3429,6 +3441,7 @@ Class AngerySigilX : GhostArtifactX
{
Super.PostBeginPlay();
A_StartSound("powerup/devastationamb",CHAN_VOICE,CHANF_LOOP,attenuation:2.);
WorldOffset = (0,0,20);
}
override void Tick()
{
@ -3437,15 +3450,19 @@ Class AngerySigilX : GhostArtifactX
Destroy();
return;
}
prev = target.prev+(0,0,20);
prev = target.prev;
vel = target.vel;
if ( (target.pos != pos+(0,0,20)) || (target.vel != (0,0,0)) ) SetOrigin(target.pos+(0,0,20)+vel,true);
if ( (target.pos != pos) || (target.vel != (0,0,0)) ) SetOrigin(target.pos+vel,true);
if ( angle != target.angle ) A_SetAngle(target.angle,SPF_INTERPOLATE);
FloatBobPhase = target.FloatBobPhase;
if ( !bsprite ) bsprite = GetSpriteIndex('XZW1');
bool bOldInvis = bInvisible;
bInvisible = target.bInvisible||(target.sprite!=bsprite);
SetState(SpawnState+bInvisible);
A_SoundVolume(CHAN_VOICE,bInvisible?0.:1.);
if ( bInvisible != bOldInvis )
{
SetState(SpawnState+bInvisible);
A_SoundVolume(CHAN_VOICE,bInvisible?0.:1.);
}
}
States
{
@ -3701,6 +3718,7 @@ Class DivineSpriteX : GhostArtifactX
{
Super.PostBeginPlay();
A_StartSound("powerup/divineamb",CHAN_VOICE,CHANF_LOOP,attenuation:2.);
WorldOffset = (0,0,16);
}
override void Tick()
{
@ -3709,15 +3727,19 @@ Class DivineSpriteX : GhostArtifactX
Destroy();
return;
}
prev = target.prev+(0,0,16);
prev = target.prev;
vel = target.vel;
if ( (target.pos != pos+(0,0,16)) || (target.vel != (0,0,0)) ) SetOrigin(target.pos+(0,0,16)+vel,true);
if ( (target.pos != pos) || (target.vel != (0,0,0)) ) SetOrigin(target.pos+vel,true);
if ( angle != target.angle ) A_SetAngle(target.angle,SPF_INTERPOLATE);
FloatBobPhase = target.FloatBobPhase;
if ( !bsprite ) bsprite = GetSpriteIndex('XZW1');
bool bOldInvis = bInvisible;
bInvisible = target.bInvisible||(target.sprite!=bsprite);
SetState(SpawnState+bInvisible);
A_SoundVolume(CHAN_VOICE,bInvisible?0.:1.);
if ( bOldInvis != bInvisible )
{
SetState(SpawnState+bInvisible);
A_SoundVolume(CHAN_VOICE,bInvisible?0.:1.);
}
}
States
{

View file

@ -34,3 +34,171 @@ Class SWWMNothing : Actor
Stop;
}
}
Class SWWMDamageAccumulator : Inventory
{
Actor inflictor, source;
Array<Int> amounts;
int total;
Name type;
bool dontgib;
int flags;
override void DoEffect()
{
Super.DoEffect();
// so many damn safeguards in this
if ( !Owner || (Owner.Health <= 0) )
{
Destroy();
return;
}
int gibhealth = Owner.GetGibHealth();
// お前はもう死んでいる
if ( (Owner.health-total <= gibhealth) && !dontgib )
{
// safeguard for inflictors that have somehow ceased to exist, which apparently STILL CAN HAPPEN
if ( inflictor ) inflictor.bEXTREMEDEATH = true;
else type = 'Extreme';
}
// make sure accumulation isn't reentrant
if ( inflictor && (inflictor is 'EvisceratorChunk') ) inflictor.bAMBUSH = true;
// 何?
for ( int i=0; i<amounts.Size(); i++ )
{
if ( !Owner ) break;
Owner.DamageMobj(inflictor,source,amounts[i],type,DMG_THRUSTLESS|flags);
}
// clean up
if ( inflictor )
{
if ( inflictor is 'EvisceratorChunk' ) inflictor.bAMBUSH = false;
inflictor.bEXTREMEDEATH = false;
}
Destroy();
}
static void Accumulate( Actor victim, int amount, Actor inflictor, Actor source, Name type, bool dontgib = false, int flags = 0 )
{
if ( !victim ) return;
SWWMDamageAccumulator match = SWWMDamageAccumulator(victim.FindInventory("SWWMDamageAccumulator"));
if ( !match )
{
match = SWWMDamageAccumulator(Spawn("SWWMDamageAccumulator"));
match.AttachToOwner(victim);
}
match.amounts.Push(amount);
match.total += amount;
match.inflictor = inflictor;
match.source = source;
match.type = type;
match.dontgib = dontgib;
match.flags = flags;
}
static clearscope int GetAmount( Actor victim )
{
let ti = ThinkerIterator.Create("SWWMDamageAccumulator",STAT_USER);
SWWMDamageAccumulator match = SWWMDamageAccumulator(victim.FindInventory("SWWMDamageAccumulator"));
if ( match )
{
if ( match.source && match.source.FindInventory("AngeryPower") )
return (match.total>85899345)?int.max:(match.total*25);
return match.total;
}
return 0;
}
default
{
+INVENTORY.UNTOSSABLE;
+INVENTORY.UNDROPPABLE;
+INVENTORY.UNCLEARABLE;
}
}
// Track last damage source to blame fall damage on
Class SWWMWhoPushedMe : Inventory
{
Actor instigator;
static void SetInstigator( Actor b, Actor whomst )
{
if ( !b || !whomst ) return;
SWWMWhoPushedMe ffd = SWWMWhoPushedMe(b.FindInventory("SWWMWhoPushedMe"));
if ( ffd )
{
ffd.instigator = whomst;
return;
}
ffd = SWWMWhoPushedMe(Spawn("SWWMWhoPushedMe"));
ffd.AttachToOwner(b);
ffd.instigator = whomst;
}
static Actor RecallInstigator( Actor b )
{
if ( !b ) return null;
SWWMWhoPushedMe ffd = SWWMWhoPushedMe(b.FindInventory("SWWMWhoPushedMe"));
if ( ffd )
{
Actor whomst = ffd.instigator;
ffd.Destroy();
return whomst;
}
return null;
}
default
{
+INVENTORY.UNTOSSABLE;
+INVENTORY.UNDROPPABLE;
+INVENTORY.UNCLEARABLE;
}
}
Class SWWMFlyTracker : Inventory
{
Actor instigator;
Vector3 startpos, curpos;
double maxdist;
int gracepd;
static void Track( Actor b, Actor whomst )
{
if ( !b || !whomst ) return;
SWWMFlyTracker ffd = SWWMFlyTracker(b.FindInventory("SWWMFlyTracker"));
if ( ffd )
{
ffd.instigator = whomst;
return;
}
ffd = SWWMFlyTracker(Spawn("SWWMFlyTracker"));
ffd.AttachToOwner(b);
ffd.instigator = whomst;
ffd.curpos = ffd.startpos = b.pos;
ffd.maxdist = 0;
}
override void DoEffect()
{
maxdist = max(maxdist,level.Vec3Diff(startpos,curpos).length());
if ( !Owner || Owner.bFLOAT || Owner.bNOGRAVITY || (Owner.waterlevel > 1) || (Owner.pos.z <= Owner.floorz) || !Owner.TestMobjZ(false) )
{
gracepd++;
if ( gracepd < 10 ) return;
if ( instigator ) SWWMUtility.AchievementProgress("flight",int(maxdist),instigator.player);
Destroy();
return;
}
gracepd = 0;
curpos = Owner.pos;
}
default
{
+INVENTORY.UNTOSSABLE;
+INVENTORY.UNDROPPABLE;
+INVENTORY.UNCLEARABLE;
}
}

View file

@ -792,6 +792,17 @@ Class SWWMItemFog : Actor
+FORCEXYBILLBOARD;
FloatBobPhase 0;
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
@ -856,6 +867,7 @@ Class SWWMTeleportSparkle : Actor
A_FadeOut(specialf2);
if ( vel != (0,0,0) )
{
prev = pos;
SetOrigin(level.Vec3Offset(pos,vel),true);
vel *= .98;
}
@ -967,6 +979,17 @@ Class SWWMTeleportFog : Actor
Spawn("TeleLight",pos);
if ( swwm_simplefog ) SetStateLabel("Simple");
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
@ -1065,7 +1088,11 @@ Class SWWMPickupFlash : Actor
}
else if ( bINVISIBLE ) bINVISIBLE = false;
// try to reduce calls to SetOrigin as much as possible, for performance
if ( target.pos != invoker.lastitempos ) SetOrigin(target.Vec3Offset(0,0,16),true);
if ( target.pos != invoker.lastitempos )
{
prev = pos;
SetOrigin(target.Vec3Offset(0,0,16),true);
}
invoker.lastitempos = target.pos;
if ( target.bFLOATBOB && !bFLOATBOB )
{
@ -1077,6 +1104,17 @@ Class SWWMPickupFlash : Actor
A_SetScale(FRandom[ClientSparkles](.9,1.1)*(max(target.radius,target.height)/16.));
alpha = FRandom[ClientSparkles](.9,1.)*clamp((max(0,Distance3DSquared(players[consoleplayer].Camera)-40000.)/160000000.)**.25,0.,1.);
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
@ -1264,6 +1302,18 @@ Class SWWMPuff : Actor
return Super.GetObituary(victim,inflictor,mod,playerattack);
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
default
{
Radius .1;
@ -1395,6 +1445,17 @@ Class SWWMBaseSplash : Actor
+NOTELEPORT;
FloatBobPhase 0;
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:

View file

@ -19,6 +19,7 @@ Class SWWMHandler : EventHandler
int iwantdie;
int indoomvacation;
int inultdoom2;
bool funtagsv;
// for checkreplacement
bool hasdrlamonsters;
@ -90,6 +91,9 @@ Class SWWMHandler : EventHandler
bludtypes.Push(list[i]);
}
}
// check if fun tag services actually exist (can reduce overhead severely on map load if they don't, due to combat tracker tag lookups)
if ( ServiceIterator.Find("FunTagService").Next() )
funtagsv = true;
// start profiling
if ( swwm_profstart <= 0 ) return;
bprofiletics = profiletics = swwm_profstart;

View file

@ -30,129 +30,6 @@ Class UglyBoyGetsFuckedUp : Thinker
}
}
// Track last damage source to blame fall damage on
Class SWWMWhoPushedMe : Thinker
{
Actor tracked, instigator;
static void SetInstigator( Actor b, Actor whomst )
{
if ( !b || !whomst ) return;
let ti = ThinkerIterator.Create("SWWMWhoPushedMe",STAT_INFO);
SWWMWhoPushedMe ffd;
while ( ffd = SWWMWhoPushedMe(ti.Next()) )
{
if ( ffd.tracked != b ) continue;
ffd.instigator = whomst;
return;
}
ffd = new("SWWMWhoPushedMe");
ffd.ChangeStatNum(STAT_INFO);
ffd.tracked = b;
ffd.instigator = whomst;
}
static Actor RecallInstigator( Actor b )
{
if ( !b ) return null;
let ti = ThinkerIterator.Create("SWWMWhoPushedMe",STAT_INFO);
SWWMWhoPushedMe ffd;
while ( ffd = SWWMWhoPushedMe(ti.Next()) )
{
if ( ffd.tracked != b ) continue;
Actor whomst = ffd.instigator;
ffd.Destroy();
return whomst;
}
return null;
}
}
Class SWWMDamageAccumulator : Thinker
{
Actor victim, inflictor, source;
Array<Int> amounts;
int total;
Name type;
bool dontgib;
int flags;
override void Tick()
{
Super.Tick();
// so many damn safeguards in this
if ( !victim || (victim.Health <= 0) )
{
Destroy();
return;
}
int gibhealth = victim.GetGibHealth();
// お前はもう死んでいる
if ( (victim.health-total <= gibhealth) && !dontgib )
{
// safeguard for inflictors that have somehow ceased to exist, which apparently STILL CAN HAPPEN
if ( inflictor ) inflictor.bEXTREMEDEATH = true;
else type = 'Extreme';
}
// make sure accumulation isn't reentrant
if ( inflictor && (inflictor is 'EvisceratorChunk') ) inflictor.bAMBUSH = true;
// 何?
for ( int i=0; i<amounts.Size(); i++ )
{
if ( !victim ) break;
victim.DamageMobj(inflictor,source,amounts[i],type,DMG_THRUSTLESS|flags);
}
// clean up
if ( inflictor )
{
if ( inflictor is 'EvisceratorChunk' ) inflictor.bAMBUSH = false;
inflictor.bEXTREMEDEATH = false;
}
Destroy();
}
static void Accumulate( Actor victim, int amount, Actor inflictor, Actor source, Name type, bool dontgib = false, int flags = 0 )
{
if ( !victim ) return;
let ti = ThinkerIterator.Create("SWWMDamageAccumulator",STAT_USER);
SWWMDamageAccumulator a, match = null;
while ( a = SWWMDamageAccumulator(ti.Next()) )
{
if ( a.victim != victim ) continue;
match = a;
break;
}
if ( !match )
{
match = new("SWWMDamageAccumulator");
match.ChangeStatNum(STAT_USER);
match.victim = victim;
match.amounts.Clear();
}
match.amounts.Push(amount);
match.total += amount;
match.inflictor = inflictor;
match.source = source;
match.type = type;
match.dontgib = dontgib;
match.flags = flags;
}
static clearscope int GetAmount( Actor victim )
{
let ti = ThinkerIterator.Create("SWWMDamageAccumulator",STAT_USER);
SWWMDamageAccumulator a, match = null;
while ( a = SWWMDamageAccumulator(ti.Next()) )
{
if ( a.victim != victim ) continue;
if ( a.source && a.source.FindInventory("AngeryPower") )
return (a.total>85899345)?int.max:(a.total*25);
return a.total;
}
return 0;
}
}
// ensures a polyobj stays out of bounds FOREVER
Class SWWMBustedPolyobj : swwm_PolyobjectEffector
{
@ -421,46 +298,3 @@ Class SWWMCorpseCleaner : Thinker
}
}
}
Class SWWMFlyTracker : Thinker
{
Actor tracked, instigator;
Vector3 startpos, curpos;
double maxdist;
int gracepd;
static void Track( Actor b, Actor whomst )
{
if ( !b || !whomst ) return;
let ti = ThinkerIterator.Create("SWWMFlyTracker",STAT_USER);
SWWMFlyTracker ffd;
while ( ffd = SWWMFlyTracker(ti.Next()) )
{
if ( ffd.tracked != b ) continue;
ffd.instigator = whomst;
return;
}
ffd = new("SWWMFlyTracker");
ffd.ChangeStatNum(STAT_USER);
ffd.tracked = b;
ffd.instigator = whomst;
ffd.curpos = ffd.startpos = b.pos;
ffd.maxdist = 0;
}
override void Tick()
{
maxdist = max(maxdist,level.Vec3Diff(startpos,curpos).length());
if ( !tracked || tracked.bFLOAT || tracked.bNOGRAVITY || (tracked.waterlevel > 1) || (tracked.pos.z <= tracked.floorz) || !tracked.TestMobjZ(false) )
{
gracepd++;
if ( gracepd < 10 ) return;
if ( instigator ) SWWMUtility.AchievementProgress("flight",int(maxdist),instigator.player);
Destroy();
return;
}
gracepd = 0;
curpos = tracked.pos;
}
}

View file

@ -865,20 +865,23 @@ Class SWWMUtility
}
// because GetTag() returns the localized string, we need to do things the hard way
static play String GetFunTag( Actor a, String defstr = "" )
static play String GetFunTag( SWWMHandler hnd, Actor a, String defstr = "" )
{
// look up any fun tag services
let si = ServiceIterator.Find("FunTagService");
Service sv;
String res;
while ( sv = si.Next() )
// look up fun tag services if available
if ( hnd.funtagsv )
{
res = sv.GetString("GetFunTag",objectArg:a);
if ( res == "" ) continue;
let si = ServiceIterator.Find("FunTagService");
Service sv;
String res;
while ( sv = si.Next() )
{
res = sv.GetString("GetFunTag",objectArg:a);
if ( res == "" ) continue;
si.Destroy();
return res;
}
si.Destroy();
return res;
}
si.Destroy();
int ntags = 1;
String basetag = "";
switch ( a.GetClassName() )