Fixed the sizes and offsets of player models. Adjusted weapon offsets to be more in line with the originals. Implemented all armors and most of the usable items. Add lights to some item pickups. This might get done to DT too. Key display on both HUD types, along with some fixes. ASMD has complete animations. Other weapons will follow.
688 lines
25 KiB
Text
688 lines
25 KiB
Text
// An almost 1:1 recreation of the Unreal 1 HUD
|
|
Class UnrealHUD : BaseStatusBar
|
|
{
|
|
double FracTic;
|
|
|
|
// 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, MedFont, WhiteFont, TinyFont, TinyWhiteFont, TinyRedFont;
|
|
HUDFont mMapFont;
|
|
|
|
// Common Textures
|
|
TextureID HalfHud, HudLine, HudAmmo, IconHeal, IconSkul, IconSel, IconBase, KeyIcons[7];
|
|
|
|
// 0.83 HUD stuff
|
|
String OldAmmo[18];
|
|
Class<Inventory> OldAmmoType[18];
|
|
String OldArmor[6];
|
|
Class<Inventory> OldArmorType[6];
|
|
String OldKeys[7];
|
|
HUDFont mOldDigits;
|
|
|
|
// Translations
|
|
int RedIcon;
|
|
|
|
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.FindFont('ULargeFont');
|
|
LargeRedFont = Font.FindFont('ULargeRedFont');
|
|
MedFont = Font.FindFont('UMedFont');
|
|
WhiteFont = Font.FindFont('UWhiteFont');
|
|
TinyFont = Font.FindFont('UTinyFont');
|
|
TinyWhiteFont = Font.FindFont('UTinyWhiteFont');
|
|
TinyRedFont = Font.FindFont('UTinyRedFont');
|
|
mMapFont = HUDFont.Create(WhiteFont);
|
|
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.FindFont('U083Digits'),26,Mono_CellLeft);
|
|
OldAmmo[0] = "Disp083";
|
|
OldAmmo[1] = "Clip083";
|
|
OldAmmo[2] = "Tary083";
|
|
OldAmmo[3] = "Asmd083";
|
|
OldAmmo[4] = "Rokt083";
|
|
OldAmmo[5] = "Flak083";
|
|
OldAmmo[6] = "Razor083";
|
|
OldAmmo[7] = "Bio083";
|
|
OldAmmo[8] = "Rifle083";
|
|
OldAmmo[9] = "Mini083";
|
|
OldAmmo[10] = "Shell083";
|
|
OldAmmo[11] = "Impal083";
|
|
OldAmmo[12] = "Flame083";
|
|
OldAmmo[13] = "Tele083";
|
|
OldAmmo[14] = "Stun083";
|
|
OldAmmo[15] = "Big083";
|
|
OldAmmo[16] = "Smini083";
|
|
OldAmmo[17] = "Peace083";
|
|
OldAmmoType[0] = "DispersionAmmo";
|
|
OldAmmoType[1] = "UMiniAmmo";
|
|
OldAmmoType[2] = "StingerAmmo";
|
|
OldAmmoType[3] = "AsmdAmmo";
|
|
OldAmmoType[4] = "URocketAmmo";
|
|
OldAmmoType[5] = "UFlakBox";
|
|
OldAmmoType[6] = "RazorAmmo";
|
|
OldAmmoType[7] = "UBioAmmo";
|
|
OldAmmoType[8] = "URifleAmmo";
|
|
OldAmmoType[9] = "UMinigun";
|
|
OldAmmoType[10] = "UShells";
|
|
OldAmmoType[11] = "ImpalerAmmo";
|
|
OldAmmoType[12] = "FlameAmmo";
|
|
OldAmmoType[13] = "UTranslocatorAmmo";
|
|
OldAmmoType[14] = "StunnerAmmo";
|
|
OldAmmoType[15] = "BigAmmo";
|
|
OldAmmoType[16] = "SMiniAmmo";
|
|
OldAmmoType[17] = "PeaceAmmo";
|
|
OldArmor[0] = "Armor083";
|
|
OldArmor[1] = "Kev083";
|
|
OldArmor[2] = "Asb083";
|
|
OldArmor[3] = "Tox083";
|
|
OldArmor[4] = "Belt083";
|
|
OldArmor[5] = "Pbelt083";
|
|
OldArmorType[0] = "UArmor";
|
|
OldArmorType[1] = "KevlarSuit";
|
|
OldArmorType[2] = "AsbestosSuit";
|
|
OldArmorType[3] = "ToxinSuit";
|
|
OldArmorType[4] = "ShieldBelt";
|
|
OldArmorType[5] = "PowerShield";
|
|
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 )
|
|
{
|
|
Super.Draw(state,TicFrac);
|
|
HudMode = CVar.GetCVar('stinger_hudmode',players[consoleplayer]).GetInt();
|
|
scalev.x = scalev.y = Max(0,CVar.GetCVar('stinger_hudscale',players[consoleplayer]).GetInt());
|
|
if ( scalev.x == 0 ) scalev.x = scalev.y = max(1,min(Screen.GetWidth()/640.,Screen.GetHeight()/480.));
|
|
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_StatusBar )
|
|
{
|
|
BeginStatusBar();
|
|
FracTic = TicFrac;
|
|
DrawUnrealBar();
|
|
}
|
|
else if ( state == HUD_Fullscreen )
|
|
{
|
|
BeginHUD();
|
|
FracTic = TicFrac;
|
|
DrawUnrealHUD();
|
|
}
|
|
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);
|
|
}
|
|
|
|
private void DrawNumberOf( Inventory i, double x, double y )
|
|
{
|
|
if ( i.Amount <= 1 ) return;
|
|
double TempX = CurX, TempY = CurY;
|
|
string itxt = String.Format("%d",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 )
|
|
{
|
|
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/mscl, dy = CurY/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).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 )
|
|
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<Weapon> wslots[10];
|
|
// clear the arrays before work
|
|
for ( int i=0; i<10; i++ ) wslots[i].Clear();
|
|
// first run, populate the full array of weapons
|
|
for ( int i=0; i<10; i++ )
|
|
{
|
|
for ( Inv = CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
|
|
{
|
|
if ( !(Inv is 'Weapon') ) continue;
|
|
let w = Weapon(Inv);
|
|
if ( w.SlotNumber != i ) continue;
|
|
int slot = w.SlotNumber;
|
|
wslots[slot].Push(w);
|
|
}
|
|
}
|
|
// second run, sort the slot arrays
|
|
for ( int i=0; i<10; i++ )
|
|
{
|
|
int j = 1;
|
|
while ( j < wslots[i].Size() )
|
|
{
|
|
int k = j;
|
|
while ( (k > 0) && (wslots[i][k-1].SelectionOrder >= wslots[i][k].SelectionOrder) )
|
|
{
|
|
Weapon tmp = wslots[i][k];
|
|
wslots[i][k] = wslots[i][k-1];
|
|
wslots[i][k-1] = tmp;
|
|
k--;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
// draw the slots
|
|
if ( (HudMode < 4) && !bNoWeapons )
|
|
{
|
|
for ( int i=0; i<10; i++ )
|
|
{
|
|
if ( wslots[i].Size() <= 0 ) continue;
|
|
Font cfont = TinyFont;
|
|
if ( cwslot == i ) cfont = TinyWhiteFont;
|
|
int realslot = i?i:10;
|
|
CurX = HalfHUDX-3+realslot*6;
|
|
CurY = HalfHUDY+4;
|
|
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<wslots[i].Size(); j++ ) if ( wslots[i][j].Ammo1 ) nammo++;
|
|
if ( nammo <= 0 ) continue;
|
|
int cbar = 0;
|
|
for ( int j=0; j<wslots[i].Size(); j++ )
|
|
{
|
|
let amo = wslots[i][j].Ammo1;
|
|
if ( !amo ) 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 ( wslots[i][j] != cw ) 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++;
|
|
}
|
|
}
|
|
}
|
|
// draw translator
|
|
if ( translator )
|
|
{
|
|
if ( translator.bCurrentlyActivated ) translator.DrawTranslator(scalev,ClipX,ClipY);
|
|
else bFlashTranslator = (translator.bNewMessage || translator.bNotNewMessage);
|
|
}
|
|
// draw the inventory bar
|
|
if ( (HUDMode == 5) || !SelectedItem ) return;
|
|
Count++;
|
|
if ( Count > 20 ) Count = 0;
|
|
if ( Prev )
|
|
{
|
|
bRed = ((Prev is 'UnrealInventory') && UnrealInventory(Prev).bActive) || (Prev is 'Powerup') || ((Prev is 'UTranslator') && bFlashTranslator);
|
|
DrawHudIcon(x,y,Prev,bRed);
|
|
if ( Prev.MaxAmount > 1 ) DrawNumberOf(Prev,x,y);
|
|
}
|
|
bRed = ((SelectedItem is 'UnrealInventory') && UnrealInventory(SelectedItem).bActive) || (SelectedItem is 'Powerup') || ((SelectedItem is 'UTranslator') && bFlashTranslator);
|
|
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 ) DrawNumberOf(SelectedItem,CurX,y);
|
|
if ( Next )
|
|
{
|
|
bRed = ((Next is 'UnrealInventory') && UnrealInventory(Next).bActive) || (Next is 'Powerup') || ((Next is 'UTranslator') && bFlashTranslator);
|
|
DrawHudIcon(x+64,y,Next,bRed);
|
|
if ( Next.MaxAmount > 1 ) DrawNumberOf(Next,x+64,y);
|
|
}
|
|
}
|
|
|
|
private void DrawArmor( double x, double y, bool bDrawOne = 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 )
|
|
{
|
|
DrawHudIcon(CurX,y,Inv,false);
|
|
CurX += 32;
|
|
CurY += HudMode?29:27;
|
|
DrawIconValue(Inv.Amount);
|
|
CurY -= HudMode?29:27;
|
|
}
|
|
else if ( UTArmor(Inv).absorb > CurAbs )
|
|
{
|
|
CurAbs = UTArmor(Inv).absorb;
|
|
BestArmor = Inv;
|
|
}
|
|
}
|
|
if ( bDrawOne && BestArmor )
|
|
{
|
|
DrawHudIcon(CurX,Y,BestArmor,false);
|
|
CurX += 32;
|
|
CurY += HudMode?29:27;
|
|
DrawIconValue(BestArmor.Amount);
|
|
CurY -= HudMode?29:27;
|
|
}
|
|
if ( (ArmorAmount > 0) && !HudMode )
|
|
Screen.DrawText(LargeFont,Font.CR_UNTRANSLATED,CurX+2,Y,String.Format("%d",ArmorAmount),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
|
|
}
|
|
|
|
private void DrawAmmo( double x, double y )
|
|
{
|
|
CurX = x;
|
|
CurY = y;
|
|
if ( !CPlayer.ReadyWeapon || !CPlayer.ReadyWeapon.Ammo1 ) return;
|
|
Font cfont = LargeFont;
|
|
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);
|
|
}
|
|
CurX = x;
|
|
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/mscl, dy = CurY/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.));
|
|
// TODO secondary ammo display
|
|
}
|
|
|
|
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()
|
|
{
|
|
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());
|
|
CurX = (ClipX-WhiteFont.StringWidth(tname))/2;
|
|
CurY = ClipY-54;
|
|
Screen.DrawText(WhiteFont,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*WhiteFont.GetHeight();
|
|
tname = String.Format("\c[%s]%s:\c[%s] %d",cl1,StringTable.Localize("$M_HEALTH"),cl2,lastseen.Health);
|
|
Screen.DrawText(WhiteFont,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) ) return; // no key display for these ATM (will do eventually)
|
|
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 )
|
|
{
|
|
DrawInventory(ClipX-96,0);
|
|
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(0,ClipY-32);
|
|
}
|
|
else
|
|
{
|
|
// Display Keys
|
|
if ( HudMode < 3 ) DrawKeys(ClipX-(deathmatch?48:16),ClipY-48);
|
|
else if ( HudMode == 3 ) DrawKeys(deathmatch?32:0,ClipY-48,true);
|
|
else if ( HudMode == 4 ) DrawKeys(deathmatch?32:0,ClipY-16,true);
|
|
}
|
|
// Display Identification Info
|
|
DrawIdentifyInfo();
|
|
}
|
|
|
|
private void DrawUnrealBar()
|
|
{
|
|
// 0.83 status bar, just for funsies
|
|
DrawImage("Bar083",(0,336),DI_ITEM_OFFSETS);
|
|
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));
|
|
DrawImage("Slot083",(slotofs[i],342),DI_ITEM_OFFSETS,used?1.:.8);
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
for ( int i=0; i<6; i++ )
|
|
{
|
|
if ( !(BestArmor is OldArmorType[i]) ) continue;
|
|
DrawImage(OldArmor[i],(4,340),DI_ITEM_OFFSETS);
|
|
break;
|
|
}
|
|
if ( ArmorAmount ) DrawString(mOldDigits,FormatNumber(ArmorAmount,3),(167,366),DI_TEXT_ALIGN_RIGHT);
|
|
Inventory Ammo1, Ammo2;
|
|
[Ammo1, Ammo2] = GetCurrentAmmo();
|
|
if ( Ammo1 )
|
|
{
|
|
if ( Ammo1.Amount ) DrawString(mOldDigits,FormatNumber(Ammo1.Amount,3),(549,366),DI_TEXT_ALIGN_RIGHT);
|
|
for ( int i=0; i<18; i++ )
|
|
{
|
|
// match by ammo
|
|
if ( (OldAmmoType[i] is 'Ammo') && !(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);
|
|
break;
|
|
}
|
|
}
|
|
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 (and translator)
|
|
DrawInventory(ClipX-(deathmatch?128:96),0,false,true);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
CPlayer.inventorytics = 0;
|
|
vtracer.ignore = CPlayer.mo;
|
|
vtracer.trace(CPlayer.mo.Vec2OffsetZ(0,0,CPlayer.viewz),CPlayer.mo.CurSector,(cos(CPlayer.mo.angle)*cos(CPlayer.mo.pitch),sin(CPlayer.mo.angle)*cos(CPlayer.mo.pitch),-sin(CPlayer.mo.pitch)),1000,0);
|
|
if ( vtracer.Results.HitType != TRACE_HitActor ) return;
|
|
lastseen = vtracer.Results.HitActor;
|
|
lastseentic = gametic;
|
|
}
|
|
|
|
override void DrawAutomapHUD( double ticFrac )
|
|
{
|
|
int crdefault = Font.CR_GREY;
|
|
int highlight = Font.CR_RED;
|
|
double cbottom = Screen.GetHeight()*0.99;
|
|
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 < 6) && CPlayer.mo.InvSel )
|
|
rtop += (32*scalev.y)/scale.Y;
|
|
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;
|
|
}
|
|
}
|
|
}
|