// 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:364); if ( type != PRINT_LOW ) ls = fnt.BreakLines(nstr,284); } } Class KeyGet { Class 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_SYDON, MCR_NOKOROKINYLUM, MCR_DEMOBLUE, MCR_DEMOPINK, MCR_ORANGE, MCR_GRASS, MCR_MINT, MCR_AQUA, MCR_MAGENTA, MCR_PINK, MCR_SKIN, MCR_FIRE, MCR_SULFUR, MCR_WITCH, MCR_CYANBLU, MCR_ICE, MCR_PURPUR, MCR_TOMATO, MCR_BLURP, MCR_PURB, MCR_NOKRON, MCR_KABBADON, 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[2], bgtex, FaceTex[19]; Font mSmallFont, mSmallFontOutline, mSmallFontOutlineAlt, mTinyFont, mTinyFontOutline, mTinyFontOutlineAlt, MiniHUDFont, MiniHUDFontOutline; int mhudfontcol[NUM_MINIHUD_COLOR]; Array MainQueue, PickupQueue; transient ThinkerIterator cti; // the event handler, holding all sorts of stuff SWWMHandler hnd; // shared stuff double hsA, hsT; double hs, hs0, hs1, hs2; Vector2 ss, ss0, ss1, ss2; int ymargin, xmargin; int ymargin0; // for pickups/oneliners double FracTic; double FrameTime; double PrevFrame; int chatopen; int pausetime, pausecol; 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; SWWMWeaponSwapTip cstip; double mm_zoom; 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 = 50; // half the size of the minimap draw region (unscaled) const HALFMAPSIZE_SMALL = 40; // half of size when using small minimap // minimap colors (thats a lot of 'em) 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; transient bool mm_cvfirstdraw; transient Canvas mm_canvas; transient TextureID mm_canvastex; // deathmatch stuff int playercount, rank, lead; bool tiedscore; Array sortplayers; Array teamactive; Array teamscore; int PulsePhase; // for health pulsing // for flashing some elements in the hud Array 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; // top stuff levelname splitting transient ui String cached_ln; transient ui BrokenLines ln_bl; 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 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; // please do not misread int cummscoreup, cummspanup, cummflashup; int cummscoredn, cummspandn, cummflashdn; transient ui int rss; // called by static handler when loading a game // forcibly flushes our interpolators void Flush() { FlushStatus(); FlushWeapons(); } // 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/ChatBoxTopSmol.png"); ChatTex[4] = TexMan.CheckForTexture("graphics/HUD/ChatBoxLineSmol.png"); ChatTex[5] = TexMan.CheckForTexture("graphics/HUD/ChatBoxBottomSmol.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[0] = TexMan.CheckForTexture("graphics/HUD/MinimapBox.png"); MiniBox[1] = TexMan.CheckForTexture("graphics/HUD/MinimapBoxSmol.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'); mSmallFontOutlineAlt = Font.GetFont('TewiFontOutlineAlt'); mTinyFont = Font.GetFont('MiniwiFont'); mTinyFontOutline = Font.GetFont('MiniwiFontOutline'); mTinyFontOutlineAlt = Font.GetFont('MiniwiFontOutlineAlt'); 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_SYDON] = Font.FindFontColor('MiniSydon'); 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_SKIN] = Font.FindFontColor('MiniSkin'); 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_NOKRON] = Font.FindFontColor('MiniNokron'); mhudfontcol[MCR_KABBADON] = Font.FindFontColor('MiniKabbadon'); mhudfontcol[MCR_FLASH] = Font.FindFontColor('MiniFlash'); mhudfontcol[MCR_REDFLASH] = Font.FindFontColor('MiniRedFlash'); mhudfontcol[MCR_WHITEFLASH] = Font.FindFontColor('MiniWhiteFlash'); GetMinimapColors(); 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]"; mm_zoom = 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,(ss0.x-mTinyFontOutline.StringWidth(str))/2,4,str,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.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 = ss0.y-14; Screen.Dim(0xFF000000,.8,0,Screen.GetHeight()-int(15*hs0),Screen.GetWidth(),int(15*hs0)); 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 > ss0.x-4 ) { // draw trailing dots Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,"...",DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.y,DTA_KeepRatio,true); // shift back xx -= w-(ss0.x-4); // draw trimmed Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,fullstr,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.y,DTA_KeepRatio,true,DTA_ClipLeft,int(26*hs0)); } else Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,fullstr,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.y,DTA_KeepRatio,true); return true; } override bool DrawPaused( int player ) { static const int pausepal[] = { MCR_RED, MCR_ORANGE, MCR_YELLOW, MCR_GRASS, MCR_GREEN, MCR_MINT, MCR_CYAN, MCR_AQUA, MCR_BLUE, MCR_PURPLE, MCR_MAGENTA, MCR_PINK }; 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,0xA0000000,DTA_Alpha,.5); } else Screen.Dim(0xFF000000,.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); pausecol = 8; } 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; pausecol = (pausecol+1)%12; } if ( pausepos.x < ((fnt.StringWidth(str)*3+8)*CleanXFac/2) ) { pausedir.x = 1; pausecol = (pausecol+1)%12; } if ( pausepos.y >= Screen.GetHeight()-((fnt.GetHeight()*3+8)*CleanYFac/2) ) { pausedir.y = -1; pausecol = (pausecol+1)%12; } if ( pausepos.y < ((fnt.GetHeight()*3+8)*CleanYFac/2) ) { pausedir.y = 1; pausecol = (pausecol+1)%12; } } 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 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 || (deadtimer > 0) ) { double dimalph = goner?1.:min(deadtimer/80.,.8); Screen.Dim(0xFF000000,dimalph,0,0,Screen.GetWidth(),Screen.GetHeight()); if ( demo && (demo.revivefail > level.maptime) ) { Screen.Dim(0xFFFF0000,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((ss0.x-len)/2.); yy = ss0.y-48; if ( ((demo.revivefail-level.maptime)%16) < 8 ) Screen.DrawText(mSmallFont,Font.CR_RED,xx,yy,str,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.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((ss0.x-len)/2.); yy = (ss0.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 += ss0.y/3.+mSmallFont.GetHeight(); Screen.DrawText(mSmallFont,Font.CR_RED,xx,yy,str,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.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((ss0.x-len)/2.); yy = ss0.y/2.; // shift down if scoreboard is shown if ( (deathmatch && sb_deathmatch_enable && (!teamplay || sb_teamdeathmatch_enable)) || (multiplayer && sb_cooperative_enable) ) yy += ss0.y/3.; Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,str,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.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((ss0.x-len)/2.); yy = ss0.y/2.; Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,str,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.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((ss0.x-len)/2.); yy = (ss0.y+mSmallFont.GetHeight()*2)/2.; Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,str,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.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 ( !hnd ) hnd = SWWMHandler(EventHandler.Find('SWWMHandler')); hsA = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/360.)),1.); hsT = max(min(floor(Screen.GetWidth()/480.),floor(Screen.GetHeight()/270.)),1.); ymargin = clamp(swwm_hudmargin,0,10); int hudscale = swwm_hudscale; int hudscale0 = swwm_hudscale0; int hudscale1 = swwm_hudscale1; int hudscale2 = swwm_hudscale2; if ( hudscale > 0 ) hs = hudscale; else if ( hudscale < 0 ) hs = hsT; else hs = hsA; if ( hudscale0 > 0 ) hs0 = hudscale0; else if ( hudscale0 < 0 ) hs0 = hsT; else hs0 = hsA; if ( hudscale1 > 0 ) hs1 = hudscale1; else if ( hudscale1 < 0 ) hs1 = max(hsT-1.,1.); else hs1 = max(hsA-1.,1.); if ( hudscale2 > 0 ) hs2 = hudscale2; else if ( hudscale2 < 0 ) hs2 = max(hsT-2.,1.); else hs2 = max(hsA-2.,1.); ss = (Screen.GetWidth()/hs,Screen.GetHeight()/hs); ss0 = (Screen.GetWidth()/hs0,Screen.GetHeight()/hs0); ss1 = (Screen.GetWidth()/hs1,Screen.GetHeight()/hs1); ss2 = (Screen.GetWidth()/hs2,Screen.GetHeight()/hs2); // calculate margin for ultrawide screens, mostly so hud // elements don't get too spread out xmargin = ymargin+max(int(ss.x-ss.y/.5625)/2,0); // calculate vertical margin for hudscale0 (relative to base hudscale) ymargin0 = int(ymargin*(hs/hs0)); FracTic = TicFrac; if ( (state != HUD_StatusBar) && (state != HUD_Fullscreen) ) { if ( state == HUD_AltHud ) { String str = StringTable.Localize("$SWWM_WARNALTHUD"); Screen.DrawText(NewSmallFont,Font.CR_RED,(ss0.x-NewSmallFont.StringWidth(str))/2,ymargin0,str,DTA_VirtualWidthF,ss0.x,DTA_VirtualHeightF,ss0.y,DTA_KeepRatio,true); } PrevFrame = CurFrame; return; } if ( (players[consoleplayer].Camera is 'Demolitionist') && (state <= HUD_Fullscreen) ) { DrawTarget(); if ( hnd ) hnd.DrawBossBar(self); DrawTopStuff(); DrawInventory(); DrawStatus(); DrawWeapons(); } DrawPickups(); double malph = DrawDeath(); DrawMessages(malph); PrevFrame = CurFrame; } }