swwmgz_m/zscript/hud/swwm_hud.zsc

631 lines
24 KiB
Text

// The Demolitionist HUD is mostly built on top of what I had already done for
// SWWM Z, but with lots of color, gradient text and bars, beveled borders,
// drop shadows, and much more to give off this sorta "retro UI" vibe.
// (The SWWM Z hud was built entirely on borderless flat graphics and smooth
// gradient shadows, not exactly the finest looking aesthetic, to be honest)
Class MsgLine
{
String str;
transient BrokenLines l, ls;
int tic, type, rep;
int lastrep;
int lastsz;
void UpdateText( int sz = 0 )
{
bool mustupdate = (!l||!ls||(lastrep!=rep)||((type==PRINT_LOW)&&(sz!=lastsz)));
if ( !mustupdate ) return;
if ( l ) l.Destroy();
if ( ls ) ls.Destroy();
lastsz = sz;
lastrep = rep;
String nstr = str;
if ( rep > 1 ) nstr.AppendFormat(" (x%d)",rep);
let fnt = Font.GetFont('TewiFont');
l = fnt.BreakLines(nstr,(type==PRINT_LOW)?sz:361);
if ( type != PRINT_LOW ) ls = fnt.BreakLines(nstr,211);
}
}
Class KeyGet
{
Class<Key> got;
int flashtime;
}
Enum EMiniHUDFontColor
{
MCR_DEMOHUD,
MCR_IBUKIHUD,
MCR_SAYAHUD,
MCR_KIRINHUD,
MCR_MARISAHUD,
MCR_VOIDHUD,
MCR_WHITE,
MCR_RED,
MCR_GREEN,
MCR_BLUE,
MCR_YELLOW,
MCR_CYAN,
MCR_PURPLE,
MCR_BRASS,
MCR_SILVER,
MCR_GOLD,
MCR_MANA,
MCR_CRIMSON,
MCR_ELDRITCH,
MCR_KINYLUM,
MCR_NOKRON,
MCR_NOKOROKINYLUM,
MCR_DEMOBLUE,
MCR_DEMOPINK,
MCR_ORANGE,
MCR_GRASS,
MCR_MINT,
MCR_AQUA,
MCR_MAGENTA,
MCR_PINK,
MCR_CRYSTAL,
MCR_FIRE,
MCR_SULFUR,
MCR_WITCH,
MCR_CYANBLU,
MCR_ICE,
MCR_PURPUR,
MCR_TOMATO,
MCR_BLURP,
MCR_PURB,
MCR_FLASH,
MCR_REDFLASH,
MCR_WHITEFLASH,
NUM_MINIHUD_COLOR
};
Class SWWMStatusBar : BaseStatusBar
{
TextureID StatusTex, WeaponTex, ScoreTex, InventoryTex, ChatTex[6],
HealthTex[9], FuelTex[2], DashTex, EnemyBTex, EnemyHTex[7],
GenericAmmoTex[3], AmmoTex[3], MiniBox, bgtex, FaceTex[19];
Font mSmallFont, mSmallFontOutline, mTinyFont, mTinyFontOutline, MiniHUDFont, MiniHUDFontOutline;
int mhudfontcol[NUM_MINIHUD_COLOR];
Array<MsgLine> MainQueue, PickupQueue;
transient ThinkerIterator cti;
// the event handler, holding all sorts of stuff
SWWMHandler hnd;
// shared stuff
double hs;
double hs1;
double hs2;
Vector2 ss;
Vector2 ss1;
Vector2 ss2;
int margin;
double FracTic;
double FrameTime;
double PrevFrame;
int chatopen;
int pausetime;
Vector2 pausepos, pausedir;
// constants
const MAXSHOWN = 4;
const MAXSHOWNBIG = 10;
const MAXPICKUP = 5;
const CHATDURATION = 25;
const MSGDURATION = 5;
const PICKDURATION = 3;
// shared from renderunderlay, needed for proper interpolation of some things
Vector3 viewpos, viewrot;
// projection data cache
SWWMProjectionData projdata;
DynamicValueInterpolator ScoreInter;
Inventory lastsel;
Weapon lastwep;
String ntagstr;
int ntagtic, ntagcol;
String midstr;
int midtic, midtype;
transient BrokenLines midl;
int midsz;
int puzzlecnt, realpuzzlecnt;
SWWMWeaponTooltip ctip;
transient ThinkerIterator mi; // for map markers
double minimapzoom, oldminimapzoom;
// minimap constants
const CLIPDIST = 800; // clip distance for minimap view, with rotation accounted
const MAPVIEWDIST = 1132; // maximum distance for something to be considered visible (rounded up CLIPDIST*sqrt(2))
const HALFMAPSIZE = 40; // half the size of the minimap draw region (unscaled)
// minimap colors (thats a lot of 'em)
int mm_colorset;
Color mm_backcolor, mm_cdwallcolor, mm_efwallcolor, mm_fdwallcolor, mm_interlevelcolor, mm_intralevelcolor, mm_lockedcolor, mm_notseencolor, mm_portalcolor, mm_secretsectorcolor, mm_secretwallcolor, mm_specialwallcolor, mm_thingcolor, mm_thingcolor_citem, mm_thingcolor_friend, mm_thingcolor_item, mm_thingcolor_monster, mm_thingcolor_ncmonster, mm_thingcolor_shootable, mm_thingcolor_vipitem, mm_thingcolor_missile, mm_tswallcolor, mm_unexploredsecretcolor, mm_wallcolor, mm_yourcolor;
bool mm_displaylocks;
// deathmatch stuff
int playercount, rank, lead;
bool tiedscore;
Array<PlayerInfo> sortplayers;
Array<bool> teamactive;
Array<int> teamscore;
int PulsePhase; // for health pulsing
// for flashing some elements in the hud
Array<KeyGet> keyflash;
int oldkills, olditems, oldsecrets;
int oldtkills, oldtitems, oldtsecrets;
int oldpkills, oldpitems, oldpsecrets;
transient int killflash, itemflash, secretflash;
transient int tkillflash, titemflash, tsecretflash;
transient int pkillflash, pitemflash, psecretflash;
// top stuff colors
int tclabel, tcvalue, tcextra, tccompl, tcsucks;
String tclabel_s, tcextra_s;
transient int AmmoFlash[18]; // flash when new ammo is received
int AmmoOldAmounts[18]; // to detect when to flash
transient int AmmoMaxFlash[18]; // flash when ammo max amount changes
int AmmoOldMaxAmounts[18]; // to detect when to flash
Class<SWWMAmmo> AmmoSlots[18]; // ammo type on each slot
String AmmoNames[18]; // ammo 4-letter names
transient int HealthFlash; // flash when healing
int LastHealth; // to detect when to flash
int LagHealth[10]; // for delayed decay bar
SmoothDynamicValueInterpolator HealthInter, FuelInter, DashInter;
SmoothLinearValueInterpolator LagHealthInter;
transient ui int rss;
// called by static handler when loading a game
// forcibly flushes our interpolators
void Flush()
{
FlushTopStuff();
FlushStatus();
}
// separated so they can be auto-ticked by the demolitionist menu
void TickInterpolators()
{
// ensure money updates when using the store
TickTopStuffInterpolators();
// ensure healthbar updates when buying healing items
TickStatusInterpolators();
// ensure ammo flashes when buying
TickWeaponInterpolators();
}
override void Tick()
{
Super.Tick();
if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
pausetime = gametic;
SWWMUtility.PrepareProjData(projdata,ViewPos,ViewRot.x,ViewRot.y,ViewRot.z,players[consoleplayer].fov);
// interpolators first
TickInterpolators();
// subcategory tickers
TickMessages();
TickStatus();
TickTopStuff();
TickWeapons();
// part of gross hackery to override nametag display
if ( CPlayer.inventorytics > 0 )
{
if ( CPlayer.mo.InvSel && (CPlayer.mo.InvSel != lastsel) && (displaynametags&1) && (CPlayer == players[consoleplayer]) )
{
ntagstr = CPlayer.mo.InvSel.GetTag();
ntagtic = level.totaltime;
ntagcol = nametagcolor;
}
lastsel = CPlayer.mo.InvSel;
}
if ( CPlayer.PendingWeapon && (CPlayer.PendingWeapon != WP_NOCHANGE) && (CPlayer.PendingWeapon != lastwep) )
{
if ( (displaynametags&2) && (CPlayer == players[consoleplayer]) && !(CPlayer.PendingWeapon is 'SWWMGesture') && !(CPlayer.PendingWeapon is 'SWWMItemGesture') )
{
ntagstr = CPlayer.PendingWeapon.GetTag();
ntagtic = level.totaltime;
ntagcol = nametagcolor;
}
}
lastwep = CPlayer.PendingWeapon;
}
override void Init()
{
StatusTex = TexMan.CheckForTexture("graphics/HUD/StatusBox.png");
DashTex = TexMan.CheckForTexture("graphics/HUD/DashBar.png");
FuelTex[0] = TexMan.CheckForTexture("graphics/HUD/FuelBar.png");
FuelTex[1] = TexMan.CheckForTexture("graphics/HUD/FuelBarS.png");
HealthTex[0] = TexMan.CheckForTexture("graphics/HUD/HealthBar0.png");
HealthTex[1] = TexMan.CheckForTexture("graphics/HUD/HealthBar1.png");
HealthTex[2] = TexMan.CheckForTexture("graphics/HUD/HealthBar2.png");
HealthTex[3] = TexMan.CheckForTexture("graphics/HUD/HealthBar3.png");
HealthTex[4] = TexMan.CheckForTexture("graphics/HUD/HealthBarS.png");
HealthTex[5] = TexMan.CheckForTexture("graphics/HUD/HealthBarD.png");
HealthTex[6] = TexMan.CheckForTexture("graphics/HUD/HealthBarP.png");
HealthTex[7] = TexMan.CheckForTexture("graphics/HUD/HealthBarF.png");
HealthTex[8] = TexMan.CheckForTexture("graphics/HUD/HealthBarL.png");
ScoreTex = TexMan.CheckForTexture("graphics/HUD/ScoreBox.png");
WeaponTex = TexMan.CheckForTexture("graphics/HUD/WeaponBox.png");
ChatTex[0] = TexMan.CheckForTexture("graphics/HUD/ChatBoxTop.png");
ChatTex[1] = TexMan.CheckForTexture("graphics/HUD/ChatBoxLine.png");
ChatTex[2] = TexMan.CheckForTexture("graphics/HUD/ChatBoxBottom.png");
ChatTex[3] = TexMan.CheckForTexture("graphics/HUD/ChatBoxTop_Smol.png");
ChatTex[4] = TexMan.CheckForTexture("graphics/HUD/ChatBoxLine_Smol.png");
ChatTex[5] = TexMan.CheckForTexture("graphics/HUD/ChatBoxBottom_Smol.png");
InventoryTex = TexMan.CheckForTexture("graphics/HUD/InventoryBox.png");
EnemyBTex = TexMan.CheckForTexture("graphics/HUD/EnemyBox.png");
EnemyHTex[0] = TexMan.CheckForTexture("graphics/HUD/EnemyBar.png");
EnemyHTex[1] = TexMan.CheckForTexture("graphics/HUD/EnemyBarS.png");
EnemyHTex[2] = TexMan.CheckForTexture("graphics/HUD/EnemyBarL.png");
EnemyHTex[3] = TexMan.CheckForTexture("graphics/HUD/EnemyBar1.png");
EnemyHTex[4] = TexMan.CheckForTexture("graphics/HUD/EnemyBar2.png");
EnemyHTex[5] = TexMan.CheckForTexture("graphics/HUD/EnemyBar3.png");
EnemyHTex[6] = TexMan.CheckForTexture("graphics/HUD/EnemyBarD.png");
GenericAmmoTex[0] = TexMan.CheckForTexture("graphics/HUD/GenericAmmoBoxL.png");
GenericAmmoTex[1] = TexMan.CheckForTexture("graphics/HUD/GenericAmmoBoxM.png");
GenericAmmoTex[2] = TexMan.CheckForTexture("graphics/HUD/GenericAmmoBoxR.png");
AmmoTex[0] = TexMan.CheckForTexture("graphics/HUD/AmmoBoxT.png");
AmmoTex[1] = TexMan.CheckForTexture("graphics/HUD/AmmoBoxM.png");
AmmoTex[2] = TexMan.CheckForTexture("graphics/HUD/AmmoBoxB.png");
MiniBox = TexMan.CheckForTexture("graphics/HUD/MinimapBox.png");
bgtex = TexMan.CheckForTexture("graphics/tempbg.png");
FaceTex[0] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Head.png");
FaceTex[1] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Flash.png");
FaceTex[2] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Default.png");
FaceTex[3] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Unamused.png");
FaceTex[4] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Blink.png");
FaceTex[5] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Grin.png");
FaceTex[6] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Evil.png");
FaceTex[7] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Hurt.png");
FaceTex[8] = TexMan.CheckForTexture("graphics/HUD/DemoFace_HurtLeft.png");
FaceTex[9] = TexMan.CheckForTexture("graphics/HUD/DemoFace_HurtRight.png");
FaceTex[10] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Ouch.png");
FaceTex[11] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Dead.png");
FaceTex[12] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Smug.png");
FaceTex[13] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Angery.png");
FaceTex[14] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Barrier.png");
FaceTex[15] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Rage.png");
FaceTex[16] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Angerage.png");
FaceTex[17] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Sad.png");
FaceTex[18] = TexMan.CheckForTexture("graphics/HUD/DemoFace_Wink.png");
// other expressions will be added when needed
mSmallFont = Font.GetFont('TewiFont');
mSmallFontOutline = Font.GetFont('TewiFontOutline');
mTinyFont = Font.GetFont('MiniwiFont');
mTinyFontOutline = Font.GetFont('MiniwiFontOutline');
MiniHudFont = Font.GetFont("MiniHUDShadow");
MiniHudFontOutline = Font.GetFont("MiniHUDOutline");
mhudfontcol[MCR_DEMOHUD] = Font.FindFontColor("MiniDemoHUD");
mhudfontcol[MCR_IBUKIHUD] = Font.FindFontColor("MiniIbukiHUD");
mhudfontcol[MCR_SAYAHUD] = Font.FindFontColor("MiniSayaHUD");
mhudfontcol[MCR_KIRINHUD] = Font.FindFontColor("MiniKirinHUD");
mhudfontcol[MCR_MARISAHUD] = Font.FindFontColor("MiniMarisaHUD");
mhudfontcol[MCR_VOIDHUD] = Font.FindFontColor("MiniVoidHUD");
mhudfontcol[MCR_WHITE] = Font.FindFontColor("MiniWhite");
mhudfontcol[MCR_RED] = Font.FindFontColor("MiniRed");
mhudfontcol[MCR_GREEN] = Font.FindFontColor("MiniGreen");
mhudfontcol[MCR_BLUE] = Font.FindFontColor("MiniBlue");
mhudfontcol[MCR_YELLOW] = Font.FindFontColor("MiniYellow");
mhudfontcol[MCR_CYAN] = Font.FindFontColor("MiniCyan");
mhudfontcol[MCR_PURPLE] = Font.FindFontColor("MiniPurple");
mhudfontcol[MCR_BRASS] = Font.FindFontColor("MiniBrass");
mhudfontcol[MCR_SILVER] = Font.FindFontColor("MiniSilver");
mhudfontcol[MCR_GOLD] = Font.FindFontColor("MiniGold");
mhudfontcol[MCR_MANA] = Font.FindFontColor("MiniMana");
mhudfontcol[MCR_CRIMSON] = Font.FindFontColor("MiniCrimson");
mhudfontcol[MCR_ELDRITCH] = Font.FindFontColor("MiniEldritch");
mhudfontcol[MCR_KINYLUM] = Font.FindFontColor("MiniKinylum");
mhudfontcol[MCR_NOKRON] = Font.FindFontColor("MiniNokron");
mhudfontcol[MCR_NOKOROKINYLUM] = Font.FindFontColor("MiniNokorokinylum");
mhudfontcol[MCR_DEMOBLUE] = Font.FindFontColor("MiniDemoBlue");
mhudfontcol[MCR_DEMOPINK] = Font.FindFontColor("MiniDemoPink");
mhudfontcol[MCR_ORANGE] = Font.FindFontColor("MiniOrange");
mhudfontcol[MCR_GRASS] = Font.FindFontColor("MiniGrass");
mhudfontcol[MCR_MINT] = Font.FindFontColor("MiniMint");
mhudfontcol[MCR_AQUA] = Font.FindFontColor("MiniAqua");
mhudfontcol[MCR_MAGENTA] = Font.FindFontColor("MiniMagenta");
mhudfontcol[MCR_PINK] = Font.FindFontColor("MiniPink");
mhudfontcol[MCR_CRYSTAL] = Font.FindFontColor("MiniCrystal");
mhudfontcol[MCR_FIRE] = Font.FindFontColor("MiniFire");
mhudfontcol[MCR_SULFUR] = Font.FindFontColor("MiniSulfur");
mhudfontcol[MCR_WITCH] = Font.FindFontColor("MiniWitch");
mhudfontcol[MCR_CYANBLU] = Font.FindFontColor("MiniCyanblu");
mhudfontcol[MCR_ICE] = Font.FindFontColor("MiniIce");
mhudfontcol[MCR_PURPUR] = Font.FindFontColor("MiniPurpur");
mhudfontcol[MCR_TOMATO] = Font.FindFontColor("MiniTomato");
mhudfontcol[MCR_BLURP] = Font.FindFontColor("MiniBlurp");
mhudfontcol[MCR_PURB] = Font.FindFontColor("MiniPurb");
mhudfontcol[MCR_FLASH] = Font.FindFontColor("MiniFlash");
mhudfontcol[MCR_REDFLASH] = Font.FindFontColor("MiniRedFlash");
mhudfontcol[MCR_WHITEFLASH] = Font.FindFontColor("MiniWhiteFlash");
tclabel = mhudfontcol[MCR_CYANBLU];
tcvalue = mhudfontcol[MCR_WHITE];
tcextra = mhudfontcol[MCR_IBUKIHUD];
tccompl = mhudfontcol[MCR_BRASS];
tcsucks = mhudfontcol[MCR_RED];
tclabel_s = "[MiniCyanblu]";
tcextra_s = "[MiniIbukiHUD]";
minimapzoom = oldminimapzoom = 1.;
LastHealth = CPlayer?CPlayer.health:100;
let d = Demolitionist(CPlayer?CPlayer.mo:null);
HealthInter = SmoothDynamicValueInterpolator.Create(LastHealth,.5);
FuelInter = SmoothDynamicValueInterpolator.Create(d?(d.dashfuel/2):120,.5);
DashInter = SmoothDynamicValueInterpolator.Create(d?((40-d.dashcooldown)*3):40,.5);
LagHealthInter = SmoothLinearValueInterpolator.Create(LastHealth,2);
for ( int i=0; i<10; i++ ) LagHealth[i] = LastHealth;
AmmoSlots[0] = 'RedShell';
AmmoSlots[1] = 'GoldShell';
AmmoSlots[2] = 'SMW05Ammo';
AmmoSlots[3] = 'EvisceratorShell';
AmmoSlots[4] = 'SheenAmmo';
AmmoSlots[5] = 'HellblazerMissiles';
AmmoSlots[6] = 'QuadravolAmmo';
AmmoSlots[7] = 'SparkUnit';
AmmoSlots[8] = 'SparksterBAmmo';
AmmoSlots[9] = 'SparksterRAmmo';
AmmoSlots[10] = 'SilverBulletAmmo';
AmmoSlots[11] = 'RayAmmo';
AmmoSlots[12] = 'CandyGunAmmo';
AmmoSlots[13] = 'CandyGunSpares';
AmmoSlots[14] = 'MisterAmmo';
AmmoSlots[15] = 'MisterGAmmo';
AmmoSlots[16] = 'YnykronAmmo';
AmmoSlots[17] = 'UltimateAmmo';
AmmoNames[0] = "SHOT";
AmmoNames[1] = "GOLD";
AmmoNames[2] = "SCRW";
AmmoNames[3] = "FLAK";
AmmoNames[4] = "MACH";
AmmoNames[5] = "MISL";
AmmoNames[6] = "QUAD";
AmmoNames[7] = "BSPK";
AmmoNames[8] = "KINY";
AmmoNames[9] = "NOKR";
AmmoNames[10] = "RIFL";
AmmoNames[11] = "BOLT";
AmmoNames[12] = "CAND";
AmmoNames[13] = "CGUN";
AmmoNames[14] = "MSTR";
AmmoNames[15] = "MGRN";
AmmoNames[16] = "CRYS";
AmmoNames[17] = "ULTI";
for ( int i=0; i<18; i++ )
{
AmmoFlash[i] = 0;
AmmoOldAmounts[i] = int.min;
AmmoMaxFlash[i] = 0;
AmmoOldMaxAmounts[i] = int.min;
}
ScoreInter = DynamicValueInterpolator.Create(0,.1,1,999999999);
hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
PrevFrame = MSTimeF();
}
override void DrawMyPos()
{
String str = String.Format("(%d,%d,%d)",CPlayer.mo.pos.X,CPlayer.mo.pos.Y,CPlayer.mo.pos.Z);
Screen.DrawText(mTinyFontOutline,Font.CR_GREEN,(ss.x-mTinyFontOutline.StringWidth(str))/2,4,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
override bool DrawChat( String txt )
{
// ignore during intermission
if ( gamestate != GS_LEVEL ) return false;
chatopen = gametic+1; // have to add 1 because DrawChat is called after everything else
double xx = 2;
double yy = ss.y-14;
Screen.Dim("Black",.8,0,Screen.GetHeight()-int(15*hs),Screen.GetWidth(),int(15*hs));
String pname = players[consoleplayer].GetUserName();
// strip colors
SWWMUtility.StripColor(pname);
String fullstr = String.Format("\cq%s\cd@\cqdemolitionist%d\cn ~ \cd% \c-wall %s_",pname,consoleplayer+1,txt);
// cut out to fit
int w = mSmallFont.StringWidth(fullstr);
if ( w > ss.x-4 )
{
// draw trailing dots
Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,"...",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
// shift back
xx -= w-(ss.x-4);
// draw trimmed
Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,fullstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ClipLeft,int(26*hs));
}
else Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,fullstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
return true;
}
override bool DrawPaused( int player )
{
let fnt = mSmallFontOutline?mSmallFontOutline:NewSmallFont;
let fnt2 = mSmallFont?mSmallFont:NewConsoleFont;
if ( swwm_fuzz )
{
Vector2 tsize = TexMan.GetScaledSize(bgtex);
double zoom = max(ceil(Screen.GetWidth()/tsize.x),ceil(Screen.GetHeight()/tsize.y));
Vector2 vsize = (Screen.GetWidth(),Screen.GetHeight())/zoom;
Screen.DrawTexture(bgtex,false,(vsize.x-tsize.x)/2,(vsize.y-tsize.y)/2,DTA_VirtualWidthF,vsize.x,DTA_VirtualHeightF,vsize.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(192,0,0,0),DTA_Alpha,.5);
}
else Screen.Dim("Black",.5,0,0,Screen.GetWidth(),Screen.GetHeight());
String str = StringTable.Localize("$SWWM_PAUSE");
if ( gametic < pausetime+1000 )
{
pausepos.x = Screen.GetWidth()/2;
pausepos.y = Screen.GetHeight()/2;
pausedir = (1,1);
}
else
{
pausepos.x += pausedir.x*CleanXFac;
pausepos.y += pausedir.y*CleanYFac;
if ( pausepos.x >= Screen.GetWidth()-((fnt.StringWidth(str)*3+8)*CleanXFac/2) )
pausedir.x = -1;
if ( pausepos.x < ((fnt.StringWidth(str)*3+8)*CleanXFac/2) )
pausedir.x = 1;
if ( pausepos.y >= Screen.GetHeight()-((fnt.GetHeight()*3+8)*CleanYFac/2) )
pausedir.y = -1;
if ( pausepos.y < ((fnt.GetHeight()*3+8)*CleanYFac/2) )
pausedir.y = 1;
}
double xx = pausepos.x-(fnt.StringWidth(str)*3*CleanXFac)/2;
double yy = pausepos.y-(fnt.GetHeight()*3*CleanYFac)/2;
int tlen = str.CodePointCount();
for ( int i=0, pos=0; i<tlen; i++ )
{
int ch;
[ch, pos] = str.GetNextCodePoint(pos);
Screen.DrawChar(fnt,Font.CR_BLUE,xx,yy+4*sin(32*i+8*gametic)*CleanYFac,ch,DTA_ScaleX,CleanXFac*3,DTA_ScaleY,CleanYFac*3);
xx += (fnt.GetCharWidth(ch)+fnt.GetDefaultKerning())*3*CleanXFac;
}
yy += fnt.GetHeight()*3*CleanYFac;
if ( multiplayer && (player != -1) )
{
str = String.Format(StringTable.Localize("$TXT_BY"),players[player].GetUserName());
xx = pausepos.x-fnt2.StringWidth(str)*CleanXFac/2;
Screen.DrawText(fnt2,Font.CR_WHITE,xx,yy,str,DTA_CleanNoMove,true);
}
return true;
}
private double DrawDeath()
{
// death prompt
let demo = Demolitionist(CPlayer.mo);
let goner = PlayerGone(CPlayer.mo);
if ( (!demo && !goner) || (CPlayer.Health > 0) || (CPlayer != players[consoleplayer]) ) return 1.;
String str;
double alph;
int len;
double xx, yy;
double deadtimer = (goner?goner.deadtimer:demo.deadtimer)+fractic;
if ( goner || (demo.player.viewheight <= 6) )
{
double dimalph = goner?1.:min(deadtimer/80.,.8);
Screen.Dim("Black",dimalph,0,0,Screen.GetWidth(),Screen.GetHeight());
if ( demo && (demo.revivefail > level.maptime) )
{
Screen.Dim("Red",clamp((demo.revivefail-(level.maptime+fractic))/60.,0.,.2),0,0,Screen.GetWidth(),Screen.GetHeight());
str = StringTable.Localize("$SWWM_REFAIL");
len = mSmallFont.StringWidth(str);
xx = int((ss.x-len)/2.);
yy = ss.y-48;
if ( ((demo.revivefail-level.maptime)%16) < 8 )
Screen.DrawText(mSmallFont,Font.CR_RED,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
alph = clamp((deadtimer-60)/60.,0.,1.);
String nam = CPlayer.GetUserName();
if ( !multiplayer || (nam == "Player") ) str = StringTable.Localize("$SWWM_URDED_GEN");
else str = String.Format(StringTable.Localize("$SWWM_URDED"),nam);
len = mSmallFont.StringWidth(str);
xx = int((ss.x-len)/2.);
yy = (ss.y-mSmallFont.GetHeight()*4)/2.;
// shift down if scoreboard is shown
if ( (deathmatch && sb_deathmatch_enable && (!teamplay || sb_teamdeathmatch_enable)) || (multiplayer && sb_cooperative_enable) )
yy += ss.y/3.+mSmallFont.GetHeight();
Screen.DrawText(mSmallFont,Font.CR_RED,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
if ( multiplayer || level.AllowRespawn || sv_singleplayerrespawn || G_SkillPropertyInt(SKILLP_PlayerRespawn) )
{
if ( sv_norespawn ) return (1.-dimalph);
alph = clamp((deadtimer-90)/60.,0.,1.);
str = String.Format(StringTable.Localize("$SWWM_URDEDMP"));
len = mSmallFont.StringWidth(str);
xx = int((ss.x-len)/2.);
yy = ss.y/2.;
// shift down if scoreboard is shown
if ( (deathmatch && sb_deathmatch_enable && (!teamplay || sb_teamdeathmatch_enable)) || (multiplayer && sb_cooperative_enable) )
yy += ss.y/3.;
Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
return (1.-dimalph);
}
alph = clamp((deadtimer-140)/60.,0.,1.);
str = String.Format(StringTable.Localize("$SWWM_URDED2"));
len = mSmallFont.StringWidth(str);
xx = int((ss.x-len)/2.);
yy = ss.y/2.;
Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
if ( goner || hnd.gdat.disablerevive || !swwm_revive )
return (1.-dimalph);
alph = clamp((deadtimer-160)/60.,0.,1.);
str = String.Format(StringTable.Localize("$SWWM_URDED3"));
len = mSmallFont.StringWidth(str);
xx = int((ss.x-len)/2.);
yy = (ss.y+mSmallFont.GetHeight()*2)/2.;
Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
return (1.-dimalph);
}
return 1.;
}
override void Draw( int state, double TicFrac )
{
double CurFrame = MSTimeF();
// 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
if ( deathmatch )
{
// forcibly strip these messages
// (I decided to drop MP support, so even though there are no
// actual spree/multikill announcements in this mod, keeping
// the vanilla ones out is important for graphical consistency)
DetachMessageID(0x4b535052); // KSPR
DetachMessageID(0x5250534b);
DetachMessageID(0x4d4b494c); // MKIL
DetachMessageID(0x4c494b4d);
}
Super.Draw(state,TicFrac);
FrameTime = (CurFrame-PrevFrame)/1000.;
if ( (state != HUD_StatusBar) && (state != HUD_Fullscreen) )
{
PrevFrame = CurFrame;
return;
}
if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/360.)),1.);
ss = (Screen.GetWidth()/hs,Screen.GetHeight()/hs);
margin = clamp(swwm_hudmargin,0,20);
hs1 = max(hs-1.,1.);
hs2 = max(hs-2.,1.);
ss1 = (Screen.GetWidth()/hs1,Screen.GetHeight()/hs1);
ss2 = (Screen.GetWidth()/hs2,Screen.GetHeight()/hs2);
FracTic = TicFrac;
if ( (players[consoleplayer].Camera is 'Demolitionist') && (state <= HUD_Fullscreen) )
{
if ( hnd ) hnd.DrawBossBar(self);
DrawTarget();
DrawTopStuff();
DrawInventory();
DrawStatus();
DrawWeapons();
}
DrawPickups();
double malph = DrawDeath();
DrawMessages(malph);
if ( state == HUD_AltHud )
{
String str = StringTable.Localize("$SWWM_WARNALTHUD");
Screen.DrawText(NewSmallFont,Font.CR_RED,(ss.x-NewSmallFont.StringWidth(str))/2,margin,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
PrevFrame = CurFrame;
}
}