416 lines
22 KiB
Text
416 lines
22 KiB
Text
// Targeter
|
|
extend Class SWWMStatusBar
|
|
{
|
|
|
|
static private string FormatDist( double dist )
|
|
{
|
|
double meters = dist/32.;
|
|
if ( meters > 1000. ) return String.Format("\cj%d\cc%s",int(meters/1000.),StringTable.Localize("$SWWM_UNIT_KILOMETER"));
|
|
return String.Format("\cj%d\cc%s",int(meters),StringTable.Localize("$SWWM_UNIT_METER"));
|
|
}
|
|
|
|
private void DrawInterest( Vector3 viewvec, bool &projinit )
|
|
{
|
|
String tag;
|
|
SWWMInterest poi = hnd.intpoints;
|
|
if ( !poi ) 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,poi.pos);
|
|
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir);
|
|
if ( ndc.z <= 0. ) continue;
|
|
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 ( (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(mTinyFontOutlineAlt,Font.CR_WHITE,vpos.x-mTinyFontOutlineAlt.StringWidth(tag)/2.,vpos.y-mTinyFontOutlineAlt.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(mTinyFontOutlineAlt,Font.CR_WHITE,vpos.x-mTinyFontOutlineAlt.StringWidth(tag)/2.,vpos.y+mTinyFontOutlineAlt.GetHeight()/2.,tag,DTA_VirtualWidthF,ss2.x,DTA_VirtualHeightF,ss2.y,DTA_KeepRatio,true);
|
|
}
|
|
while ( poi = poi.next );
|
|
}
|
|
|
|
private int GetItemFontColor( SWWMitemSense s )
|
|
{
|
|
let col = s.scoreitem?Font.CR_YELLOW:Font.CR_WHITE;
|
|
let i = (s.item is 'SWWMRespawnTimer')?s.item.tracer:s.item;
|
|
if ( i is 'Weapon' ) col = s.vipitem?Font.FindFontColor('VIPGold'):Font.CR_GOLD;
|
|
else if ( i is 'MagAmmo' ) col = s.vipitem?Font.FindFontColor('VIPTan'):Font.CR_TAN;
|
|
else if ( (i is 'BackpackItem') || (i is 'HammerspaceEmbiggener') ) col = Font.CR_DARKBROWN;
|
|
else if ( i is 'Ammo' ) col = s.vipitem?Font.FindFontColor('VIPBrown'):Font.CR_BROWN;
|
|
else if ( (i is 'PowerupGiver') || (i is 'AmmoFabricator') || (i is 'Chancebox') || ((i is 'Inventory') && Inventory(i).bBIGPOWERUP) ) col = s.vipitem?Font.FindFontColor('VIPPurple'):Font.CR_PURPLE;
|
|
else if ( (i is 'Health') || (i is 'HealthPickup') || (i is 'SWWMHealth') ) col = Font.CR_RED;
|
|
else if ( (i is 'Armor') || (i is 'SWWMSpareArmor') ) col = Font.CR_GREEN;
|
|
else if ( i is 'PuzzleItem' ) col = Font.CR_LIGHTBLUE;
|
|
else if ( i is 'Key' ) col = Font.CR_UNTRANSLATED;
|
|
else if ( i is 'SWWMCollectible' ) col = Font.CR_PURPLE;
|
|
return col;
|
|
}
|
|
|
|
private void DrawItemSense( Vector3 viewvec, 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(mTinyFontOutlineAlt,GetItemFontColor(s),vpos.x-mTinyFontOutlineAlt.StringWidth(tag)/2.,vpos.y-mTinyFontOutlineAlt.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(mTinyFontOutlineAlt,Font.CR_WHITE,vpos.x-mTinyFontOutlineAlt.StringWidth(tag)/2.,vpos.y+mTinyFontOutlineAlt.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(mTinyFontOutlineAlt,Font.CR_WHITE,vpos.x-mTinyFontOutlineAlt.StringWidth(tag)/2.,vpos.y+mTinyFontOutlineAlt.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, bool &projinit )
|
|
{
|
|
let cam = players[consoleplayer].camera;
|
|
if ( !cti ) cti = ThinkerIterator.Create('SWWMQuickCombatTracker',Thinker.STAT_INVENTORY);
|
|
else cti.Reinit();
|
|
SWWMQuickCombatTracker ct;
|
|
bool onlymonsters = (swwm_targeter >= 2);
|
|
bool onlyfriends = (swwm_targeter >= 3);
|
|
bool drawvalues = swwm_targetvals;
|
|
int fadedist = swwm_bardist;
|
|
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 if max health is zero (SOMEHOW can happen)
|
|
if ( ct.maxhealth <= 0 ) continue;
|
|
// ignore player trackers unless voodoo dolls
|
|
if ( ct.Owner.player && (ct.Owner.player.mo == ct.Owner) ) continue;
|
|
// ignore local player or camera
|
|
if ( (ct.Owner == CPlayer.mo) || (ct.Owner == cam) ) continue;
|
|
// ignore trackers not of this player
|
|
if ( ct.myplayer != CPlayer ) continue;
|
|
// ignore non-monsters if filtering monsters
|
|
// easy check since they have empty tags
|
|
if ( onlymonsters && (ct.mytag == "") ) continue;
|
|
// ignore enemies if filtering friends
|
|
if ( onlyfriends && (!ct.Owner.IsFriend(CPlayer.mo) || ct.Owner.player) ) 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);
|
|
// ignore trackers that are too far away
|
|
double dist = tdir.length();
|
|
if ( (fadedist > 0) && (dist > fadedist*1.5) ) continue;
|
|
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
|
if ( ndc.z <= 0. ) continue;
|
|
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs1;
|
|
double fin = clamp(ct.fadein+fractic,0.,5.)/5.;
|
|
double fout = clamp(ct.lifespan-fractic,0.,25.)/25.;
|
|
double alph = fin*fout;
|
|
if ( fadedist > 0 )
|
|
{
|
|
double df = 1.-(clamp((dist-fadedist)/fadedist,0.,.5)*2.);
|
|
alph *= df;
|
|
}
|
|
Vector2 barpos = vpos-(27,15);
|
|
if ( drawvalues )
|
|
{
|
|
String val = String.Format("%d %d",ct.maxhealth,ct.maxhealth);
|
|
int valw = MiniHUDFontOutline.StringWidth(val);
|
|
val = String.Format("%d \c[MiniWhite]%d",ct.lasthealth,ct.maxhealth);
|
|
int ofsw = valw-MiniHUDFontOutline.StringWidth(val);
|
|
int col = (ct.lasthealth>ct.maxhealth)?mhudfontcol[MCR_BRASS]:(ct.lasthealth>(ct.maxhealth/2))?mhudfontcol[MCR_WHITE]:(ct.lasthealth>(ct.maxhealth/4))?mhudfontcol[MCR_TOMATO]:(ct.lasthealth>0)?mhudfontcol[MCR_RED]:mhudfontcol[MCR_SAYAHUD];
|
|
Screen.DrawText(MiniHUDFontOutline,col,vpos.x-int((valw/2)-ofsw),barpos.y-(MiniHUDFontOutline.GetHeight()+2),val,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
Screen.DrawChar(MiniHUDFontOutline,mhudfontcol[MCR_IBUKIHUD],vpos.x-3,barpos.y-(MiniHUDFontOutline.GetHeight()+2),0x2F,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
}
|
|
if ( swwm_targettags && (ct.mytag != "") )
|
|
{
|
|
Font fnt = swwm_bigtags?mSmallFontOutlineAlt:mTinyFontOutlineAlt;
|
|
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 ( 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
|
|
}
|
|
// voodoo dolls aren't friends
|
|
if ( ct.Owner.IsFriend(CPlayer.mo) && !ct.Owner.player ) tag = "\cg♥\c- "..tag.." \cg♥\c-";
|
|
int ofsh = drawvalues?(MiniHUDFontOutline.GetHeight()+4):2;
|
|
Screen.DrawText(fnt,Font.CR_WHITE,vpos.x-fnt.StringWidth(tag)/2,barpos.y-(fnt.GetHeight()+ofsh),tag,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);
|
|
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+4,barpos.y+8,(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+4,barpos.y+8,(ct.cummdamage>=Actor.TELEFRAG_DAMAGE)?"∞":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 and voodoo dolls
|
|
if ( !ct.Owner.player || (ct.Owner.player.mo != ct.Owner) ) continue;
|
|
// ignore local player or camera
|
|
if ( (ct.Owner == CPlayer.mo) || (ct.Owner == cam) ) continue;
|
|
// ignore trackers not of this player
|
|
if ( ct.myplayer != CPlayer ) continue;
|
|
// ignore enemies if filtering friends
|
|
if ( onlyfriends && !ct.Owner.IsFriend(CPlayer.mo) ) 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);
|
|
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,viewpos+tdir);
|
|
if ( ndc.z <= 0. ) continue;
|
|
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs1;
|
|
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,15);
|
|
if ( drawvalues )
|
|
{
|
|
// player health values are drawn as a single number
|
|
// font color is the same as in the status box
|
|
String val = String.Format("%d",clamp(ct.lasthealth,0,999));
|
|
int valw = MiniHUDFontOutline.StringWidth(val);
|
|
int col = (ct.lasthealth>500)?mhudfontcol[MCR_GOLD]:(ct.lasthealth>200)?mhudfontcol[MCR_PURPLE]:(ct.lasthealth>100)?mhudfontcol[MCR_AQUA]:mhudfontcol[MCR_RED];
|
|
if ( ct.Owner.bINVULNERABLE || (ct.Owner.player.cheats&(CF_GODMODE|CF_GODMODE2)) || ct.Owner.FindInventory('InvinciballPower') )
|
|
col = mhudfontcol[MCR_WHITE];
|
|
if ( ct.Owner.FindInventory('DivineSpriteEffect') )
|
|
{
|
|
double falph = clamp((ct.intp.GetValue(fractic)-1000)/6000.,0.,1.);
|
|
String tst;
|
|
double ffalph = .1;
|
|
int trl = 9;
|
|
for ( double ffalph = .1; ffalph <= .5; ffalph += .1 )
|
|
{
|
|
tst = "AAA";
|
|
SWWMUtility.ObscureText(tst,(gametic-trl)/3,minihud:true);
|
|
trl--;
|
|
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_WHITE],vpos.x-(valw/2),barpos.y-(MiniHUDFontOutline.GetHeight()+2),tst,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph*falph*ffalph,DTA_LegacyRenderStyle,STYLE_Add);
|
|
}
|
|
Screen.DrawText(MiniHUDFontOutline,col,vpos.x-(valw/2),barpos.y-(MiniHUDFontOutline.GetHeight()+2),val,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph*(1.-falph));
|
|
}
|
|
else Screen.DrawText(MiniHUDFontOutline,col,vpos.x-(valw/2),barpos.y-(MiniHUDFontOutline.GetHeight()+2),val,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
}
|
|
Font fnt = swwm_bigtags?mSmallFontOutlineAlt:mTinyFontOutlineAlt;
|
|
int col = Font.CR_WHITE;
|
|
if ( teamplay )
|
|
{
|
|
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;
|
|
}
|
|
int ofsh = drawvalues?(MiniHUDFontOutline.GetHeight()+4):2;
|
|
Screen.DrawText(fnt,col,vpos.x-fnt.StringWidth(ct.mytag)/2,barpos.y-(fnt.GetHeight()+ofsh),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,10000);
|
|
double hw = (ht*50.)/100.;
|
|
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[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 > 100 )
|
|
{
|
|
hw = (min(ht-100,100)*50.)/100.;
|
|
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 > 200 )
|
|
{
|
|
hw = (min(ht-200,300)*50.)/100.;
|
|
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 > 500 )
|
|
{
|
|
hw = (min(ht-500,500)*50.)/100.;
|
|
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-1000)/6000.,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
|
|
{
|
|
ht = clamp(ct.intpl.GetValue(fractic),0,100);
|
|
hw = min((ht*50.)/100.,100.);
|
|
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,(ct.cummdamage>=Actor.TELEFRAG_DAMAGE)?"∞":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);
|
|
}
|
|
}
|
|
|
|
private void DrawNumbers( Vector3 viewvec, bool &projinit )
|
|
{
|
|
SWWMDamNum snum = hnd.damnums;
|
|
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);
|
|
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir,true);
|
|
if ( ndc.z <= 0. ) continue;
|
|
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc)/hs0;
|
|
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,ss0.x,DTA_VirtualHeightF,ss0.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
}
|
|
while ( snum = snum.next );
|
|
}
|
|
|
|
private void DrawScores( Vector3 viewvec, 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);
|
|
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,ViewPos+tdir);
|
|
if ( ndc.z <= 0. ) 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.);
|
|
// score rises linearly
|
|
Vector2 fo = (0,snum.initialspan-(snum.lifespan-fractic));
|
|
Screen.DrawText(mTinyFontOutlineAlt,snum.tcolor,vpos.x-(fo.x+mTinyFontOutlineAlt.StringWidth(tag)/2.),vpos.y-(fo.y+(mTinyFontOutlineAlt.GetHeight()/2.)),tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
// extra strings (if available)
|
|
fo.y += mTinyFontOutlineAlt.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(mTinyFontOutlineAlt,snum.xtcolor[i],vpos.x-(fo.x+mTinyFontOutlineAlt.StringWidth(tag)/2.),vpos.y-(fo.y+(mTinyFontOutlineAlt.GetHeight()/2.)),tag,DTA_VirtualWidthF,ss1.x,DTA_VirtualHeightF,ss1.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
fo.y += mTinyFontOutlineAlt.GetHeight();
|
|
}
|
|
}
|
|
while ( snum = snum.next );
|
|
}
|
|
|
|
private void DrawTarget()
|
|
{
|
|
// don't draw when dead or with automap open
|
|
if ( (CPlayer.health <= 0) || (automapactive && !viewactive) ) 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();
|
|
}
|
|
}
|