swwmgz_m/zscript/hud/swwm_hudextra.zsc
2021-09-14 18:40:22 +02:00

496 lines
14 KiB
Text

// additional hud things
// Press F to Pay Respects
Class PayRespects : HUDMessageBase
{
Vector2 basepos;
int lifespan, initialspan, starttic;
transient Font TewiFont;
double scale;
Vector2 hs, ss;
int seed, seed2;
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();
return f;
}
override bool Tick()
{
lifespan--;
return (lifespan<=0);
}
override void ScreenSizeChanged()
{
hs = StatusBar.GetHUDScale()*scale;
hs.y = hs.x;
ss = (Screen.GetWidth()/hs.x,Screen.GetHeight()/hs.y);
}
override void Draw( int bottom, int visibility )
{
Vector2 realpos = (basepos.x*ss.x,basepos.y*ss.y);
if ( !TewiFont ) TewiFont = Font.GetFont('TewiShaded');
Vector2 fo = (TewiFont.StringWidth("F")/2.,-TewiFont.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 = SWWMStatusBar(statusbar)?SWWMStatusBar(statusbar).fractic:0;
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(TewiFont,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;
int lifespan, curtime;
transient Font TewiFont, MPlusFont;
static SWWMOneLiner Make( String whichline, int lifespan )
{
let l = new("SWWMOneLiner");
l.whichline = whichline;
l.curtime = l.lifespan = lifespan;
return l;
}
override bool Tick()
{
if ( players[consoleplayer].Health <= 0 ) curtime = int.min;
curtime--;
return (curtime<-20);
}
override void Draw( int bottom, int visibility )
{
if ( !TewiFont ) TewiFont = Font.GetFont('TewiShaded');
if ( !MPlusFont ) MPlusFont = Font.GetFont('MPlusShaded');
int margin = swwm_hudmargin;
Vector2 hs;
if ( swwm_hudscale <= 0 ) hs = StatusBar.GetHUDScale();
else hs.x = swwm_hudscale;
hs.y = hs.x;
Vector2 ss = (Screen.GetWidth()/hs.x,Screen.GetHeight()/hs.y);
String loc = StringTable.Localize(whichline);
if ( loc.Length() <= 0 ) return; // don't draw empty strings
String locs = StringTable.Localize("$SWWM_LQUOTE")..loc..StringTable.Localize("$SWWM_RQUOTE");
Font fnt = TewiFont;
if ( language ~== "jp" ) fnt = MPlusFont;
// split so it can fit
BrokenLines l = fnt.BreakLines(locs,int(ss.x*.5));
int maxlen = 0;
for ( int i=0; i<l.Count(); i++ )
{
int len = fnt.StringWidth(l.StringAt(i));
if ( len > maxlen ) maxlen = len;
}
int h = fnt.GetHeight();
int fh = h*l.Count();
double alph = clamp((curtime/20.)+1.,0.,1.);
alph *= clamp((lifespan-curtime)/10.,0.,1.);
Screen.Dim("Black",alph*.8,int((Screen.GetWidth()-(maxlen+12)*hs.x)/2.),int(bottom-(margin+2+fh)*hs.y),int((maxlen+12)*hs.x),int((fh+4)*hs.y));
int yy = margin+fh;
for ( int i=0; i<l.Count(); i++ )
{
int len = fnt.StringWidth(l.StringAt(i));
Screen.DrawText(fnt,Font.CR_FIRE,int((ss.x-len)/2.),(bottom/hs.y)-yy,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
yy -= h;
}
}
}
// Screen flashes from DT
Class GenericFlash : HUDMessageBase
{
Color col;
int duration;
double alpha;
Actor cam;
GenericFlash Setup( Actor camera, Color c, int d )
{
alpha = 1.0;
col = c;
duration = d;
cam = camera;
return self;
}
override bool Tick()
{
if ( duration > 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;
Screen.Dim(col,(col.a/255.)*alpha*swwm_flashstrength,0,0,Screen.GetWidth(),Screen.GetHeight());
}
}
Class QueuedFlash
{
Color c;
int duration;
int tic;
Actor cam;
}
// Achievement notification
Class SWWMAchievementNotification : HUDMessageBase
{
String tag, txt;
int num;
TextureID icon, frame;
double tics, holdtics, fadeintics, fadeouttics;
transient Font tewifont, mplusfont, miniwifont, k6x8font;
SWWMAchievementNotification Init( String bname, TextureID icon, int bnum = 0 )
{
tag = "$SWWM_ACHIEVEMENT_"..bname.."_TAG";
txt = "$SWWM_ACHIEVEMENT_"..bname.."_TXT";
num = bnum;
self.icon = icon;
frame = TexMan.CheckForTexture("graphics/HUD/AchievementNotification.png",TexMan.Type_Any);
holdtics = 150;
fadeintics = 20;
fadeouttics = 30;
tics = 0;
return self;
}
override bool Tick()
{
return (++tics > holdtics+fadeintics+fadeouttics);
}
override void Draw( int bottom, int visibility )
{
if ( !tewifont ) tewifont = Font.GetFont('TewiShaded');
if ( !mplusfont ) mplusfont = Font.GetFont('MPlusShaded');
if ( !miniwifont ) miniwifont = Font.GetFont('MiniwiShaded');
if ( !k6x8font ) k6x8font = Font.GetFont('k6x8Shaded');
let fnt = tewifont;
let fnt2 = miniwifont;
if ( language ~== "jp" )
{
fnt = mplusfont;
fnt2 = k6x8font;
}
double margin = swwm_hudmargin;
Vector2 hs;
if ( swwm_hudscale <= 0 ) hs = StatusBar.GetHUDScale();
else hs.x = swwm_hudscale;
hs.y = hs.x;
Vector2 ss = (Screen.GetWidth()/hs.x,Screen.GetHeight()/hs.y);
double alpha = (tics<fadeintics)?(tics/fadeintics):(tics<(fadeintics+holdtics))?1.:(1.-(tics-(fadeintics+holdtics))/fadeouttics);
Vector2 pos = (int(ss.x-256)/2,(ss.y-(margin+36))+int(margin+40)*(1.-alpha));
String loctag = StringTable.Localize(tag);
String loctxt = num?String.Format(StringTable.Localize(txt),num):StringTable.Localize(txt);
BrokenLines l = fnt2.BreakLines(loctxt,200);
int th = 14+(9*l.Count());
Screen.DrawTexture(frame,false,pos.x,pos.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
if ( icon.IsValid() ) Screen.DrawTexture(icon,false,pos.x+2,pos.y+2,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
int yy = 2+(32-th)/2;
Screen.DrawText(fnt,Font.CR_GREEN,pos.x+40,pos.y+yy,loctag,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
yy += 14;
for ( int i=0; i<l.Count(); i++ )
{
Screen.DrawText(fnt2,Font.CR_WHITE,pos.x+44,pos.y+yy,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
yy += 9;
}
}
}
Class SWWMSewerCount : HUDMessageBase
{
int tics;
String str;
SWWMSewerCount Init()
{
tics = 200;
str = String.Format("Sewer Count: %d",swwm_sewercount);
return self;
}
override bool Tick()
{
if ( tics == 100 ) S_StartSound("misc/sewercount",CHAN_VOICE,CHANF_UI,1.,0.);
return (tics--<=0);
}
override void Draw( int bottom, int visibility )
{
if ( tics > 100 ) return;
double alph = clamp(tics/20.,0.,1.);
double x = (Screen.GetWidth()-(newsmallfont.StringWidth(str)*CleanXFac*2))/2;
double y = int(Screen.GetHeight()*.75)-(newsmallfont.GetHeight()*CleanYFac*2)/2;
Screen.DrawText(newsmallfont,Font.CR_GREEN,x,y,str,DTA_ScaleX,CleanXFac*2,DTA_ScaleY,CleanYFac*2,DTA_Alpha,alph);
}
}
// Used sparingly for some events
Class SWWMDirectMessage : HUDMessageBase
{
TextureID MessageBox, BG, Avatar, Blink[2], Talk[5], Noiz[4];
transient Font fnt, jpfnt;
transient BrokenLines l;
String seqname, chrname, chrfullname;
bool znvspecial; // seqnum 2 string replacement
int seqnum, seqcnt, delay, charcnt, blinktics, talktics, talkframe;
int enddelay, pausedelay;
int rss;
int fadein, fadeout;
Vector2 ss, hs, origin;
SWWMDirectMessage nextmsg; // for chaining messages together from different characters
bool nextdirect; // skips directly to next message without delays or fades
private int GetRandom()
{
return (rss = (rss<<1)*35447+(rss/87));
}
virtual SWWMDirectMessage Init( String chrn, String chrfn, String texn )
{
MessageBox = TexMan.CheckForTexture("graphics/HUD/DM/DirectMessageBox.png",TexMan.Type_Any);
BG = TexMan.CheckForTexture("graphics/HUD/DM/"..texn.."AvatarBG.png",TexMan.Type_Any);
Avatar = TexMan.CheckForTexture("graphics/HUD/DM/"..texn.."Avatar.png",TexMan.Type_Any);
for ( int i=0; i<2; i++ )
Blink[i] = TexMan.CheckForTexture("graphics/HUD/DM/"..texn.."AvatarBlink"..i..".png",TexMan.Type_Any);
for ( int i=0; i<5; i++ )
Talk[i] = TexMan.CheckForTexture("graphics/HUD/DM/"..texn.."AvatarTalk"..i..".png",TexMan.Type_Any);
for ( int i=0; i<4; i++ )
Noiz[i] = TexMan.CheckForTexture("graphics/HUD/DM/DirectMessageStatic"..i..".png",TexMan.Type_Any);
chrname = chrn;
chrfullname = chrfn;
seqnum = -1;
charcnt = 0;
blinktics = 30;
talktics = 0;
talkframe = -1;
enddelay = 40;
pausedelay = 30;
rss = 1232;
return self;
}
private void SetText()
{
String txt;
if ( (seqnum == 2) && znvspecial )
{
// replace with number of years since 2010
int nyears = SystemTime.Format("%Y",SystemTime.Now()).ToInt()-2010;
txt = String.Format(StringTable.Localize("$SWWM_"..seqname..seqnum),nyears);
}
else txt = StringTable.Localize("$SWWM_"..seqname..seqnum);
l = fnt.BreakLines(txt,220);
// append to the player's chat log
let bar = SWWMStatusBar(StatusBar);
if ( bar )
{
let l = new("MsgLine");
l.str = chrname..": "..txt;
l.tic = level.totaltime;
l.rep = 1;
l.type = PRINT_CHAT;
bar.FullHistory.Push(l);
}
}
private void DrawText()
{
if ( !fnt ) fnt = Font.GetFont('TewiShaded');
if ( !jpfnt ) jpfnt = Font.GetFont('MPlusShaded');
if ( !l ) SetText();
int cur = charcnt;
Vector2 pos = origin+(47,2);
for ( int i=0; i<l.Count(); i++ )
{
if ( cur <= 0 ) break;
String part = l.StringAt(i).Left(cur);
Screen.DrawText((language~=="jp")?jpfnt:fnt,Font.CR_WHITE,pos.x,pos.y,part,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
pos.y += 13;
cur -= l.StringAt(i).Length();
}
}
private void DrawAvatar()
{
int blinkframe = -1;
switch ( blinktics )
{
case -1:
case -3:
blinkframe = 0;
break;
case -2:
blinkframe = 1;
break;
}
Screen.DrawTexture(BG,false,origin.x+2,origin.y+2,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
Screen.DrawTexture(Avatar,false,origin.x+2,origin.y+2,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
if ( (seqnum > 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[(gametic/2)%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<l.Count(); i++ )
len += l.StringAt(i).Length();
return len;
}
private String GetChar( int pos )
{
if ( !l ) SetText();
int cur = pos;
for ( int i=0; i<l.Count(); i++ )
{
int len = l.StringAt(i).Length();
if ( cur < len )
return l.StringAt(i).Mid(cur,1);
cur -= len;
}
return "";
}
private void AdvanceText()
{
String notalk = " \t\n,;:.-!?";
String punctuation = ",;:.";
if ( charcnt >= TotalLength() )
{
seqnum++;
charcnt = 0;
if ( (seqnum > seqcnt) && !nextdirect ) S_StartSound("misc/chat",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()
{
if ( seqnum < 0 )
{
delay--;
if ( delay <= 0 )
{
Console.Printf(StringTable.Localize("$SWWM_INCOMINGMSG"),chrfullname);
S_StartSound("misc/chat",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 = 30;
seqnum++;
}
return false;
}
if ( seqnum == (seqcnt+1) )
{
if ( nextmsg && nextdirect )
{
nextmsg.seqnum = 1;
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.;
if ( seqnum == 0 ) alph = fadein/15.;
else if ( seqnum == (seqcnt+1) ) alph = 1.-fadeout/30.;
if ( swwm_hudscale <= 0 ) hs = StatusBar.GetHUDScale();
else hs.x = swwm_hudscale;
hs.y = hs.x;
ss = (Screen.GetWidth()/hs.x,Screen.GetHeight()/hs.y);
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();
DrawText();
}
}