// additional hud things // Press F to Pay Respects Class PayRespects : HUDMessageBase { Vector2 basepos; int lifespan, initialspan, starttic; double scale; double hs; Vector2 ss; int seed, seed2; Font mSmallFont; static PayRespects PressF() { let f = new("PayRespects"); f.basepos = (FRandom[FInTheChat](0.,1.),FRandom[FInTheChat](1.02,1.05)); f.scale = FRandom[FInTheChat](.5,2.); f.lifespan = f.initialspan = Random[FInTheChat](20,80); f.starttic = level.maptime; f.seed = Random[FInTheChat](); f.seed2 = Random[FInTheChat](); f.ScreenSizeChanged(); f.mSmallFont = Font.GetFont('TewiFont'); return f; } override bool Tick() { lifespan--; return (lifespan<=0); } override void ScreenSizeChanged() { hs = CleanXFac*scale; ss = (Screen.GetWidth(),Screen.GetHeight())/hs; } override void Draw( int bottom, int visibility ) { Vector2 realpos = (basepos.x*ss.x,basepos.y*ss.y); Vector2 fo = (mSmallFont.StringWidth("F")/2.,-mSmallFont.GetHeight()); // F rise up int initspd = (128-seed); if ( (initspd >= 0) && (initspd < 32) ) initspd = 32; if ( (initspd < 0) && (initspd > -32) ) initspd = -32; int boostup = 32+(seed2/4); double fractic = System.GetTimeFrac(); fo.x += (.15*initspd)*((initialspan-(lifespan-fractic))**.6); fo.y += ((initialspan-(lifespan-fractic))**1.6)-boostup*sin((90./initialspan)*(level.maptime+fractic-starttic)); double alph = clamp((lifespan+fractic)/double(initialspan),0.,1.); Screen.DrawText(mSmallFont,Font.CR_GREEN,realpos.x-fo.x,realpos.y-fo.y,"F",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph); } } // One-liners Class SWWMOneLiner : HUDMessageBase { String whichline; transient BrokenLines l; int lifespan, curtime; Font mSmallFont; static SWWMOneLiner Make( String whichline, int lifespan ) { let l = new("SWWMOneLiner"); if ( StringTable.Localize(whichline) == "" ) l.whichline = ""; else l.whichline = StringTable.Localize("$SWWM_LQUOTE")..StringTable.Localize(whichline)..StringTable.Localize("$SWWM_RQUOTE"); l.curtime = l.lifespan = lifespan; l.mSmallFont = Font.GetFont('TewiFont'); return l; } override bool Tick() { if ( players[consoleplayer].Health <= 0 ) curtime = int.min; curtime--; return (curtime<-20); } override void ScreenSizeChanged() { if ( l ) l.Destroy(); } override void Draw( int bottom, int visibility ) { int margin = swwm_hudmargin; double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/360.)),1.); Vector2 ss = (Screen.GetWidth()/hs,Screen.GetHeight()/hs); if ( whichline == "" ) return; // don't draw empty strings // split so it can fit if ( !l ) l = mSmallFont.BreakLines(whichline,int(ss.x*.5)); int maxlen = 0; for ( int i=0; i maxlen ) maxlen = len; } int h = mSmallFont.GetHeight(); int fh = h*l.Count(); double fractic = System.GetTimeFrac(); double fcurtime = curtime-fractic; double alph = clamp((fcurtime/20.)+1.,0.,1.); alph *= clamp((lifespan-fcurtime)/10.,0.,1.); Screen.Dim("Black",alph*.8,int((Screen.GetWidth()-(maxlen+12)*hs)/2.),int(bottom-(margin+2+fh)*hs),int((maxlen+12)*hs),int((fh+4)*hs)); int yy = margin+fh; for ( int i=0; i 0 ) alpha -= 1./duration; return (alpha<=0)||(!cam); } override void Draw( int bottom, int visibility ) { if ( automapactive || (visibility != BaseStatusBar.HUDMSGLayer_UnderHUD) ) return; if ( cam && (players[consoleplayer].camera != cam) ) return; double fractic = System.GetTimeFrac(); double falpha = alpha-fractic*(1./duration); Screen.Dim(col,(col.a/255.)*falpha*swwm_flashstrength,0,0,Screen.GetWidth(),Screen.GetHeight(),STYLE_Add); } } Class QueuedFlash { Color c; int duration; int tic; Actor cam; } // Achievement notification Class SWWMAchievementNotification : HUDMessageBase { String tag, txt; transient BrokenLines l; TextureID icon, frame; double tics, holdtics, fadeintics, fadeouttics; Font mSmallFont, mTinyFont; SWWMAchievementNotification Init( String bname, TextureID icon, int num = 0 ) { tag = StringTable.Localize("$SWWM_ACHIEVEMENT_"..bname.."_TAG"); txt = StringTable.Localize("$SWWM_ACHIEVEMENT_"..bname.."_TXT"); if ( num ) txt = String.Format(txt,SWWMUtility.ThousandsNum(num)); self.icon = icon; frame = TexMan.CheckForTexture("graphics/HUD/AchievementNotification.png"); holdtics = 150; fadeintics = 20; fadeouttics = 30; tics = 0; mSmallFont = Font.GetFont('TewiFont'); mTinyFont = Font.GetFont('MiniwiFont'); return self; } override bool Tick() { return (++tics > holdtics+fadeintics+fadeouttics); } override void Draw( int bottom, int visibility ) { double margin = swwm_hudmargin; double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/360.)),1.); Vector2 ss = (Screen.GetWidth()/hs,Screen.GetHeight()/hs); double fractic = System.GetTimeFrac(); double ftics = tics+fractic; double alpha = (ftics weapon ) { let def = GetDefaultByType(weapon); wpn = def.GetTag(); txt = StringTable.Localize(def.tooltip); holdtics = 150; fadeintics = 5; fadeouttics = 15; tics = -10; mSmallFont = Font.GetFont('TewiFont'); mTinyFont = Font.GetFont('MiniwiFont'); return self; } override bool Tick() { bool clearme = (++tics > holdtics+fadeintics+fadeouttics); if ( clearme && next ) StatusBar.AttachMessage(next,-2910); return clearme; } override void Draw( int bottom, int visibility ) { if ( tics <= 0 ) return; double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/360.)),1.); Vector2 ss = (Screen.GetWidth()/hs,Screen.GetHeight()/hs); double fractic = System.GetTimeFrac(); double ftics = tics+fractic; double alpha = (ftics w ) w = lw; } int cw = int(ceil((max(w1,w)+8)/6.))*6; int h = mSmallFont.GetHeight()+8+mTinyFont.GetHeight()*l.Count(); Vector2 pos = (int(ss.x/2),ss.y-(swwm_hudmargin+80+h)); Screen.Dim("Black",.5*alpha,int((pos.x-(cw+4)/2)*hs),int((pos.y-2)*hs),int((cw+4)*hs),int((h+4)*hs)); Screen.DrawText(mSmallFont,Font.CR_FIRE,pos.x-w1/2,pos.y,wpn,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha); for ( int i=0; i seqcnt) ) return; // some messages may have newlines in them, split them Array storemsg; txt.Split(storemsg,"\n"); foreach ( msg:storemsg ) { EventHandler.SendNetworkEvent("swwmstoremessage."..chrname..": "..msg,level.totaltime,PRINT_CHAT,consoleplayer); // stick it into the console as well Console.PrintfEx(PRINT_CHAT|PRINT_NONOTIFY,chrname..": "..msg); } } private void DrawText() { if ( !l ) SetText(); int cur = charcnt; Vector2 pos = origin+(47,3); for ( int i=0; i 0) && (seqnum < (seqcnt+1)) ) { if ( blinkframe >= 0 ) Screen.DrawTexture(Blink[blinkframe],false,origin.x+2,origin.y+2,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); if ( talkframe >= 0 ) Screen.DrawTexture(Talk[talkframe],false,origin.x+2,origin.y+2,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); } Screen.DrawTexture(Noiz[int(((gametic+fractic)/GameTicRate)*15)%4],false,origin.x+2,origin.y+2,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Multiply); } private int TotalLength() { if ( !l ) SetText(); int len = 0; for ( int i=0; i= TotalLength() ) { seqnum++; charcnt = 0; if ( (seqnum > seqcnt) && !nextdirect ) S_StartSound("menu/demochat",CHAN_VOICE,CHANF_UI,1.,0.); else SetText(); return; } String ch = GetChar(charcnt); // skip over color escapes if ( ch == "\c" ) { ch = GetChar(++charcnt); if ( ch == "[" ) while ( (ch = GetChar(++charcnt)) != "]" ); charcnt++; ch = GetChar(charcnt); } // speech if ( notalk.IndexOf(ch) == -1 ) { S_StartSound("misc/voice",CHAN_VOICE,CHANF_UI,.6,ATTN_NONE); talktics = 5; } // delay relative to stuff delay = 1; int idx = punctuation.IndexOf(ch); if ( idx >= 0 ) delay += (idx*2)+1; charcnt++; // utf-8 skipping (naive but works, as we don't have to EXPECT invalid sequences in the input) if ( ch.ByteAt(0)&0xE0 == 0xC0 ) charcnt++; else if ( ch.ByteAt(0)&0xF0 == 0xE0 ) charcnt += 2; else if ( ch.ByteAt(0)&0xF8 == 0xF0 ) charcnt += 3; if ( charcnt >= TotalLength() ) delay += (seqnum==seqcnt)?enddelay:pausedelay; } override bool Tick() { // reset when loading from a save, to avoid some wacky nonsense if ( !bDontResetMe ) { bDontResetMe = true; seqnum = -1; delay = 10; fadein = fadeout = 0; } if ( seqnum < 0 ) { // if there's a map message active, wait until it isn't if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( hnd.mapmsg ) return false; delay--; if ( delay <= 0 ) { Console.Printf(StringTable.Localize("$SWWM_INCOMINGMSG"),chrfullname); S_StartSound("menu/demochat",CHAN_VOICE,CHANF_UI,1.,0.); seqnum++; } return false; } if ( blinktics <= 0 ) { blinktics--; if ( blinktics < -3 ) blinktics = (abs(GetRandom())%10)?(60+abs(GetRandom())%30):6; } else blinktics--; if ( talktics > 0 ) { if ( !(gametic%3) ) talkframe = (talkframe==-1)?(abs(GetRandom())%5):-1; talktics--; } else talkframe = -1; if ( seqnum > (seqcnt+1) ) { if ( nextmsg ) StatusBar.AttachMessage(nextmsg,-1232); return true; } if ( seqnum == 0 ) { fadein++; if ( fadein > 15 ) { delay = startdelay; seqnum++; } return false; } if ( seqnum == (seqcnt+1) ) { if ( nextmsg && nextdirect ) { nextmsg.seqnum = 1; nextmsg.bDontResetMe = true; StatusBar.AttachMessage(nextmsg,-1232); return true; } fadeout++; if ( fadeout > 30 ) seqnum++; return false; } if ( delay > 0 ) { delay--; return false; } AdvanceText(); return false; } override void Draw( int bottom, int visibility ) { if ( (seqnum < 0) || (seqnum > (seqcnt+1)) ) return; double alph = 1.; double fractic = System.GetTimeFrac(); if ( seqnum == 0 ) alph = (fadein+fractic)/15.; else if ( seqnum == (seqcnt+1) ) alph = 1.-(fadeout+fractic)/30.; double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/360.)),1.); ss = (Screen.GetWidth()/hs,Screen.GetHeight()/hs); origin = (int(ss.x-270)/2,swwm_hudmargin+70); Screen.DrawTexture(MessageBox,false,origin.x,origin.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph); if ( (seqnum < 1) || (seqnum > seqcnt) ) return; DrawAvatar(fractic); DrawText(); } } // used to manually trigger dialogues // the AMBUSH flag means the dialogue only shows for the activator Class SWWMDialogueTrigger : SWWMNonInteractiveActor { override void Activate( Actor activator ) { if ( !bAMBUSH || (activator && (activator.player == players[consoleplayer])) ) EventHandler.SendInterfaceEvent(consoleplayer,"swwmsetdialogue",args[0]); Destroy(); } override void Tick() {} } // I'm just doing this as an experiment, don't mind me Class DSMapTitle : HUDMessageBase { Struct FntGlyph { int x, y, width, height, xofs, yofs, advance; }; TextureID atlas, atlas_sub; FntGlyph glyphs[256], glyphs_sub[256]; int fheight, fheight_sub; String txt, txtsub; int tics, holdtics, fadeintics, fadeouttics; int ultics; transient bool bDontDeleteMe; // safeguard for savegames // all the actual hard code int MyStringWidth( String str ) { int w = 0; int lw = 0; int len = str.CodePointCount(); for ( int i=0, pos=0; i 255 ) continue; lw += glyphs[ch].advance; // newline, restart line width if ( ch == 0x0a ) { w = max(w,lw); lw = 0; } } w = max(w,lw); return w; } int MySubStringWidth( String str ) { int w = 0; int lw = 0; int len = str.CodePointCount(); for ( int i=0, pos=0; i 255 ) continue; lw += glyphs_sub[ch].advance; // newline, restart line width if ( ch == 0x0a ) { w = max(w,lw); lw = 0; } } w = max(w,lw); return w; } void MyDrawText( String str, double x, double y, Vector2 ss, double alpha = 1. ) { int len = str.CodePointCount(); double xx = x; double yy = y; for ( int i=0, pos=0; i 255 ) continue; if ( glyphs[ch].width && glyphs[ch].height ) { Screen.DrawTexture(atlas,false,xx-glyphs[ch].xofs,yy-glyphs[ch].yofs, DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true, DTA_SrcX,glyphs[ch].x,DTA_SrcY,glyphs[ch].y, DTA_SrcWidth,glyphs[ch].width,DTA_SrcHeight,glyphs[ch].height, DTA_DestWidth,glyphs[ch].width,DTA_DestHeight,glyphs[ch].height, DTA_Alpha,alpha); } xx += glyphs[ch].advance; // newline if ( ch == 0x0a ) { xx = x; yy += fheight; } } } void MySubDrawText( String str, double x, double y, Vector2 ss, double alpha = 1. ) { int len = str.CodePointCount(); double xx = x; double yy = y; for ( int i=0, pos=0; i 255 ) continue; if ( glyphs_sub[ch].width && glyphs_sub[ch].height ) { Screen.DrawTexture(atlas_sub,false,xx-glyphs_sub[ch].xofs,yy-glyphs_sub[ch].yofs, DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true, DTA_SrcX,glyphs_sub[ch].x,DTA_SrcY,glyphs_sub[ch].y, DTA_SrcWidth,glyphs_sub[ch].width,DTA_SrcHeight,glyphs_sub[ch].height, DTA_DestWidth,glyphs_sub[ch].width,DTA_DestHeight,glyphs_sub[ch].height, DTA_Alpha,alpha); } xx += glyphs_sub[ch].advance; // newline if ( ch == 0x0a ) { xx = x; yy += fheight_sub; } } } // stretches the "_" glyph over a specific width, center-aligned void DrawUnderline( double x, double y, Vector2 ss, double width, double alpha = 1. ) { double xx = x-width/2; // l stem Screen.DrawTexture(atlas,false,xx-4,y, DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true, DTA_SrcX,glyphs[95].x,DTA_SrcY,glyphs[95].y, DTA_SrcWidth,4,DTA_SrcHeight,glyphs[95].height, DTA_DestWidthF,4,DTA_DestHeight,glyphs[95].height, DTA_Alpha,alpha); // long Screen.DrawTexture(atlas,false,xx,y, DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true, DTA_SrcX,glyphs[95].x+4,DTA_SrcY,glyphs[95].y, DTA_SrcWidth,glyphs[95].width-8,DTA_SrcHeight,glyphs[95].height, DTA_DestWidthF,width,DTA_DestHeight,glyphs[95].height, DTA_Alpha,alpha); // r stem Screen.DrawTexture(atlas,false,xx+width,y, DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true, DTA_SrcX,glyphs[95].x+(glyphs[95].width-4),DTA_SrcY,glyphs[95].y, DTA_SrcWidth,4,DTA_SrcHeight,glyphs[95].height, DTA_DestWidthF,4,DTA_DestHeight,glyphs[95].height, DTA_Alpha,alpha); } DSMapTitle Init() { txt = level.levelname; txtsub = level.authorname; if ( txt.Left(1) == "$" ) txt = StringTable.Localize(txt); if ( txtsub.Left(1) == "$" ) txtsub = StringTable.Localize(txtsub); tics = -10; holdtics = 140; fadeintics = 20; fadeouttics = 40; ultics = 50; atlas = TexMan.CheckForTexture("graphics/dsmapfont.png"); if ( !atlas.IsValid() || atlas.IsNull() ) ThrowAbortException("font atlas texture not found"); let lmp = Wads.CheckNumForFullname("graphics/dsmapfont.txt"); if ( lmp == -1 ) ThrowAbortException("font definition file not found"); String dat = Wads.ReadLump(lmp); Array list, ln; // fucking Windows dat.Replace("\r",""); list.Clear(); dat.Split(list,"\n"); int ch = 0; for ( int i=0; i holdtics+fadeintics+fadeouttics); } override void Draw( int bottom, int visibility ) { if ( tics <= 0 ) return; double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/360.)),1.); Vector2 ss = (Screen.GetWidth(),Screen.GetHeight())/hs; double fractic = System.GetTimeFrac(); double ftics = tics+fractic; double alpha = (ftics