swwmgz_m/zscript/hud/swwm_hudextra.zsc

570 lines
17 KiB
Text

// 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 = 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(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<l.Count(); i++ )
{
int len = mSmallFont.StringWidth(l.StringAt(i));
if ( len > maxlen ) maxlen = len;
}
int h = mSmallFont.GetHeight();
int fh = h*l.Count();
double fractic = SWWMStatusBar(statusbar)?SWWMStatusBar(statusbar).fractic:0;
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<l.Count(); i++ )
{
int len = mSmallFont.StringWidth(l.StringAt(i));
Screen.DrawText(mSmallFont,Font.CR_FIRE,int((ss.x-len)/2.),(bottom/hs)-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;
double fractic = SWWMStatusBar(statusbar)?SWWMStatusBar(statusbar).fractic:0;
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,num);
self.icon = icon;
frame = TexMan.CheckForTexture("graphics/HUD/AchievementNotification.png",TexMan.Type_Any);
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 = SWWMStatusBar(statusbar)?SWWMStatusBar(statusbar).fractic:0;
double ftics = tics+fractic;
double alpha = (ftics<fadeintics)?(ftics/fadeintics):(ftics<(fadeintics+holdtics))?1.:(1.-(ftics-(fadeintics+holdtics))/fadeouttics);
Vector2 pos = (int(ss.x-256)/2,(ss.y-(margin+36))+int(margin+40)*(1.-alpha));
if ( !l ) l = mTinyFont.BreakLines(txt,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(mSmallFont,Font.CR_GREEN,pos.x+40,pos.y+yy,tag,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(mTinyFont,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 fractic = SWWMStatusBar(statusbar)?SWWMStatusBar(statusbar).fractic:0;
double ftics = tics-fractic;
double alph = clamp(ftics/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);
}
}
// weapon tooltips
Class SWWMWeaponTooltip : HUDMessageBase
{
String wpn, txt;
double tics, holdtics, fadeintics, fadeouttics;
transient BrokenLines l;
SWWMWeaponTooltip next;
Font mSmallFont, mTinyFont;
SWWMWeaponTooltip Init( Class<SWWMWeapon> 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 = SWWMStatusBar(statusbar)?SWWMStatusBar(statusbar).fractic:0;
double ftics = tics+fractic;
double alpha = (ftics<fadeintics)?(ftics/fadeintics):(ftics<(fadeintics+holdtics))?1.:(1.-(ftics-(fadeintics+holdtics))/fadeouttics);
int w = mSmallFont.StringWidth(wpn);
if ( !l ) l = mTinyFont.BreakLines(txt,600);
int w1 = w;
w = 0;
for ( int i=0; i<l.Count(); i++ )
{
let lw = mTinyFont.StringWidth(l.StringAt(i));
if ( lw > 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<cw; i+=6 )
Screen.DrawChar(mSmallFont,Font.CR_FIRE,(pos.x-cw/2)+i,pos.y+6,0x5F,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
pos.y += mSmallFont.GetHeight()+8;
for ( int i=0; i<l.Count(); i++ )
{
Screen.DrawText(mTinyFont,Font.CR_WHITE,pos.x-w/2,pos.y,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
pos.y += mTinyFont.GetHeight();
}
}
}
// Used sparingly for some events
Class SWWMDirectMessage : HUDMessageBase
{
TextureID MessageBox, BG, Avatar, Blink[2], Talk[5], Noiz[4];
transient BrokenLines l;
String seqname, chrname, chrfullname;
bool znvspecial; // seqnum 2 string replacement
int seqnum, seqcnt, delay, charcnt, blinktics, talktics, talkframe;
int startdelay, enddelay, pausedelay;
int rss;
int fadein, fadeout;
double hs;
Vector2 ss, origin;
SWWMDirectMessage nextmsg; // for chaining messages together from different characters
bool nextdirect; // skips directly to next message without delays or fades
Font mSmallFont;
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;
startdelay = 30;
enddelay = 40;
pausedelay = 30;
rss = 1232;
mSmallFont = Font.GetFont('TewiFont');
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);
if ( l ) l.Destroy();
l = mSmallFont.BreakLines(txt,220);
// append to the player's chat log (if it's valid)
if ( (seqnum < 1) || (seqnum > seqcnt) ) return;
EventHandler.SendNetworkEvent("swwmstoremessage."..chrname..": "..txt,level.totaltime,PRINT_CHAT,consoleplayer);
}
private void DrawText()
{
if ( !l ) SetText();
int cur = charcnt;
Vector2 pos = origin+(47,3);
for ( int i=0; i<l.Count(); i++ )
{
if ( cur <= 0 ) break;
String part = l.StringAt(i).Left(cur);
Screen.DrawText(mSmallFont,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( double fractic )
{
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[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<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 = startdelay;
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.;
double fractic = SWWMStatusBar(statusbar)?SWWMStatusBar(statusbar).fractic:0;
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 through a hacky method in the hud
// because zscript is fucking stupid with its handling of names, we can't
// pass the dialogue name to arguments, so it'll have to be hardcoded
Class SWWMDialogueTrigger : Actor
{
default
{
+NOBLOCKMAP;
+NOGRAVITY;
+NOINTERACTION;
+DONTSPLASH;
}
override void Activate( Actor activator )
{
static const String dlglist[] =
{
"swwmultdoom2map20dlg"
};
if ( !swwm_nomapmsg )
Console.MidPrint(null,dlglist[args[0]]);
Destroy();
}
override void Tick() {}
}