Force weapons to always bob, like in DT/Doomreal. Will fine tune this later so the bobbing doesn't make firing guns look awkward. Fixed crash when opening the chat prompt due to an excess %s. Consider the possibility of adding dual wielding to the Explodium Gun eventually.
912 lines
36 KiB
Text
912 lines
36 KiB
Text
// The SWWM GZ HUD is mostly built on top of what I had already done for SWWM Z, also a bit of Dark Souls
|
|
|
|
Class MsgLine
|
|
{
|
|
String str;
|
|
int tic, type, rep;
|
|
}
|
|
|
|
Class SWWMStatusBar : BaseStatusBar
|
|
{
|
|
TextureID StatusTex, WeaponTex, ScoreTex, InventoryTex, ChatTex[6],
|
|
HealthTex[5], FuelTex, DashTex, EnemyBTex, EnemyHTex[5];
|
|
HUDFont mTewiFont, mMiniwiFont, mMPlusFont;
|
|
|
|
// "Full History" contains all messages since session start, nothing is flushed
|
|
// this can be accessed from a section of the knowledge base
|
|
Array<MsgLine> MainQueue, PickupQueue, FullHistory;
|
|
|
|
// sorted arrays of various elements
|
|
Array<SWWMInterest> intpoints;
|
|
Array<SWWMScoreObj> scoreobjs;
|
|
Array<SWWMCombatTracker> trackers;
|
|
|
|
// the event handler, holding all sorts of stuff
|
|
SWWMHandler hnd;
|
|
|
|
// client cvars
|
|
transient CVar safezone, maxchat[2], maxpick, chatduration, msgduration, pickduration, chatcol, teamcol, obitcol, critcol, pickcol, targetter, healthnums, scorenums, scorebonus, targettag, lang;
|
|
|
|
// shared stuff
|
|
Vector2 ss, hs;
|
|
int margin;
|
|
double FracTic;
|
|
int chatopen;
|
|
|
|
// shared from renderunderlay, needed for proper interpolation of some things
|
|
Vector3 viewpos, viewrot;
|
|
|
|
// libeye stuff
|
|
swwmLe__ProjScreen proj;
|
|
swwmLe__GLScreen gl_proj;
|
|
swwmLe__SWScreen sw_proj;
|
|
swwmLe__Viewport viewport;
|
|
bool can_project;
|
|
transient CVar cvar_renderer;
|
|
|
|
DynamicValueInterpolator HealthInter, ScoreInter, FuelInter, DashInter;
|
|
|
|
// returns MPlus if we're playing in Japanese, otherwise returns the requested font
|
|
Font LangFont( HUDFont req )
|
|
{
|
|
if ( !lang ) lang = CVar.GetCVar('language',players[consoleplayer]);
|
|
if ( lang.GetString() ~== "jp" ) return mMPlusFont.mFont;
|
|
return req.mFont;
|
|
}
|
|
|
|
override void FlushNotify()
|
|
{
|
|
// flush interpolators (useful since this virtual gets called
|
|
// when loading saves, too)
|
|
HealthInter.Reset(CPlayer.Health);
|
|
ScoreInter.Reset(SWWMCredits.Get(CPlayer));
|
|
FuelInter.Reset((CPlayer.mo is 'Demolitionist')?int(Demolitionist(CPlayer.mo).dashfuel):0);
|
|
DashInter.Reset((CPlayer.mo is 'Demolitionist')?int((40-Demolitionist(CPlayer.mo).dashcooldown)*3.):0);
|
|
if ( level.maptime <= 1 )
|
|
{
|
|
// flush ALL messages
|
|
MainQueue.Clear();
|
|
PickupQueue.Clear();
|
|
return;
|
|
}
|
|
// flush non-chat messages
|
|
for ( int i=0; i<MainQueue.Size(); i++ )
|
|
{
|
|
if ( MainQueue[i].type >= PRINT_CHAT ) continue;
|
|
MainQueue.Delete(i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
override bool ProcessMidPrint( Font fnt, String msg, bool bold )
|
|
{
|
|
// check for Korax lines
|
|
if ( msg == StringTable.Localize("$TXT_ACS_MAP02_11_AREYO") )
|
|
EventHandler.SendNetworkEvent("swwmkoraxline",0,consoleplayer);
|
|
else if ( msg == StringTable.Localize("$TXT_ACS_MAP13_11_MYSER") )
|
|
EventHandler.SendNetworkEvent("swwmkoraxline",1,consoleplayer);
|
|
else if ( msg == StringTable.Localize("$TXT_ACS_MAP22_29_ITHIN") )
|
|
EventHandler.SendNetworkEvent("swwmkoraxline",2,consoleplayer);
|
|
else if ( msg == StringTable.Localize("$TXT_ACS_MAP27_10_THENA") )
|
|
EventHandler.SendNetworkEvent("swwmkoraxline",3,consoleplayer);
|
|
else if ( msg == StringTable.Localize("$TXT_ACS_MAP35_14_TOFAC") )
|
|
EventHandler.SendNetworkEvent("swwmkoraxline",4,consoleplayer);
|
|
return false;
|
|
}
|
|
|
|
override bool ProcessNotify( EPrintLevel printlevel, String outline )
|
|
{
|
|
let m = new("MsgLine");
|
|
m.str = outline.Left(outline.Length()-1); // strip newline
|
|
m.type = printlevel;
|
|
m.tic = level.maptime;
|
|
m.rep = 1;
|
|
// append chat messages to full history
|
|
if ( (printlevel == PRINT_CHAT) || (printlevel == PRINT_TEAMCHAT) )
|
|
FullHistory.Push(m);
|
|
// ignore during intermission
|
|
if ( gamestate != GS_LEVEL ) return false;
|
|
if ( (printlevel < PRINT_LOW) || (printlevel > PRINT_TEAMCHAT) ) return true; // we couldn't care less about these
|
|
if ( printlevel == PRINT_LOW )
|
|
{
|
|
// check if repeated
|
|
for ( int i=0; i<PickupQueue.Size(); i++ )
|
|
{
|
|
if ( PickupQueue[i].str != m.str ) continue;
|
|
// delete old one and add its repeats
|
|
m.rep += PickupQueue[i].rep;
|
|
PickupQueue.Delete(i);
|
|
break;
|
|
}
|
|
PickupQueue.Push(m);
|
|
}
|
|
else
|
|
{
|
|
// check if repeated
|
|
for ( int i=0; i<MainQueue.Size(); i++ )
|
|
{
|
|
if ( MainQueue[i].str != m.str ) continue;
|
|
// delete old one and add its repeats
|
|
m.rep += MainQueue[i].rep;
|
|
MainQueue.Delete(i);
|
|
break;
|
|
}
|
|
MainQueue.Push(m);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void PrepareProjection()
|
|
{
|
|
if ( !cvar_renderer ) cvar_renderer = CVar.GetCVar("vid_rendermode",players[consoleplayer]);
|
|
if ( !cvar_renderer )
|
|
{
|
|
can_project = proj = gl_proj;
|
|
return;
|
|
}
|
|
switch ( cvar_renderer.GetInt() )
|
|
{
|
|
case 0:
|
|
case 1:
|
|
proj = sw_proj;
|
|
break;
|
|
default:
|
|
proj = gl_proj;
|
|
break;
|
|
}
|
|
can_project = proj;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
PrepareProjection();
|
|
if ( !chatduration ) chatduration = CVar.GetCVar('swwm_chatduration',players[consoleplayer]);
|
|
if ( !msgduration ) msgduration = CVar.GetCVar('swwm_msgduration',players[consoleplayer]);
|
|
if ( !pickduration ) pickduration = CVar.GetCVar('swwm_pickduration',players[consoleplayer]);
|
|
if ( !targetter ) targetter = CVar.GetCVar('swwm_targeter',players[consoleplayer]);
|
|
if ( !healthnums ) healthnums = CVar.GetCVar('swwm_healthnums',players[consoleplayer]);
|
|
if ( !scorenums ) scorenums = CVar.GetCVar('swwm_scorenums',players[consoleplayer]);
|
|
// prune old messages
|
|
for ( int i=0; i<PickupQueue.Size(); i++ )
|
|
{
|
|
if ( level.maptime < (PickupQueue[i].tic+35*pickduration.GetInt()) ) continue;
|
|
PickupQueue.Delete(i);
|
|
i--;
|
|
}
|
|
for ( int i=0; i<MainQueue.Size(); i++ )
|
|
{
|
|
if ( (MainQueue[i].type <= PRINT_HIGH) && (level.maptime < (MainQueue[i].tic+35*msgduration.GetInt())) ) continue;
|
|
else if ( (MainQueue[i].type > PRINT_HIGH) && (level.maptime < (MainQueue[i].tic+35*chatduration.GetInt())) ) continue;
|
|
MainQueue.Delete(i);
|
|
i--;
|
|
}
|
|
// update interpolators
|
|
HealthInter.Update(CPlayer.health);
|
|
if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
|
ScoreInter.Update(SWWMCredits.Get(CPlayer));
|
|
let d = Demolitionist(CPlayer.mo);
|
|
if ( d )
|
|
{
|
|
FuelInter.Update(int(d.dashfuel));
|
|
DashInter.Update(int((40-d.dashcooldown)*3.));
|
|
}
|
|
else
|
|
{
|
|
FuelInter.Update(0);
|
|
DashInter.Update(0);
|
|
}
|
|
// let weapons update their own interpolators
|
|
if ( CPlayer.ReadyWeapon is 'SWWMWeapon' )
|
|
SWWMWeapon(CPlayer.ReadyWeapon).HudTick();
|
|
bool thesight = CPlayer.mo.FindInventory("Omnisight");
|
|
if ( thesight )
|
|
{
|
|
// 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 )
|
|
intpoints[i++] = poi;
|
|
// sort by distance
|
|
for ( int i=0; i<hnd.intpoints_cnt; i++ )
|
|
{
|
|
int j = 1;
|
|
while ( j < hnd.intpoints_cnt )
|
|
{
|
|
int k = j;
|
|
while ( (k > 0) && (CmpInterest(intpoints[k-1],intpoints[k]) || CmpDist(intpoints[k-1].pos,intpoints[k].pos)) )
|
|
{
|
|
SWWMInterest tmp = intpoints[k];
|
|
intpoints[k] = intpoints[k-1];
|
|
intpoints[k-1] = tmp;
|
|
k--;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
if ( targetter.GetBool() )
|
|
{
|
|
// update target stuff
|
|
if ( trackers.Size() != hnd.trackers_cnt )
|
|
trackers.Resize(hnd.trackers_cnt);
|
|
int i = 0, actual = 0;
|
|
for ( SWWMCombatTracker trk=hnd.trackers; trk; trk=trk.next )
|
|
{
|
|
actual++;
|
|
// ignore player unless chasecamming
|
|
if ( (trk.mytarget == players[consoleplayer].mo) && (players[consoleplayer].Camera == players[consoleplayer].mo) && !(players[consoleplayer].cheats&CF_CHASECAM) ) continue;
|
|
if ( trk.myplayer && deathmatch ) continue; // no players in dm
|
|
int mtime = 35;
|
|
if ( thesight && (trk.lasthealth > 0) ) mtime += 105;
|
|
if ( level.maptime > trk.updated+mtime ) continue;
|
|
trackers[i++] = trk;
|
|
}
|
|
// squeeze if some were discarded
|
|
if ( i != hnd.trackers_cnt )
|
|
trackers.Resize(i);
|
|
// sort by distance (give priority to players)
|
|
for ( int i=0; i<trackers.Size(); i++ )
|
|
{
|
|
int j = 1;
|
|
while ( j < trackers.Size() )
|
|
{
|
|
int k = j;
|
|
while ( (k > 0) && (CmpTarget(trackers[k-1],trackers[k]) || CmpDist(trackers[k-1].pos,trackers[k].pos)) )
|
|
{
|
|
SWWMCombatTracker tmp = trackers[k];
|
|
trackers[k] = trackers[k-1];
|
|
trackers[k-1] = tmp;
|
|
k--;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
// update floating scores, adding the scorenums first, then the damnums
|
|
int total_sz = 0;
|
|
if ( scorenums.GetBool() ) total_sz += hnd.scorenums_cnt;
|
|
if ( healthnums.GetBool() ) total_sz += min(50,hnd.damnums_cnt);
|
|
if ( scoreobjs.Size() != total_sz )
|
|
scoreobjs.Resize(total_sz);
|
|
int i = 0;
|
|
if ( scorenums.GetBool() )
|
|
{
|
|
for ( SWWMScoreObj scr=hnd.scorenums; scr; scr=scr.next )
|
|
scoreobjs[i++] = scr;
|
|
}
|
|
if ( healthnums.GetBool() )
|
|
{
|
|
for ( SWWMScoreObj scr=hnd.damnums; scr && (i<total_sz); scr=scr.next )
|
|
scoreobjs[i++] = scr;
|
|
}
|
|
// sort by distance
|
|
for ( int i=0; i<total_sz; i++ )
|
|
{
|
|
int j = 1;
|
|
while ( j < total_sz )
|
|
{
|
|
int k = j;
|
|
while ( (k > 0) && (CmpScore(scoreobjs[k-1],scoreobjs[k]) || CmpDist(scoreobjs[k-1].pos,scoreobjs[k].pos)) )
|
|
{
|
|
SWWMScoreObj tmp = scoreobjs[k];
|
|
scoreobjs[k] = scoreobjs[k-1];
|
|
scoreobjs[k-1] = tmp;
|
|
k--;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
override void Init()
|
|
{
|
|
Super.Init();
|
|
SetSize(0,640,360);
|
|
StatusTex = TexMan.CheckForTexture("graphics/HUD/StatusBox.png",TexMan.Type_Any);
|
|
DashTex = TexMan.CheckForTexture("graphics/HUD/DashBar.png",TexMan.Type_Any);
|
|
FuelTex = TexMan.CheckForTexture("graphics/HUD/FuelBar.png",TexMan.Type_Any);
|
|
HealthTex[0] = TexMan.CheckForTexture("graphics/HUD/HealthBar0.png",TexMan.Type_Any);
|
|
HealthTex[1] = TexMan.CheckForTexture("graphics/HUD/HealthBar1.png",TexMan.Type_Any);
|
|
HealthTex[2] = TexMan.CheckForTexture("graphics/HUD/HealthBar2.png",TexMan.Type_Any);
|
|
HealthTex[3] = TexMan.CheckForTexture("graphics/HUD/HealthBar3.png",TexMan.Type_Any);
|
|
HealthTex[4] = TexMan.CheckForTexture("graphics/HUD/HealthBarS.png",TexMan.Type_Any);
|
|
ScoreTex = TexMan.CheckForTexture("graphics/HUD/ScoreBox.png",TexMan.Type_Any);
|
|
WeaponTex = TexMan.CheckForTexture("graphics/HUD/WeaponBox.png",TexMan.Type_Any);
|
|
ChatTex[0] = TexMan.CheckForTexture("graphics/HUD/ChatBoxTop.png",TexMan.Type_Any);
|
|
ChatTex[1] = TexMan.CheckForTexture("graphics/HUD/ChatBoxLine.png",TexMan.Type_Any);
|
|
ChatTex[2] = TexMan.CheckForTexture("graphics/HUD/ChatBoxBottom.png",TexMan.Type_Any);
|
|
ChatTex[3] = TexMan.CheckForTexture("graphics/HUD/ChatBoxTop_Smol.png",TexMan.Type_Any);
|
|
ChatTex[4] = TexMan.CheckForTexture("graphics/HUD/ChatBoxLine_Smol.png",TexMan.Type_Any);
|
|
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);
|
|
mTewiFont = HUDFont.Create("TewiShaded");
|
|
mMiniwiFont = HUDFont.Create("MiniwiShaded");
|
|
mMPlusFont = HUDFont.Create("MPlusShaded");
|
|
HealthInter = DynamicValueInterpolator.Create(100,.1,1,100);
|
|
ScoreInter = DynamicValueInterpolator.Create(0,.1,1,1000);
|
|
FuelInter = DynamicValueInterpolator.Create(120,.5,1,100);
|
|
DashInter = DynamicValueInterpolator.Create(120,.5,1,40);
|
|
gl_proj = new("swwmLe__GLScreen");
|
|
sw_proj = new("swwmLe__SWScreen");
|
|
PrepareProjection();
|
|
hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
|
}
|
|
|
|
static private string FormatDist( double dist )
|
|
{
|
|
double meters = dist/32.;
|
|
if ( meters > 1000. ) return String.Format("\cj%d\cckm",int(meters/1000.));
|
|
return String.Format("\cj%d\ccm",int(meters));
|
|
}
|
|
|
|
private void DrawTarget()
|
|
{
|
|
// don't draw when dead or with automap open
|
|
if ( (CPlayer.health <= 0) || automapactive ) return;
|
|
if ( !targettag ) targettag = CVar.GetCVar('swwm_targettags',players[consoleplayer]);
|
|
viewport.FromHud();
|
|
proj.CacheResolution();
|
|
proj.CacheFov(players[consoleplayer].fov);
|
|
proj.Reorient(ViewPos,ViewRot);
|
|
proj.BeginProjection();
|
|
Vector3 vdir = (cos(ViewRot.x)*cos(ViewRot.y),sin(ViewRot.x)*cos(ViewRot.y),-sin(ViewRot.y));
|
|
bool thesight = !!CPlayer.mo.FindInventory("Omnisight");
|
|
// points of interest
|
|
String tag;
|
|
if ( thesight )
|
|
{
|
|
for ( int i=0; i<intpoints.Size(); i++ )
|
|
{
|
|
let poi = intpoints[i];
|
|
if ( !poi ) continue;
|
|
Vector3 tdir = Level.Vec3Diff(ViewPos,poi.pos);
|
|
proj.ProjectWorldPos(ViewPos+tdir);
|
|
Vector2 npos = proj.ProjectToNormal();
|
|
if ( !proj.IsInFront() ) continue;
|
|
Vector2 vpos = viewport.SceneToWindow(npos);
|
|
if ( poi.type == INT_Key ) tag = String.Format("\cf%s\c-",StringTable.Localize(poi.trackedkey.GetTag()));
|
|
else if ( poi.type == INT_Exit )
|
|
{
|
|
if ( poi.trackedline.special == Exit_Secret )
|
|
tag = String.Format("\cx%s\c-",StringTable.Localize("$SWWM_SEXIT"));
|
|
else tag = String.Format("\cy%s\c-",StringTable.Localize("$SWWM_NEXIT"));
|
|
}
|
|
Font fnt = LangFont(mMiniwiFont);
|
|
Screen.DrawText(fnt,Font.CR_WHITE,(vpos.x-hs.x*fnt.StringWidth(tag)/2.)/hs.x,(vpos.y-hs.y*fnt.GetHeight()/2.)/hs.y,tag,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
tag = String.Format("\cu(%s\cu)\c-",FormatDist(tdir.length()));
|
|
Screen.DrawText(fnt,Font.CR_WHITE,(vpos.x-hs.x*fnt.StringWidth(tag)/2.)/hs.x,(vpos.y+hs.y*fnt.GetHeight()/2.)/hs.y,tag,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
// targetting array
|
|
int displayed = 0;
|
|
for ( int i=0; i<trackers.Size(); i++ )
|
|
{
|
|
let targ = trackers[i];
|
|
if ( !targ ) continue;
|
|
// cap to 40, so the screen isn't too cluttered
|
|
if ( displayed++ > 40 ) break;
|
|
Vector3 tdir = Level.Vec3Diff(ViewPos,targ.prevpos*(1.-fractic)+targ.pos*fractic);
|
|
proj.ProjectWorldPos(ViewPos+tdir);
|
|
Vector2 npos = proj.ProjectToNormal();
|
|
if ( !proj.IsInFront() ) continue;
|
|
Vector2 vpos = viewport.SceneToWindow(npos);
|
|
tag = targ.mytag;
|
|
if ( targ.legged )
|
|
{
|
|
if ( StringTable.Localize("$SWWM_LEGPREFIX") == "R" ) tag = tag..StringTable.Localize("$SWWM_LEG");
|
|
else tag = StringTable.Localize("$SWWM_LEG")..tag;
|
|
}
|
|
int mtime = 35;
|
|
if ( thesight && (targ.lasthealth > 0) ) mtime += 105;
|
|
double alph = clamp(((targ.updated+mtime)-level.maptime)/35.,0.,1.);
|
|
Vector2 barsiz = TexMan.GetScaledSize(EnemyBTex);
|
|
barsiz.x *= hs.x;
|
|
barsiz.y *= hs.y;
|
|
Vector2 barpos = vpos-(barsiz/2.);
|
|
barpos.y -= 16.;
|
|
Font fnt = LangFont(mMiniwiFont);
|
|
if ( targettag.GetBool() || targ.myplayer && (tag != "") )
|
|
Screen.DrawText(fnt,Font.CR_WHITE,(barpos.x+barsiz.x/2.-(fnt.StringWidth(tag)*hs.x)/2.)/hs.x,(barpos.y-fnt.GetHeight()*hs.y)/hs.y,tag,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
Screen.DrawTexture(EnemyBTex,false,barpos.x/hs.x,barpos.y/hs.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
int ht = clamp(targ.intp.GetValue(),0,targ.maxhealth*10);
|
|
int hw = int((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.DrawTexture(EnemyHTex[4],false,(barpos.x+2*hs.x)/hs.x,(barpos.y+2*hs.y)/hs.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRight,hw);
|
|
continue;
|
|
}
|
|
Screen.DrawTexture(EnemyHTex[0],false,(barpos.x+2*hs.x)/hs.x,(barpos.y+2*hs.y)/hs.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRight,hw);
|
|
if ( ht > targ.maxhealth )
|
|
{
|
|
hw = int((min(ht-targ.maxhealth,targ.maxhealth)*50.)/targ.maxhealth);
|
|
Screen.DrawTexture(EnemyHTex[1],false,(barpos.x+2*hs.x)/hs.x,(barpos.y+2*hs.y)/hs.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRight,hw);
|
|
}
|
|
if ( ht > targ.maxhealth*2 )
|
|
{
|
|
hw = int((min(ht-targ.maxhealth*2,targ.maxhealth*3)*50.)/(targ.maxhealth*3));
|
|
Screen.DrawTexture(EnemyHTex[2],false,(barpos.x+2*hs.x)/hs.x,(barpos.y+2*hs.y)/hs.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRight,hw);
|
|
}
|
|
if ( ht > targ.maxhealth*5 )
|
|
{
|
|
hw = int((min(ht-targ.maxhealth*5,targ.maxhealth*5)*50.)/(targ.maxhealth*5));
|
|
Screen.DrawTexture(EnemyHTex[3],false,(barpos.x+2*hs.x)/hs.x,(barpos.y+2*hs.y)/hs.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_WindowRight,hw);
|
|
}
|
|
}
|
|
if ( !scorebonus ) scorebonus = CVar.GetCVar('swwm_scorebonus',players[consoleplayer]);
|
|
// floating kill scores and others
|
|
for ( int i=0; i<scoreobjs.Size(); i++ )
|
|
{
|
|
let snum = scoreobjs[i];
|
|
if ( !snum ) continue;
|
|
Vector3 tdir = Level.Vec3Diff(ViewPos,snum.pos);
|
|
proj.ProjectWorldPos(ViewPos+tdir);
|
|
Vector2 npos = proj.ProjectToNormal();
|
|
if ( !proj.IsInFront() ) continue;
|
|
Vector2 vpos = viewport.SceneToWindow(npos);
|
|
if ( snum.str != "" )
|
|
{
|
|
if ( !scorebonus.GetBool() ) continue;
|
|
tag = StringTable.Localize(snum.str);
|
|
if ( snum.score == int.max ) tag.AppendFormat(" %s",StringTable.Localize("$SWWM_MAX"));
|
|
else if ( snum.score > 0 ) tag.AppendFormat(" x%d",snum.score);
|
|
}
|
|
else tag = String.Format("%+d",snum.score);
|
|
double alph = clamp((snum.lifespan+fractic)/35.,0.,1.);
|
|
Vector2 fo = (0,0);
|
|
if ( snum.tcolor == Font.CR_RED )
|
|
{
|
|
// damage falls down
|
|
int initspd = (128-snum.seed);
|
|
if ( initspd >= 0 && initspd < 32 ) initspd = 32;
|
|
if ( initspd < 0 && initspd > -32 ) initspd = -32;
|
|
int boostup = 64+snum.seed2/2;
|
|
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 if ( snum.tcolor == Font.CR_GREEN )
|
|
{
|
|
// health falls up (?)
|
|
int initspd = (128-snum.seed);
|
|
if ( initspd >= 0 && initspd < 32 ) initspd = 32;
|
|
if ( initspd < 0 && initspd > -32 ) initspd = -32;
|
|
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 fo.y = snum.initialspan-(snum.lifespan-fractic); // score rises linearly
|
|
Font fnt = (snum.str!="")?LangFont(mMiniwiFont):mMiniwiFont.mFont;
|
|
fo.y += snum.ofs*fnt.GetHeight();
|
|
Screen.DrawText(fnt,snum.tcolor,(vpos.x-hs.x*(fo.x+fnt.StringWidth(tag)/2.))/hs.x,(vpos.y-hs.y*(fo.y+(fnt.GetHeight()/2.)))/hs.y,tag,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
}
|
|
}
|
|
|
|
private void DrawScore()
|
|
{
|
|
Screen.DrawTexture(ScoreTex,false,ss.x-(margin+73),margin,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,ss.x-(margin+58),margin+1,String.Format("%09d",clamp(ScoreInter.GetValue(),0,999999999)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// in doom/heretic (draw key icons)
|
|
if ( !(gameinfo.gametype&(GAME_DOOMCHEX|GAME_HERETIC)) ) return;
|
|
Vector2 keypos = (ss.x-(margin+2),margin+19);
|
|
int rowc = 0;
|
|
double roww = 0;
|
|
for ( Inventory i=CPlayer.mo.Inv; i; i=i.Inv )
|
|
{
|
|
if ( !(i is "Key") || !i.Icon.IsValid() ) continue;
|
|
Vector2 siz = TexMan.GetScaledSize(i.Icon);
|
|
Screen.DrawTexture(i.Icon,false,keypos.x-siz.x,keypos.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
keypos.y += siz.y+2;
|
|
roww = max(roww,siz.x);
|
|
if ( ++rowc == 3 )
|
|
{
|
|
keypos.y = margin+19;
|
|
keypos.X -= roww+2;
|
|
roww = rowc = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawInvIcon( Inventory i, double xx, double yy, double alpha = 1., bool forceamt = false, bool aspowerup = false )
|
|
{
|
|
if ( !i || !i.Icon.IsValid() ) return;
|
|
Vector2 scl = TexMan.GetScaledSize(i.Icon);
|
|
double mscl = 30./max(scl.x,scl.y);
|
|
double dw = (ss.x/mscl), dh = (ss.y/mscl);
|
|
double dx = (xx+(30-scl.x*mscl)/2)/mscl, dy = (yy+(30-scl.y*mscl)/2)/mscl;
|
|
if ( i is 'Powerup' )
|
|
{
|
|
Screen.DrawTexture(i.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,Powerup(i).IsBlinking()?alpha*.5:alpha,DTA_TopOffset,0,DTA_LeftOffset,0);
|
|
String nstr = String.Format("%ds",Powerup(i).EffectTics/Thinker.TICRATE);
|
|
int len = mTewiFont.mFont.StringWidth(nstr);
|
|
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,Powerup(i).IsBlinking()?alpha*.5:alpha);
|
|
return;
|
|
}
|
|
if ( (i is 'SWWMLamp') && aspowerup )
|
|
{
|
|
Screen.DrawTexture(i.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,SWWMLamp(i).isBlinking()?alpha*.5:alpha,DTA_TopOffset,0,DTA_LeftOffset,0);
|
|
String nstr = String.Format("%d%%",SWWMLamp(i).Charge);
|
|
int len = mTewiFont.mFont.StringWidth(nstr);
|
|
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,SWWMLamp(i).isBlinking()?alpha*.5:alpha);
|
|
return;
|
|
}
|
|
Screen.DrawTexture(i.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,alpha,DTA_TopOffset,0,DTA_LeftOffset,0);
|
|
if ( (i.Amount > 1) || forceamt )
|
|
{
|
|
String nstr;
|
|
if ( (i.Amount > 99999) && !forceamt ) nstr = "99999";
|
|
else nstr = String.Format("%d",i.Amount);
|
|
int len = mTewiFont.mFont.StringWidth(nstr);
|
|
Screen.DrawText(mTewiFont.mFont,Font.CR_FIRE,(xx+30)-len,(yy+30)-11,nstr,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,alpha);
|
|
}
|
|
}
|
|
|
|
private void DrawInventory()
|
|
{
|
|
// active items (armor / powerups)
|
|
double xx = margin+2;
|
|
double yy = ss.y-(margin+60);
|
|
if ( CPlayer.mo.InvSel && !isInventoryBarVisible() ) yy -= 34;
|
|
bool drewarmor = false;
|
|
for ( Inventory i=CPlayer.mo.Inv; i; i=i.Inv )
|
|
{
|
|
if ( (i.Amount <= 0) || (!(i is 'SWWMArmor') && !(i is 'BasicArmor')) ) continue;
|
|
DrawInvIcon(i,xx,yy,forceamt:true);
|
|
yy -= 34;
|
|
drewarmor = true;
|
|
}
|
|
yy = ss.y-(margin+60);
|
|
if ( drewarmor ) xx += 40;
|
|
else if ( CPlayer.mo.InvSel && !isInventoryBarVisible() ) yy -= 34;
|
|
for ( Inventory i=CPlayer.mo.Inv; i; i=i.Inv )
|
|
{
|
|
if ( (i is 'SWWMLamp') )
|
|
{
|
|
DrawInvIcon(i,xx,yy,aspowerup:true);
|
|
yy -= 34;
|
|
continue;
|
|
}
|
|
if ( !(i is 'Powerup') || (Powerup(i).EffectTics <= 0) || !(Powerup(i).Icon) ) continue;
|
|
DrawInvIcon(i,xx,yy);
|
|
yy -= 34;
|
|
}
|
|
// inventory box / bar
|
|
if ( !CPlayer.mo.InvSel ) return;
|
|
if ( isInventoryBarVisible() )
|
|
{
|
|
Array<Inventory> bar;
|
|
bar.Clear();
|
|
for ( Inventory i=CPlayer.mo.FirstInv(); i; i=i.NextInv() ) bar.Push(i);
|
|
int ps = bar.Find(CPlayer.mo.InvSel);
|
|
Inventory prev[2], next[2];
|
|
if ( bar.Size() > 1 )
|
|
{
|
|
if ( ps+1 >= bar.Size() ) next[0] = bar[0];
|
|
else next[0] = bar[ps+1];
|
|
if ( ps-1 < 0 ) prev[0] = bar[bar.Size()-1];
|
|
else prev[0] = bar[ps-1];
|
|
}
|
|
if ( bar.Size() > 2 )
|
|
{
|
|
if ( ps+2 >= bar.Size() ) next[1] = bar[(ps+2)-bar.Size()];
|
|
else next[1] = bar[ps+2];
|
|
if ( ps-2 < 0 ) prev[1] = bar[bar.Size()+(ps-2)];
|
|
else prev[1] = bar[ps-2];
|
|
}
|
|
xx = (ss.x-34)/2;
|
|
yy = (ss.y+64)/2;
|
|
Screen.DrawTexture(InventoryTex,false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
DrawInvIcon(CPlayer.mo.InvSel,xx+2,yy+2);
|
|
DrawInvIcon(prev[0],xx-32,yy+2,2./3.);
|
|
DrawInvIcon(prev[1],xx-66,yy+2,1./3.);
|
|
DrawInvIcon(next[0],xx+36,yy+2,2./3.);
|
|
DrawInvIcon(next[1],xx+70,yy+2,1./3.);
|
|
return;
|
|
}
|
|
Screen.DrawTexture(InventoryTex,false,margin,ss.y-(margin+61),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
DrawInvIcon(CPlayer.mo.InvSel,margin+2,ss.y-(margin+59));
|
|
}
|
|
|
|
private void DrawWeapon()
|
|
{
|
|
if ( CPlayer.ReadyWeapon is 'SWWMWeapon' ) SWWMWeapon(CPlayer.ReadyWeapon).DrawWeapon(FracTic,ss.x-margin,ss.y-(margin+28),hs,ss);
|
|
else
|
|
{
|
|
// TODO generic display
|
|
}
|
|
Screen.DrawTexture(WeaponTex,false,ss.x-(margin+61),ss.y-(margin+29),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
double xx = ss.x-(margin+58), yy = ss.y-(margin+29);
|
|
for ( int i=1; i<=10; i++ )
|
|
{
|
|
int ncolor = Font.CR_WHITE;
|
|
if ( !CPlayer.HasWeaponsInSlot(i%10) ) ncolor = Font.CR_DARKGRAY;
|
|
else if ( CPlayer.PendingWeapon && (CPlayer.PendingWeapon != WP_NOCHANGE) && (CPlayer.PendingWeapon.SlotNumber == (i%10)) ) ncolor = Font.CR_FIRE;
|
|
else if ( (!CPlayer.PendingWeapon || (CPlayer.PendingWeapon == WP_NOCHANGE)) && CPlayer.ReadyWeapon && (CPlayer.ReadyWeapon.SlotNumber == (i%10)) ) ncolor = Font.CR_FIRE;
|
|
else
|
|
{
|
|
bool hasammo = false;
|
|
for ( Inventory inv=CPlayer.mo.Inv; inv; inv=inv.Inv )
|
|
{
|
|
bool dummy;
|
|
int slot;
|
|
if ( inv is 'Weapon' ) [dummy, slot] = CPlayer.weapons.LocateWeapon(Weapon(inv).GetClass());
|
|
if ( slot != (i%10) ) continue;
|
|
// CheckAmmo can't be called from ui, so we have to improvise
|
|
// for SWWM weapons I made a function for this at least
|
|
if ( (inv is 'SWWMWeapon') && SWWMWeapon(inv).ReportHUDAmmo() )
|
|
hasammo = true;
|
|
else if ( !(inv is 'SWWMWeapon') && ((!Weapon(inv).Ammo1 || (Weapon(inv).Ammo1.Amount > 0)) || (Weapon(inv).Ammo2 && (Weapon(inv).Ammo2.Amount > 0))) )
|
|
hasammo = true;
|
|
}
|
|
if ( !hasammo ) ncolor = Font.CR_RED;
|
|
}
|
|
Screen.DrawText(mTewiFont.mFont,ncolor,xx,yy,String.Format("%d",(i%10)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx += 12;
|
|
if ( i == 5 )
|
|
{
|
|
xx = ss.x-(margin+58);
|
|
yy += 14;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawStatus()
|
|
{
|
|
Screen.DrawTexture(StatusTex,false,margin,ss.y-(margin+27),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
let d = Demolitionist(CPlayer.mo);
|
|
int dw = DashInter.GetValue();
|
|
double alph = .6;
|
|
if ( !d || (d.dashfuel > 20) || ((gametic%10) < 5) ) alph = 1.;
|
|
Screen.DrawTexture(DashTex,false,margin+2,ss.y-(margin+21),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,dw,DTA_Alpha,alph);
|
|
int fw = FuelInter.GetValue();
|
|
Screen.DrawTexture(FuelTex,false,margin+2,ss.y-(margin+25),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,fw);
|
|
int ht = clamp(HealthInter.GetValue(),0,10000);
|
|
int hw = min(ht,100);
|
|
if ( isInvulnerable() || CPlayer.mo.FindInventory("InvinciballPower") )
|
|
{
|
|
Screen.DrawTexture(HealthTex[4],false,margin+2,ss.y-(margin+15),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(mTewiFont.mFont,Font.CR_WHITE,margin+108,ss.y-(margin+16),String.Format("%3d",Random[HudStuff](0,999)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
Screen.DrawTexture(HealthTex[0],false,margin+2,ss.y-(margin+15),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,hw);
|
|
if ( ht > 100 )
|
|
{
|
|
hw = min(ht-100,100);
|
|
Screen.DrawTexture(HealthTex[1],false,margin+2,ss.y-(margin+15),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,hw);
|
|
}
|
|
if ( ht > 200 )
|
|
{
|
|
hw = int(min(ht-200,300)/3.);
|
|
Screen.DrawTexture(HealthTex[2],false,margin+2,ss.y-(margin+15),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,hw);
|
|
}
|
|
if ( ht > 500 )
|
|
{
|
|
hw = int(min(ht-500,500)/5.);
|
|
Screen.DrawTexture(HealthTex[3],false,margin+2,ss.y-(margin+15),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,hw);
|
|
}
|
|
int hcolor = Font.CR_RED;
|
|
if ( ht > 500 ) hcolor = Font.CR_GOLD;
|
|
else if ( ht > 200 ) hcolor = Font.CR_PURPLE;
|
|
else if ( ht > 100 ) hcolor = Font.CR_CYAN;
|
|
Screen.DrawText(mTewiFont.mFont,hcolor,margin+108,ss.y-(margin+16),String.Format("%3d",clamp(ht,0,999)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
|
|
private void DrawMessages()
|
|
{
|
|
if ( !chatduration ) chatduration = CVar.GetCVar('swwm_chatduration',players[consoleplayer]);
|
|
if ( !msgduration ) msgduration = CVar.GetCVar('swwm_msgduration',players[consoleplayer]);
|
|
if ( !pickduration ) pickduration = CVar.GetCVar('swwm_pickduration',players[consoleplayer]);
|
|
if ( !pickcol ) pickcol = CVar.GetCVar('msg0color',players[consoleplayer]);
|
|
if ( !obitcol ) obitcol = CVar.GetCVar('msg1color',players[consoleplayer]);
|
|
if ( !critcol ) critcol = CVar.GetCVar('msg2color',players[consoleplayer]);
|
|
if ( !chatcol ) chatcol = CVar.GetCVar('msg3color',players[consoleplayer]);
|
|
if ( !teamcol ) teamcol = CVar.GetCVar('msg4color',players[consoleplayer]);
|
|
// common message area
|
|
if ( MainQueue.Size() > 0 )
|
|
{
|
|
int mstart = max(0,MainQueue.Size()-(1+maxchat[chatopen>=gametic].GetInt()));
|
|
double xx = margin, yy = margin;
|
|
bool smol = (ss.x<640);
|
|
Screen.DrawTexture(ChatTex[smol?3:0],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy++;
|
|
for ( int i=mstart; i<MainQueue.Size(); i++ )
|
|
{
|
|
int col = critcol.GetInt();
|
|
if ( MainQueue[i].type == PRINT_MEDIUM ) col = obitcol.GetInt();
|
|
else if ( MainQueue[i].type == PRINT_CHAT ) col = chatcol.GetInt();
|
|
else if ( MainQueue[i].type == PRINT_TEAMCHAT ) col = teamcol.GetInt();
|
|
String cstr = MainQueue[i].str;
|
|
if ( MainQueue[i].rep > 1 ) cstr.AppendFormat(" (x%d)",MainQueue[i].rep);
|
|
int curtime = MainQueue[i].tic-level.maptime;
|
|
if ( MainQueue[i].type < PRINT_CHAT ) curtime += 35*msgduration.GetInt();
|
|
else curtime += 35*chatduration.GetInt();
|
|
double alph = clamp(curtime/20.,0.,1.);
|
|
Font fnt = LangFont(mTewiFont);
|
|
BrokenLines l = fnt.BreakLines(cstr,smol?211:361);
|
|
for ( int j=0; j<l.Count(); j++ )
|
|
{
|
|
Screen.DrawTexture(ChatTex[smol?4:1],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(fnt,col,xx+4,yy,l.StringAt(j),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
yy += 13;
|
|
}
|
|
}
|
|
Screen.DrawTexture(ChatTex[smol?5:2],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
// pickup messages
|
|
if ( PickupQueue.Size() > 0 )
|
|
{
|
|
// reverse order since they're drawn bottom to top
|
|
int mend = max(0,PickupQueue.Size()-(1+maxpick.GetInt()));
|
|
double yy = ss.y-(margin+50);
|
|
for ( int i=PickupQueue.Size()-1; i>=mend; i-- )
|
|
{
|
|
String cstr = PickupQueue[i].str;
|
|
if ( PickupQueue[i].rep > 1 ) cstr.AppendFormat(" (x%d)",PickupQueue[i].rep);
|
|
int curtime = (PickupQueue[i].tic+35*pickduration.GetInt())-level.maptime;
|
|
double alph = clamp(curtime/20.,0.,1.);
|
|
Font fnt = LangFont(mTewiFont);
|
|
BrokenLines l = fnt.BreakLines(cstr,int(ss.x*.75));
|
|
int maxlen = 0;
|
|
for ( int j=0; j<l.Count(); j++ )
|
|
{
|
|
int len = fnt.StringWidth(l.StringAt(j));
|
|
if ( len > maxlen ) maxlen = len;
|
|
}
|
|
int h = fnt.GetHeight();
|
|
double xx = (ss.x-maxlen)/2.;
|
|
Screen.Dim("Black",.8*alph,int((xx-6)*hs.x),int((yy-h*(l.Count()-1))*hs.y),int((maxlen+12)*hs.x),int((h*l.Count()+4)*hs.y));
|
|
for ( int j=l.Count()-1; j>=0; j-- )
|
|
{
|
|
int len = fnt.StringWidth(l.StringAt(j));
|
|
xx = (ss.x-len)/2.;
|
|
Screen.DrawText(fnt,pickcol.GetInt(),xx,yy+2,l.StringAt(j),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
yy -= h;
|
|
}
|
|
yy -= 6;
|
|
}
|
|
}
|
|
}
|
|
|
|
override bool DrawChat( String txt )
|
|
{
|
|
// ignore during intermission
|
|
if ( gamestate != GS_LEVEL ) return false;
|
|
chatopen = gametic+1; // have to add 1 because DrawChat is called after everything else
|
|
double xx = 2;
|
|
double yy = ss.y-14;
|
|
Screen.Dim("Black",.8,0,Screen.GetHeight()-int(15*hs.y),Screen.GetWidth(),int(15*hs.y));
|
|
String pname = players[consoleplayer].GetUserName();
|
|
// strip colors
|
|
SWWMUtility.StripColor(pname);
|
|
String fullstr = String.Format("\cq%s\cd@\cqdemolitionist%d\cn ~ \c-wall %s_",pname,consoleplayer+1,txt);
|
|
Font fnt = LangFont(mTewiFont);
|
|
// cut out to fit
|
|
int w = fnt.StringWidth(fullstr);
|
|
if ( w > ss.x-4 )
|
|
{
|
|
// draw trailing dots
|
|
Screen.DrawText(fnt,Font.CR_WHITE,xx,yy,"...",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// shift back
|
|
xx -= w-(ss.x-4);
|
|
// draw trimmed
|
|
Screen.DrawText(fnt,Font.CR_WHITE,xx,yy,fullstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ClipLeft,int(26*hs.x));
|
|
}
|
|
else Screen.DrawText(fnt,Font.CR_WHITE,xx,yy,fullstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return true;
|
|
}
|
|
|
|
override void DrawPowerups()
|
|
{
|
|
// don't do anything
|
|
}
|
|
|
|
private void DrawDeath()
|
|
{
|
|
// death prompt
|
|
let demo = Demolitionist(CPlayer.mo);
|
|
if ( !demo || (CPlayer.Health > 0) ) return;
|
|
String str;
|
|
double alph;
|
|
int len;
|
|
double xx, yy;
|
|
Font fnt;
|
|
if ( demo.player.viewheight <= 6 )
|
|
{
|
|
Screen.Dim("Black",min(demo.deadtimer/80.,1.),0,0,Screen.GetWidth(),Screen.GetHeight());
|
|
if ( demo.revivefail > level.maptime )
|
|
{
|
|
Screen.Dim("Red",clamp((demo.revivefail-level.maptime)/60.,0.,.2),0,0,Screen.GetWidth(),Screen.GetHeight());
|
|
str = StringTable.Localize("$SWWM_REFAIL");
|
|
fnt = LangFont(mTewiFont);
|
|
len = fnt.StringWidth(str);
|
|
xx = (ss.x-len)/2.;
|
|
yy = ss.y-48;
|
|
if ( (gametic%16) < 8 )
|
|
Screen.DrawText(fnt,Font.CR_RED,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
alph = clamp((demo.deadtimer-60)/60.,0.,1.);
|
|
str = String.Format(StringTable.Localize("$SWWM_URDED"),CPlayer.GetUserName());
|
|
fnt = LangFont(mTewiFont);
|
|
len = fnt.StringWidth(str);
|
|
xx = (ss.x-len)/2.;
|
|
yy = (ss.y-fnt.GetHeight()*4)/2.;
|
|
Screen.DrawText(fnt,Font.CR_RED,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
alph = clamp((demo.deadtimer-140)/60.,0.,1.);
|
|
str = String.Format(StringTable.Localize("$SWWM_URDED2"),CPlayer.GetUserName());
|
|
fnt = LangFont(mTewiFont);
|
|
len = fnt.StringWidth(str);
|
|
xx = (ss.x-len)/2.;
|
|
yy = ss.y/2.;
|
|
Screen.DrawText(fnt,Font.CR_WHITE,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
if ( !swwm_revive )
|
|
return;
|
|
alph = clamp((demo.deadtimer-160)/60.,0.,1.);
|
|
str = String.Format(StringTable.Localize("$SWWM_URDED3"),CPlayer.GetUserName());
|
|
fnt = LangFont(mTewiFont);
|
|
len = fnt.StringWidth(str);
|
|
xx = (ss.x-len)/2.;
|
|
yy = (ss.y+fnt.GetHeight()*2)/2.;
|
|
Screen.DrawText(fnt,Font.CR_WHITE,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
|
|
}
|
|
}
|
|
|
|
override void Draw( int state, double TicFrac )
|
|
{
|
|
Super.Draw(state,TicFrac);
|
|
if ( (state != HUD_StatusBar) && (state != HUD_Fullscreen) ) return;
|
|
if ( !safezone ) safezone = CVar.GetCVar('swwm_hudmargin',players[consoleplayer]);
|
|
if ( !maxchat[0] ) maxchat[0] = CVar.GetCVar('swwm_maxshown',players[consoleplayer]);
|
|
if ( !maxchat[1] ) maxchat[1] = CVar.GetCVar('swwm_maxshownbig',players[consoleplayer]);
|
|
if ( !maxpick ) maxpick = CVar.GetCVar('swwm_maxpickup',players[consoleplayer]);
|
|
BeginHUD();
|
|
hs = GetHUDScale();
|
|
ss = (Screen.GetWidth()/hs.x,Screen.GetHeight()/hs.y);
|
|
margin = clamp(safezone.GetInt(),0,(ss.x<640)?10:40);
|
|
FracTic = TicFrac;
|
|
DrawTarget();
|
|
DrawScore();
|
|
DrawInventory();
|
|
DrawStatus();
|
|
DrawWeapon();
|
|
DrawMessages();
|
|
DrawDeath();
|
|
}
|
|
}
|