flak_m/zscript/uthud.zsc
Marisa Kirisame fb96c7523e Portal awareness adjustments to various vector operations.
Got rid of the deprecated Matrix4.GetAxes method. Next step is to get rid of more stuff by migrating to libeye.
Mirrored Translocator model so it shows the actually detailed side. At some point in UT's development it got flipped around for some reason.
Weapon code cleanup (most noticeable on states).
Backported scope shader from Doomreal.
Added optional "dummied out" Sniper zoom sounds from a dubious source.
2019-09-28 20:06:51 +02:00

1143 lines
44 KiB
Text

// An almost 1:1 recreation of the UT HUD
// Because this requires some flexibility, it barely makes use of the Statusbar
// functions and instead uses the raw Screen API.
Class ViewTracer : LineTracer
{
Actor ignore;
override ETraceStatus TraceCallback()
{
if ( Results.HitType == TRACE_HitActor )
{
if ( (Results.HitActor == ignore) || !Results.HitActor.player || !Results.HitActor.bSHOOTABLE || Results.HitActor.bINVISIBLE ) return TRACE_Skip;
return TRACE_Stop;
}
else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) )
{
if ( !Results.HitLine.sidedef[1] ) return TRACE_Stop;
return TRACE_Skip;
}
return TRACE_Stop;
}
}
Class UTHud : BaseStatusBar
{
TextureID AmmoBar, Boxes[4], Keys[5], BigNum[12], Flash, Slots[10], Icons[14], Uses[14], Man[5], Woman[5], Boss[5], WeaponBox, IconTloc2, UseTloc2, IconSaw2, UseSaw2, ItemBox, ItemSel, ItemFlash, ItemArrow[2], LastItem, FacePanel[3];
Class<Weapon> IconClasses[14];
double HScale;
Color tintcolor, bgcolor;
int opacity;
int lastfrag, lastfragcnt, lastpickup, lastslot, lastamount;
ViewTracer vtracer;
Actor lastseen;
int lastseentic;
bool showweapons, showfrags, showammo, showstatus, showinfo;
double hudsize, weaponsize, statussize;
HUDFont mUTFont12, mUTFont40;
String PickupMsg;
int PickupMsgTic;
String ShortMsg[4];
int ShortMsgTic[4];
int ShortMsgCol[4];
int LastMsgTic;
TextureID LastTalkFace; // guessed from voice type
int LastTalkTic, faceout;
String MidPrintStr;
int MidPrintTic;
double MidPrintScale;
// For easier UT Canvas drawing
Color DrawColor, WhiteColor, GoldColor;
double CurX, CurY;
double FracTic;
override void Init()
{
Super.Init();
SetSize(0,640,480); // this exists here merely to scale the automap text
lastfrag = int.min;
lastfragcnt = 0;
vtracer = new("ViewTracer");
mUTFont12 = HUDFont.Create("UTFONT12");
mUTFont40 = HUDFont.Create("UTFONT40");
// Set defaults
DrawColor = WhiteColor = "White";
GoldColor = "Gold";
// Load textures
AmmoBar = TexMan.CheckForTexture("AmoBar",TexMan.Type_Any);
Boxes[0] = TexMan.CheckForTexture("AmoBox",TexMan.Type_Any);
Boxes[1] = TexMan.CheckForTexture("ArmoBox",TexMan.Type_Any);
Boxes[2] = TexMan.CheckForTexture("HPBox",TexMan.Type_Any);
Boxes[3] = TexMan.CheckForTexture("FragBox",TexMan.Type_Any);
Keys[0] = TexMan.CheckForTexture("RKey",TexMan.Type_Any);
Keys[1] = TexMan.CheckForTexture("BKey",TexMan.Type_Any);
Keys[2] = TexMan.CheckForTexture("YKey",TexMan.Type_Any);
Keys[3] = TexMan.CheckForTexture("Skul",TexMan.Type_Any);
Keys[4] = TexMan.CheckForTexture("GKey",TexMan.Type_Any); // Heretic compat
BigNum[0] = TexMan.CheckForTexture("Big0",TexMan.Type_Any);
BigNum[1] = TexMan.CheckForTexture("Big1",TexMan.Type_Any);
BigNum[2] = TexMan.CheckForTexture("Big2",TexMan.Type_Any);
BigNum[3] = TexMan.CheckForTexture("Big3",TexMan.Type_Any);
BigNum[4] = TexMan.CheckForTexture("Big4",TexMan.Type_Any);
BigNum[5] = TexMan.CheckForTexture("Big5",TexMan.Type_Any);
BigNum[6] = TexMan.CheckForTexture("Big6",TexMan.Type_Any);
BigNum[7] = TexMan.CheckForTexture("Big7",TexMan.Type_Any);
BigNum[8] = TexMan.CheckForTexture("Big8",TexMan.Type_Any);
BigNum[9] = TexMan.CheckForTexture("Big9",TexMan.Type_Any);
BigNum[10] = TexMan.CheckForTexture("BigColon",TexMan.Type_Any);
BigNum[11] = TexMan.CheckForTexture("BigMinus",TexMan.Type_Any);
Flash = TexMan.CheckForTexture("HFlash",TexMan.Type_Any);
Slots[0] = TexMan.CheckForTexture("SlotImp",TexMan.Type_Any);
Slots[1] = TexMan.CheckForTexture("SlotAuto",TexMan.Type_Any);
Slots[2] = TexMan.CheckForTexture("SlotBio",TexMan.Type_Any);
Slots[3] = TexMan.CheckForTexture("SlotASMD",TexMan.Type_Any);
Slots[4] = TexMan.CheckForTexture("SlotPuls",TexMan.Type_Any);
Slots[5] = TexMan.CheckForTexture("SlotRip",TexMan.Type_Any);
Slots[6] = TexMan.CheckForTexture("SlotMini",TexMan.Type_Any);
Slots[7] = TexMan.CheckForTexture("SlotFlak",TexMan.Type_Any);
Slots[8] = TexMan.CheckForTexture("Slot8bal",TexMan.Type_Any);
Slots[9] = TexMan.CheckForTexture("SlotRifl",TexMan.Type_Any);
Icons[0] = TexMan.CheckForTexture("IconImpH",TexMan.Type_Any);
Icons[1] = TexMan.CheckForTexture("IconAuto",TexMan.Type_Any);
Icons[2] = TexMan.CheckForTexture("IconBio",TexMan.Type_Any);
Icons[3] = TexMan.CheckForTexture("IconASMD",TexMan.Type_Any);
Icons[4] = TexMan.CheckForTexture("IconPuls",TexMan.Type_Any);
Icons[5] = TexMan.CheckForTexture("IconRip",TexMan.Type_Any);
Icons[6] = TexMan.CheckForTexture("IconMini",TexMan.Type_Any);
Icons[7] = TexMan.CheckForTexture("IconFlak",TexMan.Type_Any);
Icons[8] = TexMan.CheckForTexture("Icon8bal",TexMan.Type_Any);
Icons[9] = TexMan.CheckForTexture("IconRifl",TexMan.Type_Any);
Icons[10] = TexMan.CheckForTexture("IconSaw",TexMan.Type_Any);
Icons[11] = TexMan.CheckForTexture("IconTrns",TexMan.Type_Any);
Icons[12] = TexMan.CheckForTexture("IconWarH",TexMan.Type_Any);
Icons[13] = TexMan.CheckForTexture("IconASMD",TexMan.Type_Any);
Uses[0] = TexMan.CheckForTexture("UseImpH",TexMan.Type_Any);
Uses[1] = TexMan.CheckForTexture("UseAuto",TexMan.Type_Any);
Uses[2] = TexMan.CheckForTexture("UseBio",TexMan.Type_Any);
Uses[3] = TexMan.CheckForTexture("UseASMD",TexMan.Type_Any);
Uses[4] = TexMan.CheckForTexture("UsePuls",TexMan.Type_Any);
Uses[5] = TexMan.CheckForTexture("UseRip",TexMan.Type_Any);
Uses[6] = TexMan.CheckForTexture("UseMini",TexMan.Type_Any);
Uses[7] = TexMan.CheckForTexture("UseFlak",TexMan.Type_Any);
Uses[8] = TexMan.CheckForTexture("Use8bal",TexMan.Type_Any);
Uses[9] = TexMan.CheckForTexture("UseRifl",TexMan.Type_Any);
Uses[10] = TexMan.CheckForTexture("UseSaw",TexMan.Type_Any);
Uses[11] = TexMan.CheckForTexture("UseTrns",TexMan.Type_Any);
Uses[12] = TexMan.CheckForTexture("UseWarH",TexMan.Type_Any);
Uses[13] = TexMan.CheckForTexture("UseASMD",TexMan.Type_Any);
IconClasses[0] = "ImpactHammer";
IconClasses[1] = "Enforcer";
IconClasses[2] = "BioRifle";
IconClasses[3] = "ShockRifle";
IconClasses[4] = "PulseGun";
IconClasses[5] = "Ripper2";
IconClasses[6] = "Minigun";
IconClasses[7] = "FlakCannon";
IconClasses[8] = "UTRocketLauncher";
IconClasses[9] = "SniperRifle";
IconClasses[10] = "UTChainsaw";
IconClasses[11] = "Translocator";
IconClasses[12] = "WarheadLauncher";
IconClasses[13] = "EnhancedShockRifle";
Man[0] = TexMan.CheckForTexture("Man",TexMan.Type_Any);
Man[1] = TexMan.CheckForTexture("ManArmo",TexMan.Type_Any);
Man[2] = TexMan.CheckForTexture("ManPad",TexMan.Type_Any);
Man[3] = TexMan.CheckForTexture("ManBoot",TexMan.Type_Any);
Man[4] = TexMan.CheckForTexture("ManBelt",TexMan.Type_Any);
Woman[0] = TexMan.CheckForTexture("Woman",TexMan.Type_Any);
Woman[1] = TexMan.CheckForTexture("WomanArm",TexMan.Type_Any);
Woman[2] = TexMan.CheckForTexture("WomanPad",TexMan.Type_Any);
Woman[3] = TexMan.CheckForTexture("WomanBot",TexMan.Type_Any);
Woman[4] = TexMan.CheckForTexture("WomanBlt",TexMan.Type_Any);
Boss[0] = TexMan.CheckForTexture("Boss",TexMan.Type_Any);
Boss[1] = TexMan.CheckForTexture("BossArm",TexMan.Type_Any);
Boss[2] = TexMan.CheckForTexture("BossPad",TexMan.Type_Any);
Boss[3] = TexMan.CheckForTexture("BossBot",TexMan.Type_Any);
Boss[4] = TexMan.CheckForTexture("BossBlt",TexMan.Type_Any);
WeaponBox = TexMan.CheckForTexture("WpSel",TexMan.Type_Any);
ItemBox = TexMan.CheckForTexture("ItemBox",TexMan.Type_Any);
ItemSel = TexMan.CheckForTexture("ItmSel",TexMan.Type_Any);
ItemFlash = TexMan.CheckForTexture("IFlash",TexMan.Type_Any);
ItemArrow[0] = TexMan.CheckForTexture("ItmArrw1",TexMan.Type_Any);
ItemArrow[1] = TexMan.CheckForTexture("ItmArrw2",TexMan.Type_Any);
IconTloc2 = TexMan.CheckForTexture("IconTrn2",TexMan.Type_Any);
UseTloc2 = TexMan.CheckForTexture("UseTrn2",TexMan.Type_Any);
IconSaw2 = TexMan.CheckForTexture("IconSaw2",TexMan.Type_Any);
UseSaw2 = TexMan.CheckForTexture("UseSaw2",TexMan.Type_Any);
FacePanel[0] = TexMan.CheckForTexture("FacePnl",TexMan.Type_Any);
FacePanel[1] = TexMan.CheckForTexture("FacePnlA",TexMan.Type_Any);
FacePanel[2] = TexMan.CheckForTexture("Static1",TexMan.Type_Any);
}
override void Draw( int state, double TicFrac )
{
Super.Draw(state,TicFrac);
HScale = Screen.GetWidth()/1280.;
switch ( CVar.GetCVar('flak_colorprefs',CPlayer).GetInt() )
{
case 0:
if ( CPlayer.GetTeam() >= Teams.Size() )
tintcolor = Color("White");
else tintcolor = Color(Teams[CPlayer.GetTeam()].mName);
break;
case 1:
tintcolor = CPlayer.GetColor();
break;
case 2:
tintcolor = Color(CVar.GetCVar('flak_colorcustom',CPlayer).GetString());
break;
}
opacity = CVar.GetCVar('flak_opacity',players[consoleplayer]).GetInt();
bgcolor = Color("Black");
showweapons = CVar.GetCVar('flak_showweapons',players[consoleplayer]).GetBool();
showstatus = CVar.GetCVar('flak_showstatus',players[consoleplayer]).GetBool();
showfrags = CVar.GetCVar('flak_showfrags',players[consoleplayer]).GetBool();
showammo = CVar.GetCVar('flak_showammo',players[consoleplayer]).GetBool();
showinfo = CVar.GetCVar('flak_showinfo',players[consoleplayer]).GetBool();
hudsize = CVar.GetCVar('flak_hudsize',players[consoleplayer]).GetFloat();
weaponsize = CVar.GetCVar('flak_weaponsize',players[consoleplayer]).GetFloat();
statussize = CVar.GetCVar('flak_statussize',players[consoleplayer]).GetFloat();
double lbottom = Screen.GetHeight();
if ( showweapons )
{
if ( weaponsize*hudsize>=1.0 ) lbottom -= 64*hudsize*HScale;
if ( showfrags ) lbottom -= 64*hudsize*HScale;
}
if ( (CPlayer.ReadyWeapon is 'UTWeapon') )
UTWeapon(CPlayer.ReadyWeapon).PreRender(lbottom);
if ( (state == HUD_StatusBar) || (state == HUD_Fullscreen) )
{
BeginHUD();
FracTic = TicFrac;
DrawUTHUD(lbottom);
}
if ( (CPlayer.ReadyWeapon is 'UTWeapon') )
UTWeapon(CPlayer.ReadyWeapon).PostRender(lbottom);
}
private Color LerpColor( Color a, Color b, double x )
{
return Color(a.a,int(a.r*(1.-x)+b.r*x),int(a.g*(1.-x)+b.g*x),int(a.b*(1.-x)+b.b*x));
}
private void UTDrawTintedTex( TextureID tx, double sx = 1.0, int opacity = -1, Color tint = Color("Black"), bool flip = false, bool animated = false )
{
double ss = (HScale*sx);
double dw = (Screen.GetWidth()/ss), dh = (Screen.GetHeight()/ss);
double dx = CurX/ss, dy = CurY/ss;
if ( opacity == -1 ) opacity = self.opacity;
if ( opacity >= 16 ) Screen.DrawTexture(tx,animated,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_FillColor,bgcolor,DTA_TopOffset,0,DTA_LeftOffset,0);
double alpha = clamp(opacity/15.,0.0,1.0);
Screen.DrawTexture(tx,animated,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,alpha,DTA_LegacyRenderStyle,STYLE_AddShaded,DTA_FillColor,(tint!="Black")?tint:tintcolor,DTA_TopOffset,0,DTA_LeftOffset,0,DTA_FlipX,flip);
}
private void UTDrawPlainTex( TextureID tx, double sx = 1.0, int opacity = -1, bool flip = false, bool animated = false )
{
double ss = (HScale*sx);
double dw = (Screen.GetWidth()/ss), dh = (Screen.GetHeight()/ss);
double dx = CurX/ss, dy = CurY/ss;
if ( opacity == -1 ) opacity = self.opacity;
if ( opacity >= 16 ) Screen.DrawTexture(tx,animated,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_FillColor,bgcolor,DTA_TopOffset,0,DTA_LeftOffset,0,DTA_FlipX,flip);
double alpha = clamp(opacity/15.,0.0,1.0);
Screen.DrawTexture(tx,animated,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,alpha,DTA_TopOffset,0,DTA_LeftOffset,0,DTA_FlipX,flip);
}
private bool UTDrawWeaponIcon( Weapon w, bool use, double sx = 1.0 )
{
for ( int i=0; i<14; i++ )
{
Color halftint = Color(tintcolor.a,tintcolor.r/2,tintcolor.g/2,tintcolor.b/2);
if ( !(w is IconClasses[i]) ) continue;
if ( use )
{
if ( (i == 10) && flak_sawammo )
UTDrawTintedTex(UseSaw2,sx,opacity+7);
else if ( (i == 11) && flak_transloc2k4 )
UTDrawTintedTex(UseTloc2,sx,opacity+7);
else UTDrawTintedTex(Uses[i],sx,opacity+7);
}
else
{
if ( (i == 10) && flak_sawammo )
UTDrawTintedTex(IconSaw2,sx,opacity,halftint);
else if ( (i == 11) && flak_transloc2k4 )
UTDrawTintedTex(IconTloc2,sx,opacity,halftint);
else UTDrawTintedTex(Icons[i],sx,opacity,halftint);
}
return true;
}
return false;
}
// UT's implementation doesn't seem to translate well to this, so I improvised a bit and made something not so ugly
// This whole function might need to be rewritten in a prettier way someday
private void UTDrawBigNum( int value, double sx = 1.0 )
{
double step = 25*HScale*sx;
double ss = (HScale*sx);
double dw = (Screen.GetWidth()/ss), dh = (Screen.GetHeight()/ss);
String digits = String.Format("%d",min(abs(value),9999));
double flen = 3*step;
double len = digits.length()*step;
double alpha = clamp((opacity+7)/15.,0.0,1.0);
for ( int i=0; i<digits.length(); i++ ) if ( digits.ByteAt(i) == 0x31 ) len -= 0.5*step;
CurX += (flen-len)*0.5;
if ( digits.ByteAt(0) == 0x31 ) CurX -= 0.5*step;
if ( value < 0 )
{
if ( opacity+7 > 15 ) Screen.DrawTexture(BigNum[11],false,CurX/ss,CurY/ss,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_FillColor,bgcolor);
Screen.DrawTexture(BigNum[11],false,CurX/ss,CurY/ss,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,alpha,DTA_LegacyRenderStyle,STYLE_AddShaded,DTA_FillColor,DrawColor);
CurX += step;
}
for ( int i=0; i<digits.length(); i++ )
{
if ( opacity+7 > 15 ) Screen.DrawTexture(BigNum[digits.ByteAt(i)-0x30],false,CurX/ss,CurY/ss,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_FillColor,bgcolor);
Screen.DrawTexture(BigNum[digits.ByteAt(i)-0x30],false,CurX/ss,CurY/ss,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,alpha,DTA_LegacyRenderStyle,STYLE_AddShaded,DTA_FillColor,DrawColor);
CurX += ((i<digits.length()-1)&&(digits.ByteAt(i+1)==0x31))?step*0.5:step;
}
}
private void DrawAmmo()
{
Inventory ammotype1, ammotype2;
[ammotype1, ammotype2] = GetCurrentAmmo();
CurX = showweapons?(Screen.GetWidth()-128*hudsize*HScale):(Screen.GetWidth()*0.5+128*hudsize*HScale);
CurY = Screen.GetHeight()-64*hudsize*HScale;
if ( showweapons && ((weaponsize*hudsize)>=1.0) ) CurY -= 64*hudsize*HScale;
double BaseX = CurX;
double BaseY = CurY;
UTDrawTintedTex(Boxes[0],hudsize);
CurX += 8*hudsize*HScale;
CurY += 14*hudsize*HScale;
DrawColor = WhiteColor;
let cw = CPlayer.ReadyWeapon;
if ( ammotype1 ) UTDrawBigNum(ammotype1.Amount,hudsize);
if ( ammotype2 && (ammotype2 != ammotype1) )
{
CurX = showweapons?(Screen.GetWidth()-128*hudsize*HScale):((Screen.GetWidth()+256*hudsize*HScale)*0.5);
CurY = showweapons?(Screen.GetHeight()-128*hudsize*HScale):(Screen.GetHeight()-64*hudsize*HScale);
if ( showweapons && ((weaponsize*hudsize)>=1.0) ) CurY -= 64*hudsize*HScale;
UTDrawTintedTex(Boxes[0]);
CurX += 8*hudsize*HScale;
CurY += 14*hudsize**HScale;
UTDrawBigNum(ammotype2.Amount,hudsize);
}
// extra bars
if ( flak_transloc2k4 && (cw is 'Translocator') )
{
// draw ammo charge bar
double ch = Translocator(cw).ammocharge;
CurX = BaseX+6*hudsize*HScale;
CurY = BaseY+54*hudsize*HScale;
Vector2 ss = (0.54,0.25)*hudsize*HScale;
double dw = (Screen.GetWidth()/ss.x), dh = (Screen.GetHeight()/ss.y);
double dx = CurX/ss.x, dy = CurY/ss.y;
Vector2 bs = TexMan.GetScaledSize(AmmoBar);
double ddw = bs.x*ch;
double alpha = clamp((opacity+7)/15.,0.0,1.0);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw,DTA_Alpha,alpha);
}
else if ( flak_enforcerreload && (cw is 'Enforcer') )
{
// draw clip(s)
double ch = Enforcer(cw).ClipCount/double(Enforcer(cw).default.ClipCount);
CurX = BaseX+6*hudsize*HScale;
CurY = BaseY+53*hudsize*HScale;
Vector2 ss;
ss = (0.54,(cw.Amount>1)?0.125:0.3)*hudsize*HScale;
double dw = (Screen.GetWidth()/ss.x), dh = (Screen.GetHeight()/ss.y);
double dx = CurX/ss.x, dy = CurY/ss.y;
Vector2 bs = TexMan.GetScaledSize(AmmoBar);
double ddw = bs.x*ch;
double alpha = clamp((opacity+7)/15.,0.0,1.0);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw,DTA_Alpha,alpha);
if ( cw.Amount > 1 )
{
ch = Enforcer(cw).SlaveClipCount/double(Enforcer(cw).default.SlaveClipCount);
CurY += 3*hudsize*HScale;
ss = (0.54,0.125)*hudsize*HScale;
dw = (Screen.GetWidth()/ss.x);
dh = (Screen.GetHeight()/ss.y);
dx = CurX/ss.x;
dy = CurY/ss.y;
ddw = bs.x*ch;
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw,DTA_Alpha,alpha);
}
}
else if ( flak_pulsereload && (cw is 'Pulsegun') )
{
// draw clip
double ch = Pulsegun(cw).ClipCount/double(Pulsegun(cw).default.ClipCount);
CurX = BaseX+6*hudsize*HScale;
CurY = BaseY+53*hudsize*HScale;
Vector2 ss = (0.54,0.3)*hudsize*HScale;
double dw = (Screen.GetWidth()/ss.x), dh = (Screen.GetHeight()/ss.y);
double dx = CurX/ss.x, dy = CurY/ss.y;
Vector2 bs = TexMan.GetScaledSize(AmmoBar);
double ddw = bs.x*ch;
double alpha = clamp((opacity+7)/15.,0.0,1.0);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw,DTA_Alpha,alpha);
}
else if ( cw is 'ImpactHammer' )
{
double ch = min(ImpactHammer(cw).chargesize,1.5)/1.5;
CurX = BaseX+6*hudsize*HScale;
CurY = BaseY+53*hudsize*HScale;
Vector2 ss = (0.54,0.3)*hudsize*HScale;
double dw = (Screen.GetWidth()/ss.x), dh = (Screen.GetHeight()/ss.y);
double dx = CurX/ss.x, dy = CurY/ss.y;
Vector2 bs = TexMan.GetScaledSize(AmmoBar);
double ddw = bs.x*ch;
double alpha = clamp((opacity+7)/15.,0.0,1.0);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw,DTA_Alpha,alpha);
}
else if ( cw is 'BioRifle' )
{
double ch = min(BioRifle(cw).charge,5.1)/5.1;
CurX = BaseX+6*hudsize*HScale;
CurY = BaseY+53*hudsize*HScale;
Vector2 ss = (0.54,0.3)*hudsize*HScale;
double dw = (Screen.GetWidth()/ss.x), dh = (Screen.GetHeight()/ss.y);
double dx = CurX/ss.x, dy = CurY/ss.y;
Vector2 bs = TexMan.GetScaledSize(AmmoBar);
double ddw = bs.x*ch;
double alpha = clamp((opacity+7)/15.,0.0,1.0);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw,DTA_Alpha,alpha);
}
else if ( cw is 'UTRocketLauncher' )
{
double ch = cw.special1/6.;
CurX = BaseX+6*hudsize*HScale;
CurY = BaseY+53*hudsize*HScale;
Vector2 ss = (0.54,0.3)*hudsize*HScale;
double dw = (Screen.GetWidth()/ss.x), dh = (Screen.GetHeight()/ss.y);
double dx = CurX/ss.x, dy = CurY/ss.y;
Vector2 bs = TexMan.GetScaledSize(AmmoBar);
double ddw = bs.x*ch;
double alpha = clamp((opacity+7)/15.,0.0,1.0);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw,DTA_Alpha,alpha);
}
}
private void DrawStatus()
{
UTArmor b, a, t, s;
b = UTArmor(CPlayer.mo.FindInventory("UTArmorBonus"));
a = UTArmor(CPlayer.mo.FindInventory("UTBodyArmor"));
t = UTArmor(CPlayer.mo.FindInventory("UTThighPads"));
s = UTArmor(CPlayer.mo.FindInventory("UTShieldBelt"));
if ( showstatus )
{
CurX = Screen.GetWidth()-128*HScale*hudsize*statussize;
CurY = 0;
Color dollcolor = tintcolor;
DamageAmplifier d;
UTJumpBoots j;
d = DamageAmplifier(CPlayer.mo.FindInventory("DamageAmplifier"));
j = UTJumpBoots(CPlayer.mo.FindInventory("UTJumpBoots"));
if ( d && !d.isBlinking() ) dollcolor = d.BlendColor;
int dolltype = 0;
if ( CPlayer.mo is 'UTPlayer' ) dolltype = UTPlayer(CPlayer.mo).DollType;
else
{
// female doll for female, male doll for male/neutral, boss doll for object
dolltype = (CPlayer.GetGender()==3)?UTPlayer.DOLL_Boss:(CPlayer.GetGender()==1)?UTPlayer.DOLL_Female:UTPlayer.DOLL_Male;
}
if ( dolltype == UTPlayer.DOLL_Boss )
{
UTDrawTintedTex(Boss[0],hudsize*statussize,min(opacity,15),dollcolor);
if ( a ) UTDrawTintedTex(Boss[1],hudsize*statussize,int(min(opacity,15)*(a.Amount/double(a.MaxAmount))),dollcolor);
if ( t ) UTDrawTintedTex(Boss[2],hudsize*statussize,int(min(opacity,15)*(t.Amount/double(t.MaxAmount))),dollcolor);
if ( j ) UTDrawTintedTex(Boss[3],hudsize*statussize,int(min(opacity,15)*(j.Amount/double(j.MaxAmount))),dollcolor);
if ( s ) UTDrawTintedTex(Boss[4],hudsize*statussize,int(min(opacity,15)*(s.Amount/double(s.MaxAmount))),GoldColor);
}
else if ( dolltype == UTPlayer.DOLL_Female )
{
UTDrawTintedTex(Woman[0],hudsize*statussize,min(opacity,15),dollcolor);
if ( a ) UTDrawTintedTex(Woman[1],hudsize*statussize,int(min(opacity,15)*(a.Amount/double(a.MaxAmount))),dollcolor);
if ( t ) UTDrawTintedTex(Woman[2],hudsize*statussize,int(min(opacity,15)*(t.Amount/double(t.MaxAmount))),dollcolor);
if ( j ) UTDrawTintedTex(Woman[3],hudsize*statussize,int(min(opacity,15)*(j.Amount/double(j.MaxAmount))),dollcolor);
if ( s ) UTDrawTintedTex(Woman[4],hudsize*statussize,int(min(opacity,15)*(s.Amount/double(s.MaxAmount))),GoldColor);
}
else
{
UTDrawTintedTex(Man[0],hudsize*statussize,min(opacity,15),dollcolor);
if ( a ) UTDrawTintedTex(Man[1],hudsize*statussize,int(min(opacity,15)*(a.Amount/double(a.MaxAmount))),dollcolor);
if ( t ) UTDrawTintedTex(Man[2],hudsize*statussize,int(min(opacity,15)*(t.Amount/double(t.MaxAmount))),dollcolor);
if ( j ) UTDrawTintedTex(Man[3],hudsize*statussize,int(min(opacity,15)*(j.Amount/double(j.MaxAmount))),dollcolor);
if ( s ) UTDrawTintedTex(Man[4],hudsize*statussize,int(min(opacity,15)*(s.Amount/double(s.MaxAmount))),GoldColor);
}
}
DrawColor = WhiteColor;
if ( !showstatus && !showweapons )
{
CurX = Screen.GetWidth()*0.5-128*hudsize*HScale;
CurY = Screen.GetHeight()-64*hudsize*HScale;
}
else
{
CurX = Screen.GetWidth()-140*hudsize*HScale;
if ( showstatus ) CurX -= 128*statussize*hudsize*HScale;
CurY = 0;
}
UTDrawTintedTex(Boxes[1],hudsize);
int allarmor = 0;
if ( b ) allarmor += b.amount;
if ( a ) allarmor += a.amount;
if ( t ) allarmor += t.amount;
if ( s ) allarmor += s.amount;
CurX += 8*hudsize*HScale;
CurY += 14*hudsize*HScale;
if ( !showstatus && b ) DrawColor = GoldColor;
UTDrawBigNum(allarmor,hudsize);
DrawColor = WhiteColor;
if ( !showstatus && !showweapons )
{
CurX = Screen.GetWidth()*0.5;
CurY = Screen.GetHeight()-64*hudsize*HScale;
}
else
{
CurX = Screen.GetWidth()-140*hudsize*HScale;
if ( showstatus ) CurX -= 128*statussize*hudsize*HScale;
CurY = 64*hudsize*HScale;
}
if ( CPlayer.mo.Health < CPlayer.mo.SpawnHealth()/2 )
{
Color blinkcolor;
double blinky = ((level.time+fractic)/Thinker.TICRATE)*1.5;
blinky = blinky-floor(blinky);
blinkcolor = LerpColor(tintcolor,WhiteColor,blinky);
UTDrawTintedTex(Boxes[2],hudsize,-1,blinkcolor);
DrawColor = LerpColor(WhiteColor,blinkcolor,blinky);
CurX += 8*hudsize*HScale;
CurY += 14*hudsize*HScale;
UTDrawBigNum(Max(0,CPlayer.mo.Health),hudsize);
}
else
{
UTDrawTintedTex(Boxes[2],hudsize);
CurX += 8*hudsize*HScale;
CurY += 14*hudsize*HScale;
UTDrawBigNum(Max(0,CPlayer.mo.Health),hudsize);
}
}
private void DrawWeapons()
{
Color halftint = Color(tintcolor.a,tintcolor.r/2,tintcolor.g/2,tintcolor.b/2);
double WeapScale = hudsize*weaponsize*HScale;
double BaseX = (Screen.GetWidth()-(1280*WeapScale))*0.5;
double BaseY = Screen.GetHeight()-64*WeapScale;
double WeaponOffset = 128*WeapScale;
let cw = CPlayer.ReadyWeapon;
int cwslot = -1;
if ( cw && (cw.SlotNumber != -1) )
{
cwslot = cw.SlotNumber?(cw.SlotNumber-1):9;
CurX = BaseX+cwslot*WeaponOffset;
CurY = BaseY;
UTDrawWeaponIcon(cw,true,hudsize*weaponsize);
CurX = BaseX+cwslot*WeaponOffset;
CurY = BaseY;
}
let pw = CPlayer.PendingWeapon;
int pwslot = -1;
if ( pw && (pw != WP_NOCHANGE) && (pw.SlotNumber != -1) )
{
pwslot = pw.SlotNumber?(pw.SlotNumber-1):9;
CurX = BaseX+pwslot*WeaponOffset-64*WeapScale;
CurY = BaseY-32*WeapScale;
UTDrawTintedTex(Flash,hudsize*weaponsize,min(opacity,15),GoldColor);
CurX = BaseX+pwslot*WeaponOffset;
CurY = BaseY;
UTDrawWeaponIcon(pw,true,hudsize*weaponsize);
}
if ( cwslot != -1 )
{
CurX = BaseX+cwslot*WeaponOffset;
UTDrawPlainTex(WeaponBox,hudsize*weaponsize,opacity+7);
}
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 ( Inventory i = CPlayer.mo.Inv; i; i=i.Inv )
{
if ( !(i is 'Weapon') ) continue;
let w = Weapon(i);
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;
}
}
for ( int i=0; i<10; i++ )
{
CurX = BaseX+i*WeaponOffset;
CurY = BaseY;
if ( !wslots[i] )
UTDrawTintedTex(Slots[i],2*hudsize*weaponsize,-1,halftint);
else if ( (i != cwslot) && (i != pwslot) )
if ( !UTDrawWeaponIcon(wslots[i],false,hudsize*weaponsize) )
UTDrawTintedTex(Slots[i],2*hudsize*weaponsize,-1,halftint);
}
for ( int i=0; i<10; i++ )
{
if ( !wslots[i] ) continue;
CurX = BaseX+i*WeaponOffset+4*WeapScale;
CurY = BaseY+4*WeapScale;
UTDrawTintedTex(BigNum[(i==9)?0:(i+1)],0.75*hudsize*weaponsize,opacity+7,GoldColor);
if ( !wslots[i].Ammo1 ) continue;
CurY = BaseY+52*WeapScale;
Vector2 ss = (0.6875,0.5)*WeapScale;
double dw = (Screen.GetWidth()/ss.x), dh = (Screen.GetHeight()/ss.y);
double dx = CurX/ss.x, dy = CurY/ss.y;
Vector2 bs = TexMan.GetScaledSize(AmmoBar);
double ddw = bs.x*(wslots[i].Ammo1.Amount/double(wslots[i].Ammo1.MaxAmount));
double alpha = clamp((opacity+7)/15.,0.0,1.0);
Screen.DrawTexture(AmmoBar,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_WindowRightF,ddw,DTA_Alpha,alpha);
}
}
private void DrawFragCount()
{
CurX = showweapons?0:(Screen.GetWidth()*0.5-256*hudsize*HScale);
CurY = Screen.GetHeight()-64*hudsize*HScale;
if ( showweapons && ((weaponsize*hudsize)>=1.0) ) CurY -= 64*hudsize*HScale;
DrawColor = tintcolor;
double whiten = ((level.time+fractic)-lastfrag)/Thinker.TICRATE;
if ( whiten < 3.0 )
{
if ( tintcolor == GoldColor )
DrawColor = WhiteColor;
else DrawColor = GoldColor;
CurX -= 64*hudsize*HScale;
CurY -= 32*hudsize*HScale;
UTDrawTintedTex(Flash,hudsize,min(opacity,15),DrawColor);
CurX += 64*hudsize*HScale;
CurY += 32*hudsize*HScale;
whiten = 4*whiten-int(4*whiten);
DrawColor = lerpcolor(tintcolor,DrawColor,whiten);
}
UTDrawTintedTex(Boxes[3],hudsize,-1,DrawColor);
CurX += 44*hudsize*HScale;
CurY += 14*hudsize*HScale;
DrawColor = WhiteColor;
UTDrawBigNum((deathmatch||teamplay)?CPlayer.fragcount:CPlayer.killcount,hudsize);
}
private void DrawIdentifyInfo()
{
double lalpha = 2.0-((level.time+fractic)-lastseentic)/Thinker.TICRATE;
if ( !lastseen || (lalpha <= 0) ) return;
String cl1 = "UTHUDTextLight", cl2 = "UTHUDText";
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());
double scl = HScale/5.;
CurX = (640-mUTFont40.mFont.StringWidth(tname)*scl)*0.5;
CurY = 480*0.75;
Screen.DrawText(mUTFont40.mFont,Font.CR_UNTRANSLATED,CurX/scl,CurY/scl,tname,DTA_VirtualWidthF,640/scl,DTA_VirtualHeightF,480/scl,DTA_Alpha,lalpha/2.,DTA_LegacyRenderStyle,STYLE_Add);
if ( !deathmatch || (lastseen.IsTeammate(CPlayer.mo)) )
{
tname = String.Format("\c[%s]%s:\c[%s] %d",cl1,StringTable.Localize("$M_HEALTH"),cl2,lastseen.Health);
CurY += mUTFont40.mFont.GetHeight()*scl;
CurX = (640-mUTFont40.mFont.StringWidth(tname)*scl)*0.5;
Screen.DrawText(mUTFont40.mFont,Font.CR_UNTRANSLATED,CurX/scl,CurY/scl,tname,DTA_VirtualWidthF,640/scl,DTA_VirtualHeightF,480/scl,DTA_Alpha,lalpha/2.,DTA_LegacyRenderStyle,STYLE_Add);
}
}
private void DrawKeys()
{
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)
bool locks[6];
for ( int i=0; i<6; i++ ) locks[i] = CPlayer.mo.CheckKeys(i+1,false,true);
int nrows = 0, nrowss = 0;
for ( int i=0; i<3; i++ ) if ( locks[i] ) nrows++;
for ( int i=3; i<6; i++ ) if ( locks[i] ) nrowss++;
CurX = (Screen.GetWidth()-64*hudsize*HScale);
CurY = (Screen.GetHeight()-nrows*64*hudsize*HScale)*0.5;
CurY -= max(0,nrows-1)*4*hudsize*HScale;
if ( locks[0] )
{
if ( gameinfo.gametype&GAME_Heretic ) UTDrawTintedTex(Keys[4],hudsize,min(opacity,15),Color("Green"));
else UTDrawTintedTex(Keys[0],hudsize,min(opacity,15),Color("Red"));
CurY += 72*hudsize*HScale;
}
if ( locks[1] )
{
UTDrawTintedTex(Keys[1],hudsize,min(opacity,15),Color("Blue"));
CurY += 72*hudsize*HScale;
}
if ( locks[2] )
{
UTDrawTintedTex(Keys[2],hudsize,min(opacity,15),Color("Gold"));
CurY += 72*hudsize*HScale;
}
if ( nrows ) CurX -= 56*hudsize*HScale;
CurY = (Screen.GetHeight()-nrowss*64*hudsize*HScale)*0.5;
CurY += max(0,nrowss-1)*2*hudsize*HScale;
if ( locks[3] )
{
DrawColor = "Red";
UTDrawTintedTex(Keys[3],hudsize,min(opacity,15),Color("Red"));
CurY += 60*hudsize*HScale;
}
if ( locks[4] )
{
UTDrawTintedTex(Keys[3],hudsize,min(opacity,15),Color("Blue"));
CurY += 60*hudsize*HScale;
}
if ( locks[5] )
{
UTDrawTintedTex(Keys[3],hudsize,min(opacity,15),Color("Gold"));
CurY += 60*hudsize*HScale;
}
}
private void DrawInventory( double lbottom )
{
if ( isInventoryBarVisible() )
{
CPlayer.mo.InvFirst = ValidateInvFirst(5);
if ( !CPlayer.mo.InvFirst ) return;
// draw the boxes
double BaseX, BaseY;
BaseX = CurX = (Screen.GetWidth()-64*5*hudsize*HScale)/2.;
BaseY = CurY = Screen.GetHeight()-224*hudsize*HScale;
for ( int i=0; i<5; i++ )
{
UTDrawTintedTex(ItemBox,hudsize);
CurX += 64*hudsize*HScale;
}
int i = 0;
Inventory itm;
for ( itm=CPlayer.mo.InvFirst; (itm && (i < 5)); itm=itm.NextInv() )
{
// scale to fit
Vector2 scl = TexMan.GetScaledSize(itm.Icon);
double mscl = 56./max(scl.x,scl.y);
CurX = BaseX+(4+(56.-scl.x*mscl)/2.)*hudsize*HScale;
CurY = BaseY+4*hudsize*HScale;
UTDrawTintedTex(itm.Icon,hudsize*mscl);
// amount if >1
if ( itm.Amount > 1 )
{
CurX = BaseX+32*hudsize*HScale;
CurY = BaseY+40*hudsize*HScale;
DrawColor = WhiteColor;
UTDrawBigNum(itm.Amount,hudsize*0.5);
}
// selection box if current item
if ( itm == CPlayer.mo.InvSel )
{
CurX = BaseX;
CurY = BaseY;
UTDrawPlainTex(ItemSel,hudsize,opacity+7);
}
BaseX += 64*hudsize*HScale;
i++;
}
// draw arrows
CurY = Screen.GetHeight()-204*hudsize*HScale;
CurX = (Screen.GetWidth()-(64*5+40)*hudsize*HScale)/2.;
UTDrawTintedTex(ItemArrow[CPlayer.mo.InvFirst!=CPlayer.mo.FirstInv()],hudsize,flip:true);
CurX = (Screen.GetWidth()+(64*5+8)*hudsize*HScale)/2.;
UTDrawTintedTex(ItemArrow[!!itm],hudsize);
}
else if ( CPlayer.mo.InvSel || artiflashtick )
{
// flashie
if ( artiflashtick )
{
DrawColor = GoldColor;
CurX = -32*hudsize*HScale;
CurY = lbottom-96*hudsize*HScale;
UTDrawTintedTex(ItemFlash,hudsize,min(opacity,15),DrawColor);
}
// position 64x64 box
CurX = 0;
CurY = lbottom-64*hudsize*HScale;
UTDrawTintedTex(ItemBox,hudsize);
if ( artiflashtick )
{
// scale to fit
Vector2 scl = TexMan.GetScaledSize(LastItem);
double mscl = 56./max(scl.x,scl.y);
CurX += (4+(56.-scl.x*mscl)/2.)*hudsize*HScale;
CurY += 4*hudsize*HScale;
UTDrawTintedTex(LastItem,hudsize*mscl);
if ( LastAmount <= 1 ) return;
CurX = 32*hudsize*HScale;
CurY = lbottom-24*hudsize*HScale;
DrawColor = WhiteColor;
UTDrawBigNum(LastAmount,hudsize*0.5);
return;
}
if ( !CPlayer.mo.InvSel ) return;
// scale to fit
Vector2 scl = TexMan.GetScaledSize(CPlayer.mo.InvSel.Icon);
double mscl = 56./max(scl.x,scl.y);
CurX += (4+(56.-scl.x*mscl)/2.)*hudsize*HScale;
CurY += 4*hudsize*HScale;
UTDrawTintedTex(CPlayer.mo.InvSel.Icon,hudsize*mscl);
// amount if >1
if ( CPlayer.mo.InvSel.Amount <= 1 ) return;
CurX = 32*hudsize*HScale;
CurY = lbottom-24*hudsize*HScale;
DrawColor = WhiteColor;
UTDrawBigNum(CPlayer.mo.InvSel.Amount,hudsize*0.5);
}
}
private bool IsAutoTaunt( String str )
{
// checks if this critical message is pretending to be a chat msg
if ( str.IndexOf("\c*") == 0 ) return true;
return false;
}
private void SetChatFace( String str, bool isauto = false )
{
Array<String> splitme;
str.Split(splitme,":");
if ( splitme.Size() < 2 ) return;
String pname = splitme[0];
// autotaunts have a leading chat color escape
if ( isauto && (pname.IndexOf("\c*") == 0) ) pname.Remove(0,2);
if ( pname.RightIndexOf("\c*") == pname.Length()-2 ) pname.Remove(pname.Length()-2,2);
// guess the player
int p = -1;
for ( int i=0; i<MAXPLAYERS; i++ )
{
if ( !playeringame[i] ) continue;
if ( players[i].GetUserName() != pname ) continue;
p = i;
break;
}
if ( (p == -1) || !(players[p].mo is 'UTPlayer') ) return;
switch ( UTPlayer(players[p].mo).VoiceType )
{
case UTPlayer.VOICE_FemaleOne:
LastTalkFace = TexMan.CheckForTexture("Ivana",TexMan.Type_Any);
break;
case UTPlayer.VOICE_FemaleTwo:
LastTalkFace = TexMan.CheckForTexture("Lauren",TexMan.Type_Any);
break;
case UTPlayer.VOICE_MaleOne:
LastTalkFace = TexMan.CheckForTexture("Blake",TexMan.Type_Any);
break;
case UTPlayer.VOICE_MaleTwo:
LastTalkFace = TexMan.CheckForTexture("Brock",TexMan.Type_Any);
break;
case UTPlayer.VOICE_Boss:
LastTalkFace = TexMan.CheckForTexture("Xan",TexMan.Type_Any);
break;
}
LastTalkTic = gametic+90;
}
override bool ProcessNotify( EPrintLevel printlevel, String outline )
{
if ( gamestate != GS_LEVEL ) return false; // not during intermissions
if ( printlevel == PRINT_LOW ) // pickups
{
PickupMsg = outline;
PickupMsgTic = gametic+50;
return true;
}
else if ( printlevel == PRINT_MEDIUM ) // obituaries
{
AppendMessage(outline,Font.CR_RED);
return true;
}
else if ( (printlevel == PRINT_CHAT) || (printlevel == PRINT_TEAMCHAT) ) // chat
{
AppendMessage(outline,Font.CR_GREEN);
SetChatFace(outline);
return true;
}
else if ( IsAutoTaunt(outline) ) // autotaunts
{
AppendMessage(outline,Font.CR_GREEN);
SetChatFace(outline,true);
return true;
}
else // other messages
{
AppendMessage(outline,Font.CR_WHITE);
return true;
}
return false;
}
override bool ProcessMidPrint( Font fnt, String msg, bool bold )
{
if ( !fnt || (fnt == SmallFont) || (fnt == OriginalSmallFont) || (fnt == NewSmallFont) )
{
MidPrintStr = msg;
MidPrintScale = 2.5;
MidPrintTic = gametic+70;
return true;
}
else if ( fnt == BigFont )
{
MidPrintStr = msg;
MidPrintScale = 1.2;
MidPrintTic = gametic+70;
return true;
}
return false;
}
private void AppendMessage( String msg, int col )
{
BrokenLines lines = mUTFont40.mFont.BreakLines(msg,2450);
for ( int i=0; i<lines.Count(); i++ )
{
// push back old lines
for ( int j=3; j>0; j-- )
{
ShortMsg[j] = ShortMsg[j-1];
ShortMsgTic[j] = ShortMsgTic[j-1];
ShortMsgCol[j] = ShortMsgCol[j-1];
}
// jam it in
ShortMsg[0] = lines.StringAt(i);
LastMsgTic = ShortMsgTic[0] = gametic+170;
ShortMsgCol[0] = col;
}
}
override void FlushNotify()
{
for ( int i=0; i<4; i++ )
{
ShortMsg[i] = "";
ShortMsgTic[i] = int.min;
ShortMsgCol[i] = Font.CR_UNTRANSLATED;
}
LastTalkTic = LastMsgTic = PickupMsgTic = int.min;
LastTalkFace.SetNull();
PickupMsg = "";
PickupMsgTic = int.min;
MidPrintStr = "";
MidPrintTic = int.min;
}
override bool DrawChat( String txt )
{
if ( gamestate != GS_LEVEL ) return false; // not during intermissions
CurX = 0;
CurY = 68*HScale;
if ( LastTalkTic > gametic ) CurX += (68+faceout)*HScale;
int areatime = max(LastTalkTic,LastMsgTic)+30;
if ( areatime > gametic ) UTDrawTintedTex(FacePanel[1],opacity:clamp(int((areatime-gametic+fractic)*0.75),0,15));
CurX += 6*HScale;
CurY += HScale;
double scl = HScale/3.;
String fullstr = String.Format("(> Say %s%s",txt,mUTFont40.mFont.GetCursor());
// cut out until it fits
while ( (mUTFont40.mFont.StringWidth(fullstr) > 2450) && (fullstr.Length() > 7) )
fullstr.Remove(7,1);
Screen.DrawText(mUTFont40.mFont,Font.CR_GREEN,CurX/scl,CurY/scl,fullstr,DTA_VirtualWidthF,Screen.GetWidth()/scl,DTA_VirtualHeightF,Screen.GetHeight()/scl,DTA_KeepRatio,true);
return true;
}
private void DrawTalkFace()
{
// this doesn't even get close to how it's supposed to look but whatever
double ss = (HScale*0.265625);
double dw = (Screen.GetWidth()/ss), dh = (Screen.GetHeight()/ss);
double dx = CurX/ss, dy = CurY/ss;
Screen.DrawTexture(FacePanel[2],false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_FillColor,Color("Black"));
Screen.DrawTexture(FacePanel[2],true,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_AddShaded,DTA_FillColor,tintcolor);
ss = HScale;
dw = (Screen.GetWidth()/ss);
dh = (Screen.GetHeight()/ss);
dx = (CurX+2*HScale)/ss;
dy = (CurY+2*HScale)/ss;
Screen.DrawTexture(LastTalkFace,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_Alpha,0.8);
Screen.DrawTexture(LastTalkFace,false,dx,dy,DTA_VirtualWidthF,dw,DTA_VirtualHeightF,dh,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add);
}
private void DrawMessages()
{
// midprint
if ( (MidPrintStr.Length() > 0) && (MidPrintTic > gametic) )
{
double scl = HScale/MidPrintScale;
CurX = (Screen.GetWidth()-mUTFont40.mFont.StringWidth(MidPrintStr)*scl)/2;
CurY = 256*HScale;
Screen.DrawText(mUTFont40.mFont,Font.FindFontColor('UTHudText'),CurX/scl,CurY/scl,MidPrintStr,DTA_VirtualWidthF,Screen.GetWidth()/scl,DTA_VirtualHeightF,Screen.GetHeight()/scl,DTA_KeepRatio,true,DTA_Alpha,clamp((MidPrintTic-gametic+fractic)*0.1,0,1),DTA_LegacyRenderStyle,STYLE_Add);
}
// pickup message
if ( PickupMsgTic > gametic )
{
double scl = HScale/2.2;
CurX = (Screen.GetWidth()-mUTFont40.mFont.StringWidth(PickupMsg)*scl)/2;
CurY = Screen.GetHeight()-112*HScale;
Screen.DrawText(mUTFont40.mFont,Font.CR_WHITE,CurX/scl,CurY/scl,PickupMsg,DTA_VirtualWidthF,Screen.GetWidth()/scl,DTA_VirtualHeightF,Screen.GetHeight()/scl,DTA_KeepRatio,true,DTA_Alpha,clamp((PickupMsgTic-gametic+fractic)*0.1,0,1),DTA_LegacyRenderStyle,STYLE_Add);
}
// talk face
CurX = 0;
CurY = 0;
if ( LastTalkTic > gametic )
{
if ( (LastTalkTic-gametic) < 30 ) faceout = max(-68,faceout-8);
else faceout = 0;
CurX = faceout*HScale;
DrawTalkFace();
CurX += 68*HScale;
}
// message frame
int areatime = max(LastTalkTic,LastMsgTic)+30;
if ( areatime > gametic )
UTDrawTintedTex(FacePanel[0],opacity:clamp(int((areatime-gametic+fractic)*0.75),0,15));
// messages themselves
if ( LastMsgTic < gametic ) return;
CurX = 8*HScale;
if ( LastTalkTic > gametic ) CurX += (68+faceout)*HScale;
CurY = HScale;
double scl = HScale/3.;
for ( int i=3; i>=0; i-- )
{
if ( ShortMsgTic[i] < gametic ) continue;
Screen.DrawText(mUTFont40.mFont,ShortMsgCol[i],CurX/scl,CurY/scl,ShortMsg[i],DTA_VirtualWidthF,Screen.GetWidth()/scl,DTA_VirtualHeightF,Screen.GetHeight()/scl,DTA_KeepRatio,true);
CurY += 16*HScale;
}
}
override void Tick()
{
Super.Tick();
if ( CPlayer.mo.InvSel && !artiflashtick )
{
LastItem = CPlayer.mo.InvSel.Icon;
LastAmount = CPlayer.mo.InvSel.Amount-1;
}
if ( deathmatch||teamplay )
{
if ( CPlayer.fragcount != lastfragcnt ) lastfrag = level.time;
lastfragcnt = CPlayer.fragcount;
}
else
{
if ( CPlayer.killcount != lastfragcnt ) lastfrag = level.time;
lastfragcnt = CPlayer.killcount;
}
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 = level.time;
}
private void DrawUTHUD( double lbottom )
{
// Display Weapons
if ( showweapons ) DrawWeapons();
// Display Frag count
if ( showfrags ) DrawFragCount();
// Draw Ammo
if ( showammo ) DrawAmmo();
// Draw Health/Armor status
DrawStatus();
// Display Keys
DrawKeys();
// Inventory Bar
DrawInventory(lbottom);
// Display Identification Info
if ( CPlayer == players[consoleplayer] && showinfo ) DrawIdentifyInfo();
// Display messages
DrawMessages();
}
override void DrawAutomapHUD( double ticFrac )
{
int crdefault = Font.FindFontColor('UTHUDTextLight');
int highlight = Font.FindFontColor('UTHUDText');
HScale = Screen.GetWidth()/1280.;
showweapons = CVar.GetCVar('flak_showweapons',players[consoleplayer]).GetBool();
showstatus = CVar.GetCVar('flak_showstatus',players[consoleplayer]).GetBool();
weaponsize = CVar.GetCVar('flak_weaponsize',players[consoleplayer]).GetFloat();
statussize = CVar.GetCVar('flak_statussize',players[consoleplayer]).GetFloat();
double cbottom = Screen.GetHeight()*0.99;
let scale = GetHUDScale();
double textdist = 8./scale.Y;
int height = mUTFont12.mFont.GetHeight();
String printtext;
int SCREENWIDTH = screen.GetWidth();
BeginHUD();
let y = textdist;
let width = mUTFont12.mFont.StringWidth("00:00:00");
double tmp, hres;
[tmp,tmp,hres] = StatusbarToRealCoords(0,0,HorizontalResolution);
double swidth = 0;
if ( !(players[consoleplayer].camera is 'GuidedWarShell') )
{
if ( showweapons ) cbottom -= 64*hudsize*weaponsize*HScale;
else if ( showfrags || showammo || !showstatus ) cbottom -= 64*hudsize*HScale;
if ( showstatus ) swidth += 128*hudsize*statussize*HScale;
if ( showweapons ) swidth += 140*hudsize*HScale+Screen.GetWidth()*0.01;
}
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(mUTFont12,level.TimeFormatted(),(-textdist-width,y),0,crdefault);
y += height;
}
if ( am_showtotaltime ) DrawString(mUTFont12,level.TimeFormatted(true),(-textdist-width,y),0,crdefault);
if ( !deathmatch )
{
y = textdist;
if ( am_showmonsters )
{
DrawString(mUTFont12,String.Format("%s\34%c %d/%d",Stringtable.Localize("$AM_MONSTERS"),crdefault+65,level.killed_monsters,level.total_monsters),(textdist,y),0,highlight);
y += height;
}
if ( am_showsecrets )
{
DrawString(mUTFont12,String.Format("%s\34%c %d/%d",Stringtable.Localize("$AM_SECRETS"),crdefault+65,level.found_secrets,level.total_secrets),(textdist,y),0,highlight);
y += height;
}
if ( am_showitems ) DrawString(mUTFont12,String.Format("%s\34%c %d/%d",Stringtable.Localize("$AM_ITEMS"),crdefault+65,level.found_items,level.total_items),(textdist,y),0,highlight);
}
String mapname = level.FormatMapName(crdefault);
BrokenLines lines = mUTFont12.mFont.BreakLines(mapname,int(SCREENWIDTH/scale.X));
int numlines = lines.Count();
int finalwidth = int(mUTFont12.mFont.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(mUTFont12,lines.StringAt(i),(0,y),DI_TEXT_ALIGN_CENTER|DI_SCREEN_HCENTER|DI_SCREEN_TOP,highlight);
y += height;
}
}
}