// 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;

	// Translations
	int RedIcon;

	override void Init()
	{
		Super.Init();
		SetSize(0,320,200);
		// 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');
	}

	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) || (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( int n, double x, double y )
	{
		if ( n <= 0 ) return;
		CurX = X-4;
		CurY = Y+20;
		n++;
		string itxt = String.Format("%d",n);
		CurX -= TinyRedFont.StringWidth(itxt);
		Screen.DrawText(TinyRedFont,Font.CR_UNTRANSLATED,CurX,CurY,itxt,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
	}

	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);
		}
	}

	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 )
	{
		bool bGotNext, bGotPrev, bGotSelected, bRed, bFlashTranslator;
		Inventory Inv, Prev, Next, SelectedItem;
		UTranslator translator;
		double HalfHUDX, HalfHUDY;
		double AmmoBarSize;
		if ( HudMode < 4 )	// 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?(cw.SlotNumber-1):9;
		let pw = CPlayer.PendingWeapon;
		int pwslot = -1;
		if ( pw && (pw != WP_NOCHANGE) && (pw.SlotNumber != -1) ) pwslot = pw.SlotNumber?(pw.SlotNumber-1):9;
		Weapon wslots[10];
		// zero-initialize, fixes asmjit crash
		for ( int i=0; i<10; i++ )
			wslots[i] = null;
		// first run, populate the full array of weapons
		for ( int i=0; i<10; i++ )
		{
			int sslot = (i<9)?(i+1):0;
			for ( Inv = CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
			{
				if ( !(Inv is 'Weapon') ) continue;
				let w = Weapon(Inv);
				if ( w.SlotNumber != sslot ) continue;
				int slot = w.SlotNumber?(w.SlotNumber-1):9;
				if ( !wslots[slot] )
				{
					wslots[slot] = w;
					continue;
				}
				if ( (wslots[slot] == pw) || (wslots[slot] == cw) ) continue;
				if ( (w == pw) || (w == cw) )
				{
					wslots[slot] = w;
					continue;
				}
				if ( (w.SelectionOrder < wslots[slot].SelectionOrder) && (!w.Ammo1 || (w.Ammo1.Amount > 0)) )
					wslots[slot] = w;
				else if ( (w.SelectionOrder >= wslots[slot].SelectionOrder) && wslots[slot].Ammo1 && (wslots[slot].Ammo1.Amount <= 0) )
					wslots[slot] = w;
			}
		}
		// draw the slots
		if ( HudMode < 4 )
		{
			for ( int i=0; i<10; i++ )
			{
				if ( !wslots[i] ) continue;
				Font cfont = TinyFont;
				if ( cwslot == i ) cfont = TinyWhiteFont;
				int realslot = (i<9)?(i+1):9;
				CurX = HalfHUDX-3+realslot*6;
				CurY = HalfHUDY+4;
				Screen.DrawText(cfont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",realslot),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
				// Draw ammo bar
				let amo = wslots[i].Ammo1;
				if ( !amo ) continue;
				CurY = HalfHUDY+11;
				AmmoBarSize = 16*min(1.0,amo.Amount/double(amo.MaxAmount));
				CurY = HalfHUDY+29-AmmoBarSize;
				if ( (AmmoBarSize < 8) && (amo.Amount < 10) && (amo.Amount > 0) )
				{
					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 = "00 FF 00";
				if ( AmmoBarSize < 8 ) DrawColor = Color(255-int(AmmoBarSize)*30,int(AmmoBarSize)*30+40,0);
				if ( amo.Amount > 0 )
				{
					Screen.DrawTexture(HudAmmo,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_FillColor,BlackColor,DTA_DestWidth,4,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_DestWidth,4,DTA_DestHeightF,AmmoBarSize);
				}
			}
		}
		// 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.Amount,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);
		if ( SelectedItem.MaxAmount > 1 ) DrawNumberOf(SelectedItem.Amount,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.Amount,x+64,y);
		}
	}

	private void DrawArmor( double x, double y, bool bDrawOne )
	{
		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);
				DrawIconValue(Inv.Amount);
				CurX += 32;
			}
			else if ( UTArmor(Inv).absorb > CurAbs )
			{
				CurAbs = UTArmor(Inv).absorb;
				BestArmor = Inv;
			}
		}
		if ( bDrawOne && BestArmor )
		{
			DrawHudIcon(CurX,Y,BestArmor,false);
			DrawIconValue(BestArmor.Amount);
			CurX += 32;
		}
		if ( (ArmorAmount > 0) && !HudMode )
			Screen.DrawText(LargeFont,Font.CR_UNTRANSLATED,CurX,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 )
		{
			Screen.DrawTexture(IconBase,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
			return;
		}
		Font cfont = LargeFont;
		if ( CPlayer.ReadyWeapon.Ammo1.Amount < 10 ) cfont = LargeRedFont;
		if ( !HudMode )
		{
			CurX -= cfont.StringWidth(String.Format("%d",CPlayer.ReadyWeapon.Ammo1.Amount));
			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(27.*(CPlayer.ReadyWeapon.Ammo1.Amount/double(CPlayer.ReadyWeapon.Ammo1.MaxAmount)),27.));
	}

	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,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(27.*(CPlayer.mo.Health/double(CPlayer.mo.SpawnHealth())),27.));
	}

	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 )
	{
		// TODO draws the key icons from right to left, bottom to top
	}

	private void DrawUnrealHUD()
	{
		if ( HudMode == 5 )
		{
			DrawInventory(ClipX-96,0,false);
			return;
		}
		if ( ClipX < 320 ) HudMode = 4;
		// Draw Armor
		if ( HudMode < 2 ) DrawArmor(0,0,false);
		else if ( (HudMode == 3) || (HudMode == 2) ) DrawArmor(0,ClipY-32,false);
		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,false);
		else if ( HudMode == 3 ) DrawInventory(ClipX-96,ClipY-64,false);
		else if ( HudMode == 4 ) DrawInventory(ClipX-64,ClipY-64,true);
		else if ( HudMode == 2 ) DrawInventory(ClipX/2-64,ClipY-32,false);
		// 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);
		// Display Keys
		if ( HudMode < 3 ) DrawKeys(ClipX-32,ClipY-32);
		else if ( HudMode < 6 ) DrawKeys(ClipX,ClipY-32);
		// Display Identification Info
		DrawIdentifyInfo();
	}

	override void Tick()
	{
		Super.Tick();
		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;
		CPlayer.inventorytics = 0;
	}

	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 < 2 )
		{
			for ( Inventory Inv=CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
			{
				if ( !(Inv is 'UTArmor') ) continue;
				if ( (Inv.Amount <= 0) || Inv.Icon.IsNull() ) continue;
				rtop += 64*scalev.y;
				break;
			}
			if ( CPlayer.mo.InvSel ) ltop += 64*scalev.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;
		}
	}
}
