Migrate various thinkers to plain objects.

WIP: Gib models currently in progress.
WIP: IK re-rigging of Demolitionist in progress.
This commit is contained in:
Mari the Deer 2022-02-28 23:44:50 +01:00
commit a7eda2702a
22 changed files with 192 additions and 257 deletions

View file

@ -111,6 +111,7 @@ All the hard stuff *(some of these aren't guaranteed)*.
- Layers of White *(Summon the White Lady)*
- Fluffy Moth *(Pet the White Lady 50 times)*
- Ara Ara *(Have the White Lady kill a total of 100 enemies)*
* **Re-animate all base models with IK *(important for consistency)***
* **Additional gestures + gesture menu**
- Clap
- The Bird

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\cyDEMOLITIONIST \cw1.2pre r174 \cu(Mon 28 Feb 17:31:35 CET 2022)\c-";
SWWM_SHORTVER="\cw1.2pre r174 \cu(2022-02-28 17:31:35)\c-";
SWWM_MODVER="\cyDEMOLITIONIST \cw1.2pre r176 \cu(Mon 28 Feb 23:45:18 CET 2022)\c-";
SWWM_SHORTVER="\cw1.2pre r176 \cu(2022-02-28 23:45:18)\c-";

Binary file not shown.

BIN
models/GibBreast.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
models/GibBreast_a.3d Normal file

Binary file not shown.

BIN
models/GibBreast_d.3d Normal file

Binary file not shown.

BIN
models/GibDrumstick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
models/GibDrumstick_a.3d Normal file

Binary file not shown.

BIN
models/GibDrumstick_d.3d Normal file

Binary file not shown.

BIN
models/GibModels.blend Normal file

Binary file not shown.

BIN
models/GibSteak.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
models/GibSteak_a.3d Normal file

Binary file not shown.

BIN
models/GibSteak_d.3d Normal file

Binary file not shown.

View file

@ -20,7 +20,6 @@ version "4.7.1"
#include "zscript/swwm_handler.zsc"
#include "zscript/swwm_statichandler.zsc"
#include "zscript/swwm_thinkers.zsc"
#include "zscript/swwm_thinkers_hud.zsc"
#include "zscript/swwm_thinkers_player.zsc"
#include "zscript/swwm_player.zsc"
#include "zscript/swwm_player_fx.zsc"
@ -60,6 +59,7 @@ version "4.7.1"
// hud
#include "zscript/hud/swwm_hud.zsc"
#include "zscript/hud/swwm_hudextra.zsc"
#include "zscript/hud/swwm_hudobjects.zsc"
// kbase
#include "zscript/kbase/swwm_kbase.zsc"
#include "zscript/kbase/swwm_kbase_priv.zsc"

View file

@ -277,79 +277,39 @@ extend Class SWWMHandler
if ( e.DamageType == 'Push' )
{
score += 500;
if ( scr )
{
scr.xscore[ofs] = 0;
scr.xstr[ofs] = StringTable.Localize("$SWWM_SHAMEFUL");
scr.xcnt = ++ofs;
}
if ( scr ) scr.AppendXString(StringTable.Localize("$SWWM_SHAMEFUL"));
}
else if ( e.DamageType == 'Buttslam' )
{
score += 300;
if ( scr )
{
scr.xscore[ofs] = 0;
scr.xstr[ofs] = StringTable.Localize("$SWWM_BUTTSLAM");
scr.xcnt = ++ofs;
}
if ( scr ) scr.AppendXString(StringTable.Localize("$SWWM_BUTTSLAM"));
}
else if ( e.DamageType == 'Love' )
{
score += 600;
if ( scr )
{
scr.xscore[ofs] = 0;
scr.xtcolor[ofs] = Font.FindFontColor('BlushPink');
scr.xstr[ofs] = StringTable.Localize(((e.Thing is 'WolfensteinSS')||(e.Thing.Species=='WolfensteinSS'))?"$SWWM_LOVED_ALT":"$SWWM_LOVED");
scr.xcnt = ++ofs;
}
if ( scr ) scr.AppendXString(StringTable.Localize(((e.Thing is 'WolfensteinSS')||(e.Thing.Species=='WolfensteinSS'))?"$SWWM_LOVED_ALT":"$SWWM_LOVED"),0,Font.FindFontColor('BlushPink'));
}
else if ( e.Inflictor is 'FroggyChair' )
{
score += 1440;
if ( scr )
{
scr.xscore[ofs] = 0;
scr.xtcolor[ofs] = Font.CR_GREEN;
scr.xstr[ofs] = StringTable.Localize("$SWWM_FROGGED");
scr.xcnt = ++ofs;
}
if ( scr ) scr.AppendXString(StringTable.Localize("$SWWM_FROGGED"),0,Font.CR_GREEN);
}
Inventory pb;
if ( e.Inflictor && (pb = e.Inflictor.FindInventory('ParriedBuff')) )
{
score += 200;
if ( pb.special1&1 ) score += 200;
if ( scr )
{
scr.xscore[ofs] = 0;
if ( pb.special1&1 ) scr.xstr[ofs] = StringTable.Localize("$SWWM_PPARRY");
else scr.xstr[ofs] = StringTable.Localize("$SWWM_PARRY");
scr.xcnt = ++ofs;
}
if ( scr ) scr.AppendXString(StringTable.Localize((pb.special1&1)?"$SWWM_PPARRY":"$SWWM_PARRY"));
}
if ( (e.Damage >= e.Thing.GetSpawnHealth()*2) || (((e.Thing.Health <= e.Thing.GetGibHealth()) || (src.bEXTREMEDEATH) || (e.Inflictor && e.Inflictor.bEXTREMEDEATH) || (e.DamageType == 'Extreme')) && !src.bNOEXTREMEDEATH && (!e.Inflictor || !e.Inflictor.bNOEXTREMEDEATH)) )
{
score *= 2;
if ( scr )
{
scr.xscore[ofs] = 0;
scr.xstr[ofs] = StringTable.Localize("$SWWM_OVERKILL");
scr.xcnt = ++ofs;
}
if ( scr ) scr.AppendXString(StringTable.Localize("$SWWM_OVERKILL"));
SWWMUtility.AchievementProgressInc("gib",1,src.player);
}
score = int(score*(1.+.5*min(multilevel[pnum],16)));
if ( (multilevel[pnum] > 0) && scr )
{
if ( scr )
{
scr.xscore[ofs] = (multilevel[pnum]>=16)?int.max:(multilevel[pnum]+1);
scr.xstr[ofs] = StringTable.Localize("$SWWM_MULTIKILL");
scr.xcnt = ++ofs;
}
}
scr.AppendXString(StringTable.Localize("$SWWM_MULTIKILL"),(multilevel[pnum]>=16)?int.max:(multilevel[pnum]+1));
spreecount[pnum]++;
if ( s && (spreecount[pnum] > s.skill) && !tookdamage[pnum] )
s.skill = spreecount[pnum];
@ -360,21 +320,12 @@ extend Class SWWMHandler
if ( spreecount[pnum] > 10 ) spreebonus = int(10*((spreecount[pnum]/10.)**.25));
score += 100+spreebonus;
if ( (spreecount[pnum] > 0) && scr )
{
scr.xscore[ofs] = spreecount[pnum];
scr.xstr[ofs] = StringTable.Localize("$SWWM_SPREEKILL");
scr.xcnt = ++ofs;
}
scr.AppendXString(StringTable.Localize("$SWWM_SPREEKILL"),spreecount[pnum]);
}
if ( e.Thing.bBOSS || e.Thing.FindInventory("BossMarker") )
{
score += 2000;
if ( scr )
{
scr.xscore[ofs] = 0;
scr.xstr[ofs] = StringTable.Localize("$SWWM_BOSSKILL");
scr.xcnt = ++ofs;
}
if ( scr ) scr.AppendXString(StringTable.Localize("$SWWM_BOSSKILL"));
}
SWWMCredits.Give(src.player,score);
if ( scr ) scr.score = score; // update final score

View file

@ -153,7 +153,13 @@ extend Class SWWMHandler
if ( swwm_notrack )
{
int n = trackers_cnt;
while ( trackers ) trackers.Destroy(); // wow that's simple, all in one line
while ( trackers )
{
let next = trackers.next;
trackers.Destroy(); // wow that's simple, all in one line
trackers = next;
}
trackers_cnt = 0;
Console.Printf("%d trackers removed.",n);
}
else
@ -717,5 +723,4 @@ extend Class SWWMHandler
}
return false;
}
}

View file

@ -223,6 +223,77 @@ extend Class SWWMHandler
SWWMUtility.MarkAchievement("wantdie",players[consoleplayer]);
}
private void UpdateHUDObjects()
{
// score objects
SWWMScoreObj so = scorenums;
SWWMScoreObj soprev = null, sonext;
while ( so )
{
sonext = so.next;
if ( so.Tick() )
{
if ( soprev ) soprev.next = sonext;
else scorenums = sonext;
so.Destroy();
scorenums_cnt--;
}
else soprev = so;
so = sonext;
}
so = damnums;
soprev = null;
while ( so )
{
sonext = so.next;
if ( so.Tick() )
{
if ( soprev ) soprev.next = sonext;
else damnums = sonext;
so.Destroy();
scorenums_cnt--;
}
else soprev = so;
so = sonext;
}
// interest markers
SWWMInterest ip = intpoints;
SWWMInterest ipprev = null, ipnext;
while ( ip )
{
ipnext = ip.next;
if ( ip.Tick() )
{
if ( ipprev ) ipprev.next = ipnext;
else intpoints = ipnext;
ip.Destroy();
intpoints_cnt--;
}
else ipprev = ip;
ip = ipnext;
}
// combat trackers
SWWMCombatTracker trk = trackers;
SWWMCombatTracker trkprev = null, trknext;
int dbar = swwm_damagetarget;
int mxdist = swwm_maxtargetdist;
while ( trk )
{
trknext = trk.next;
trk.dbar = dbar;
trk.mxdist = mxdist;
if ( trk.Tick() )
{
if ( trkprev ) trkprev.next = trknext;
else trackers = trknext;
trk.Destroy();
trackers_cnt--;
}
else trkprev = trk;
trk = trknext;
}
}
// "simple" tracking (used by the minimap)
private void SimpleTracking()
{
@ -348,9 +419,10 @@ extend Class SWWMHandler
}
}
SWWMSimpleTracker trk = strackers;
SWWMSimpleTracker prev = null, next;
while ( trk )
{
SWWMSimpleTracker next = trk.next;
next = trk.next;
// minimize lifespan of destroyed targets
if ( !trk.target ) trk.lastupdate = min(trk.lastupdate,level.maptime);
else if ( !trk.expired )
@ -366,12 +438,12 @@ extend Class SWWMHandler
// prune expired trackers
if ( trk.lastupdate+140 < level.maptime )
{
if ( !trk.prev ) strackers = trk.next;
else trk.prev.next = trk.next;
if ( trk.next ) trk.next.prev = trk.prev;
if ( !prev ) strackers = trk.next;
else prev.next = trk.next;
trk.Destroy();
strackers_cnt--;
}
else prev = trk;
trk = next;
}
}

View file

@ -1373,7 +1373,7 @@ Class SWWMStatusBar : BaseStatusBar
// extra strings (if available)
if ( !swwm_scorebonus ) continue;
fo.y += smallfont2.GetHeight();
for ( int i=0; i<snum.xcnt; i++ )
for ( int i=0; i<snum.xstr.Size(); i++ )
{
tag = snum.xstr[i];
if ( snum.xscore[i] == int.max ) tag.AppendFormat(" MAX");
@ -2740,7 +2740,7 @@ Class SWWMStatusBar : BaseStatusBar
double deadtimer = (goner?goner.deadtimer:demo.deadtimer)+fractic;
if ( goner || (demo.player.viewheight <= 6) )
{
double dimalph = goner?1.:min(deadtimer/80.,1.);
double dimalph = goner?1.:min(deadtimer/80.,.8);
Screen.Dim("Black",dimalph,0,0,Screen.GetWidth(),Screen.GetHeight());
if ( demo && (demo.revivefail > level.maptime) )
{

View file

@ -1,32 +1,5 @@
// thinkers related to the hud
// "Full History" contains all messages since session start, nothing is flushed
// this can be accessed from a section of the knowledge base
Class SWWMFullHistory : Thinker
{
Array<MsgLine> msg;
static clearscope SWWMFullHistory Get()
{
let fh = SWWMFullHistory(ThinkerIterator.Create("SWWMFullHistory",STAT_STATIC).Next());
return fh;
}
static void PushMessage( String str, int tic, int type )
{
let fh = SWWMFullHistory(ThinkerIterator.Create("SWWMFullHistory",STAT_STATIC).Next());
if ( !fh )
{
fh = new("SWWMFullHistory");
fh.ChangeStatNum(STAT_STATIC);
}
MsgLine m = new("MsgLine");
m.str = str;
m.tic = tic;
m.type = type;
fh.msg.Push(m);
}
}
// hud-related storage objects
// (used to be thinkers, but this might be lighter on performance)
Enum EScoreObjType
{
@ -37,18 +10,17 @@ Enum EScoreObjType
};
// floating scores
Class SWWMScoreObj : Thinker
Class SWWMScoreObj play
{
int xcnt;
int xtcolor[6];
int xscore[6];
String xstr[6];
Array<int> xtcolor;
Array<int> xscore;
Array<String> xstr;
int tcolor;
int score;
Vector3 pos;
int lifespan, initialspan;
int starttic, seed, seed2;
SWWMScoreObj prev, next;
SWWMScoreObj next;
bool damnum;
Actor acc;
@ -60,7 +32,6 @@ Class SWWMScoreObj : Thinker
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !hnd ) return null;
let o = new("SWWMScoreObj");
o.ChangeStatNum(STAT_USER);
o.score = score;
o.pos = pos;
o.lifespan = o.initialspan = 60;
@ -84,58 +55,33 @@ Class SWWMScoreObj : Thinker
o.seed = Random[ScoreBits]();
o.seed2 = Random[ScoreBits]();
o.damnum = (type > ST_Score);
o.xcnt = 0;
for ( int i=0; i<6; i++ ) o.xtcolor[i] = swwm_numcolor_bonus;
o.acc = acc;
if ( o.damnum )
{
o.next = hnd.damnums;
if ( hnd.damnums ) hnd.damnums.prev = o;
hnd.damnums = o;
hnd.damnums_cnt++;
}
else
{
o.next = hnd.scorenums;
if ( hnd.scorenums ) hnd.scorenums.prev = o;
hnd.scorenums = o;
hnd.scorenums_cnt++;
}
return o;
}
override void OnDestroy()
void AppendXString( String xstr, int xscore = 0, int xtcolor = int.min )
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd )
{
if ( damnum )
{
hnd.damnums_cnt--;
if ( !prev ) hnd.damnums = next;
}
else
{
hnd.scorenums_cnt--;
if ( !prev ) hnd.scorenums = next;
}
if ( !prev )
{
if ( next ) next.prev = null;
}
else
{
prev.next = next;
if ( next ) next.prev = prev;
}
}
Super.OnDestroy();
self.xscore.Push(xscore);
self.xstr.Push(xstr);
self.xtcolor.Push((xtcolor==int.min)?swwm_numcolor_bonus:xtcolor);
}
override void Tick()
bool Tick()
{
lifespan--;
if ( lifespan <= 0 ) Destroy();
return (lifespan <= 0);
}
}
@ -161,14 +107,14 @@ Class SWWMInterestMarker : MapMarker
}
}
Class SWWMInterest : Thinker
Class SWWMInterest play
{
int type, exittype;
Key trackedkey;
Line trackedline;
Actor marker;
Vector3 pos;
SWWMInterest prev, next;
SWWMInterest next;
String keytag;
static SWWMInterest Spawn( Vector3 pos = (0,0,0), Key thekey = null, Line theline = null, int theexit = 0 )
@ -177,7 +123,6 @@ Class SWWMInterest : Thinker
if ( !hnd ) return null;
if ( (!thekey && !theline) || (thekey && theline) ) return null;
let i = new("SWWMInterest");
i.ChangeStatNum(STAT_USER);
i.trackedkey = thekey;
i.trackedline = theline;
if ( thekey )
@ -211,56 +156,36 @@ Class SWWMInterest : Thinker
}
i.pos = thekey?thekey.Vec3Offset(0,0,thekey.height/2):pos;
i.next = hnd.intpoints;
if ( hnd.intpoints ) hnd.intpoints.prev = i;
hnd.intpoints = i;
hnd.intpoints_cnt++;
return i;
}
override void OnDestroy()
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd )
{
hnd.intpoints_cnt--;
if ( !prev )
{
hnd.intpoints = next;
if ( next ) next.prev = null;
}
else
{
prev.next = next;
if ( next ) next.prev = prev;
}
}
Super.OnDestroy();
}
override void Tick()
bool Tick()
{
// update
if ( (type == INT_Key) && (!trackedkey || trackedkey.Owner) )
{
marker.Destroy();
Destroy();
return true;
}
else if ( trackedkey )
if ( trackedkey )
{
pos = trackedkey.Vec3Offset(0,0,trackedkey.height/2);
marker.SetOrigin(pos,true);
}
return false;
}
}
Class SWWMItemSense : Thinker
Class SWWMItemSense play
{
Actor item;
String tag;
int updated;
bool scoreitem, vipitem;
Demolitionist parent;
SWWMItemSense prev, next;
SWWMItemSense next;
Vector3 pos;
static SWWMItemSense Spawn( Demolitionist parent, Actor item )
@ -275,7 +200,6 @@ Class SWWMItemSense : Thinker
return s;
}
let i = new("SWWMItemSense");
i.ChangeStatNum(STAT_USER);
i.item = item;
if ( item is 'SWWMRespawnTimer' )
{
@ -292,7 +216,6 @@ Class SWWMItemSense : Thinker
i.UpdateTag();
i.pos = item.Vec3Offset(0,0,item.height);
i.next = parent.itemsense;
if ( parent.itemsense ) parent.itemsense.prev = i;
parent.itemsense = i;
parent.itemsense_cnt++;
return i;
@ -309,39 +232,16 @@ Class SWWMItemSense : Thinker
else tag = i.GetTag();
}
override void OnDestroy()
bool Tick()
{
if ( parent )
{
parent.itemsense_cnt--;
if ( !prev )
{
parent.itemsense = next;
if ( next ) next.prev = null;
}
else
{
prev.next = next;
if ( next ) next.prev = prev;
}
}
Super.OnDestroy();
}
override void Tick()
{
if ( !parent )
{
Destroy();
return;
}
// expire
if ( level.maptime > updated+70 ) Destroy();
if ( !parent || (level.maptime > updated+70) ) return true;
return false;
}
}
// enemy combat tracker
Class SWWMCombatTracker : Thinker
Class SWWMCombatTracker play
{
Actor mytarget;
String mytag;
@ -349,7 +249,7 @@ Class SWWMCombatTracker : Thinker
DynamicValueInterpolator intp;
Vector3 pos, prevpos, oldpos, oldprev;
PlayerInfo myplayer;
SWWMCombatTracker prev, next;
SWWMCombatTracker next;
bool legged, mutated;
int tcnt;
double height;
@ -388,7 +288,6 @@ Class SWWMCombatTracker : Thinker
return t;
}
t = new("SWWMCombatTracker");
t.ChangeStatNum(STAT_USER);
t.mytarget = target;
t.UpdateTag();
if ( target.player )
@ -408,51 +307,13 @@ Class SWWMCombatTracker : Thinker
t.next = hnd.trackers;
t.bBOSS = target.bBOSS;
t.bFRIENDLY = target.IsFriend(players[consoleplayer].mo);
if ( hnd.trackers )
{
hnd.trackers.prev = t;
// propagate cvar values
t.mxdist = hnd.trackers.mxdist;
t.dbar = hnd.trackers.dbar;
}
hnd.trackers = t;
hnd.trackers_cnt++;
return t;
}
override void OnDestroy()
bool Tick()
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd )
{
hnd.trackers_cnt--;
if ( !prev )
{
hnd.trackers = next;
if ( next ) next.prev = null;
}
else
{
prev.next = next;
if ( next ) next.prev = prev;
}
}
Super.OnDestroy();
}
override void Tick()
{
// only the first tracker accesses the CVars, saves on perf
if ( !prev )
{
dbar = swwm_damagetarget;
mxdist = swwm_maxtargetdist;
}
if ( next )
{
next.dbar = dbar;
next.mxdist = mxdist;
}
// is target gone or dead?
if ( !mytarget || (mytarget.Health <= 0) )
{
@ -461,12 +322,12 @@ Class SWWMCombatTracker : Thinker
lasthealth = 0;
prevpos = pos; // prevent stuttering
intp.Update(lasthealth);
if ( level.maptime > updated+35 ) Destroy();
return;
if ( level.maptime > updated+35 ) return true;
return false;
}
// don't update dormant targets
if ( mytarget.bDORMANT )
return;
return false;
// only update height/position while alive
bool heightchanged = false;
if ( height != mytarget.height ) heightchanged = true;
@ -504,8 +365,7 @@ Class SWWMCombatTracker : Thinker
t.bUpdateMorph = true;
t.unmorphedtag = t.mytag;
t.mytag = String.Format("%s (%s)",mytag,t.unmorphedtag);
Destroy();
return;
return true;
}
}
}
@ -542,9 +402,9 @@ Class SWWMCombatTracker : Thinker
if ( dbar && !mytarget.player )
{
if ( (dbar == 2) && (lasthealth >= maxhealth) )
return;
return false;
else if ( (dbar == 1) && !firsthit )
return;
return false;
}
if ( (mytarget.bISMONSTER || mytarget.player) && !mytarget.bINVISIBLE && !mytarget.bCORPSE )
{
@ -567,11 +427,12 @@ Class SWWMCombatTracker : Thinker
// special stuff, only if visible
if ( ((mxdist <= 0) || (mytarget.Vec3To(players[consoleplayer].Camera).length() < (mxdist/4))) && players[consoleplayer].Camera.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime;
}
return false;
}
}
// ultralight trackers for certain things
Class SWWMSimpleTracker : Thinker
Class SWWMSimpleTracker play
{
Actor target;
double radius;
@ -591,7 +452,7 @@ Class SWWMSimpleTracker : Thinker
bool isbeam;
int lastupdate;
ui double smoothalpha; // smoothened alpha, for ui
SWWMSimpleTracker prev, next;
SWWMSimpleTracker next;
void Update()
{
@ -667,11 +528,9 @@ Class SWWMSimpleTracker : Thinker
return t;
}
t = new("SWWMSimpleTracker");
t.ChangeStatNum(STAT_INFO);
t.target = target;
t.Update();
t.next = hnd.strackers;
if ( hnd.strackers ) hnd.strackers.prev = t;
hnd.strackers = t;
hnd.strackers_cnt++;
return t;

View file

@ -145,6 +145,7 @@ Class SWWMHandler : EventHandler
ItemCountTrack();
CombatTrack();
OneHundredPercentCheck();
UpdateHUDObjects();
SimpleTracking();
VanillaBossTick();
if ( !profiling ) return;

View file

@ -521,18 +521,36 @@ Class Demolitionist : PlayerPawn
}
void SenseItems()
{
let bt = BlockThingsIterator.Create(self,800);
while ( bt.Next() )
if ( player.cmd.buttons&BT_USER3 )
{
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 && !CheckSight(i,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
SWWMItemSense.Spawn(self,i);
let bt = BlockThingsIterator.Create(self,800);
while ( bt.Next() )
{
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 && !CheckSight(i,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
SWWMItemSense.Spawn(self,i);
}
bt.Destroy();
}
SWWMItemsense itm = itemsense;
SWWMItemsense prev = null, next;
while ( itm )
{
next = itm.next;
if ( itm.Tick() )
{
if ( prev ) prev.next = next;
else itemsense = next;
itm.Destroy();
itemsense_cnt--;
}
else prev = itm;
itm = next;
}
bt.Destroy();
}
void CheckDefaceTexture()
{
@ -1070,7 +1088,7 @@ Class Demolitionist : PlayerPawn
}
else mystats.swimdist += traveldist;
CheckUnderwaterAmb();
if ( player.cmd.buttons&BT_USER3 ) SenseItems();
SenseItems();
if ( vel.length() > mystats.topspeed ) mystats.topspeed = vel.length();
if ( vel.length() > ((3600*GameTicRate)/32000.) )
SWWMUtility.AchievementProgress("sanic",int((vel.length()*3600*GameTicRate)/32000.),player);

View file

@ -1,5 +1,33 @@
// player-specific thinkers
// "Full History" contains all messages since session start, nothing is flushed
// this can be accessed from a section of the knowledge base
Class SWWMFullHistory : Thinker
{
Array<MsgLine> msg;
static clearscope SWWMFullHistory Get()
{
let fh = SWWMFullHistory(ThinkerIterator.Create("SWWMFullHistory",STAT_STATIC).Next());
return fh;
}
static void PushMessage( String str, int tic, int type )
{
let fh = SWWMFullHistory(ThinkerIterator.Create("SWWMFullHistory",STAT_STATIC).Next());
if ( !fh )
{
fh = new("SWWMFullHistory");
fh.ChangeStatNum(STAT_STATIC);
}
MsgLine m = new("MsgLine");
m.str = str;
m.tic = tic;
m.type = type;
fh.msg.Push(m);
}
}
// Stats
Class WeaponUsage
{