stinger_m/zscript/unrealhud.zsc

1048 lines
38 KiB
Text

// An almost 1:1 recreation of the Unreal 1 HUD
Class UnrealHUD : BaseStatusBar
{
double FracTic;
// for easy access to ammo slots
UnrealMainHandler hnd;
// Unreal HUD variables
Color RedColor, GreenColor, BlackColor;
int HudMode;
// Helpers
Vector2 scalev;
double CurX, CurY, ClipX, ClipY;
Color DrawColor;
ViewTracer vtracer;
Actor lastseen;
int lastseentic, Count;
// Fonts
Font LargeFont, LargeRedFont, UBigFont, MedFont, WhiteFont, TinyFont, TinyWhiteFont, TinyRedFont;
HUDFont mMapFont;
// Common Textures
TextureID HalfHud, HudLine, HudAmmo, IconHeal, IconSkul, IconSel, IconBase, KeyIcons[7];
// messaging stuff
String PickupMsg;
int PickupMsgTic;
String ShortMsg[4];
int ShortMsgTic[4];
int ShortMsgCol[4];
String MidPrintStr;
int MidPrintTic;
bool MidPrintLarge;
Weapon lastwep;
String ntagstr;
int ntagtic;
// 0.83 HUD stuff
Array<String> OldAmmo;
Array<Class<Inventory> > OldAmmoType;
Array<String> OldArmor;
Array<Class<Inventory> > OldArmorType;
String OldKeys[7];
HUDFont mOldDigits, mOldDigitsSmall;
Font OldLargeFont, OldSmallFont;
// Translations
int RedIcon;
// Translator menu interaction
transient bool bTranslatorActive;
override void Init()
{
Super.Init();
SetSize(64,640,400);
// Initialize
Count = 0;
vtracer = new("ViewTracer");
RedColor = "FF 00 00";
GreenColor = "00 FF 00";
BlackColor = "00 00 00";
DrawColor = "FF FF FF";
LargeFont = Font.GetFont('ULargeFont');
LargeRedFont = Font.GetFont('ULargeRedFont');
UBigFont = Font.GetFont('UBigFont');
MedFont = Font.GetFont('UMedFont');
WhiteFont = Font.GetFont('UWhiteFont');
TinyFont = Font.GetFont('UTinyFont');
TinyWhiteFont = Font.GetFont('UTinyWhiteFont');
TinyRedFont = Font.GetFont('UTinyRedFont');
HalfHud = TexMan.CheckForTexture("HalfHud",TexMan.Type_Any);
HudLine = TexMan.CheckForTexture("HudLine",TexMan.Type_Any);
HudAmmo = TexMan.CheckForTexture("HudAmmo",TexMan.Type_Any);
IconHeal = TexMan.CheckForTexture("IconHeal",TexMan.Type_Any);
IconSkul = TexMan.CheckForTexture("IconSkul",TexMan.Type_Any);
IconSel = TexMan.CheckForTexture("IconSel",TexMan.Type_Any);
IconBase = TexMan.CheckForTexture("IconBase",TexMan.Type_Any);
RedIcon = Translation.GetID('RedIcon');
KeyIcons[0] = TexMan.CheckForTexture("I_KeyR",TexMan.Type_Any);
KeyIcons[1] = TexMan.CheckForTexture("I_KeyB",TexMan.Type_Any);
KeyIcons[2] = TexMan.CheckForTexture("I_KeyY",TexMan.Type_Any);
KeyIcons[3] = TexMan.CheckForTexture("I_SkullR",TexMan.Type_Any);
KeyIcons[4] = TexMan.CheckForTexture("I_SkullB",TexMan.Type_Any);
KeyIcons[5] = TexMan.CheckForTexture("I_SkullY",TexMan.Type_Any);
KeyIcons[6] = TexMan.CheckForTexture("I_KeyG",TexMan.Type_Any);
mOldDigits = HUDFont.Create(Font.GetFont('U083Digits'),26,Mono_CellLeft);
mOldDigitsSmall = HUDFont.Create(Font.GetFont('U083DigitsSmall'),13,Mono_CellLeft);
mMapFont = HUDFont.Create(WhiteFont);
OldLargeFont = Font.GetFont('UOldLargeFont');
OldSmallFont = Font.GetFont('UOldSmallFont');
// load icon lists
Array<String> lst, ent;
String dat;
for ( int lmp = Wads.FindLump("oldammoicons.txt"); lmp > 0; lmp = Wads.FindLump("oldammoicons.txt",lmp+1) )
{
dat = Wads.ReadLump(lmp);
lst.Clear();
dat.Split(lst,"\n",0);
for ( int i=0; i<lst.Size(); i++ )
{
if ( (lst[i].Length() <= 0) || (lst[i].Left(1) ~== "#") ) continue;
ent.Clear();
lst[i].Split(ent,",",0);
if ( ent.Size() != 2 ) continue;
Class<Inventory> i = ent[1];
if ( !i ) continue;
OldAmmo.Push(ent[0]);
OldAmmoType.Push(i);
}
}
for ( int lmp = Wads.FindLump("oldarmoricons.txt"); lmp > 0; lmp = Wads.FindLump("oldarmoricons.txt",lmp+1) )
{
dat = Wads.ReadLump(lmp);
lst.Clear();
dat.Split(lst,"\n",0);
for ( int i=0; i<lst.Size(); i++ )
{
if ( (lst[i].Length() <= 0) || (lst[i].Left(1) ~== "#") ) continue;
ent.Clear();
lst[i].Split(ent,",",0);
if ( ent.Size() != 2 ) continue;
Class<Inventory> i = ent[1];
if ( !i ) continue;
OldArmor.Push(ent[0]);
OldArmorType.Push(i);
}
}
OldKeys[0] = "Redk083";
OldKeys[1] = "Bluek083";
OldKeys[2] = "Goldk083";
OldKeys[3] = "Rskul083";
OldKeys[4] = "Bskul083";
OldKeys[5] = "Gskul083";
OldKeys[6] = "Grenk083";
}
override void Draw( int state, double TicFrac )
{
// make sure vanilla nametags don't display
DetachMessageID(0x5745504e); // WEPN
DetachMessageID(0x53494e56); // SINV
// also try with different endianness, just in case
DetachMessageID(0x4e504557); // WEPN
DetachMessageID(0x564e4953); // SINV
Super.Draw(state,TicFrac);
FracTic = TicFrac;
HudMode = sting_hudmode;
scalev.x = scalev.y = hud_scale;
if ( scalev.x <= 0 )
{
scalev.x = CleanXFac_1;
scalev.y = CleanYFac_1;
}
ClipX = Screen.GetWidth()/scalev.x;
ClipY = Screen.GetHeight()/scalev.y;
CurX = 0;
CurY = 0;
double lbottom = Screen.GetHeight()-32*scalev.y;
for ( Inventory i=CPlayer.mo.inv; i; i=i.inv )
if ( i is 'UnrealInventory' )
UnrealInventory(i).PreRender(lbottom);
if ( CPlayer.ReadyWeapon is 'UTWeapon' )
UTWeapon(CPlayer.ReadyWeapon).PreRender(lbottom);
if ( state == HUD_Fullscreen )
{
BeginHUD();
DrawUnrealHUD();
}
else if ( state == HUD_StatusBar )
{
BeginStatusBar();
DrawUnrealBar();
}
for ( Inventory i=CPlayer.mo.inv; i; i=i.inv )
if ( i is 'UnrealInventory' )
UnrealInventory(i).PostRender(lbottom);
if ( CPlayer.ReadyWeapon is 'UTWeapon' )
UTWeapon(CPlayer.ReadyWeapon).PostRender(lbottom);
DrawIdentifyInfo(state);
DrawMessages(state);
}
private void DrawNumberOf( Inventory i, double x, double y )
{
if ( (i.Amount <= 1) && !((i is 'UnrealInventory') && UnrealInventory(i).bDRAWSPECIAL) ) return;
double TempX = CurX, TempY = CurY;
string itxt = String.Format("%d",((i is 'UnrealInventory')&&UnrealInventory(i).bDRAWSPECIAL)?i.special1:min(99999,i.Amount));
CurX += 30;
CurY += 23;
CurX -= TinyRedFont.StringWidth(itxt);
Screen.DrawText(TinyRedFont,Font.CR_UNTRANSLATED,CurX,CurY,itxt,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX = TempX;
CurY = TempY;
}
private void DrawIconValue( int n, bool bIsArmor = false )
{
if ( !HudMode || (HudMode == 3) ) return;
double TempX = CurX, TempY = CurY;
string itxt = String.Format("%d",n);
CurX -= 2;
CurY -= 6;
CurX -= TinyFont.StringWidth(itxt);
Screen.DrawText(TinyFont,Font.CR_UNTRANSLATED,CurX,CurY,itxt,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX = TempX;
CurY = TempY;
}
private void DrawHudIcon( double x, double y, Inventory i, bool bRed )
{
if ( i.Icon.IsNull() ) return;
double width = CurX;
CurX = x;
CurY = y;
// scale to fit
Vector2 scl = TexMan.GetScaledSize(i.Icon);
double mscl = 32./max(scl.x,scl.y);
double dw = (ClipX/mscl), dh = (ClipY/mscl);
double dx = (CurX+(32-scl.x*mscl)/2)/mscl, dy = (CurY+(32-scl.y*mscl)/2)/mscl;
if ( bRed )
{
Screen.DrawTexture(IconBase,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_TranslationIndex,RedIcon);
Screen.DrawTexture(i.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_TranslationIndex,RedIcon,DTA_TopOffset,0,DTA_LeftOffset,0);
}
else
{
Screen.DrawTexture(IconBase,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
Screen.DrawTexture(i.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_TopOffset,0,DTA_LeftOffset,0);
}
if ( (i is 'UnrealInventory') && (UnrealInventory(i).DefaultCharge > 0) && (UnrealInventory(i).bActive || (UnrealInventory(i).Charge < UnrealInventory(i).DefaultCharge)) )
Screen.DrawTexture(HudLine,false,CurX+2,CurY+29,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_WindowRightF,Min(28.*(UnrealInventory(i).Charge/double(UnrealInventory(i).DefaultCharge)),28.));
else if ( (i is 'UTArmor') && ((HudMode == 0) || (HudMode == 3)) )
Screen.DrawTexture(HudLine,false,CurX+2,CurY+29,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_WindowRightF,Min(28.*(i.Amount/double(i.MaxAmount)),28.));
}
private void DrawFragCount( double x, double y )
{
CurX = X;
CurY = Y;
Screen.DrawTexture(IconSkul,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX += 30;
CurY += 23;
string score = String.Format("%d",(deathmatch||teamplay)?CPlayer.fragcount:CPlayer.killcount);
CurX -= TinyWhiteFont.StringWidth(score);
Screen.DrawText(TinyWhiteFont,Font.CR_UNTRANSLATED,CurX,CurY,score,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
private void DrawInventory( double x, double y, bool bDrawOne = false, bool bNoWeapons = false )
{
bool bGotNext, bGotPrev, bGotSelected, bRed, bFlashTranslator;
Inventory Inv, Prev, Next, SelectedItem;
UTranslator translator;
double HalfHUDX, HalfHUDY;
double AmmoBarSize;
if ( (HudMode < 4) && !bNoWeapons ) // then draw HalfHUD
{
HalfHUDX = ClipX-64;
HalfHUDY = ClipY-32;
Screen.DrawTexture(HalfHUD,false,HalfHUDX,HalfHUDY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
if ( !CPlayer.mo.Inv ) return; // can this even happen?
bFlashTranslator = false;
bGotSelected = false;
bGotNext = false;
bGotPrev = false;
Prev = null;
Next = null;
SelectedItem = CPlayer.mo.InvSel;
for ( Inv=CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
{
if ( bDrawOne ) break;
// if drawing more than one inventory, find next and previous items
if ( Inv == SelectedItem ) bGotSelected = true;
else if ( Inv.bINVBAR )
{
if ( bGotSelected )
{
if ( !bGotNext )
{
Next = Inv;
bGotNext = true;
}
else if ( !bGotPrev ) Prev = Inv;
}
else
{
if ( !Next ) Next = Prev;
Prev = Inv;
bGotPrev = true;
}
}
if ( Inv is 'UTranslator' ) translator = UTranslator(Inv);
}
// drawing weapon slots differently than Unreal 1 because we have better methods here
let cw = CPlayer.ReadyWeapon;
int cwslot = -1;
if ( cw && (cw.SlotNumber != -1) ) cwslot = cw.SlotNumber;
let pw = CPlayer.PendingWeapon;
int pwslot = -1;
if ( pw && (pw != WP_NOCHANGE) && (pw.SlotNumber != -1) ) pwslot = pw.SlotNumber;
Array<Ammo> aslots[10];
// clear the arrays before work
for ( int i=0; i<10; i++ ) aslots[i].Clear();
// we need the ammo slots array, if it isn't accessible then we're fucked
if ( !hnd ) hnd = UnrealMainHandler(EventHandler.Find("UnrealMainHandler"));
if ( hnd )
{
// populate the array
for ( int i=0; i<hnd.AmmoSlots.Size(); i++ )
{
let a = Ammo(CPlayer.mo.FindInventory(hnd.AmmoSlots[i].AmmoType));
if ( !a ) continue;
for ( int j=0; j<10; j++ )
{
if ( !hnd.AmmoSlots[i].UsedInSlot[j] ) continue;
aslots[j].Push(a);
}
}
}
// draw the slots
if ( (HudMode < 4) && !bNoWeapons )
{
for ( int i=0; i<10; i++ )
{
Font cfont = TinyFont;
if ( (pwslot != -1) && (pwslot == i) || (pwslot == -1) && (cwslot == i) )
cfont = TinyWhiteFont;
int realslot = i?i:10;
CurX = HalfHUDX-3+realslot*6;
CurY = HalfHUDY+4;
if ( CPlayer.HasWeaponsInSlot(i) )
Screen.DrawText(cfont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",i),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
// Draw ammo bar(s)
int nammo = 0;
for ( int j=0; j<aslots[i].Size(); j++ ) if ( aslots[i][j].Amount ) nammo++;
if ( nammo <= 0 ) continue;
int cbar = 0;
for ( int j=0; j<aslots[i].Size(); j++ )
{
let amo = aslots[i][j];
if ( amo.Amount <= 0 ) continue;
AmmoBarSize = 16*min(1.0,amo.Amount/double(amo.MaxAmount));
CurX = HalfHUDX-3+realslot*6+(4./nammo)*cbar;
CurY = HalfHUDY+29-AmmoBarSize;
if ( (AmmoBarSize < 8) && (amo.Amount < 10) && (amo.Amount > 0) && (nammo == 1) )
{
CurY -= 9;
Screen.DrawText(TinyRedFont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",amo.Amount),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += 9;
}
DrawColor = Color(0,255,0);
if ( AmmoBarSize < 8 ) DrawColor = Color(255-int(AmmoBarSize)*30,int(AmmoBarSize)*30+40,0);
if ( !cw || (cw.Ammo1 != amo) ) DrawColor = Color(DrawColor.r/2,DrawColor.g/2,DrawColor.b/2);
if ( amo.Amount > 0 )
{
Screen.DrawTexture(HudAmmo,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_FillColor,BlackColor,DTA_DestWidthF,4./nammo,DTA_DestHeightF,AmmoBarSize);
Screen.DrawTexture(HudAmmo,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_AlphaChannel,true,DTA_FillColor,DrawColor,DTA_DestWidthF,4./nammo,DTA_DestHeightF,AmmoBarSize);
}
cbar++;
}
}
}
// flash translator icon
if ( translator ) bFlashTranslator = (translator.bNewMessage || translator.bNotNewMessage);
// draw the inventory bar
if ( (HUDMode == 5) || !SelectedItem ) return;
Count++;
if ( Count > 20 ) Count = 0;
if ( Prev && !Next && !bDrawOne ) x += 32; // this was missing from the original, causing a gap when there's only two items in the inventory
if ( Prev )
{
bRed = ((Prev is 'UnrealInventory') && UnrealInventory(Prev).bActive) || (Prev is 'Powerup') || ((Prev is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4))));
DrawHudIcon(x,y,Prev,bRed);
if ( (Prev.MaxAmount > 1) || ((Prev is 'UnrealInventory') && UnrealInventory(Prev).bDRAWSPECIAL) ) DrawNumberOf(Prev,x,y);
}
bRed = ((SelectedItem is 'UnrealInventory') && UnrealInventory(SelectedItem).bActive) || (SelectedItem is 'Powerup') || ((SelectedItem is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4))));
if ( !Next && !Prev && !bDrawOne ) DrawHudIcon(x+64,y,SelectedItem,bRed);
else DrawHudIcon(x+32,y,SelectedItem,bRed);
CurX = x+32;
if ( !Next && !Prev && !bDrawOne ) CurX = x+64;
CurY = y;
Screen.DrawTexture(IconSel,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,0.5);
if ( (SelectedItem.MaxAmount > 1) || ((SelectedItem is 'UnrealInventory') && UnrealInventory(SelectedItem).bDRAWSPECIAL) ) DrawNumberOf(SelectedItem,CurX,y);
if ( Next )
{
bRed = ((Next is 'UnrealInventory') && UnrealInventory(Next).bActive) || (Next is 'Powerup') || ((Next is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4))));
DrawHudIcon(x+64,y,Next,bRed);
if ( (Next.MaxAmount > 1) || ((Next is 'UnrealInventory') && UnrealInventory(Next).bDRAWSPECIAL) ) DrawNumberOf(Next,x+64,y);
}
}
private bool DrawArmor( double x, double y, bool bDrawOne = false, bool bCheckOnly = false )
{
bool hasdrawn = false;
int ArmorAmount = 0, CurAbs = 0;
Inventory Inv, BestArmor;
double XL, YL;
CurX = x;
CurY = y;
for ( Inv=CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
{
if ( !(Inv is 'UTArmor') ) continue;
ArmorAmount += Inv.Amount;
if ( (Inv.Amount <= 0) || Inv.Icon.IsNull() ) continue;
if ( !bDrawOne )
{
hasdrawn = true;
if ( !bCheckOnly ) DrawHudIcon(CurX,y,Inv,false);
CurX += 32;
CurY += HudMode?29:27;
if ( !bCheckOnly ) DrawIconValue(Inv.Amount);
CurY -= HudMode?29:27;
}
else if ( UTArmor(Inv).absorb > CurAbs )
{
CurAbs = UTArmor(Inv).absorb;
BestArmor = Inv;
}
}
let ba = CPlayer.mo.FindInventory("BasicArmor");
if ( ba && (ba.Amount > 0) )
{
ArmorAmount += ba.Amount;
if ( !bDrawOne )
{
hasdrawn = true;
if ( !bCheckOnly ) DrawHudIcon(CurX,y,ba,false);
CurX += 32;
CurY += HudMode?29:27;
if ( !bCheckOnly ) DrawIconValue(ba.Amount);
CurY -= HudMode?29:27;
}
}
if ( bDrawOne )
{
if ( BestArmor )
{
hasdrawn = true;
if ( !bCheckOnly ) DrawHudIcon(CurX,Y,BestArmor,false);
CurX += 32;
CurY += HudMode?29:27;
if ( !bCheckOnly ) DrawIconValue(BestArmor.Amount);
CurY -= HudMode?29:27;
}
else if ( ba && (ba.Amount > 0) )
{
hasdrawn = true;
if ( !bCheckOnly ) DrawHudIcon(CurX,Y,ba,false);
CurX += 32;
CurY += HudMode?29:27;
if ( !bCheckOnly ) DrawIconValue(ba.Amount);
CurY -= HudMode?29:27;
}
}
if ( (ArmorAmount > 0) && !HudMode )
{
hasdrawn = true;
if ( !bCheckOnly ) Screen.DrawText(LargeFont,Font.CR_UNTRANSLATED,CurX+2,Y,String.Format("%d",ArmorAmount),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
return hasdrawn;
}
private void DrawAmmo( double x, double y )
{
CurX = x;
CurY = y;
if ( !CPlayer.ReadyWeapon ) return;
int sec = -1, sec2 = -1;
bool red = false, red2 = false;
if ( CPlayer.ReadyWeapon is 'UTWeapon' )
[sec, sec2, red, red2] = UTWeapon(CPlayer.ReadyWeapon).GetClipAmount();
Font cfont = LargeFont;
if ( !CPlayer.ReadyWeapon.Ammo1 )
{
if ( CPlayer.ReadyWeapon.Icon.IsNull() ) return;
if ( !HudMode )
{
double bx = CurX;
CurX = bx-MedFont.StringWidth(String.Format("%d",sec))-2;
CurY += cfont.GetHeight()-MedFont.GetHeight()-4;
if ( sec != -1 )
Screen.DrawText(MedFont,red?Font.CR_RED:Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",sec),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX = bx-MedFont.StringWidth(String.Format("%d",sec2))-2;
CurY -= MedFont.GetHeight()+2;
if ( sec2 != -1 )
Screen.DrawText(MedFont,red2?Font.CR_RED:Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",sec2),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
CurX = x;
CurY = y;
Screen.DrawTexture(IconBase,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
// scale to fit
Vector2 scl = TexMan.GetScaledSize(CPlayer.ReadyWeapon.Icon);
double mscl = 32./max(scl.x,scl.y);
double dw = (ClipX/mscl), dh = (ClipY/mscl);
double dx = (CurX+(32-scl.x*mscl)/2)/mscl, dy = (CurY+(32-scl.y*mscl)/2)/mscl;
Screen.DrawTexture(CPlayer.ReadyWeapon.Icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_TopOffset,0,DTA_LeftOffset,0);
if ( HudMode )
{
CurX = x;
CurY = y;
Screen.DrawTexture(IconBase,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX = (x+30)-TinyFont.StringWidth(String.Format("%d",sec));
CurY = y+2;
if ( sec != -1 )
Screen.DrawText(red?TinyRedFont:TinyFont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",sec),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX = x+3;
if ( sec2 != -1 )
Screen.DrawText(red2?TinyRedFont:TinyFont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",sec2),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
return;
}
if ( CPlayer.ReadyWeapon.Ammo1.Amount <= min(9,CPlayer.ReadyWeapon.Ammo1.MaxAmount/3) ) cfont = LargeRedFont;
if ( !HudMode )
{
CurX -= cfont.StringWidth(String.Format("%d",CPlayer.ReadyWeapon.Ammo1.Amount))+2;
Screen.DrawText(cfont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",CPlayer.ReadyWeapon.Ammo1.Amount),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
double bx = CurX;
CurX = bx-MedFont.StringWidth(String.Format("%d",sec))-2;
CurY += cfont.GetHeight()-MedFont.GetHeight()-4;
if ( sec != -1 )
Screen.DrawText(MedFont,red?Font.CR_RED:Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",sec),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX = bx-MedFont.StringWidth(String.Format("%d",sec2))-2;
CurY -= MedFont.GetHeight()+2;
if ( sec2 != -1 )
Screen.DrawText(MedFont,red2?Font.CR_RED:Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",sec2),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
CurX = x;
CurY = y;
Screen.DrawTexture(IconBase,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
TextureID icon = CPlayer.ReadyWeapon.Icon.IsNull()?CPlayer.ReadyWeapon.Ammo1.Icon:CPlayer.ReadyWeapon.Icon;
// scale to fit
Vector2 scl = TexMan.GetScaledSize(icon);
double mscl = 32./max(scl.x,scl.y);
double dw = (ClipX/mscl), dh = (ClipY/mscl);
double dx = (CurX+(32-scl.x*mscl)/2)/mscl, dy = (CurY+(32-scl.y*mscl)/2)/mscl;
Screen.DrawTexture(icon,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_TopOffset,0,DTA_LeftOffset,0);
CurX += 32;
CurY += 29;
DrawIconValue(CPlayer.ReadyWeapon.Ammo1.Amount);
CurX = X+2;
CurY = Y+29;
if ( (HudMode != 1) && (HudMode != 2) && (HudMode != 4) )
Screen.DrawTexture(HudLine,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_WindowRightF,Min(28.*(CPlayer.ReadyWeapon.Ammo1.Amount/double(CPlayer.ReadyWeapon.Ammo1.MaxAmount)),28.));
if ( HudMode )
{
CurX = (x+30)-TinyFont.StringWidth(String.Format("%d",sec));
CurY = y+2;
if ( sec != -1 )
Screen.DrawText(red?TinyRedFont:TinyFont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",sec),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX = x+3;
if ( sec2 != -1 )
Screen.DrawText(red2?TinyRedFont:TinyFont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",sec2),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
}
private void DrawHealth( double x, double y )
{
CurX = X;
CurY = Y;
Font cfont = LargeFont;
if ( CPlayer.mo.Health < 25 ) cfont = LargeRedFont;
Screen.DrawTexture(IconHeal,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX += 32;
CurY += 29;
DrawIconValue(Max(0,CPlayer.mo.Health));
CurY -= 29;
if ( !HudMode ) Screen.DrawText(cfont,Font.CR_UNTRANSLATED,CurX+2,CurY,String.Format("%d",Max(0,CPlayer.mo.Health)),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurX = X+2;
CurY = Y+29;
if ( (HudMode != 1) && (HudMode != 2) && (HudMode != 4) )
Screen.DrawTexture(HudLine,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_WindowRightF,Min(28.*(CPlayer.mo.Health/double(CPlayer.mo.SpawnHealth())),28.));
}
private void DrawIdentifyInfo( int state )
{
double lalpha = 2.0-((gametic+fractic)-lastseentic)/Thinker.TICRATE;
if ( !lastseen || (lalpha <= 0) ) return;
String cl1 = "DarkGreen", cl2 = "Green";
if ( deathmatch && (lastseen.player.GetTeam() < teams.size()) )
{
cl2 = teams[lastseen.player.GetTeam()].mName;
cl1 = String.Format("Dark%s",cl2);
}
String tname = String.Format("\c[%s]%s:\c[%s] %s",cl1,StringTable.Localize("$M_NAME"),cl2,lastseen.player.GetUserName());
let fnt = (state==HUD_Fullscreen)?WhiteFont:OldSmallFont;
CurX = (ClipX-fnt.StringWidth(tname))/2;
CurY = ClipY-54;
Screen.DrawText(fnt,Font.CR_UNTRANSLATED,CurX,CurY,tname,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,lalpha/2.);
if ( !deathmatch || (lastseen.IsTeammate(CPlayer.mo)) )
{
CurY += 1.2*fnt.GetHeight();
tname = String.Format("\c[%s]%s:\c[%s] %d",cl1,StringTable.Localize("$M_HEALTH"),cl2,lastseen.Health);
Screen.DrawText(fnt,Font.CR_UNTRANSLATED,CurX,CurY,tname,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,lalpha/2.);
}
}
private void DrawKeys( double x, double y, bool leftright = false )
{
if ( deathmatch ) return; // no need to draw in DM
if ( gameinfo.gametype&(GAME_Hexen|GAME_Strife) )
{
if ( !automapactive ) return;
int kw = (gameinfo.gametype&GAME_Strife)?20:30,
kh = (gameinfo.gametype&GAME_Strife)?20:40;
int nkeys = 0;
Array<int> rows;
Array<Inventory> keys;
keys.Clear();
rows.Clear();
rows.Push(0);
for ( Inventory i=CPlayer.mo.inv; i; i=i.inv )
{
if ( !(i is 'Key') ) continue;
keys.Push(i);
if ( rows[rows.Size()-1] >= 6 ) rows.Push(1);
else rows[rows.Size()-1]++;
}
int j = 0;
CurX = (ClipX-kw);
for ( int i=0; i<rows.Size(); i++ )
{
CurY = (ClipY-rows[i]*kh)*0.5;
for ( int k=0; k<rows[i]; k++ )
{
Screen.DrawTexture(keys[j].Icon,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
j++;
CurY += kh;
}
CurX -= kw;
}
return;
}
CurX = x;
CurY = y;
int cnt = 0;
for ( int i=0; i<6; i++ )
{
if ( !CPlayer.mo.CheckKeys(i+1,false,true) ) continue;
Screen.DrawTexture(KeyIcons[((i==0)&&(gameinfo.gametype&GAME_Heretic))?6:i],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
cnt++;
if ( !(cnt%3) )
{
CurX = x;
CurY -= 16;
}
else CurX += leftright?16:-16;
}
}
private void DrawUnrealHUD()
{
if ( HudMode >= 5 )
{
// minimal hud
int ArmorAmount = 0;
for ( Inventory Inv=CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
{
if ( !(Inv is 'UTArmor') ) continue;
ArmorAmount += Inv.Amount;
}
int AmmoAmount1 = 0, AmmoAmount2 = 0;
Ammo amo1, amo2;
[amo1, amo2] = GetCurrentAmmo();
if ( amo1 )
{
AmmoAmount1 = amo1.Amount;
if ( amo2 ) AmmoAmount2 = amo2.Amount;
}
String str;
if ( amo1 && amo2 && (amo2 != amo1) ) str = String.Format(StringTable.Localize("$S_MINHUD2"),CPlayer.Health,(deathmatch||teamplay)?CPlayer.fragcount:CPlayer.killcount,AmmoAmount2,AmmoAmount1);
else str = String.Format(StringTable.Localize("$S_MINHUD"),CPlayer.Health,(deathmatch||teamplay)?CPlayer.fragcount:CPlayer.killcount,AmmoAmount1);
CurX = (ClipX-OldSmallFont.StringWidth(str))/2;
CurY = 1;
Screen.DrawText(OldSmallFont,Font.CR_WHITE,CurX,CurY,str,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
return;
}
if ( ClipX < 320 ) HudMode = 4;
// Draw Armor
if ( HudMode < 2 ) DrawArmor(0,0);
else if ( (HudMode == 3) || (HudMode == 2) ) DrawArmor(0,ClipY-32);
else if ( HudMode == 4 ) DrawArmor(ClipX-64,ClipY-64,true);
// Draw Ammo
if ( HudMode != 4 ) DrawAmmo(ClipX-96,ClipY-32);
else DrawAmmo(ClipX-32,ClipY-32);
// Draw Health
if ( HudMode < 2 ) DrawHealth(0,ClipY-32);
else if ( (HudMode == 3) || (HudMode == 2) ) DrawHealth(ClipX-128,ClipY-32);
else if ( HudMode == 4 ) DrawHealth(ClipX-64,ClipY-32);
// Display Inventory
if ( HudMode < 2 ) DrawInventory(ClipX-96,0);
else if ( HudMode == 3 ) DrawInventory(ClipX-96,ClipY-64);
else if ( HudMode == 4 ) DrawInventory(ClipX-64,ClipY-64,true);
else if ( HudMode == 2 ) DrawInventory(ClipX/2-64,ClipY-32);
if ( deathmatch )
{
// Display Frag count
if ( HudMode < 3 ) DrawFragCount(ClipX-32,ClipY-64);
else if ( HudMode == 3 ) DrawFragCount(0,ClipY-64);
else if ( HudMode == 4 ) DrawFragCount(ClipX-96,ClipY-32);
}
else
{
// Display Keys
if ( HudMode < 3 ) DrawKeys(ClipX-16,ClipY-48);
else if ( HudMode == 3 ) DrawKeys(0,ClipY-48,true);
else if ( HudMode == 4 ) DrawKeys(ClipX-80,ClipY-16);
}
}
override void ReceivedWeapon( Weapon weapn )
{
Super.ReceivedWeapon(weapn);
if ( weapn.SlotNumber == -1 ) return;
// fuckin' hell
EventHandler.SendNetworkEvent("Bar083SlotFlash",weapn.SlotNumber);
}
private void DrawUnrealBar()
{
// 0.83 status bar, just for funsies
DrawImage("Bar083",(0,336),DI_ITEM_OFFSETS);
// extra widescreen filler
bool first = true;
double base = -128;
double rx, dummy;
do
{
[rx, dummy, dummy] = StatusBarToRealCoords(base,0,HorizontalResolution);
DrawImage(first?"BarL083":"BarM083",(base,336),DI_ITEM_OFFSETS);
first = false;
base -= 128;
} while ( rx >= -128 );
first = true;
base = 640;
do
{
[rx, dummy, dummy] = StatusBarToRealCoords(base,0,HorizontalResolution);
DrawImage(first?"BarR083":"BarM083",(base,336),DI_ITEM_OFFSETS);
first = false;
base += 128;
} while ( rx < Screen.GetWidth() );
static const float slotofs[] = {525, 84, 128, 173, 216, 259, 349, 392, 436, 481};
static const float keyofs[] = {187, 211, 235, 379, 403, 427};
for ( int i=0; i<10; i++ )
{
if ( !CPlayer.HasWeaponsInSlot(i) ) continue;
bool used = (CPlayer.ReadyWeapon&&(CPlayer.ReadyWeapon.SlotNumber==i));
if ( CPlayer.PendingWeapon && (CPlayer.PendingWeapon != WP_NOCHANGE) )
used = (CPlayer.PendingWeapon.SlotNumber==i);
DrawImage(used?"Used083":"Slot083",(slotofs[i],342),DI_ITEM_OFFSETS);
}
let hnd = UnrealMainHandler(EventHandler.Find("UnrealMainHandler"));
if ( hnd )
{
for ( int i=0; i<10; i++ )
if ( hnd.slotflash[i] > gametic )
DrawImage("Flsh083",(slotofs[i],342),DI_ITEM_OFFSETS,(hnd.slotflash[i]-gametic+FracTic)/20.);
}
DrawString(mOldDigits,FormatNumber(CPlayer.health,3),(358,366),DI_TEXT_ALIGN_RIGHT);
int ArmorAmount = 0, CurAbs = -1;
Inventory BestArmor = null;
for ( Inventory Inv=CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
{
if ( !(Inv is 'UTArmor') ) continue;
ArmorAmount += Inv.Amount;
if ( Inv.Amount <= 0 ) continue;
if ( UTArmor(Inv).absorb > CurAbs )
{
CurAbs = UTArmor(Inv).absorb;
BestArmor = Inv;
}
}
let ba = CPlayer.mo.FindInventory("BasicArmor");
if ( ba ) ArmorAmount += ba.amount;
bool drawnarmor = false;
for ( int i=0; i<OldArmor.Size(); i++ )
{
if ( !(BestArmor is OldArmorType[i]) ) continue;
DrawImage(OldArmor[i],(4,340),DI_ITEM_OFFSETS);
drawnarmor = true;
break;
}
if ( !drawnarmor && ba && (ba.Amount > 0) )
DrawInventoryIcon(ba,(40,366),DI_ITEM_CENTER,1.,(-1,-1),(2.,2.));
if ( ArmorAmount ) DrawString(mOldDigits,FormatNumber(ArmorAmount,3),(167,366),DI_TEXT_ALIGN_RIGHT);
Inventory Ammo1, Ammo2;
[Ammo1, Ammo2] = GetCurrentAmmo();
if ( Ammo1 && Ammo1.Amount ) DrawString(mOldDigits,FormatNumber(Ammo1.Amount,3),(549,366),DI_TEXT_ALIGN_RIGHT);
bool drawn = false;
for ( int i=0; i<OldAmmo.Size(); i++ )
{
// match by ammo
if ( (OldAmmoType[i] is 'Ammo') && (!Ammo1 || !(Ammo1 is OldAmmoType[i])) ) continue;
// match by weapon
if ( (OldAmmoType[i] is 'Weapon') && !(CPlayer.ReadyWeapon is OldAmmoType[i]) ) continue;
DrawImage(OldAmmo[i],(560,336),DI_ITEM_OFFSETS);
drawn = true;
break;
}
if ( !drawn && Ammo1 )
DrawInventoryIcon(Ammo1,(600,366),DI_ITEM_CENTER,1.,(-1,-1),(2.,2.));
int sec = -1, sec2 = -1;
if ( CPlayer.ReadyWeapon && (CPlayer.ReadyWeapon is 'UTWeapon') )
[sec, sec2] = UTWeapon(CPlayer.ReadyWeapon).GetClipAmount();
if ( sec != -1 )
DrawString(mOldDigitsSmall,FormatNumber(sec,3),(633,378),DI_TEXT_ALIGN_RIGHT);
if ( sec2 != -1 )
DrawString(mOldDigitsSmall,FormatNumber(sec2,3),(556,378),DI_TEXT_ALIGN_LEFT);
if ( gameinfo.gametype&(GAME_Hexen|GAME_Strife) ) DrawKeys(0,0);
else
{
for ( int i=0; i<6; i++ )
{
if ( !CPlayer.mo.CheckKeys(i+1,false,true) ) continue;
DrawImage(OldKeys[((i==0)&&(gameinfo.gametype&GAME_Heretic))?6:i],(keyofs[i],366),DI_ITEM_OFFSETS);
}
}
if ( HudMode > 5 ) return;
// Draw frags in DM
if ( deathmatch ) DrawFragCount(ClipX-32,0);
// Need to draw the inventory bar
DrawInventory(ClipX-(deathmatch?128:96),0,false,true);
}
override void Tick()
{
Super.Tick();
if ( CPlayer.inventorytics > 0 )
{
if ( CPlayer.mo.InvSel )
Console.Printf(StringTable.Localize("$M_ISELECT"),CPlayer.mo.InvSel.GetTag());
CPlayer.inventorytics = 0;
}
// part of gross hackery to override nametag display
if ( CPlayer.PendingWeapon && (CPlayer.PendingWeapon != WP_NOCHANGE) && (CPlayer.PendingWeapon != lastwep) )
{
// make sure to avoid instantly overriding the current pickup message
if ( (displaynametags&2) && (CPlayer == players[consoleplayer]) && (PickupMsgTic != gametic+50) )
{
ntagstr = CPlayer.PendingWeapon.GetTag();
ntagtic = gametic+50;
}
}
lastwep = CPlayer.PendingWeapon;
vtracer.ignore = CPlayer.mo;
Vector3 origin = dt_Utility.GetPlayerEye(CPlayer.mo);
vtracer.trace(origin,level.PointInSector(origin.xy),dt_Utility.GetPlayerViewDir(CPlayer.mo),1000,0);
if ( vtracer.Results.HitType != TRACE_HitActor ) return;
lastseen = vtracer.Results.HitActor;
lastseentic = gametic;
}
override void FlushNotify()
{
for ( int i=0; i<4; i++ )
{
ShortMsg[i] = "";
ShortMsgTic[i] = int.min;
}
PickupMsg = "";
PickupMsgTic = int.min;
MidPrintStr = "";
MidPrintTic = int.min;
}
override bool ProcessNotify( EPrintLevel printlevel, String outline )
{
if ( gamestate != GS_LEVEL ) return false; // not during intermissions
int rprintlevel = printlevel&PRINT_TYPES;
if ( (rprintlevel < PRINT_LOW) || (rprintlevel > PRINT_TEAMCHAT) ) rprintlevel = PRINT_HIGH;
outline.DeleteLastCharacter();
if ( rprintlevel == PRINT_LOW )
{
// set pickup message
PickupMsg = outline;
PickupMsgTic = gametic+50;
return true;
}
else
{
// put message into queue
for ( int i=3; i>0; i-- )
{
ShortMsg[i] = ShortMsg[i-1];
ShortMsgTic[i] = ShortMsgTic[i-1];
ShortMsgCol[i] = ShortMsgCol[i-1];
}
if ( rprintlevel == PRINT_MEDIUM ) ShortMsgCol[0] = Font.CR_RED;
else if ( (rprintlevel == PRINT_CHAT) || (rprintlevel == PRINT_TEAMCHAT) ) ShortMsgCol[0] = Font.CR_GREEN;
else ShortMsgCol[0] = Font.CR_WHITE;
ShortMsg[0] = outline;
ShortMsgTic[0] = gametic+70;
return true;
}
return false;
}
override bool ProcessMidPrint( Font fnt, String msg, bool bold )
{
if ( !fnt || (fnt == SmallFont) || (fnt == OriginalSmallFont) || (fnt == NewSmallFont) )
{
MidPrintStr = msg;
MidPrintLarge = false;
MidPrintTic = gametic+70;
return true;
}
else if ( fnt == BigFont )
{
MidPrintStr = msg;
MidPrintLarge = true;
MidPrintTic = gametic+70;
return true;
}
return false;
}
override bool DrawChat( String txt )
{
CurX = 4;
CurY = ((screenblocks<=10)||automapactive)?(GetTopOfStatusBar()/scalev.y):(ClipY-((screenblocks>11)?0:32));
CurY -= WhiteFont.GetHeight()+4;
String fullstr = String.Format("(> Say %s%s",txt,WhiteFont.GetCursor());
// cut out until it fits
while ( (WhiteFont.StringWidth(fullstr) > ClipX) && fullstr.Length() > 7 )
fullstr.Remove(7,1);
Screen.DrawText(WhiteFont,Font.CR_GREEN,CurX,CurY,fullstr,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
return true;
}
override bool DrawPaused( int player )
{
Screen.Dim(Color(0,24,64),.4,0,0,Screen.GetWidth(),Screen.GetHeight(),STYLE_Add);
String str = "PAUSED";
double xx = (Screen.GetWidth()-LargeFont.StringWidth(str))/2;
double yy = (Screen.GetHeight()-LargeFont.GetHeight())/2;
Screen.DrawText(LargeFont,Font.CR_UNTRANSLATED,xx,yy,str);
if ( multiplayer && (player != -1) )
{
str = "by "..players[player].GetUserName();
xx = (Screen.GetWidth()-MedFont.StringWidth(str))/2;
yy += LargeFont.GetHeight();
Screen.DrawText(MedFont,Font.CR_UNTRANSLATED,xx,yy,str);
}
return true;
}
private void DrawMessages( int state )
{
if ( (MidPrintStr.Length() > 0) && (MidPrintTic > gametic) )
{
let mfnt = MidPrintLarge?UBigFont:WhiteFont;
CurX = (ClipX-mfnt.StringWidth(MidPrintStr))/2;
CurY = 96;
Screen.DrawText(mfnt,Font.FindFontColor('UTHudText'),CurX,CurY,MidPrintStr,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,clamp((MidPrintTic-gametic+fractic)*0.05,0,1),DTA_LegacyRenderStyle,STYLE_Add);
}
if ( PickupMsgTic > gametic )
{
CurX = (ClipX-WhiteFont.StringWidth(PickupMsg))/2;
if ( state == HUD_Statusbar ) CurY = GetTopOfStatusBar()/scalev.y-31;
else CurY = ClipY-41;
Screen.DrawText(WhiteFont,Font.CR_WHITE,CurX,CurY,PickupMsg,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,clamp((PickupMsgTic-gametic+fractic)*0.05,0,1),DTA_LegacyRenderStyle,STYLE_Add);
}
if ( ntagtic > gametic )
{
CurX = (ClipX-WhiteFont.StringWidth(ntagstr))/2;
if ( state == HUD_Statusbar ) CurY = GetTopOfStatusBar()/scalev.y-15;
else CurY = ClipY-25;
Screen.DrawText(WhiteFont,Font.CR_WHITE,CurX,CurY,ntagstr,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,clamp((ntagtic-gametic+fractic)*0.05,0,1),DTA_LegacyRenderStyle,STYLE_Add);
}
// draw messages
if ( (state == HUD_Fullscreen) && (HudMode < 2) && DrawArmor(0,0,false,true) ) CurY = 36;
else CurY = 4;
CurX = 4;
for ( int i=3; i>=0; i-- )
{
if ( ShortMsgTic[i] < gametic ) continue;
let lines = WhiteFont.BreakLines(ShortMsg[i],int(ClipX/2));
for ( int j=0; j<lines.Count(); j++ )
{
Screen.DrawText(WhiteFont,ShortMsgCol[i],CurX,CurY,lines.StringAt(j),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += WhiteFont.GetHeight()+2;
}
}
}
override void DrawAutomapHUD( double ticFrac )
{
int crdefault = Font.CR_GREY;
int highlight = Font.CR_RED;
let scale = GetHUDScale();
double textdist = 8./scale.Y;
int height = WhiteFont.GetHeight();
String printtext;
int SCREENWIDTH = screen.GetWidth();
BeginHUD();
let y = textdist;
let width = WhiteFont.StringWidth("00:00:00");
double tmp, hres;
[tmp,tmp,hres] = StatusbarToRealCoords(0,0,HorizontalResolution);
double swidth = 0;
double ltop = 0, rtop = 0;
if ( (HudMode < 5) && CPlayer.mo.InvSel )
rtop += (32*scalev.y)/scale.Y;
double cbottom = GetTopOfStatusBar()-textdist;
int protrusion = GetProtrusion(swidth/hres);
[tmp,tmp,hres] = StatusbarToRealCoords(0,0,protrusion);
width += int((swidth-hres)/scale.X);
if ( am_showtime )
{
printtext = level.TimeFormatted();
DrawString(mMapFont,level.TimeFormatted(),(-textdist-width,y+rtop),0,crdefault);
y += height;
}
if ( am_showtotaltime ) DrawString(mMapFont,level.TimeFormatted(true),(-textdist-width,y+rtop),0,crdefault);
if ( !deathmatch )
{
y = textdist;
if ( am_showmonsters )
{
DrawString(mMapFont,String.Format("%s\34%c %d/%d",Stringtable.Localize("$AM_MONSTERS"),crdefault+65,level.killed_monsters,level.total_monsters),(textdist,y+ltop),0,highlight);
y += height;
}
if ( am_showsecrets )
{
DrawString(mMapFont,String.Format("%s\34%c %d/%d",Stringtable.Localize("$AM_SECRETS"),crdefault+65,level.found_secrets,level.total_secrets),(textdist,y+ltop),0,highlight);
y += height;
}
if ( am_showitems ) DrawString(mMapFont,String.Format("%s\34%c %d/%d",Stringtable.Localize("$AM_ITEMS"),crdefault+65,level.found_items,level.total_items),(textdist,y+ltop),0,highlight);
}
String mapname = level.FormatMapName(crdefault);
BrokenLines lines = WhiteFont.BreakLines(mapname,int(SCREENWIDTH/scale.X));
int numlines = lines.Count();
int finalwidth = int(WhiteFont.StringWidth(lines.StringAt(numlines-1))*scale.X);
[tmp,tmp,hres] = StatusbarToRealCoords(0,0,HorizontalResolution);
protrusion = GetProtrusion(finalwidth/hres);
[tmp,tmp,tmp,hres] = StatusbarToRealCoords(0,0,0,protrusion);
y = (cbottom-hres)/scale.Y-height*numlines;
for ( int i = 0; i < numlines; i++ )
{
DrawString(mMapFont,lines.StringAt(i),(0,y+ltop),DI_TEXT_ALIGN_CENTER|DI_SCREEN_HCENTER|DI_SCREEN_TOP,highlight);
y += height;
}
}
}