Healthbar / Damnum backport from sidemods.
This commit is contained in:
parent
12018e364e
commit
b40d8d0633
1743 changed files with 683 additions and 869 deletions
|
|
@ -63,7 +63,15 @@ extend Class SWWMHandler
|
|||
// damage numbers, combat tracking, etc.
|
||||
private void DoDamageHandling( WorldEvent e )
|
||||
{
|
||||
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);
|
||||
SWWMDamNum.SpawnFromHandler(self,e.Damage,e.Thing.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+e.Thing.Height/2),e.DamageType);
|
||||
// combat tracker updates if either an ally of the player is hit, or an ally hit this enemy
|
||||
// (this automatically also does the same for the player itself, of course)
|
||||
for ( int i=0; i<MAXPLAYERS; i++ )
|
||||
{
|
||||
if ( !playeringame[i] || !players[i].mo ) continue;
|
||||
if ( players[i].mo.IsFriend(e.Thing) || (e.DamageSource && players[i].mo.IsFriend(e.DamageSource)) )
|
||||
SWWMQuickCombatTracker.Update(self,players[i],e.Thing,e.Damage);
|
||||
}
|
||||
// stats
|
||||
if ( e.Thing.player )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -126,9 +126,6 @@ extend Class SWWMHandler
|
|||
spreecount[e.playernumber] = 0;
|
||||
tookdamage[e.playernumber] = false;
|
||||
lastkill[e.playernumber] = int.min;
|
||||
// reset combat tracker
|
||||
if ( !swwm_notrack )
|
||||
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;
|
||||
|
|
@ -152,8 +149,5 @@ extend Class SWWMHandler
|
|||
spreecount[e.playernumber] = 0;
|
||||
tookdamage[e.playernumber] = false;
|
||||
lastkill[e.playernumber] = int.min;
|
||||
// reset combat tracker
|
||||
if ( !swwm_notrack )
|
||||
SWWMCombatTracker.Spawn(self,players[e.playernumber].mo,true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -257,40 +257,6 @@ extend Class SWWMHandler
|
|||
Console.Printf("Extended hitboxes can't be re-enabled at runtime. Please restart the map.");
|
||||
return;
|
||||
}
|
||||
else if ( e.Name ~== "swwmupdatetrackers" )
|
||||
{
|
||||
if ( multiplayer && (e.player != Net_Arbitrator) )
|
||||
{
|
||||
if ( e.player == consoleplayer )
|
||||
Console.Printf("Only the net arbitrator can call this event.");
|
||||
return;
|
||||
}
|
||||
if ( swwm_notrack )
|
||||
{
|
||||
int n = trackers_cnt;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
int n = trackers_cnt;
|
||||
let ti = ThinkerIterator.Create("Actor");
|
||||
Actor a;
|
||||
while ( a = Actor(ti.Next()) )
|
||||
{
|
||||
if ( (!a.bSHOOTABLE && !a.bISMONSTER) || (a is 'LampMoth') || (a is 'CompanionLamp') ) continue;
|
||||
let trk = SWWMCombatTracker.Spawn(self,a,true);
|
||||
if ( !a.player ) trk.maxhealth = max(a.health,a.GetSpawnHealth());
|
||||
}
|
||||
n = (trackers_cnt-n);
|
||||
Console.Printf("%d trackers added.",n);
|
||||
return;
|
||||
}
|
||||
else if ( e.Name ~== "swwmtrimsuckables" )
|
||||
{
|
||||
if ( multiplayer && (e.player != Net_Arbitrator) )
|
||||
|
|
|
|||
|
|
@ -92,7 +92,8 @@ extend Class SWWMHandler
|
|||
ui bool ui_initialized;
|
||||
ui TextureID bbar_f, bbar_r, bbar_d;
|
||||
ui double bossalpha;
|
||||
ui DynamicValueInterpolator ihealth, ihealthr;
|
||||
ui SmoothLinearValueInterpolator ihealth;
|
||||
ui SmoothDynamicValueInterpolator ihealthr;
|
||||
ui int thealth, hmax;
|
||||
ui int oldhealth[30];
|
||||
ui int cummdamage, lastcummtic; // please do not misread
|
||||
|
|
@ -184,7 +185,7 @@ extend Class SWWMHandler
|
|||
return MAP_EVMAP30;
|
||||
return MAP_NONE;
|
||||
}
|
||||
private void VanillaBossSpawn( WorldEvent e, SWWMCombatTracker trk )
|
||||
private void VanillaBossSpawn( WorldEvent e )
|
||||
{
|
||||
if ( bossmap == -1 ) bossmap = WhichVanillaBossMap();
|
||||
if ( bossmap == MAP_DE1M8 )
|
||||
|
|
@ -193,7 +194,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 3;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
bosstag = "$BT_BRUISERS";
|
||||
|
|
@ -204,7 +204,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 5;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
bosstag = "$BT_CYBIE";
|
||||
|
|
@ -215,7 +214,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 6;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
e.Thing.GiveInventory('EndgameBossMarker',1);
|
||||
}
|
||||
|
|
@ -227,7 +225,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 4;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
bosstag = "$BT_SPIDER2";
|
||||
|
|
@ -238,7 +235,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 2;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
bosstag = "$BT_DIMPLE";
|
||||
|
|
@ -250,7 +246,6 @@ extend Class SWWMHandler
|
|||
bossbrainactor = e.Thing;
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 40; // goodbye, instakills
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
e.Thing.GiveInventory('EndgameBossMarker',1);
|
||||
}
|
||||
|
|
@ -267,7 +262,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 4;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
bosstag = "$BT_CYBIE2";
|
||||
|
|
@ -278,7 +272,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 4;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
bosstag = "$BT_LICHES";
|
||||
|
|
@ -289,7 +282,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 3;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
bosstag = "$BT_MINOTAUR";
|
||||
|
|
@ -300,7 +292,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 2;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_DSPARIL";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
e.Thing.GiveInventory('EndgameBossMarker',1);
|
||||
|
|
@ -312,7 +303,6 @@ extend Class SWWMHandler
|
|||
initialized = false;
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 8;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_DSPARIL2";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
e.Thing.GiveInventory('EndgameBossMarker',1);
|
||||
|
|
@ -325,7 +315,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 2;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_CLERIC";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
|
|
@ -336,7 +325,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 2;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_FIGHTER";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
|
|
@ -347,7 +335,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 2;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_MAGE";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
|
|
@ -358,7 +345,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 4;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_DRAGON";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
|
|
@ -369,7 +355,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 8;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_HERESIARCH";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
}
|
||||
|
|
@ -380,7 +365,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 10;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_KORAX";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
e.Thing.GiveInventory('EndgameBossMarker',1);
|
||||
|
|
@ -392,7 +376,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 4;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_DEATHKINGS";
|
||||
initialized = true; // healthbar shows from the start
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
|
|
@ -416,7 +399,6 @@ extend Class SWWMHandler
|
|||
initialized = false;
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 5;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_ARCHANGELUS";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
e.Thing.GiveInventory('EndgameBossMarker',1);
|
||||
|
|
@ -429,7 +411,6 @@ extend Class SWWMHandler
|
|||
initialized = false;
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 5;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "$BT_ARCHANGELUS";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
e.Thing.GiveInventory('EndgameBossMarker',1);
|
||||
|
|
@ -440,7 +421,6 @@ extend Class SWWMHandler
|
|||
{
|
||||
bossactors.Push(e.Thing);
|
||||
e.Thing.StartHealth = e.Thing.Health *= 10;
|
||||
if ( trk ) trk.bBOSS = true;
|
||||
bosstag = "ROM3R-0.666";
|
||||
e.Thing.GiveInventory('BossMarker',1);
|
||||
e.Thing.GiveInventory('EndgameBossMarker',1);
|
||||
|
|
@ -497,9 +477,9 @@ extend Class SWWMHandler
|
|||
hmax = thealth;
|
||||
for ( int i=0; i<30; i++ ) oldhealth[i] = thealth;
|
||||
cummdamage = 0;
|
||||
if ( !ihealth ) ihealth = DynamicValueInterpolator.Create(thealth,.1,1,1000);
|
||||
if ( !ihealth ) ihealth = SmoothLinearValueInterpolator.Create(thealth,max(1,hmax/120));
|
||||
else ihealth.Reset(thealth);
|
||||
if ( !ihealthr ) ihealthr = DynamicValueInterpolator.Create(thealth,.5,1,1000);
|
||||
if ( !ihealthr ) ihealthr = SmoothDynamicValueInterpolator.Create(thealth,.5,1,100);
|
||||
else ihealthr.Reset(thealth);
|
||||
return;
|
||||
}
|
||||
|
|
@ -534,7 +514,7 @@ extend Class SWWMHandler
|
|||
ui void DrawBossBar( SWWMStatusBar bar )
|
||||
{
|
||||
if ( !ui_initialized || (bossalpha <= 0.) ) return;
|
||||
if ( !mSmallFont ) mSmallFont = Font.GetFont('TewiFont');
|
||||
if ( !mSmallFont ) mSmallFont = Font.GetFont('TewiFontOutline');
|
||||
if ( !bbar_f ) bbar_f = TexMan.CheckForTexture("graphics/HUD/BossHealthBarBox.png",TexMan.Type_Any);
|
||||
if ( !bbar_r ) bbar_r = TexMan.CheckForTexture("graphics/HUD/BossHealthBar.png",TexMan.Type_Any);
|
||||
if ( !bbar_d ) bbar_d = TexMan.CheckForTexture("graphics/HUD/BossHealthBarDecay.png",TexMan.Type_Any);
|
||||
|
|
@ -542,10 +522,10 @@ extend Class SWWMHandler
|
|||
Screen.DrawTexture(bbar_f,false,vpos.x-2,vpos.y-2,DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha);
|
||||
if ( hmax )
|
||||
{
|
||||
int rw = int(clamp((ihealthr.GetValue()*300.)/hmax,0.,300.));
|
||||
int dw = int(clamp((ihealth.GetValue()*300.)/hmax,0.,300.));
|
||||
Screen.DrawTexture(bbar_d,false,vpos.x,vpos.y,DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha,DTA_WindowRight,dw);
|
||||
Screen.DrawTexture(bbar_r,false,vpos.x,vpos.y,DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha,DTA_WindowRight,rw);
|
||||
double rw = clamp((ihealthr.GetValue(bar.FracTic)*300.)/hmax,0.,300.);
|
||||
double dw = clamp((ihealth.GetValue(bar.FracTic)*300.)/hmax,0.,300.);
|
||||
Screen.DrawTexture(bbar_d,false,vpos.x,vpos.y,DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha,DTA_WindowRightF,dw);
|
||||
Screen.DrawTexture(bbar_r,false,vpos.x,vpos.y,DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha,DTA_WindowRightF,rw);
|
||||
}
|
||||
if ( (cummdamage > 0) && (gametic < lastcummtic+150) )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ extend Class SWWMHandler
|
|||
// for displaying beam-type projectiles
|
||||
Array<Actor> beams;
|
||||
|
||||
// legendary monster markers (for the "has mutated" message)
|
||||
Array<Inventory> legtrack;
|
||||
|
||||
override void WorldThingRevived( WorldEvent e )
|
||||
{
|
||||
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(self,e.Thing,true);
|
||||
// reattach headpats
|
||||
if ( SWWMUtility.IdentifyingDog(e.Thing) || SWWMUtility.IdentifyingCaco(e.Thing)
|
||||
|| SWWMUtility.IdentifyingDrug(e.Thing) || SWWMUtility.IdentifyingDoubleBoi(e.Thing) )
|
||||
|
|
@ -275,6 +275,9 @@ extend Class SWWMHandler
|
|||
p.target = e.Thing;
|
||||
p.SetStateLabel("Pickup");
|
||||
}
|
||||
// for notification
|
||||
if ( e.Thing.GetClassName() == "LDLegendaryMonsterTransformed" )
|
||||
legtrack.Push(Inventory(e.Thing));
|
||||
}
|
||||
if ( swwm_doomfall && e.Thing.bISMONSTER && !e.Thing.bBOSS )
|
||||
e.Thing.bFALLDAMAGE = true;
|
||||
|
|
@ -396,9 +399,6 @@ extend Class SWWMHandler
|
|||
let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos);
|
||||
hp.target = e.Thing;
|
||||
}
|
||||
SWWMCombatTracker trk = null;
|
||||
if ( !swwm_notrack && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER) && !(e.Thing is 'LampMoth') && !(e.Thing is 'CompanionLamp') )
|
||||
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)
|
||||
|
|
@ -427,13 +427,7 @@ extend Class SWWMHandler
|
|||
}
|
||||
else if ( e.Thing.GetClass() == "LostSoul" )
|
||||
e.Thing.bNOBLOOD = true;
|
||||
VanillaBossSpawn(e,trk);
|
||||
// inflation check
|
||||
if ( trk )
|
||||
{
|
||||
trk.maxhealth = trk.lasthealth = e.Thing.Health;
|
||||
trk.intp.Reset(trk.lasthealth);
|
||||
}
|
||||
VanillaBossSpawn(e);
|
||||
if ( profiling ) ProfileTock(PT_WORLDTHINGSPAWNED);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ extend Class SWWMHandler
|
|||
transient String curlang;
|
||||
transient bool curfuntags;
|
||||
SWWMSimpleTracker strackers;
|
||||
int strackers_cnt;
|
||||
bool mnotify;
|
||||
bool allkills, allitems, allsecrets;
|
||||
bool mapclear;
|
||||
|
|
@ -18,15 +17,18 @@ extend Class SWWMHandler
|
|||
String lastmus;
|
||||
int lastorder;
|
||||
bool lastloop;
|
||||
transient ThinkerIterator cti;
|
||||
transient ThinkerIterator cti, qti;
|
||||
|
||||
private void LangRefresh()
|
||||
{
|
||||
if ( (language != curlang) || (swwm_funtags != curfuntags) )
|
||||
{
|
||||
// manually refresh some tags if language has changed
|
||||
for ( SWWMCombatTracker t=trackers; t; t=t.next )
|
||||
t.UpdateTag(self);
|
||||
if ( !qti ) qti = ThinkerIterator.Create("SWWMQuickCombatTracker",Thinker.STAT_INVENTORY);
|
||||
else qti.Reinit();
|
||||
SWWMQuickCombatTracker qt;
|
||||
while ( qt=SWWMQuickCombatTracker(qti.Next()) )
|
||||
qt.UpdateTag(self);
|
||||
for ( SWWMInterest p=intpoints; p; p=p.next )
|
||||
{
|
||||
if ( (p.type != INT_Key) || !p.trackedkey ) continue;
|
||||
|
|
@ -229,25 +231,23 @@ extend Class SWWMHandler
|
|||
if ( soprev ) soprev.next = sonext;
|
||||
else scorenums = sonext;
|
||||
so.Destroy();
|
||||
scorenums_cnt--;
|
||||
}
|
||||
else soprev = so;
|
||||
so = sonext;
|
||||
}
|
||||
so = damnums;
|
||||
soprev = null;
|
||||
while ( so )
|
||||
SWWMDamNum dn = damnums;
|
||||
SWWMDamNum dnprev = null, dnnext;
|
||||
while ( dn )
|
||||
{
|
||||
sonext = so.next;
|
||||
if ( so.Tick() )
|
||||
dnnext = dn.next;
|
||||
if ( dn.Tick() )
|
||||
{
|
||||
if ( soprev ) soprev.next = sonext;
|
||||
else damnums = sonext;
|
||||
so.Destroy();
|
||||
damnums_cnt--;
|
||||
if ( dnprev ) dnprev.next = dnnext;
|
||||
else damnums = dnnext;
|
||||
dn.Destroy();
|
||||
}
|
||||
else soprev = so;
|
||||
so = sonext;
|
||||
else dnprev = dn;
|
||||
dn = dnnext;
|
||||
}
|
||||
// interest markers
|
||||
SWWMInterest ip = intpoints;
|
||||
|
|
@ -260,29 +260,10 @@ extend Class SWWMHandler
|
|||
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;
|
||||
while ( trk )
|
||||
{
|
||||
trknext = trk.next;
|
||||
trk.dbar = dbar;
|
||||
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)
|
||||
|
|
@ -296,7 +277,6 @@ extend Class SWWMHandler
|
|||
strackers.Destroy();
|
||||
strackers = next;
|
||||
}
|
||||
strackers_cnt = 0;
|
||||
return;
|
||||
}
|
||||
// update trackers for anything around the player
|
||||
|
|
@ -432,7 +412,6 @@ extend Class SWWMHandler
|
|||
if ( !prev ) strackers = trk.next;
|
||||
else prev.next = trk.next;
|
||||
trk.Destroy();
|
||||
strackers_cnt--;
|
||||
}
|
||||
else prev = trk;
|
||||
trk = next;
|
||||
|
|
|
|||
|
|
@ -68,19 +68,15 @@ Enum EMiniHUDFontColor
|
|||
Class SWWMStatusBar : BaseStatusBar
|
||||
{
|
||||
TextureID StatusTex, WeaponTex, ScoreTex, InventoryTex, ChatTex[6],
|
||||
HealthTex[9], FuelTex[2], DashTex, EnemyBTex, EnemyHTex[6],
|
||||
HealthTex[9], FuelTex[2], DashTex, EnemyBTex, EnemyHTex[7],
|
||||
GenericAmmoTex[3], AmmoTex[3], MiniBox, bgtex, FaceTex[19];
|
||||
|
||||
Font mSmallFont, mBigFont, mTinyFont, MiniHUDFont, MiniHUDFontOutline;
|
||||
Font mSmallFont, mSmallFontOutline, mTinyFont, mTinyFontOutline, MiniHUDFont, MiniHUDFontOutline;
|
||||
int mhudfontcol[NUM_MINIHUD_COLOR];
|
||||
|
||||
Array<MsgLine> MainQueue, PickupQueue;
|
||||
|
||||
// sorted arrays of various elements
|
||||
Array<SWWMInterest> intpoints;
|
||||
Array<SWWMScoreObj> scoreobjs;
|
||||
Array<SWWMCombatTracker> trackers;
|
||||
Array<SWWMItemSense> senseitems;
|
||||
transient ThinkerIterator cti;
|
||||
|
||||
// the event handler, holding all sorts of stuff
|
||||
SWWMHandler hnd;
|
||||
|
|
@ -824,150 +820,6 @@ Class SWWMStatusBar : BaseStatusBar
|
|||
return true;
|
||||
}
|
||||
|
||||
private bool CmpTarget( SWWMCombatTracker a, SWWMCombatTracker b )
|
||||
{
|
||||
if ( !a || !b ) return true;
|
||||
return (a.myplayer && !b.myplayer);
|
||||
}
|
||||
|
||||
private bool CmpScore( SWWMScoreObj a, SWWMScoreObj b )
|
||||
{
|
||||
if ( !a || !b ) return true;
|
||||
int srt[4] = { Font.CR_GOLD, Font.CR_FIRE, Font.CR_GREEN, Font.CR_RED };
|
||||
int s1 = 0, s2 = 0;
|
||||
for ( int i=0; i<3; i++ )
|
||||
{
|
||||
if ( a.tcolor == srt[i] ) s1 = i;
|
||||
if ( b.tcolor == srt[i] ) s2 = i;
|
||||
}
|
||||
return s1 < s2;
|
||||
}
|
||||
|
||||
private bool CmpInterest( SWWMInterest a, SWWMInterest b )
|
||||
{
|
||||
if ( !a || !b ) return true;
|
||||
return a.type < b.type;
|
||||
}
|
||||
|
||||
private bool CmpDist( Vector3 a, Vector3 b )
|
||||
{
|
||||
double dista = level.Vec3Diff(viewpos,a).length();
|
||||
double distb = level.Vec3Diff(viewpos,b).length();
|
||||
return (dista < distb);
|
||||
}
|
||||
|
||||
// quicksort (points of interest)
|
||||
private int partition_intpoints( Array<SWWMInterest> a, int l, int h )
|
||||
{
|
||||
SWWMInterest pv = a[h];
|
||||
int i = (l-1);
|
||||
for ( int j=l; j<=(h-1); j++ )
|
||||
{
|
||||
if ( CmpInterest(pv,a[j]) || CmpDist(pv.pos,a[j].pos) )
|
||||
{
|
||||
i++;
|
||||
SWWMInterest tmp = a[j];
|
||||
a[j] = a[i];
|
||||
a[i] = tmp;
|
||||
}
|
||||
}
|
||||
SWWMInterest tmp = a[h];
|
||||
a[h] = a[i+1];
|
||||
a[i+1] = tmp;
|
||||
return i+1;
|
||||
}
|
||||
private void qsort_intpoints( Array<SWWMInterest> a, int l, int h )
|
||||
{
|
||||
if ( l >= h ) return;
|
||||
int p = partition_intpoints(a,l,h);
|
||||
qsort_intpoints(a,l,p-1);
|
||||
qsort_intpoints(a,p+1,h);
|
||||
}
|
||||
|
||||
// quicksort (combat trackers)
|
||||
private int partition_trackers( Array<SWWMCombatTracker> a, int l, int h )
|
||||
{
|
||||
SWWMCombatTracker pv = a[h];
|
||||
int i = (l-1);
|
||||
for ( int j=l; j<=(h-1); j++ )
|
||||
{
|
||||
if ( CmpTarget(pv,a[j]) || CmpDist(pv.pos,a[j].pos) )
|
||||
{
|
||||
i++;
|
||||
SWWMCombatTracker tmp = a[j];
|
||||
a[j] = a[i];
|
||||
a[i] = tmp;
|
||||
}
|
||||
}
|
||||
SWWMCombatTracker tmp = a[h];
|
||||
a[h] = a[i+1];
|
||||
a[i+1] = tmp;
|
||||
return i+1;
|
||||
}
|
||||
private void qsort_trackers( Array<SWWMCombatTracker> a, int l, int h )
|
||||
{
|
||||
if ( l >= h ) return;
|
||||
int p = partition_trackers(a,l,h);
|
||||
qsort_trackers(a,l,p-1);
|
||||
qsort_trackers(a,p+1,h);
|
||||
}
|
||||
|
||||
// quicksort (score objects)
|
||||
private int partition_scoreobjs( Array<SWWMScoreObj> a, int l, int h )
|
||||
{
|
||||
SWWMScoreObj pv = a[h];
|
||||
int i = (l-1);
|
||||
for ( int j=l; j<=(h-1); j++ )
|
||||
{
|
||||
if ( CmpScore(pv,a[j]) || CmpDist(pv.pos,a[j].pos) )
|
||||
{
|
||||
i++;
|
||||
SWWMScoreObj tmp = a[j];
|
||||
a[j] = a[i];
|
||||
a[i] = tmp;
|
||||
}
|
||||
}
|
||||
SWWMScoreObj tmp = a[h];
|
||||
a[h] = a[i+1];
|
||||
a[i+1] = tmp;
|
||||
return i+1;
|
||||
}
|
||||
private void qsort_scoreobjs( Array<SWWMScoreObj> a, int l, int h )
|
||||
{
|
||||
if ( l >= h ) return;
|
||||
int p = partition_scoreobjs(a,l,h);
|
||||
qsort_scoreobjs(a,l,p-1);
|
||||
qsort_scoreobjs(a,p+1,h);
|
||||
}
|
||||
|
||||
// quicksort (item sense)
|
||||
private int partition_itemsense( Array<SWWMItemSense> a, int l, int h )
|
||||
{
|
||||
SWWMItemSense pv = a[h];
|
||||
int i = (l-1);
|
||||
for ( int j=l; j<=(h-1); j++ )
|
||||
{
|
||||
if ( CmpDist(pv.pos,a[j].pos) )
|
||||
{
|
||||
i++;
|
||||
SWWMItemSense tmp = a[j];
|
||||
a[j] = a[i];
|
||||
a[i] = tmp;
|
||||
}
|
||||
}
|
||||
SWWMItemSense tmp = a[h];
|
||||
a[h] = a[i+1];
|
||||
a[i+1] = tmp;
|
||||
return i+1;
|
||||
}
|
||||
private void qsort_itemsense( Array<SWWMItemSense> a, int l, int h )
|
||||
{
|
||||
if ( l >= h ) return;
|
||||
int p = partition_itemsense(a,l,h);
|
||||
qsort_itemsense(a,l,p-1);
|
||||
qsort_itemsense(a,p+1,h);
|
||||
}
|
||||
|
||||
// quicksort (player scores)
|
||||
private int partition_playerscore( Array<PlayerInfo> a, int l, int h )
|
||||
{
|
||||
|
|
@ -1148,129 +1000,6 @@ Class SWWMStatusBar : BaseStatusBar
|
|||
minimapzoom = desiredzoom;
|
||||
}
|
||||
if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
||||
let cam = players[consoleplayer].camera;
|
||||
Vector3 viewvec = SWWMUtility.Vec3FromAngles(viewrot.x,viewrot.y);
|
||||
int sz;
|
||||
if ( level.allmap && swwm_pois )
|
||||
{
|
||||
// update omnisight stuff
|
||||
if ( intpoints.Size() != hnd.intpoints_cnt )
|
||||
intpoints.Resize(hnd.intpoints_cnt);
|
||||
int i = 0;
|
||||
for ( SWWMInterest poi=hnd.intpoints; poi; poi=poi.next )
|
||||
{
|
||||
// ignore points clearly outside of player view
|
||||
Vector3 tdir = level.Vec3Diff(viewpos,poi.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
if ( !SWWMUtility.TestScreenBounds(projdata,vpos) ) continue;
|
||||
intpoints[i++] = poi;
|
||||
}
|
||||
// squeeze if some were discarded
|
||||
if ( i != hnd.intpoints_cnt )
|
||||
intpoints.Resize(i);
|
||||
// sort by distance
|
||||
qsort_intpoints(intpoints,0,intpoints.Size()-1);
|
||||
}
|
||||
if ( swwm_targeter )
|
||||
{
|
||||
// update target stuff
|
||||
if ( trackers.Size() != hnd.trackers_cnt )
|
||||
trackers.Resize(hnd.trackers_cnt);
|
||||
int i = 0;
|
||||
for ( SWWMCombatTracker trk=hnd.trackers; trk; trk=trk.next )
|
||||
{
|
||||
// ignore dormant/invisible targets
|
||||
if ( !trk.mytarget || trk.mytarget.bDORMANT || trk.mytarget.bINVISIBLE ) continue;
|
||||
// ignore local player
|
||||
if ( trk.mytarget == CPlayer.mo ) continue;
|
||||
if ( trk.mytarget is 'PlayerGone' ) continue; // ignore "gone" players
|
||||
int mtime = GameTicRate;
|
||||
if ( level.allmap && (trk.lasthealth > 0) ) mtime += GameTicRate*3;
|
||||
if ( level.maptime > trk.updated+mtime ) continue;
|
||||
// ignore trackers clearly outside of player view
|
||||
Vector3 tdir = level.Vec3Diff(viewpos,trk.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
if ( !SWWMUtility.TestScreenBounds(projdata,vpos) ) continue;
|
||||
trackers[i++] = trk;
|
||||
}
|
||||
// squeeze if some were discarded
|
||||
if ( i != hnd.trackers_cnt )
|
||||
trackers.Resize(i);
|
||||
// sort by distance (give priority to players)
|
||||
qsort_trackers(trackers,0,trackers.Size()-1);
|
||||
}
|
||||
else trackers.Clear();
|
||||
// update floating scores, adding the scorenums first, then the damnums
|
||||
int total_sz = 0;
|
||||
if ( swwm_scorenums ) total_sz += hnd.scorenums_cnt;
|
||||
if ( swwm_healthnums ) total_sz += hnd.damnums_cnt;
|
||||
if ( scoreobjs.Size() != total_sz )
|
||||
scoreobjs.Resize(total_sz);
|
||||
int i = 0;
|
||||
if ( swwm_scorenums )
|
||||
{
|
||||
for ( SWWMScoreObj scr=hnd.scorenums; scr && (i<total_sz); scr=scr.next )
|
||||
{
|
||||
// ignore numbers clearly outside of player view
|
||||
Vector3 tdir = level.Vec3Diff(viewpos,scr.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
if ( !SWWMUtility.TestScreenBounds(projdata,vpos) ) continue;
|
||||
scoreobjs[i++] = scr;
|
||||
}
|
||||
}
|
||||
if ( swwm_healthnums )
|
||||
{
|
||||
for ( SWWMScoreObj scr=hnd.damnums; scr && (i<total_sz); scr=scr.next )
|
||||
{
|
||||
// ignore numbers clearly outside of player view
|
||||
Vector3 tdir = level.Vec3Diff(viewpos,scr.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
if ( !SWWMUtility.TestScreenBounds(projdata,vpos) ) continue;
|
||||
scoreobjs[i++] = scr;
|
||||
}
|
||||
}
|
||||
// squeeze if some were discarded
|
||||
if ( i != total_sz )
|
||||
scoreobjs.Resize(i);
|
||||
// sort by distance
|
||||
qsort_scoreobjs(scoreobjs,0,scoreobjs.Size()-1);
|
||||
// check if player has item sense
|
||||
let demo = Demolitionist(CPlayer.mo);
|
||||
if ( demo && (demo.itemsense_cnt > 0) )
|
||||
{
|
||||
if ( senseitems.Size() != demo.itemsense_cnt )
|
||||
senseitems.Resize(demo.itemsense_cnt);
|
||||
i = 0;
|
||||
for ( SWWMItemSense s=demo.itemsense; s; s=s.next )
|
||||
{
|
||||
if ( !level.allmap && (level.maptime > s.updated+GameTicRate) ) continue;
|
||||
// ignore points clearly outside of player view
|
||||
Vector3 tdir = level.Vec3Diff(viewpos,s.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
if ( !SWWMUtility.TestScreenBounds(projdata,vpos) ) continue;
|
||||
senseitems[i++] = s;
|
||||
}
|
||||
// squeeze if some were discarded
|
||||
if ( i != demo.itemsense_cnt )
|
||||
senseitems.Resize(i);
|
||||
// sort by distance
|
||||
qsort_itemsense(senseitems,0,senseitems.Size()-1);
|
||||
}
|
||||
// part of gross hackery to override nametag display
|
||||
if ( CPlayer.inventorytics > 0 )
|
||||
{
|
||||
|
|
@ -1383,12 +1112,13 @@ Class SWWMStatusBar : BaseStatusBar
|
|||
ChatTex[5] = TexMan.CheckForTexture("graphics/HUD/ChatBoxBottom_Smol.png",TexMan.Type_Any);
|
||||
InventoryTex = TexMan.CheckForTexture("graphics/HUD/InventoryBox.png",TexMan.Type_Any);
|
||||
EnemyBTex = TexMan.CheckForTexture("graphics/HUD/EnemyBox.png",TexMan.Type_Any);
|
||||
EnemyHTex[0] = TexMan.CheckForTexture("graphics/HUD/EnemyBar0.png",TexMan.Type_Any);
|
||||
EnemyHTex[1] = TexMan.CheckForTexture("graphics/HUD/EnemyBar1.png",TexMan.Type_Any);
|
||||
EnemyHTex[2] = TexMan.CheckForTexture("graphics/HUD/EnemyBar2.png",TexMan.Type_Any);
|
||||
EnemyHTex[3] = TexMan.CheckForTexture("graphics/HUD/EnemyBar3.png",TexMan.Type_Any);
|
||||
EnemyHTex[4] = TexMan.CheckForTexture("graphics/HUD/EnemyBarS.png",TexMan.Type_Any);
|
||||
EnemyHTex[5] = TexMan.CheckForTexture("graphics/HUD/EnemyBarD.png",TexMan.Type_Any);
|
||||
EnemyHTex[0] = TexMan.CheckForTexture("graphics/HUD/EnemyBar.png",TexMan.Type_Any);
|
||||
EnemyHTex[1] = TexMan.CheckForTexture("graphics/HUD/EnemyBarS.png",TexMan.Type_Any);
|
||||
EnemyHTex[2] = TexMan.CheckForTexture("graphics/HUD/EnemyBarL.png",TexMan.Type_Any);
|
||||
EnemyHTex[3] = TexMan.CheckForTexture("graphics/HUD/EnemyBar1.png",TexMan.Type_Any);
|
||||
EnemyHTex[4] = TexMan.CheckForTexture("graphics/HUD/EnemyBar2.png",TexMan.Type_Any);
|
||||
EnemyHTex[5] = TexMan.CheckForTexture("graphics/HUD/EnemyBar3.png",TexMan.Type_Any);
|
||||
EnemyHTex[6] = TexMan.CheckForTexture("graphics/HUD/EnemyBarD.png",TexMan.Type_Any);
|
||||
GenericAmmoTex[0] = TexMan.CheckForTexture("graphics/HUD/GenericAmmoBoxL.png",TexMan.Type_Any);
|
||||
GenericAmmoTex[1] = TexMan.CheckForTexture("graphics/HUD/GenericAmmoBoxM.png",TexMan.Type_Any);
|
||||
GenericAmmoTex[2] = TexMan.CheckForTexture("graphics/HUD/GenericAmmoBoxR.png",TexMan.Type_Any);
|
||||
|
|
@ -1418,8 +1148,9 @@ Class SWWMStatusBar : BaseStatusBar
|
|||
FaceTex[18] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Wink.png",TexMan.Type_Any);
|
||||
// other expressions will be added when needed
|
||||
mSmallFont = Font.GetFont('TewiFont');
|
||||
mBigFont = Font.GetFont('TewiFontOutline');
|
||||
mSmallFontOutline = Font.GetFont('TewiFontOutline');
|
||||
mTinyFont = Font.GetFont('MiniwiFont');
|
||||
mTinyFontOutline = Font.GetFont('MiniwiFontOutline');
|
||||
MiniHudFont = Font.GetFont("MiniHUDShadow");
|
||||
MiniHudFontOutline = Font.GetFont("MiniHUDOutline");
|
||||
mhudfontcol[MCR_DEMOHUD] = Font.FindFontColor("MiniDemoHUD");
|
||||
|
|
@ -1534,218 +1265,345 @@ Class SWWMStatusBar : BaseStatusBar
|
|||
return String.Format("\cj%d\cc%s",int(meters),StringTable.Localize("$SWWM_UNIT_METER"));
|
||||
}
|
||||
|
||||
private void DrawTarget()
|
||||
private void DrawInterest( Vector3 viewvec, out bool projinit )
|
||||
{
|
||||
// don't draw when dead or with automap open
|
||||
if ( (CPlayer.health <= 0) || automapactive ) return;
|
||||
SWWMUtility.PrepareProjData(projdata,ViewPos,ViewRot.x,ViewRot.y,ViewRot.z,players[consoleplayer].fov);
|
||||
Screen.SetClipRect(projdata.viewx,projdata.viewy,projdata.vieww,projdata.viewh);
|
||||
// points of interest
|
||||
String tag;
|
||||
if ( level.allmap )
|
||||
SWWMInterest poi = hnd.intpoints;
|
||||
if ( !poi ) return;
|
||||
do
|
||||
{
|
||||
for ( int i=0; i<intpoints.Size(); i++ )
|
||||
// this ensures that projection data isn't cached if there are no target array elements, to avoid needless GC thrashing
|
||||
if ( !projinit )
|
||||
{
|
||||
let poi = intpoints[i];
|
||||
if ( !poi ) continue;
|
||||
Vector3 tdir = level.Vec3Diff(ViewPos,poi.pos);
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
if ( poi.type == INT_Key ) tag = String.Format("\cf%s\c-",poi.keytag);
|
||||
else if ( poi.type == INT_Exit )
|
||||
{
|
||||
if ( (poi.trackedline.special == Teleport_EndGame)
|
||||
|| ((poi.trackedline.special == Exit_Secret) && (level.nextsecretmap.Left(6) == "enDSeQ"))
|
||||
|| ((poi.trackedline.special == Exit_Normal) && (level.nextmap.Left(6) == "enDSeQ")) )
|
||||
tag = String.Format("\cg%s\c-",StringTable.Localize("$SWWM_EEXIT"));
|
||||
else if ( poi.trackedline.special == Exit_Secret )
|
||||
{
|
||||
LevelInfo l = LevelInfo.FindLevelInfo(level.nextsecretmap);
|
||||
if ( l && l.isValid() ) tag = String.Format("\cx%s:\c- %s\c-",StringTable.Localize("$SWWM_SEXIT"),l.LookupLevelName());
|
||||
else tag = String.Format("\cx%s\c-",StringTable.Localize("$SWWM_SEXIT"));
|
||||
}
|
||||
else if ( (poi.trackedline.special == Exit_Normal) || ((poi.trackedline.special == ACS_Execute) && (poi.trackedline.Args[0] == -Int('E1M8_KNOCKOUT'))) )
|
||||
{
|
||||
LevelInfo l = LevelInfo.FindLevelInfo(level.nextmap);
|
||||
if ( l && l.isValid() ) tag = String.Format("\cy%s:\c- %s\c-",StringTable.Localize("$SWWM_NEXIT"),l.LookupLevelName());
|
||||
else tag = String.Format("\cy%s\c-",StringTable.Localize("$SWWM_NEXIT"));
|
||||
}
|
||||
else if ( poi.trackedline.special == Teleport_NewMap )
|
||||
{
|
||||
LevelInfo l = LevelInfo.FindLevelByNum(poi.trackedline.Args[0]);
|
||||
if ( l && l.isValid() ) tag = String.Format("\cy%s\c-%s\c-",StringTable.Localize("$SWWM_EXIT"),l.LookupLevelName());
|
||||
else tag = String.Format("\cy%s\c-",StringTable.Localize("$SWWM_NEXIT"));
|
||||
}
|
||||
else if ( ((poi.trackedline.special == ACS_Execute) || (poi.trackedline.special == ACS_ExecuteAlways)) && (poi.trackedline.Args[0] == -Int('MapFadeOut')) )
|
||||
{
|
||||
LevelInfo l = LevelInfo.FindLevelByNum(poi.trackedline.Args[2]);
|
||||
if ( (level.levelnum != 1) && l && l.isValid() ) tag = String.Format("\cy%s\c-%s\c-",StringTable.Localize("$SWWM_EXIT"),l.LookupLevelName());
|
||||
else tag = String.Format("\cy%s\c-",StringTable.Localize("$SWWM_NEXIT"));
|
||||
}
|
||||
}
|
||||
Screen.DrawText(mTinyFont,Font.CR_WHITE,(vpos.x-hs2*mTinyFont.StringWidth(tag)/2.)/hs2,(vpos.y-hs2*mTinyFont.GetHeight()/2.)/hs2,tag,DTA_VirtualWidthF,ss2.x,DTA_VirtualHeightF,ss2.y,DTA_KeepRatio,true);
|
||||
tag = String.Format("\cu(%s\cu)\c-",FormatDist(tdir.length()));
|
||||
Screen.DrawText(mTinyFont,Font.CR_WHITE,(vpos.x-hs2*mTinyFont.StringWidth(tag)/2.)/hs2,(vpos.y+hs2*mTinyFont.GetHeight()/2.)/hs2,tag,DTA_VirtualWidthF,ss2.x,DTA_VirtualHeightF,ss2.y,DTA_KeepRatio,true);
|
||||
projinit = true;
|
||||
SWWMUtility.PrepareProjData(projdata,ViewPos,ViewRot.x,ViewRot.y,ViewRot.z,players[consoleplayer].fov);
|
||||
Screen.SetClipRect(projdata.viewx,projdata.viewy,projdata.vieww,projdata.viewh);
|
||||
}
|
||||
}
|
||||
// sensed items
|
||||
let demo = Demolitionist(CPlayer.mo);
|
||||
if ( demo && (demo.itemsense_cnt > 0) )
|
||||
{
|
||||
for ( int i=0; i<senseitems.Size(); i++ )
|
||||
{
|
||||
let s = senseitems[i];
|
||||
if ( !s || !s.item ) continue;
|
||||
Vector3 tdir = level.Vec3Diff(ViewPos,s.pos);
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
int mtime = level.allmap?(GameTicRate*2):GameTicRate;
|
||||
double alph = clamp(((s.updated+mtime)-(level.maptime+fractic))/double(GameTicRate),0.,1.);
|
||||
alph *= clamp(1.5-1.5*(tdir.length()/(level.allmap?1200.:800.)),0.,1.);
|
||||
tag = s.tag;
|
||||
Screen.DrawText(mTinyFont,s.vipitem?Font.CR_PURPLE:s.scoreitem?Font.CR_GOLD:Font.CR_GREEN,(vpos.x-hs1*mTinyFont.StringWidth(tag)/2.)/hs1,(vpos.y-hs1*mTinyFont.GetHeight()/2.)/hs1,tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
tag = String.Format("\cu(%s\cu)\c-",FormatDist(tdir.length()));
|
||||
Screen.DrawText(mTinyFont,Font.CR_WHITE,(vpos.x-hs1*mTinyFont.StringWidth(tag)/2.)/hs1,(vpos.y+hs1*mTinyFont.GetHeight()/2.)/hs1,tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
if ( s.item is 'SWWMRespawnTimer' )
|
||||
{
|
||||
tag = String.Format(StringTable.Localize("$SWWM_TRESPAWN"),s.item.special2/GameTicRate);
|
||||
Screen.DrawText(mTinyFont,Font.CR_WHITE,(vpos.x-hs1*mTinyFont.StringWidth(tag)/2.)/hs1,(vpos.y+hs1*mTinyFont.GetHeight()*2)/hs1,tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
}
|
||||
}
|
||||
}
|
||||
// targetting array
|
||||
for ( int i=0; i<trackers.Size(); i++ )
|
||||
{
|
||||
let targ = trackers[i];
|
||||
if ( !targ ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+level.Vec3Diff(ViewPos,SWWMUtility.LerpVector3(targ.prevpos,targ.pos,fractic)));
|
||||
Vector3 tdir = level.Vec3Diff(ViewPos,poi.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
tag = targ.mytag;
|
||||
if ( (tag != "") && !targ.myplayer )
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs2;
|
||||
if ( poi.type == INT_Key ) tag = String.Format("\cf%s\c-",poi.keytag);
|
||||
else if ( poi.type == INT_Exit )
|
||||
{
|
||||
if ( targ.legged && (targ.mutated || swwm_ldspoil) )
|
||||
if ( (poi.trackedline.special == Teleport_EndGame)
|
||||
|| ((poi.trackedline.special == Exit_Secret) && (level.nextsecretmap.Left(6) == "enDSeQ"))
|
||||
|| ((poi.trackedline.special == Exit_Normal) && (level.nextmap.Left(6) == "enDSeQ")) )
|
||||
tag = String.Format("\cg%s\c-",StringTable.Localize("$SWWM_EEXIT"));
|
||||
else if ( poi.trackedline.special == Exit_Secret )
|
||||
{
|
||||
LevelInfo l = LevelInfo.FindLevelInfo(level.nextsecretmap);
|
||||
if ( l && l.isValid() ) tag = String.Format("\cx%s:\c- %s\c-",StringTable.Localize("$SWWM_SEXIT"),l.LookupLevelName());
|
||||
else tag = String.Format("\cx%s\c-",StringTable.Localize("$SWWM_SEXIT"));
|
||||
}
|
||||
else if ( (poi.trackedline.special == Exit_Normal) || ((poi.trackedline.special == ACS_Execute) && (poi.trackedline.Args[0] == -Int('E1M8_KNOCKOUT'))) )
|
||||
{
|
||||
LevelInfo l = LevelInfo.FindLevelInfo(level.nextmap);
|
||||
if ( l && l.isValid() ) tag = String.Format("\cy%s:\c- %s\c-",StringTable.Localize("$SWWM_NEXIT"),l.LookupLevelName());
|
||||
else tag = String.Format("\cy%s\c-",StringTable.Localize("$SWWM_NEXIT"));
|
||||
}
|
||||
else if ( poi.trackedline.special == Teleport_NewMap )
|
||||
{
|
||||
LevelInfo l = LevelInfo.FindLevelByNum(poi.trackedline.Args[0]);
|
||||
if ( l && l.isValid() ) tag = String.Format("\cy%s\c-%s\c-",StringTable.Localize("$SWWM_EXIT"),l.LookupLevelName());
|
||||
else tag = String.Format("\cy%s\c-",StringTable.Localize("$SWWM_NEXIT"));
|
||||
}
|
||||
else if ( ((poi.trackedline.special == ACS_Execute) || (poi.trackedline.special == ACS_ExecuteAlways)) && (poi.trackedline.Args[0] == -Int('MapFadeOut')) )
|
||||
{
|
||||
LevelInfo l = LevelInfo.FindLevelByNum(poi.trackedline.Args[2]);
|
||||
if ( (level.levelnum != 1) && l && l.isValid() ) tag = String.Format("\cy%s\c-%s\c-",StringTable.Localize("$SWWM_EXIT"),l.LookupLevelName());
|
||||
else tag = String.Format("\cy%s\c-",StringTable.Localize("$SWWM_NEXIT"));
|
||||
}
|
||||
}
|
||||
Screen.DrawText(mTinyFontOutline,Font.CR_WHITE,vpos.x-mTinyFontOutline.StringWidth(tag)/2.,vpos.y-mTinyFontOutline.GetHeight()/2.,tag,DTA_VirtualWidthF,ss2.x,DTA_VirtualHeightF,ss2.y,DTA_KeepRatio,true);
|
||||
tag = String.Format("\cu(%s\cu)\c-",FormatDist(tdir.length()));
|
||||
Screen.DrawText(mTinyFontOutline,Font.CR_WHITE,vpos.x-mTinyFontOutline.StringWidth(tag)/2.,vpos.y+mTinyFontOutline.GetHeight()/2.,tag,DTA_VirtualWidthF,ss2.x,DTA_VirtualHeightF,ss2.y,DTA_KeepRatio,true);
|
||||
}
|
||||
while ( poi = poi.next );
|
||||
}
|
||||
|
||||
private void DrawItemSense( Vector3 viewvec, out bool projinit )
|
||||
{
|
||||
let demo = Demolitionist(CPlayer.mo);
|
||||
if ( !demo ) return;
|
||||
SWWMItemSense s = demo.itemsense;
|
||||
if ( !s ) return;
|
||||
do
|
||||
{
|
||||
if ( !s.item ) continue;
|
||||
Vector3 tdir = level.Vec3Diff(ViewPos,s.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs1;
|
||||
int mtime = level.allmap?(GameTicRate*2):GameTicRate;
|
||||
double alph = clamp(((s.updated+mtime)-(level.maptime+fractic))/double(GameTicRate),0.,1.);
|
||||
alph *= clamp(1.5-1.5*(tdir.length()/(level.allmap?1200.:800.)),0.,1.);
|
||||
String tag = s.tag;
|
||||
Screen.DrawText(mTinyFontOutline,s.vipitem?Font.CR_PURPLE:s.scoreitem?Font.CR_GOLD:Font.CR_GREEN,vpos.x-mTinyFontOutline.StringWidth(tag)/2.,vpos.y-mTinyFontOutline.GetHeight()/2.,tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
tag = String.Format("\cu(%s\cu)\c-",FormatDist(tdir.length()));
|
||||
Screen.DrawText(mTinyFontOutline,Font.CR_WHITE,vpos.x-mTinyFontOutline.StringWidth(tag)/2.,vpos.y+mTinyFontOutline.GetHeight()/2.,tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
if ( s.item is 'SWWMRespawnTimer' )
|
||||
{
|
||||
tag = String.Format(StringTable.Localize("$SWWM_TRESPAWN"),s.item.special2/GameTicRate);
|
||||
Screen.DrawText(mTinyFontOutline,Font.CR_WHITE,vpos.x-mTinyFontOutline.StringWidth(tag)/2.,vpos.y+mTinyFontOutline.GetHeight()*2,tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
}
|
||||
}
|
||||
while ( s = s.next );
|
||||
}
|
||||
|
||||
private bool IsLegendary( Actor a )
|
||||
{
|
||||
for ( Inventory i=a.inv; i; i=i.inv )
|
||||
{
|
||||
if ( (i.GetClassName() == "LDLegendaryMonsterToken") && swwm_ldspoil ) return true;
|
||||
else if ( i.GetClassName() == "LDLegendaryMonsterTransformed" ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DrawTrackers( Vector3 viewvec, out bool projinit )
|
||||
{
|
||||
let cam = players[consoleplayer].camera;
|
||||
if ( !cti ) cti = ThinkerIterator.Create("SWWMQuickCombatTracker",Thinker.STAT_INVENTORY);
|
||||
else cti.Reinit();
|
||||
SWWMQuickCombatTracker ct;
|
||||
while ( ct = SWWMQuickCombatTracker(cti.Next()) )
|
||||
{
|
||||
// this ensures that projection data isn't cached if there are no target array elements, to avoid needless GC thrashing
|
||||
if ( !projinit )
|
||||
{
|
||||
projinit = true;
|
||||
SWWMUtility.PrepareProjData(projdata,ViewPos,ViewRot.x,ViewRot.y,ViewRot.z,players[consoleplayer].fov);
|
||||
Screen.SetClipRect(projdata.viewx,projdata.viewy,projdata.vieww,projdata.viewh);
|
||||
}
|
||||
// ignore unowned (can happen?)
|
||||
if ( !ct.Owner ) continue;
|
||||
// ignore player trackers
|
||||
if ( ct.Owner.player ) continue;
|
||||
// ignore local player or camera
|
||||
if ( (ct.Owner.player == CPlayer) || (ct.Owner == cam) ) continue;
|
||||
// ignore trackers not of this player
|
||||
if ( ct.myplayer != CPlayer ) continue;
|
||||
// ignore trackers clearly outside of player view
|
||||
Vector3 smpos = level.Vec3Offset(SWWMUtility.LerpVector3(ct.Owner.prev,ct.Owner.pos,fractic),(0,0,ct.lvheight));
|
||||
Vector3 tdir = level.Vec3Diff(viewpos,smpos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs1;
|
||||
if ( !SWWMUtility.TestScreenBounds(projdata,vpos) ) continue;
|
||||
double fin = clamp(ct.fadein+fractic,0.,5.)/5.;
|
||||
double fout = clamp(ct.lifespan-fractic,0.,25.)/25.;
|
||||
double alph = fin*fout;
|
||||
Vector2 barpos = vpos-(27,7);
|
||||
if ( swwm_targettags && (ct.mytag != "") )
|
||||
{
|
||||
Font fnt = swwm_bigtags?mSmallFontOutline:mTinyFontOutline;
|
||||
String tag = ct.mytag;
|
||||
if ( IsLegendary(ct.Owner) )
|
||||
{
|
||||
if ( StringTable.Localize("$SWWM_LEGPREFIX") == "R" ) tag = tag..StringTable.Localize("$SWWM_LEG");
|
||||
else tag = StringTable.Localize("$SWWM_LEG")..tag;
|
||||
}
|
||||
if ( targ.bBOSS )
|
||||
if ( ct.Owner.bBOSS || ct.Owner.FindInventory("BossMarker") )
|
||||
{
|
||||
if ( swwm_bigtags ) tag = "\cx★\c- "..tag.." \cx★\c-";
|
||||
else tag = "\cx*\c- "..tag.." \cx*\c-"; // miniwi has no stars
|
||||
}
|
||||
if ( targ.bFRIENDLY ) tag = "\cg♥\c- "..tag.." \cg♥\c-";
|
||||
if ( ct.Owner.IsFriend(CPlayer.mo) ) tag = "\cg♥\c- "..tag.." \cg♥\c-";
|
||||
Screen.DrawText(fnt,Font.CR_WHITE,vpos.x-fnt.StringWidth(tag)/2,barpos.y-(fnt.GetHeight()+2),tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
}
|
||||
int mtime = GameTicRate;
|
||||
if ( level.allmap && (targ.lasthealth > 0) ) mtime += GameTicRate*3;
|
||||
double alph = clamp(((targ.updated+mtime)-(level.maptime+fractic))/double(GameTicRate),0.,1.);
|
||||
Vector2 barsiz = TexMan.GetScaledSize(EnemyBTex);
|
||||
barsiz.x *= hs1;
|
||||
barsiz.y *= hs1;
|
||||
Vector2 barpos = vpos-(barsiz/2.);
|
||||
barpos.y -= 16.;
|
||||
Font fnt = swwm_bigtags?mSmallFont:mTinyFont;
|
||||
Screen.DrawTexture(EnemyBTex,false,barpos.x,barpos.y,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
double ht = clamp(ct.intp.GetValue(fractic),0,ct.maxhealth);
|
||||
double hw = (ht*50.)/ct.maxhealth;
|
||||
Screen.DrawTexture(EnemyHTex[ct.Owner.bINVULNERABLE?1:0],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
double ohw = hw;
|
||||
ht = clamp(ct.intpl.GetValue(fractic),0,ct.maxhealth);
|
||||
hw = (ht*50.)/ct.maxhealth;
|
||||
Screen.DrawTexture(EnemyHTex[2],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowLeftF,ohw,DTA_WindowRightF,hw);
|
||||
if ( ct.cummdamage <= 0 ) continue;
|
||||
double calph = clamp(ct.cummspan-fractic,0.,20.)/20.;
|
||||
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_RED],barpos.x+3,barpos.y+10,String.Format("%d",ct.cummdamage),DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,calph*alph);
|
||||
if ( ct.cummflash <= 0 ) continue;
|
||||
double falph = max((ct.cummflash-FracTic)/15.,0.)**1.5;
|
||||
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_REDFLASH],barpos.x+3,barpos.y+10,String.Format("%d",ct.cummdamage),DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,falph*calph*alph,DTA_LegacyRenderStyle,STYLE_Add);
|
||||
}
|
||||
// player-owned trackers are drawn last
|
||||
cti.Reinit();
|
||||
while ( ct = SWWMQuickCombatTracker(cti.Next()) )
|
||||
{
|
||||
// this ensures that projection data isn't cached if there are no target array elements, to avoid needless GC thrashing
|
||||
if ( !projinit )
|
||||
{
|
||||
projinit = true;
|
||||
SWWMUtility.PrepareProjData(projdata,ViewPos,ViewRot.x,ViewRot.y,ViewRot.z,players[consoleplayer].fov);
|
||||
Screen.SetClipRect(projdata.viewx,projdata.viewy,projdata.vieww,projdata.viewh);
|
||||
}
|
||||
// ignore unowned (can happen?)
|
||||
if ( !ct.Owner ) continue;
|
||||
// ignore non-player trackers
|
||||
if ( !ct.Owner.player ) continue;
|
||||
// ignore local player or camera
|
||||
if ( (ct.Owner.player == CPlayer) || (ct.Owner == cam) ) continue;
|
||||
// ignore trackers not of this player
|
||||
if ( ct.myplayer != CPlayer ) continue;
|
||||
// ignore trackers clearly outside of player view
|
||||
Vector3 smpos = level.Vec3Offset(SWWMUtility.LerpVector3(ct.Owner.prev,ct.Owner.pos,fractic),(0,0,ct.lvheight));
|
||||
Vector3 tdir = level.Vec3Diff(viewpos,smpos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs1;
|
||||
if ( !SWWMUtility.TestScreenBounds(projdata,vpos) ) continue;
|
||||
double fin = clamp(ct.fadein+fractic,0.,5.)/5.;
|
||||
double fout = clamp(ct.lifespan-fractic,0.,25.)/25.;
|
||||
double alph = fin*fout;
|
||||
Vector2 barpos = vpos-(27,7);
|
||||
Font fnt = swwm_bigtags?mSmallFontOutline:mTinyFontOutline;
|
||||
int col = Font.CR_WHITE;
|
||||
if ( teamplay )
|
||||
{
|
||||
int team = targ.myplayer.GetTeam();
|
||||
int team = ct.Owner.player.GetTeam();
|
||||
if ( team != -1 ) col = Font.FindFontColor(Teams[team].mName); // this works in practice because team names are the same as their text colors
|
||||
if ( col == -1 ) col = Font.CR_WHITE;
|
||||
}
|
||||
if ( swwm_targettags || targ.myplayer && (tag != "") )
|
||||
Screen.DrawText(fnt,col,(barpos.x+barsiz.x/2.-(fnt.StringWidth(tag)*hs1)/2.)/hs1,(barpos.y-fnt.GetHeight()*hs1)/hs1,tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
Screen.DrawTexture(EnemyBTex,false,barpos.x/hs1,barpos.y/hs1,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
double ht = clamp(targ.intp.GetValue(),0,targ.maxhealth*100);
|
||||
double hw = (min(ht,targ.maxhealth)*50.)/targ.maxhealth;
|
||||
if ( targ.mytarget && (targ.mytarget.bInvulnerable || (targ.myplayer && (targ.myplayer.cheats&(CF_GODMODE|CF_GODMODE2))) || targ.mytarget.FindInventory("InvinciballPower")) )
|
||||
Screen.DrawText(fnt,col,vpos.x-fnt.StringWidth(ct.mytag)/2,barpos.y-(fnt.GetHeight()+2),ct.mytag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
Screen.DrawTexture(EnemyBTex,false,barpos.x,barpos.y,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
double ht = clamp(ct.intp.GetValue(fractic),0,ct.maxhealth*100);
|
||||
double hw = (ht*50.)/ct.maxhealth;
|
||||
double ohw = hw;
|
||||
if ( ct.Owner.bINVULNERABLE || (ct.Owner.player.cheats&(CF_GODMODE|CF_GODMODE2)) || ct.Owner.FindInventory("InvinciballPower") )
|
||||
Screen.DrawTexture(EnemyHTex[1],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
else
|
||||
{
|
||||
Screen.DrawTexture(EnemyHTex[4],false,(barpos.x+2*hs1)/hs1,(barpos.y+2*hs1)/hs1,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
Screen.DrawTexture(EnemyHTex[0],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
if ( ht > ct.maxhealth )
|
||||
{
|
||||
hw = (min(ht-ct.maxhealth,ct.maxhealth)*50.)/ct.maxhealth;
|
||||
Screen.DrawTexture(EnemyHTex[3],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
}
|
||||
if ( ht > ct.maxhealth*2 )
|
||||
{
|
||||
hw = (min(ht-ct.maxhealth*2,ct.maxhealth*3)*50.)/ct.maxhealth;
|
||||
Screen.DrawTexture(EnemyHTex[4],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
}
|
||||
if ( ht > ct.maxhealth*5 )
|
||||
{
|
||||
hw = (min(ht-ct.maxhealth*5,ct.maxhealth*5)*50.)/ct.maxhealth;
|
||||
Screen.DrawTexture(EnemyHTex[5],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
}
|
||||
}
|
||||
if ( ct.Owner.FindInventory("DivineSpriteEffect") )
|
||||
{
|
||||
double falph = clamp((ht-ct.maxhealth*10)/(ct.maxhealth*60.),0.,1.);
|
||||
Screen.DrawTexture(EnemyHTex[6],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph*falph,DTA_LegacyRenderStyle,STYLE_Add);
|
||||
}
|
||||
else
|
||||
{
|
||||
Screen.DrawTexture(EnemyHTex[0],false,(barpos.x+2*hs1)/hs1,(barpos.y+2*hs1)/hs1,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
if ( ht > targ.maxhealth )
|
||||
{
|
||||
hw = (min(ht-targ.maxhealth,targ.maxhealth)*50.)/targ.maxhealth;
|
||||
Screen.DrawTexture(EnemyHTex[1],false,(barpos.x+2*hs1)/hs1,(barpos.y+2*hs1)/hs1,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
}
|
||||
if ( ht > targ.maxhealth*2 )
|
||||
{
|
||||
hw = (min(ht-targ.maxhealth*2,targ.maxhealth*3)*50.)/(targ.maxhealth*3);
|
||||
Screen.DrawTexture(EnemyHTex[2],false,(barpos.x+2*hs1)/hs1,(barpos.y+2*hs1)/hs1,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
}
|
||||
if ( ht > targ.maxhealth*5 )
|
||||
{
|
||||
hw = (min(ht-targ.maxhealth*5,targ.maxhealth*5)*50.)/(targ.maxhealth*5);
|
||||
Screen.DrawTexture(EnemyHTex[3],false,(barpos.x+2*hs1)/hs1,(barpos.y+2*hs1)/hs1,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRightF,hw);
|
||||
}
|
||||
}
|
||||
if ( targ.mytarget && targ.mytarget.FindInventory("DivineSpriteEffect") )
|
||||
{
|
||||
double falph = clamp((ht-targ.maxhealth*10)/(targ.maxhealth*60.),0.,1.);
|
||||
Screen.DrawTexture(EnemyHTex[5],false,(barpos.x+2*hs1)/hs1,(barpos.y+2*hs1)/hs1,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph*falph,DTA_LegacyRenderStyle,STYLE_Add);
|
||||
ht = clamp(ct.intpl.GetValue(fractic),0,ct.maxhealth);
|
||||
hw = (ht*50.)/ct.maxhealth;
|
||||
Screen.DrawTexture(EnemyHTex[2],false,barpos.x+2,barpos.y+2,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowLeftF,ohw,DTA_WindowRightF,hw);
|
||||
}
|
||||
if ( ct.cummdamage <= 0 ) continue;
|
||||
double calph = clamp(ct.cummspan-fractic,0.,20.)/20.;
|
||||
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_RED],barpos.x+3,barpos.y+10,(ct.cummdamage>=Actor.TELEFRAG_DAMAGE)?"∞":String.Format("%d",ct.cummdamage),DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,calph*alph);
|
||||
if ( ct.cummflash <= 0 ) continue;
|
||||
double falph = max((ct.cummflash-FracTic)/15.,0.)**1.5;
|
||||
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_REDFLASH],barpos.x+3,barpos.y+10,String.Format("%d",ct.cummdamage),DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,falph*calph*alph,DTA_LegacyRenderStyle,STYLE_Add);
|
||||
}
|
||||
// floating kill scores and others
|
||||
for ( int i=0; i<scoreobjs.Size(); i++ )
|
||||
}
|
||||
|
||||
private void DrawNumbers( Vector3 viewvec, out bool projinit )
|
||||
{
|
||||
SWWMDamNum snum = hnd.damnums;
|
||||
if ( !snum ) return;
|
||||
do
|
||||
{
|
||||
let snum = scoreobjs[i];
|
||||
if ( !snum ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+level.Vec3Diff(ViewPos,snum.pos));
|
||||
// this ensures that projection data isn't cached if there are no target array elements, to avoid needless GC thrashing
|
||||
if ( !projinit )
|
||||
{
|
||||
projinit = true;
|
||||
SWWMUtility.PrepareProjData(projdata,ViewPos,ViewRot.x,ViewRot.y,ViewRot.z,players[consoleplayer].fov);
|
||||
Screen.SetClipRect(projdata.viewx,projdata.viewy,projdata.vieww,projdata.viewh);
|
||||
}
|
||||
Vector3 tdir = level.Vec3Diff(ViewPos,snum.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
||||
tag = String.Format("%+d",snum.score);
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs;
|
||||
String tag = abs(snum.damage>=Actor.TELEFRAG_DAMAGE)?(snum.damage>0)?"-∞":"+∞":String.Format("%+d",-snum.damage);
|
||||
double alph = clamp((snum.lifespan+fractic)/35.,0.,1.);
|
||||
Vector2 fo;
|
||||
int initspd = (128-snum.seed);
|
||||
int boostup = 64+snum.seed2;
|
||||
fo.x = (.05*initspd)*((snum.initialspan-(snum.lifespan-fractic))**.8);
|
||||
fo.y = -((snum.initialspan-(snum.lifespan-fractic))**1.5)+boostup*sin((90./snum.initialspan)*(level.maptime+fractic-snum.starttic));
|
||||
Screen.DrawText(MiniHUDFontOutline,snum.tcolor,(vpos.x-fo.x)-(MiniHUDFontOutline.StringWidth(tag))/2,(vpos.y-fo.y)-(MiniHUDFontOutline.GetHeight())/2,tag,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
}
|
||||
while ( snum = snum.next );
|
||||
}
|
||||
|
||||
private void DrawScores( Vector3 viewvec, out bool projinit )
|
||||
{
|
||||
SWWMScoreObj snum = hnd.scorenums;
|
||||
if ( !snum ) return;
|
||||
do
|
||||
{
|
||||
// this ensures that projection data isn't cached if there are no target array elements, to avoid needless GC thrashing
|
||||
if ( !projinit )
|
||||
{
|
||||
projinit = true;
|
||||
SWWMUtility.PrepareProjData(projdata,ViewPos,ViewRot.x,ViewRot.y,ViewRot.z,players[consoleplayer].fov);
|
||||
Screen.SetClipRect(projdata.viewx,projdata.viewy,projdata.vieww,projdata.viewh);
|
||||
}
|
||||
Vector3 tdir = level.Vec3Diff(ViewPos,snum.pos);
|
||||
if ( viewvec dot tdir < 0 ) continue;
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs1;
|
||||
String tag = String.Format("%+d",snum.score);
|
||||
double alph = clamp((snum.lifespan+fractic)/double(GameTicRate),0.,1.);
|
||||
Vector2 fo = (0,0);
|
||||
bool isscore = false;
|
||||
if ( snum.damnum )
|
||||
{
|
||||
if ( snum.score < 0 )
|
||||
{
|
||||
// damage falls down
|
||||
int initspd = (128-snum.seed);
|
||||
int boostup = 64+snum.seed2;
|
||||
fo.x = (.05*initspd)*((snum.initialspan-(snum.lifespan-fractic))**.8);
|
||||
fo.y = -((snum.initialspan-(snum.lifespan-fractic))**1.5)+boostup*sin((90./snum.initialspan)*(level.maptime+fractic-snum.starttic));
|
||||
}
|
||||
else
|
||||
{
|
||||
// health falls up (?)
|
||||
int initspd = (128-snum.seed);
|
||||
int boostup = 16+snum.seed2/4;
|
||||
fo.x = (.15*initspd)*((snum.initialspan-(snum.lifespan-fractic))**.6);
|
||||
fo.y = ((snum.initialspan-(snum.lifespan-fractic))**1.2)-boostup*sin((90./snum.initialspan)*(level.maptime+fractic-snum.starttic));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// score rises linearly
|
||||
fo.y = snum.initialspan-(snum.lifespan-fractic);
|
||||
isscore = true;
|
||||
}
|
||||
double hs0 = isscore?hs1:hs;
|
||||
Vector2 ss0 = isscore?ss1:ss;
|
||||
Screen.DrawText(mTinyFont,snum.tcolor,(vpos.x-hs0*(fo.x+mTinyFont.StringWidth(tag)/2.))/hs0,(vpos.y-hs0*(fo.y+(mTinyFont.GetHeight()/2.)))/hs0,tag,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
// score rises linearly
|
||||
Vector2 fo = (0,snum.initialspan-(snum.lifespan-fractic));
|
||||
Screen.DrawText(mTinyFontOutline,snum.tcolor,vpos.x-(fo.x+mTinyFontOutline.StringWidth(tag)/2.),vpos.y-(fo.y+(mTinyFontOutline.GetHeight()/2.)),tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
// extra strings (if available)
|
||||
fo.y += mTinyFont.GetHeight();
|
||||
fo.y += mTinyFontOutline.GetHeight();
|
||||
for ( int i=0; i<snum.xstr.Size(); i++ )
|
||||
{
|
||||
tag = snum.xstr[i];
|
||||
if ( snum.xscore[i] == int.max ) tag.AppendFormat(" MAX");
|
||||
else if ( snum.xscore[i] > 0 ) tag.AppendFormat(" x%d",snum.xscore[i]);
|
||||
Screen.DrawText(mTinyFont,snum.xtcolor[i],(vpos.x-hs1*(fo.x+mTinyFont.StringWidth(tag)/2.))/hs1,(vpos.y-hs1*(fo.y+(mTinyFont.GetHeight()/2.)))/hs1,tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
fo.y += mTinyFont.GetHeight();
|
||||
Screen.DrawText(mTinyFontOutline,snum.xtcolor[i],vpos.x-(fo.x+mTinyFontOutline.StringWidth(tag)/2.),vpos.y-(fo.y+(mTinyFontOutline.GetHeight()/2.)),tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
||||
fo.y += mTinyFontOutline.GetHeight();
|
||||
}
|
||||
}
|
||||
while ( snum = snum.next );
|
||||
}
|
||||
|
||||
private void DrawTarget()
|
||||
{
|
||||
// don't draw when dead or with automap open
|
||||
if ( (CPlayer.health <= 0) || automapactive ) return;
|
||||
bool projinit = false;
|
||||
Vector3 viewvec = SWWMUtility.Vec3FromAngles(viewrot.x,viewrot.y);
|
||||
// points of interest
|
||||
if ( level.allmap && swwm_pois ) DrawInterest(viewvec,projinit);
|
||||
// sensed items
|
||||
DrawItemSense(viewvec,projinit);
|
||||
// targetting array
|
||||
if ( swwm_targeter ) DrawTrackers(viewvec,projinit);
|
||||
// floating kill scores and others
|
||||
if ( swwm_damnums ) DrawNumbers(viewvec,projinit);
|
||||
if ( swwm_scorenums ) DrawScores(viewvec,projinit);
|
||||
Screen.ClearClipRect();
|
||||
}
|
||||
|
||||
override void DrawMyPos()
|
||||
{
|
||||
String str = String.Format("(%d,%d,%d)",CPlayer.mo.pos.X,CPlayer.mo.pos.Y,CPlayer.mo.pos.Z);
|
||||
Screen.DrawText(mTinyFont,Font.CR_GREEN,(ss.x-mTinyFont.StringWidth(str))/2,4,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
||||
Screen.DrawText(mTinyFontOutline,Font.CR_GREEN,(ss.x-mTinyFontOutline.StringWidth(str))/2,4,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
||||
}
|
||||
|
||||
override void DrawAutomapHUD( double ticFrac )
|
||||
|
|
@ -2377,8 +2235,8 @@ Class SWWMStatusBar : BaseStatusBar
|
|||
if ( iof != -1 ) ln.Truncate(iof);
|
||||
if ( !label || ((level.clusterflags&level.CLUSTER_HUB) && (label == 2)) ) str = ln;
|
||||
else str = String.Format("%s - %s",level.mapname.MakeUpper(),ln);
|
||||
Screen.DrawText(mBigFont,tclabel,xx-mBigFont.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
||||
yy += mBigFont.GetHeight()+4;
|
||||
Screen.DrawText(mSmallFontOutline,tclabel,xx-mSmallFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
||||
yy += mSmallFontOutline.GetHeight()+4;
|
||||
}
|
||||
if ( (level.total_monsters > 0) && am_showmonsters && !deathmatch )
|
||||
{
|
||||
|
|
@ -3171,7 +3029,7 @@ Class SWWMStatusBar : BaseStatusBar
|
|||
|
||||
override bool DrawPaused( int player )
|
||||
{
|
||||
let fnt = mBigFont?mBigFont:NewSmallFont;
|
||||
let fnt = mSmallFontOutline?mSmallFontOutline:NewSmallFont;
|
||||
let fnt2 = mSmallFont?mSmallFont:NewConsoleFont;
|
||||
if ( swwm_fuzz )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,14 +1,6 @@
|
|||
// hud-related storage objects
|
||||
// (used to be thinkers, but this might be lighter on performance)
|
||||
|
||||
Enum EScoreObjType
|
||||
{
|
||||
ST_Score,
|
||||
ST_Damage,
|
||||
ST_Health,
|
||||
ST_Armor
|
||||
};
|
||||
|
||||
// floating scores
|
||||
Class SWWMScoreObj play
|
||||
{
|
||||
|
|
@ -21,65 +13,27 @@ Class SWWMScoreObj play
|
|||
int lifespan, initialspan;
|
||||
int starttic, seed, seed2;
|
||||
SWWMScoreObj next;
|
||||
bool damnum;
|
||||
Actor acc;
|
||||
|
||||
static SWWMScoreObj Spawn( int score, Vector3 pos, int type = ST_Score, int tcolor = -1 )
|
||||
static SWWMScoreObj Spawn( int score, Vector3 pos, int tcolor = -1 )
|
||||
{
|
||||
// early checks
|
||||
if ( (type == ST_SCORE) && !swwm_scorenums ) return null;
|
||||
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,tcolor);
|
||||
return SpawnFromHandler(hnd,score,pos,tcolor);
|
||||
}
|
||||
|
||||
static SWWMScoreObj SpawnFromHandler( SWWMHandler hnd, int score, Vector3 pos, int type = ST_Score, 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,tcolor);
|
||||
}
|
||||
|
||||
private static SWWMScoreObj SpawnInternal( SWWMHandler hnd, int score, Vector3 pos, int type = ST_Score, int tcolor = -1 )
|
||||
static SWWMScoreObj SpawnFromHandler( SWWMHandler hnd, int score, Vector3 pos, int tcolor = -1 )
|
||||
{
|
||||
let o = new("SWWMScoreObj");
|
||||
o.score = score;
|
||||
o.pos = pos;
|
||||
o.lifespan = o.initialspan = 60;
|
||||
if ( tcolor != -1 ) o.tcolor = tcolor;
|
||||
else switch ( type )
|
||||
{
|
||||
case ST_Score:
|
||||
o.tcolor = Font.CR_GOLD;
|
||||
break;
|
||||
case ST_Damage:
|
||||
o.tcolor = Font.CR_RED;
|
||||
break;
|
||||
case ST_Health:
|
||||
o.tcolor = Font.CR_GREEN;
|
||||
break;
|
||||
case ST_Armor:
|
||||
o.tcolor = Font.CR_BLUE;
|
||||
break;
|
||||
}
|
||||
else o.tcolor = Font.CR_GOLD;
|
||||
o.starttic = level.maptime;
|
||||
o.seed = Random[ScoreBits]();
|
||||
o.seed2 = Random[ScoreBits]();
|
||||
o.damnum = (type > ST_Score);
|
||||
if ( o.damnum )
|
||||
{
|
||||
o.next = hnd.damnums;
|
||||
hnd.damnums = o;
|
||||
hnd.damnums_cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
o.next = hnd.scorenums;
|
||||
hnd.scorenums = o;
|
||||
hnd.scorenums_cnt++;
|
||||
}
|
||||
o.next = hnd.scorenums;
|
||||
hnd.scorenums = o;
|
||||
return o;
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +51,51 @@ Class SWWMScoreObj play
|
|||
}
|
||||
}
|
||||
|
||||
// damage/health/armor numbers
|
||||
Class SWWMDamNum play
|
||||
{
|
||||
int tcolor;
|
||||
int damage;
|
||||
Vector3 pos;
|
||||
int lifespan, initialspan;
|
||||
int starttic, seed, seed2;
|
||||
SWWMDamNum next;
|
||||
|
||||
static SWWMDamNum Spawn( int damage, Vector3 pos, Name type = '' )
|
||||
{
|
||||
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
||||
if ( !hnd ) return null;
|
||||
return SpawnFromHandler(hnd,damage,pos,type);
|
||||
}
|
||||
|
||||
static SWWMDamNum SpawnFromHandler( SWWMHandler hnd, int damage, Vector3 pos, Name type = '' )
|
||||
{
|
||||
let o = new("SWWMDamNum");
|
||||
o.damage = damage;
|
||||
o.pos = pos;
|
||||
o.tcolor = Font.FindFontColor("MiniRed");
|
||||
if ( !hnd.usedamcolors ) hnd.usedamcolors = CVar.FindCVar('swwm_damnums_color');
|
||||
if ( hnd.usedamcolors.GetBool() ) for ( int i=0; i<hnd.damtypes.Size(); i++ )
|
||||
{
|
||||
if ( hnd.damtypes[i] != type ) continue;
|
||||
o.tcolor = Font.FindFontColor(hnd.damcolors[i]);
|
||||
break;
|
||||
}
|
||||
o.lifespan = o.initialspan = 60;
|
||||
o.starttic = level.maptime;
|
||||
o.seed = Random[ScoreBits]();
|
||||
o.seed2 = Random[ScoreBits]();
|
||||
o.next = hnd.damnums;
|
||||
hnd.damnums = o;
|
||||
return o;
|
||||
}
|
||||
bool Tick()
|
||||
{
|
||||
lifespan--;
|
||||
return (lifespan <= 0);
|
||||
}
|
||||
}
|
||||
|
||||
enum EInterestType
|
||||
{
|
||||
INT_Key,
|
||||
|
|
@ -167,7 +166,6 @@ Class SWWMInterest play
|
|||
i.pos = thekey?thekey.Vec3Offset(0,0,thekey.height/2):pos;
|
||||
i.next = hnd.intpoints;
|
||||
hnd.intpoints = i;
|
||||
hnd.intpoints_cnt++;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +225,6 @@ Class SWWMItemSense play
|
|||
i.pos = item.Vec3Offset(0,0,item.height);
|
||||
i.next = parent.itemsense;
|
||||
parent.itemsense = i;
|
||||
parent.itemsense_cnt++;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -250,196 +247,6 @@ Class SWWMItemSense play
|
|||
}
|
||||
}
|
||||
|
||||
// enemy combat tracker
|
||||
Class SWWMCombatTracker play
|
||||
{
|
||||
Actor mytarget;
|
||||
String mytag;
|
||||
int updated, lasthealth, maxhealth;
|
||||
DynamicValueInterpolator intp;
|
||||
Vector3 pos, prevpos, oldpos, oldprev;
|
||||
PlayerInfo myplayer;
|
||||
SWWMCombatTracker next;
|
||||
bool legged, mutated;
|
||||
int tcnt;
|
||||
double height;
|
||||
int dbar;
|
||||
bool bBOSS, bFRIENDLY;
|
||||
bool firsthit;
|
||||
bool bUpdateMorph;
|
||||
String unmorphedtag;
|
||||
|
||||
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(hnd,mytarget,FallbackTag):mytarget.GetTag(FallbackTag);
|
||||
if ( realtag == FallbackTag )
|
||||
{
|
||||
realtag = mytarget.GetClassName();
|
||||
SWWMUtility.BeautifyClassName(realtag);
|
||||
}
|
||||
mytag = mytarget.player?(mytarget.player.mo!=mytarget)?String.Format(StringTable.Localize("$FN_VOODOO"),mytarget.player.GetUserName()):mytarget.player.GetUserName():((mytarget is 'PlayerPawn')&&(!mytarget.player))?StringTable.Localize("$FN_VOODOO_NP"):realtag;
|
||||
}
|
||||
else mytag = "";
|
||||
}
|
||||
|
||||
static SWWMCombatTracker Spawn( SWWMHandler hnd, Actor target, bool update = false )
|
||||
{
|
||||
// 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
|
||||
SWWMCombatTracker t;
|
||||
if ( update ) for ( t=hnd.trackers; t; t=t.next )
|
||||
{
|
||||
if ( t.mytarget != target ) continue;
|
||||
return t;
|
||||
}
|
||||
t = new("SWWMCombatTracker");
|
||||
t.mytarget = target;
|
||||
t.UpdateTag(hnd);
|
||||
if ( target.player )
|
||||
{
|
||||
t.lasthealth = target.health;
|
||||
t.maxhealth = target.default.health;
|
||||
}
|
||||
else t.lasthealth = t.maxhealth = target.health;
|
||||
t.updated = int.min;
|
||||
t.height = target.height;
|
||||
t.pos = level.Vec3Offset(target.pos,(0,0,t.height));
|
||||
t.prevpos = level.Vec3Offset(target.prev,(0,0,t.height));
|
||||
t.oldpos = target.pos;
|
||||
t.oldprev = target.prev;
|
||||
t.intp = DynamicValueInterpolator.Create(t.lasthealth,.5,1,100);
|
||||
t.myplayer = target.player;
|
||||
t.next = hnd.trackers;
|
||||
t.bBOSS = target.bBOSS;
|
||||
t.bFRIENDLY = target.IsFriend(players[consoleplayer].mo);
|
||||
hnd.trackers = t;
|
||||
hnd.trackers_cnt++;
|
||||
return t;
|
||||
}
|
||||
|
||||
bool Tick()
|
||||
{
|
||||
// is target gone or dead?
|
||||
if ( !mytarget || (mytarget.Health <= 0) )
|
||||
{
|
||||
// we're done
|
||||
if ( updated > level.maptime ) updated = level.maptime;
|
||||
lasthealth = 0;
|
||||
prevpos = pos; // prevent stuttering
|
||||
intp.Update(lasthealth);
|
||||
if ( level.maptime > updated+35 ) return true;
|
||||
return false;
|
||||
}
|
||||
// don't update dormant targets
|
||||
if ( mytarget.bDORMANT )
|
||||
return false;
|
||||
// only update height/position while alive
|
||||
bool heightchanged = false;
|
||||
if ( height != mytarget.height ) heightchanged = true;
|
||||
height = mytarget.height;
|
||||
if ( heightchanged || (mytarget.pos != oldpos) || (mytarget.prev != oldprev) )
|
||||
{
|
||||
oldpos = mytarget.pos;
|
||||
oldprev = mytarget.prev;
|
||||
pos = level.Vec3Offset(mytarget.pos,(0,0,height));
|
||||
prevpos = level.Vec3Offset(mytarget.prev,(0,0,height));
|
||||
}
|
||||
if ( bUpdateMorph && !(mytarget is 'MorphedMonster') )
|
||||
{
|
||||
// reset our tag
|
||||
mytag = unmorphedtag;
|
||||
bUpdateMorph = false;
|
||||
}
|
||||
tcnt++;
|
||||
if ( (tcnt == 1) && !mytarget.player )
|
||||
{
|
||||
// post-spawn health inflation check
|
||||
if ( lasthealth > maxhealth )
|
||||
{
|
||||
maxhealth = lasthealth;
|
||||
intp.Reset(lasthealth);
|
||||
}
|
||||
// post-spawn morph check
|
||||
if ( (mytarget is 'MorphedMonster') && MorphedMonster(mytarget).UnmorphedMe )
|
||||
{
|
||||
// look for a previous tracker that has the same target as us
|
||||
for ( SWWMCombatTracker t=next; t; t=t.next )
|
||||
{
|
||||
if ( t.mytarget != mytarget ) continue;
|
||||
// change its tag and destroy ourselves (such is life)
|
||||
t.bUpdateMorph = true;
|
||||
t.unmorphedtag = t.mytag;
|
||||
t.mytag = String.Format("%s (%s)",mytag,t.unmorphedtag);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( (tcnt == 6) && !mytarget.player )
|
||||
{
|
||||
// legendoom check
|
||||
for ( Inventory i=mytarget.inv; i; i=i.inv )
|
||||
{
|
||||
if ( i.GetClassName() != "LDLegendaryMonsterToken" ) continue;
|
||||
legged = true;
|
||||
// adjust for health inflation
|
||||
if ( lasthealth > maxhealth )
|
||||
{
|
||||
maxhealth = lasthealth;
|
||||
intp.Reset(lasthealth);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( legged && !mutated )
|
||||
{
|
||||
// check inventory regularly to mark as mutated
|
||||
for ( Inventory i=mytarget.inv; i; i=i.inv )
|
||||
{
|
||||
if ( i.GetClassName() != "LDLegendaryMonsterTransformed" ) continue;
|
||||
mutated = true;
|
||||
Console.Printf(StringTable.Localize("$SWWM_LTFORM"),mytag);
|
||||
}
|
||||
}
|
||||
// voodoo dolls don't show as friendly
|
||||
bFRIENDLY = mytarget.IsFriend(players[consoleplayer].mo);
|
||||
if ( mytarget.Health < lasthealth ) firsthit = true;
|
||||
lasthealth = mytarget.Health;
|
||||
intp.Update(lasthealth);
|
||||
// special update conditions
|
||||
if ( dbar && !mytarget.player )
|
||||
{
|
||||
if ( (dbar == 2) && (lasthealth >= maxhealth) )
|
||||
return false;
|
||||
else if ( (dbar == 1) && !firsthit )
|
||||
return false;
|
||||
}
|
||||
if ( (mytarget.bISMONSTER || mytarget.player) && !mytarget.bINVISIBLE && !mytarget.bCORPSE )
|
||||
{
|
||||
// players (but not voodoo dolls), always if friendly, otherwise only update if visible
|
||||
if ( mytarget.player && (mytarget.player.mo == mytarget) )
|
||||
{
|
||||
if ( mytarget.IsFriend(players[consoleplayer].mo) ) updated = level.maptime+35;
|
||||
else if ( players[consoleplayer].Camera.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
|
||||
updated = level.maptime;
|
||||
}
|
||||
// friendlies within a set distance
|
||||
else if ( mytarget.bFRIENDLY && players[consoleplayer].Camera.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime+35;
|
||||
// enemies within a set distance that have us as target
|
||||
else if ( mytarget.target && (mytarget.target.Health > 0) && (mytarget.target.player == players[consoleplayer]) && players[consoleplayer].Camera.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime+70;
|
||||
// any visible enemies within one quarter of the set distance
|
||||
else if ( players[consoleplayer].Camera.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime;
|
||||
}
|
||||
else if ( (mytarget is 'BossBrain') || (mytarget is 'SWWMHangingKeen') )
|
||||
{
|
||||
// special stuff, only if visible
|
||||
if ( players[consoleplayer].Camera.CheckSight(mytarget,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) updated = level.maptime;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ultralight trackers for certain things
|
||||
Class SWWMSimpleTracker play
|
||||
{
|
||||
|
|
@ -539,7 +346,6 @@ Class SWWMSimpleTracker play
|
|||
t.Update();
|
||||
t.next = hnd.strackers;
|
||||
hnd.strackers = t;
|
||||
hnd.strackers_cnt++;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,6 @@ Class SWWMArmor : Armor abstract
|
|||
int tgive = 0;
|
||||
while ( (amount <= (MaxAmount-default.Amount)) && (Owner.CountInv(parent) > 0) )
|
||||
{
|
||||
SWWMScoreObj.Spawn(default.Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor);
|
||||
Amount += default.Amount;
|
||||
Owner.TakeInventory(parent,1);
|
||||
// absorb the extra damage too
|
||||
|
|
@ -142,7 +141,6 @@ Class SWWMSpareArmor : Inventory abstract
|
|||
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
|
||||
Owner.GiveInventory(giveme,GetDefaultByType(giveme).Amount);
|
||||
SWWMHandler.ArmorFlash(Owner.PlayerNumber());
|
||||
SWWMScoreObj.Spawn(GetDefaultByType(giveme).Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ Class SWWMHealth : Inventory abstract
|
|||
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
|
||||
SWWMHandler.HealthFlash(Owner.PlayerNumber());
|
||||
Owner.GiveInventory(giveme,GetDefaultByType(giveme).Amount);
|
||||
SWWMScoreObj.Spawn(GetDefaultByType(giveme).Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
AutoUseExtra(false);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -119,7 +118,6 @@ Class SWWMHealth : Inventory abstract
|
|||
bool morethanonce = false;
|
||||
while ( (Amount > 0) && (newdamage > 0) )
|
||||
{
|
||||
SWWMScoreObj.Spawn(GetDefaultByType(giveme).Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
newdamage = newdamage-GetDefaultByType(giveme).Amount;
|
||||
if ( newdamage < 0 ) Owner.GiveBody(-newdamage,GetDefaultByType(giveme).MaxAmount);
|
||||
newdamage = max(0,newdamage);
|
||||
|
|
|
|||
|
|
@ -294,11 +294,7 @@ Class KirinPlushGesture : SWWMItemGesture
|
|||
s.pitch = FRandom[ExploS](-90,90);
|
||||
}
|
||||
int givehp = (Health<=25)?25:(Health<=50)?15:(Health<=100)?10:5;
|
||||
if ( GiveBody(givehp,200) )
|
||||
{
|
||||
SWWMScoreObj.Spawn(givehp,Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Height/2),ST_Health);
|
||||
SWWMHandler.DoFlash(self,Color(32,224,128,255),10);
|
||||
}
|
||||
if ( GiveBody(givehp,200) ) SWWMHandler.DoFlash(self,Color(32,224,128,255),10);
|
||||
}
|
||||
action void A_KirinGiggle()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ Class RefresherRegen : Powerup
|
|||
Super.DoEffect();
|
||||
if ( !Owner || (Owner.health <= 0) || ((EffectTics-5)%175) ) return;
|
||||
if ( !Owner.GiveBody(int(Strength),500) ) return;
|
||||
SWWMScoreObj.Spawn(int(Strength),Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
SWWMHandler.DoFlash(Owner,Color(32,224,128,255),10);
|
||||
Owner.A_StartSound("powerup/refresher",CHAN_ITEMEXTRA,CHANF_LOCAL|CHANF_OVERLAP,.4);
|
||||
if ( Owner is 'Demolitionist' )
|
||||
|
|
|
|||
|
|
@ -42,12 +42,8 @@ Class GrilledCheeseSandwich : Inventory
|
|||
SWWMHandler.DoFlash(Owner,Color(64,255,255,64),10);
|
||||
Owner.A_QuakeEx(9,9,9,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
|
||||
Owner.GiveBody(1000,1000);
|
||||
SWWMScoreObj.Spawn(1000,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
if ( Owner is 'Demolitionist' )
|
||||
{
|
||||
SWWMScoreObj.Spawn(200,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor);
|
||||
SWWMScoreObj.Spawn(150,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor);
|
||||
SWWMScoreObj.Spawn(250,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor);
|
||||
let n = Owner.FindInventory("ArmorNugget");
|
||||
if ( !n ) Owner.GiveInventory("ArmorNugget",GetDefaultByType("ArmorNugget").MaxAmount);
|
||||
else n.Amount = n.MaxAmount;
|
||||
|
|
@ -1088,8 +1084,7 @@ Class RagekitPower : Powerup
|
|||
if ( !(level.maptime%30) )
|
||||
{
|
||||
SWWMHandler.DoFlash(Owner,Color(16,255,0,0),5);
|
||||
if ( Owner.GiveBody(1,100) )
|
||||
SWWMScoreObj.Spawn(1,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
Owner.GiveBody(1,100);
|
||||
Owner.A_AlertMonsters(swwm_uncapalert?0:2000);
|
||||
if ( (Owner.player == players[consoleplayer]) && (gametic > lastrage) && (swwm_mutevoice < 2) )
|
||||
lastrage = SWWMHandler.AddOneliner("ragekit",2,5)+20;
|
||||
|
|
@ -1121,8 +1116,7 @@ Class RagekitPower : Powerup
|
|||
void DoHitFX()
|
||||
{
|
||||
if ( level.maptime <= lasteffect+5 ) return;
|
||||
if ( Owner.GiveBody(5,100) )
|
||||
SWWMScoreObj.Spawn(5,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
Owner.GiveBody(5,100);
|
||||
Owner.A_AlertMonsters(swwm_uncapalert?0:5000);
|
||||
SWWMHandler.DoFlash(Owner,Color(64,255,0,0),10);
|
||||
Owner.A_QuakeEx(8,8,8,Random[Rage](3,8),0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
|
||||
|
|
@ -1165,8 +1159,7 @@ Class Ragekit : Inventory
|
|||
{
|
||||
if ( pickup && !deathmatch ) return false;
|
||||
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
|
||||
if ( Owner.GiveBody(100,100) )
|
||||
SWWMScoreObj.Spawn(100,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
Owner.GiveBody(100,100);
|
||||
SWWMUtility.AchievementProgressInc("rage",1,Owner.player);
|
||||
if ( !(Owner is 'Demolitionist') )
|
||||
{
|
||||
|
|
@ -3117,8 +3110,7 @@ Class SafetyTether : Inventory
|
|||
}
|
||||
SWWMHandler.DoFlash(Owner,Color(255,255,255,255),10);
|
||||
SWWMHandler.DoFlash(Owner,Color(255,128,192,255),30);
|
||||
if ( Owner.GiveBody(100,100) )
|
||||
SWWMScoreObj.Spawn(100,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
Owner.GiveBody(100,100);
|
||||
SWWMUtility.AchievementProgressInc("sneaky",1,Owner.player);
|
||||
Amount--;
|
||||
if ( Amount <= 0 ) DepleteOrDestroy();
|
||||
|
|
@ -3577,7 +3569,6 @@ Class DivineSpriteEffect : Inventory
|
|||
{
|
||||
healcnt = 0;
|
||||
Owner.GiveBody(1000,1000);
|
||||
SWWMScoreObj.Spawn(1000,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
SWWMHandler.DoFlash(Owner,Color(40,255,255,255),20);
|
||||
if ( Owner is 'Demolitionist' )
|
||||
Demolitionist(Owner).lastbump *= 0.97;
|
||||
|
|
@ -3586,7 +3577,6 @@ Class DivineSpriteEffect : Inventory
|
|||
else if ( !(healcnt%5) )
|
||||
{
|
||||
Owner.GiveBody(500,10000);
|
||||
SWWMScoreObj.Spawn(100,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
SWWMHandler.DoFlash(Owner,Color(10,255,255,255),10);
|
||||
Owner.A_StartSound("powerup/divinehit",CHAN_ITEMEXTRA,CHANF_OVERLAP);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,6 +203,132 @@ Class SWWMFlyTracker : Inventory
|
|||
}
|
||||
}
|
||||
|
||||
// very lightweight combat tracker, more Souls-y
|
||||
Class SWWMQuickCombatTracker : Inventory
|
||||
{
|
||||
int lifespan, lasthealth, maxhealth;
|
||||
int laghealth[10];
|
||||
int cummdamage, cummspan, cummflash; // please do not misread
|
||||
int fadein; // used for the hud
|
||||
double lvheight; // height while alive (used by the hud for positioning)
|
||||
SmoothDynamicValueInterpolator intp;
|
||||
SmoothLinearValueInterpolator intpl;
|
||||
PlayerInfo myplayer; // for multiplayer compatibility (this breaks inventory logic, but alas...)
|
||||
String mytag;
|
||||
|
||||
void UpdateTag( SWWMHandler hnd )
|
||||
{
|
||||
if ( Owner && (Owner.player || Owner.bISMONSTER || (Owner is 'BossBrain') || (Owner is 'SWWMHangingKeen') || (Owner is 'Demolitionist')) )
|
||||
{
|
||||
String realtag = swwm_funtags?SWWMUtility.GetFunTag(hnd,Owner,FallbackTag):Owner.GetTag(FallbackTag);
|
||||
if ( realtag == FallbackTag )
|
||||
{
|
||||
realtag = Owner.GetClassName();
|
||||
SWWMUtility.BeautifyClassName(realtag);
|
||||
}
|
||||
mytag = Owner.player?(Owner.player.mo!=Owner)?String.Format(StringTable.Localize("$FN_VOODOO"),Owner.player.GetUserName()):Owner.player.GetUserName():((Owner is 'PlayerPawn')&&(!Owner.player))?StringTable.Localize("$FN_VOODOO_NP"):realtag;
|
||||
}
|
||||
else mytag = "";
|
||||
}
|
||||
|
||||
static SWWMQuickCombatTracker Update( SWWMHandler hnd, PlayerInfo p, Actor target, int damage = 0 )
|
||||
{
|
||||
SWWMQuickCombatTracker t = null;
|
||||
for ( Inventory i=target.inv; i; i=i.inv )
|
||||
{
|
||||
if ( !(i is 'SWWMQuickCombatTracker') ) continue;
|
||||
let tt = SWWMQuickCombatTracker(i);
|
||||
if ( tt.myplayer != p ) continue;
|
||||
t = tt;
|
||||
break;
|
||||
}
|
||||
if ( t )
|
||||
{
|
||||
// re-fade in
|
||||
if ( t.lifespan < 20 ) t.fadein = t.lifespan/4;
|
||||
t.lifespan = max(t.lifespan,target.bISMONSTER?((damage>0)?700:70):((damage>0)?140:35));
|
||||
if ( damage > 0 )
|
||||
{
|
||||
t.cummdamage += damage;
|
||||
t.cummspan = target.bISMONSTER?120:30;
|
||||
t.cummflash = 15;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
t = SWWMQuickCombatTracker(Spawn("SWWMQuickCombatTracker"));
|
||||
t.myplayer = p;
|
||||
t.AttachToOwner(target);
|
||||
// players always use SpawnHealth
|
||||
if ( target.player ) t.maxhealth = target.SpawnHealth();
|
||||
else t.maxhealth = max(target.health,target.SpawnHealth());
|
||||
t.lasthealth = target.health;
|
||||
int prevhealth = min(t.maxhealth,target.health+damage); // guessed health before damage was dealt
|
||||
for ( int i=0; i<10; i++ ) t.laghealth[i] = prevhealth;
|
||||
if ( damage > 0 )
|
||||
{
|
||||
t.cummdamage = damage;
|
||||
t.cummspan = target.bISMONSTER?120:30;
|
||||
t.cummflash = 15;
|
||||
}
|
||||
t.intp = SmoothDynamicValueInterpolator.Create(t.lasthealth,.5,1,100);
|
||||
t.intpl = SmoothLinearValueInterpolator.Create(t.laghealth[9],max(1,t.maxhealth/20));
|
||||
t.lifespan = target.bISMONSTER?((damage>0)?700:70):((damage>0)?140:35);
|
||||
t.fadein = 0;
|
||||
t.lvheight = target.Height;
|
||||
t.UpdateTag(hnd);
|
||||
return t;
|
||||
}
|
||||
|
||||
// expiration, and interpolator updates
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
// immediately expire if the owner is gone or has morphed
|
||||
if ( !Owner || Owner.bUnmorphed )
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
// cap lifespan if owner is dead
|
||||
if ( Owner.Health <= 0 ) lifespan = min(lifespan,35);
|
||||
else lvheight = Owner.Height;
|
||||
if ( cummflash > 0 ) cummflash--;
|
||||
if ( cummspan > 0 )
|
||||
{
|
||||
cummspan--;
|
||||
if ( cummspan <= 0 ) cummdamage = 0;
|
||||
}
|
||||
if ( Owner.Health > lasthealth )
|
||||
{
|
||||
if ( !Owner.player && (Owner.Health > maxhealth) )
|
||||
maxhealth = Owner.Health;
|
||||
for ( int i=9; i>0; i-- )
|
||||
laghealth[i] = Owner.Health;
|
||||
}
|
||||
laghealth[0] = lasthealth = Owner.Health;
|
||||
intp.Update(lasthealth);
|
||||
intpl.Update(laghealth[9]);
|
||||
for ( int i=9; i>0; i-- )
|
||||
laghealth[i] = laghealth[i-1];
|
||||
if ( fadein < 5 ) fadein++;
|
||||
lifespan--;
|
||||
if ( lifespan <= 0 ) Destroy();
|
||||
}
|
||||
|
||||
override void PreTravelled()
|
||||
{
|
||||
// expire immediately when switching maps
|
||||
Destroy();
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
+INVENTORY.UNTOSSABLE;
|
||||
+INVENTORY.UNDROPPABLE;
|
||||
+INVENTORY.UNCLEARABLE;
|
||||
}
|
||||
}
|
||||
|
||||
// fractic-compatible interpolators, with double value
|
||||
Class SmoothLinearValueInterpolator
|
||||
{
|
||||
|
|
|
|||
|
|
@ -217,10 +217,7 @@ Class SWWMGesture : SWWMWeapon
|
|||
raging.DoHitFX();
|
||||
}
|
||||
if ( pt.target.GiveBody(healamt,pt.target.GetSpawnHealth()) )
|
||||
{
|
||||
SWWMScoreObj.Spawn(healamt,pt.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+pt.target.Height/2),ST_Health);
|
||||
SWWMHandler.DoFlash(pt.target,Color(32,224,128,255),10);
|
||||
}
|
||||
}
|
||||
let s = Demolitionist(self).mystats;
|
||||
if ( s ) s.pats++;
|
||||
|
|
|
|||
|
|
@ -122,10 +122,7 @@ Class LoveHeart : Actor
|
|||
raging.DoHitFX();
|
||||
}
|
||||
if ( target.GiveBody(healamt,target.GetSpawnHealth()) )
|
||||
{
|
||||
SWWMScoreObj.Spawn(healamt,target.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+target.Height/2),ST_Health);
|
||||
SWWMHandler.DoFlash(target,Color(32,224,128,255),10);
|
||||
}
|
||||
if ( SWWMUtility.IdentifyingDog(target) )
|
||||
{
|
||||
// befriend good doggo
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ Class SWWMHandler : EventHandler
|
|||
{
|
||||
transient int lastlock;
|
||||
transient int lastpickuptic[MAXPLAYERS];
|
||||
SWWMCombatTracker trackers;
|
||||
SWWMScoreObj scorenums, damnums;
|
||||
SWWMScoreObj scorenums;
|
||||
SWWMDamNum damnums;
|
||||
SWWMInterest intpoints;
|
||||
int trackers_cnt, scorenums_cnt, damnums_cnt, intpoints_cnt;
|
||||
Array<String> damtypes, damcolors;
|
||||
transient CVar usedamcolors;
|
||||
|
||||
transient int slotstrictwarn;
|
||||
transient ui String sswstr;
|
||||
|
|
@ -103,6 +104,26 @@ Class SWWMHandler : EventHandler
|
|||
bludtypes.Push(list[i]);
|
||||
}
|
||||
}
|
||||
// read damnum colors
|
||||
damtypes.Clear();
|
||||
damcolors.Clear();
|
||||
for ( int lmp = Wads.FindLump("DAMTYPES"); lmp != -1; lmp = Wads.FindLump("DAMTYPES",lmp+1) )
|
||||
{
|
||||
String dat = Wads.ReadLump(lmp);
|
||||
Array<String> list;
|
||||
// fucking Windows
|
||||
dat.Replace("\r","");
|
||||
list.Clear();
|
||||
dat.Split(list,"\n");
|
||||
for ( int i=0; i<list.Size(); i++ )
|
||||
{
|
||||
if ( (list[i].Length() == 0) || (list[i].Left(1) == "#") || (list[i].Left(1) == "") )
|
||||
continue;
|
||||
int spc = list[i].IndexOf(" ");
|
||||
damtypes.Push(list[i].Left(spc));
|
||||
damcolors.Push(list[i].Mid(spc+1));
|
||||
}
|
||||
}
|
||||
// cache various services into the handler on register
|
||||
// this dramatically reduces overhead by not having to use an iterator every time they're needed
|
||||
// especially noticeable for fun tags, as they're looked up for every monster on map load
|
||||
|
|
@ -158,6 +179,30 @@ Class SWWMHandler : EventHandler
|
|||
Console.Printf(StringTable.Localize("$SWWM_NEWMISSION"));
|
||||
}
|
||||
}
|
||||
for ( int i=0; i<legtrack.Size(); i++ )
|
||||
{
|
||||
// when a monster mutates, update its healthbar for all players
|
||||
for ( int j=0; j<MAXPLAYERS; j++ )
|
||||
{
|
||||
if ( !playeringame[j] ) continue;
|
||||
let t = SWWMQuickCombatTracker.Update(self,players[j],legtrack[i].Owner);
|
||||
if ( t.myplayer == players[consoleplayer] ) Console.Printf(StringTable.Localize("$SWWM_LTFORM"),t.mytag);
|
||||
}
|
||||
legtrack.Delete(i--);
|
||||
}
|
||||
// healthbar on whatever the player is aiming at
|
||||
for ( int i=0; i<MAXPLAYERS; i++ )
|
||||
{
|
||||
if ( !playeringame[i] || (players[i].Health <= 0) || !players[i].mo ) continue;
|
||||
let t = players[i].mo.GetPointer(AAPTR_PLAYER_GETTARGET);
|
||||
if ( t && t.bSHOOTABLE && (t.Health > 0) ) SWWMQuickCombatTracker.Update(self,players[i],t);
|
||||
// keep healthbars updated for all friends of this player
|
||||
for ( int j=0; j<MAXPLAYERS; j++ )
|
||||
{
|
||||
if ( !playeringame[j] || (players[j].Health <= 0) || !players[j].mo || !players[j].mo.IsFriend(players[i].mo) ) continue;
|
||||
SWWMQuickCombatTracker.Update(self,players[j],players[i].mo);
|
||||
}
|
||||
}
|
||||
OnelinerTick();
|
||||
FlashTick();
|
||||
ItemCountTrack();
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ Class Demolitionist : PlayerPawn
|
|||
Vector3 pretelepos;
|
||||
|
||||
SWWMItemSense itemsense;
|
||||
int itemsense_cnt;
|
||||
|
||||
int healcooldown, healtimer, oldhealth;
|
||||
bool scriptedinvul;
|
||||
|
|
@ -670,7 +669,6 @@ Class Demolitionist : PlayerPawn
|
|||
if ( prev ) prev.next = next;
|
||||
else itemsense = next;
|
||||
itm.Destroy();
|
||||
itemsense_cnt--;
|
||||
}
|
||||
else prev = itm;
|
||||
itm = next;
|
||||
|
|
@ -2551,7 +2549,6 @@ Class Demolitionist : PlayerPawn
|
|||
lastbump *= 1.5;
|
||||
SWWMHandler.DoFlash(self,Color(255,255,255,255),10);
|
||||
SWWMHandler.DoFlash(self,Color(255,128,192,255),30);
|
||||
SWWMScoreObj.Spawn(default.health,Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Height/2),ST_Health);
|
||||
if ( special1 > 2 ) special1 = 0;
|
||||
if ( (swwm_revivecooldown > 0) && (G_SkillPropertyInt(SKILLP_ACSReturn) < 4) )
|
||||
GiveInventory("ReviveCooldown",1);
|
||||
|
|
@ -3312,7 +3309,6 @@ Class Demolitionist : PlayerPawn
|
|||
si.Destroy();
|
||||
si = next;
|
||||
}
|
||||
itemsense_cnt = 0;
|
||||
SWWMMagItem mi = magitem;
|
||||
while ( mi )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ Class HealthOrb : SlayerOrb
|
|||
int hp = int(ceil(abs(scale.x*10)));
|
||||
mo.GiveBody(hp,100);
|
||||
SWWMHandler.HealthFlash(np);
|
||||
SWWMScoreObj.Spawn(hp,mo.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+mo.Height/2),ST_Health);
|
||||
}
|
||||
States
|
||||
{
|
||||
|
|
@ -127,7 +126,6 @@ Class ArmorOrb : SlayerOrb
|
|||
}
|
||||
if ( n.Amount < 100 ) n.Amount = min(n.Amount+hp,100);
|
||||
SWWMHandler.ArmorFlash(np);
|
||||
SWWMScoreObj.Spawn(hp,mo.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+mo.Height/2),ST_Armor);
|
||||
}
|
||||
States
|
||||
{
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ Class BusterWall : Thinker
|
|||
// damnums
|
||||
Vector3 bcenter = (bust.boundsmin+bust.boundsmax)*.5;
|
||||
for ( int i=0; i<bust.acchits.Size(); i++ )
|
||||
SWWMScoreObj.Spawn(-bust.acchits[i],level.Vec3Offset(bcenter,(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8))),ST_Damage);
|
||||
SWWMDamNum.Spawn(bust.acchits[i],level.Vec3Offset(bcenter,(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8))),'Wallbust');
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -624,7 +624,7 @@ Class BusterWall : Thinker
|
|||
// damnums
|
||||
Vector3 bcenter = (bust.boundsmin+bust.boundsmax)*.5;
|
||||
for ( int i=0; i<bust.acchits.Size(); i++ )
|
||||
SWWMScoreObj.Spawn(-bust.acchits[i],level.Vec3Offset(bcenter,(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8))),ST_Damage);
|
||||
SWWMDamNum.Spawn(bust.acchits[i],level.Vec3Offset(bcenter,(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8))),'Wallbust');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue