swwmgz_m/zscript/kbase/swwm_kbasetab_mission.zsc
Marisa the Magician cbb1b2a8cb Sigil 2 (v1.0) and Eviternity 2 (RC5) support.
+ Invinciball activation now voiced by Demo (thanks, Vyolette).
+ Retooled exit line merging (should fix those pesky duplicate exit markers).

Note: Oneliners for the Eviternity 2 final boss are not voiced yet.
2024-01-04 19:50:26 +01:00

320 lines
11 KiB
Text

// mission briefing tab
Class DemolitionistMissionTab : DemolitionistMenuTab
{
Array<DemolitionistMenuTextBox> mtext;
int sel;
bool drag;
SWWMMissionLog mlog;
override DemolitionistMenuTab Init( DemolitionistMenu master )
{
title = StringTable.Localize("$SWWM_MISSTAB");
bHidden = deathmatch;
sel = 0;
mlog = SWWMMissionLog.Get();
// simplified initialization if we have a dedicated mission log
// note: mission log can't exist without one entry, so no fallback checks needed
if ( mlog )
{
for ( int i=(mlog.entries.Size()-1); i>=0; i-- )
mtext.Push(new("DemolitionistMenuTextBox").Init(master,mlog.entries[i]));
return Super.Init(master);
}
// saves time
bool nrftl = false;
bool eviternity = false;
bool eviternitwo = false;
bool hexdd = false;
String missionstr;
let stats = SWWMStats.Find(players[consoleplayer]);
if ( (gameinfo.gametype&GAME_Doom) && SWWMUtility.IsKnownMap() )
{
int clus = level.cluster;
if ( clus == 11 ) nrftl = true;
eviternity = SWWMUtility.IsEviternity();
eviternitwo = SWWMUtility.IsEviternityTwo();
if ( eviternitwo )
{
// clusters in eviternity 2 have to be remapped
if ( clus == 5 ) clus = 1;
else if ( (clus == 6) || (clus == 13) ) clus = 2;
else if ( (clus == 7) || (clus == 14) ) clus = 3;
else if ( (clus == 8) || (clus == 15) ) clus = 4;
else if ( (clus == 9) || (clus == 16) ) clus = 5;
else if ( (clus == 10) || (clus == 17) ) clus = 6;
else if ( (clus == 11) || (clus == 12) || (clus == 18) || (clus == 19) ) clus = 7;
missionstr = String.Format("$SWWM_MISSION_EVITERNITYII%d",clus);
}
else if ( eviternity )
{
// we have to do some heavy lifting here because episodes don't match clusters
if ( level.levelnum <= 5 ) clus = 1;
else if ( level.levelnum <= 10 ) clus = 2;
else if ( level.levelnum <= 15 ) clus = 3;
else if ( level.levelnum <= 20 ) clus = 4;
else if ( level.levelnum <= 25 ) clus = 5;
else if ( level.levelnum <= 30 ) clus = 6;
else if ( level.levelnum <= 31 ) clus = 7;
else if ( level.levelnum <= 32 ) clus = 8;
missionstr = String.Format("$SWWM_MISSION_EVITERNITY%d",clus);
}
// naive method to guess if this is sigil
else if ( (clus == 5) && (level.mapname.Left(2) == "E5") )
missionstr = String.Format("$SWWM_MISSION_SIGIL");
else if ( (clus == 6) && (level.mapname.Left(2) == "E6") )
missionstr = String.Format("$SWWM_MISSION_SIGIL2");
else missionstr = String.Format("$SWWM_MISSION_DOOM%d",clus);
int csiz = stats.clustervisit.Size();
if ( (csiz > 0) && stats.secretdone[csiz-1] )
{
String tmpstr = missionstr.."_SECRET";
if ( !(StringTable.Localize(tmpstr) ~== tmpstr.Mid(1)) )
missionstr = tmpstr;
}
// if we came from the doom 1 episodes, use the alt mission string for Doom 2
bool fromdoomone = false;
for ( int i=0; i<csiz; i++ )
{
// also include sigil
if ( !eviternity && !eviternitwo && (stats.clustervisit[i] >= 5) && (stats.clustervisit[i] != 25) && (stats.clustervisit[i] != 26) ) continue;
fromdoomone = true;
break;
}
if ( !eviternity && !eviternitwo && (clus == 5) && fromdoomone )
missionstr = "$SWWM_MISSION_DOOM5_FROMDOOM1";
if ( StringTable.Localize(missionstr) ~== missionstr.Mid(1) )
missionstr = "$SWWM_MISSION_NONE";
mtext.Push(new("DemolitionistMenuTextBox").Init(master,missionstr));
bool firstskip = false;
for ( int i=csiz-1; i>=0; i-- )
{
if ( (stats.clustervisit[i] == clus) && !firstskip )
continue;
firstskip = true;
String xstr = String.Format(eviternitwo?"$SWWM_MISSION_EVITERNITYII%d":eviternity?"$SWWM_MISSION_EVITERNITY%d":"$SWWM_MISSION_DOOM%d",stats.clustervisit[i]);
if ( !eviternity && !eviternitwo && (stats.clustervisit[i] == 5) && fromdoomone )
xstr = "$SWWM_MISSION_DOOM5_FROMDOOM1";
if ( stats.secretdone[i] )
{
String tmpstr = xstr.."_SECRET";
if ( !(StringTable.Localize(tmpstr) ~== tmpstr.Mid(1)) )
xstr = tmpstr;
}
if ( StringTable.Localize(xstr) ~== xstr.Mid(1) )
continue;
mtext.Push(new("DemolitionistMenuTextBox").Init(master,xstr));
}
if ( eviternitwo )
{
// prepend all mission briefings from Eviternity
mtext.Push(new("DemolitionistMenuTextBox").Init(master,StringTable.Localize("$SWWM_MISSION_EVITERNITY6")));
mtext.Push(new("DemolitionistMenuTextBox").Init(master,StringTable.Localize("$SWWM_MISSION_EVITERNITY5")));
mtext.Push(new("DemolitionistMenuTextBox").Init(master,StringTable.Localize("$SWWM_MISSION_EVITERNITY4_SECRET")));
mtext.Push(new("DemolitionistMenuTextBox").Init(master,StringTable.Localize("$SWWM_MISSION_EVITERNITY8")));
mtext.Push(new("DemolitionistMenuTextBox").Init(master,StringTable.Localize("$SWWM_MISSION_EVITERNITY7")));
mtext.Push(new("DemolitionistMenuTextBox").Init(master,StringTable.Localize("$SWWM_MISSION_EVITERNITY3")));
mtext.Push(new("DemolitionistMenuTextBox").Init(master,StringTable.Localize("$SWWM_MISSION_EVITERNITY2")));
mtext.Push(new("DemolitionistMenuTextBox").Init(master,StringTable.Localize("$SWWM_MISSION_EVITERNITY1")));
}
}
else if ( (gameinfo.gametype&GAME_Heretic) && SWWMUtility.IsKnownMap() )
{
missionstr = String.Format("$SWWM_MISSION_HERETIC%d",level.cluster);
if ( StringTable.Localize(missionstr) ~== missionstr.Mid(1) )
missionstr = "$SWWM_MISSION_NONE";
mtext.Push(new("DemolitionistMenuTextBox").Init(master,missionstr));
int csiz = stats.clustervisit.Size();
bool firstskip = false;
for ( int i=csiz-1; i>=0; i-- )
{
if ( (stats.clustervisit[i] == level.cluster) && !firstskip )
continue;
firstskip = true;
String xstr = String.Format("$SWWM_MISSION_HERETIC%d",stats.clustervisit[i]);
if ( StringTable.Localize(xstr) ~== xstr.Mid(1) )
continue;
mtext.Push(new("DemolitionistMenuTextBox").Init(master,xstr));
}
}
else if ( (gameinfo.gametype&GAME_Hexen) && SWWMUtility.IsKnownMap() )
{
// detect deathkings
hexdd = SWWMUtility.IsDeathkings();
String gstr = hexdd?"HEXDD":"HEXEN";
missionstr = String.Format("$SWWM_MISSION_%s%d",gstr,level.cluster);
if ( StringTable.Localize(missionstr) ~== missionstr.Mid(1) )
missionstr = "$SWWM_MISSION_NONE";
mtext.Push(new("DemolitionistMenuTextBox").Init(master,missionstr));
int csiz = stats.clustervisit.Size();
bool firstskip = false;
for ( int i=csiz-1; i>=0; i-- )
{
if ( (stats.clustervisit[i] == level.cluster) && !firstskip )
continue;
firstskip = true;
String xstr = String.Format("$SWWM_MISSION_%s%d",gstr,stats.clustervisit[i]);
if ( StringTable.Localize(xstr) ~== xstr.Mid(1) )
continue;
mtext.Push(new("DemolitionistMenuTextBox").Init(master,xstr));
}
}
return Super.Init(master);
}
override void OnDestroy()
{
foreach ( t:mtext )
{
if ( !t ) continue;
t.Destroy();
}
}
override void MenuInput( int key )
{
if ( mtext.Size() == 0 ) return;
switch ( key )
{
case MK_DOWN:
if ( mtext[sel].Scroll(16) ) master.MenuSound("menu/demoscroll");
break;
case MK_UP:
if ( mtext[sel].Scroll(-16) ) master.MenuSound("menu/demoscroll");
break;
case MK_LEFT:
// cycle mission texts
if ( (mtext.Size() > 1) && (sel < (mtext.Size()-1)) )
{
master.MenuSound("menu/demoscroll");
sel++;
mtext[sel].smofs = 0.;
mtext[sel].ofs = 0;
drag = false; // just in case
}
break;
case MK_RIGHT:
// cycle mission texts
if ( (mtext.Size() > 1) && (sel > 0) )
{
master.MenuSound("menu/demoscroll");
sel--;
mtext[sel].smofs = 0.;
mtext[sel].ofs = 0;
drag = false; // just in case
}
break;
}
}
override void MouseInput( Vector2 pos, int btn )
{
if ( mtext.Size() == 0 ) return;
switch ( btn )
{
case MB_LEFT:
// see if we're clicking the scrollbar (if it exists)
if ( mtext[sel].scrollbar && (pos.x > (mtext[sel].x+(mtext[sel].w-8))) )
{
mtext[sel].SetOffset(pos.y);
master.MenuSound("menu/demoscroll");
drag = true;
break;
}
// cycle mission texts
if ( (mtext.Size() > 1) && (sel > 0) )
{
master.MenuSound("menu/demoscroll");
sel--;
mtext[sel].smofs = 0.;
mtext[sel].ofs = 0;
drag = false; // just in case
}
break;
case MB_RIGHT:
// cycle mission texts
if ( (mtext.Size() > 1) && (sel < (mtext.Size()-1)) )
{
master.MenuSound("menu/demoscroll");
sel++;
mtext[sel].smofs = 0.;
mtext[sel].ofs = 0;
drag = false; // just in case
}
break;
case MB_WHEELUP:
if ( mtext[sel].Scroll(-8) ) master.MenuSound("menu/demoscroll");
break;
case MB_WHEELDOWN:
if ( mtext[sel].Scroll(8) ) master.MenuSound("menu/demoscroll");
break;
case MB_DRAG:
if ( drag ) mtext[sel].SetOffset(pos.y);
break;
case MB_RELEASE:
drag = false;
break;
}
}
// stop smooth scrolling for current textbox
override void OnSelect()
{
if ( mtext.Size() == 0 ) return;
mtext[sel].smofs = mtext[sel].ofs;
}
override void OnDeselect()
{
if ( mtext.Size() == 0 ) return;
mtext[sel].smofs = mtext[sel].ofs;
}
override void Ticker()
{
// dedicated mission log can update in real time, so append new entries to the start of the array when needed and push the selector forward
if ( mlog && (mlog.entries.Size() > mtext.Size()) )
{
bool newent = false;
if ( mtext.Size() == 0 )
{
for ( int i=(mlog.entries.Size()-1); i>=0; i-- )
mtext.Push(new("DemolitionistMenuTextBox").Init(master,mlog.entries[i]));
sel = 0;
newent = true;
}
else for ( int i=(mlog.entries.Size()-1); i>=mtext.Size(); i-- )
{
mtext.Insert(0,new("DemolitionistMenuTextBox").Init(master,mlog.entries[i]));
sel++;
newent = true;
}
// notification for mission log updated
if ( newent )
{
master.tmsg = StringTable.Localize("$SWWM_NEWMISSION");
master.tmsgtic = Menu.MenuTime()+70;
}
}
// just tick the current textbox
if ( mtext.Size() == 0 ) return;
mtext[sel].Ticker();
}
override void Drawer( double fractic )
{
if ( mtext.Size() > 0 ) mtext[sel].Drawer(fractic,!!sel);
else
{
String str = StringTable.Localize("$SWWM_MISSION_NONE");
double xx = int(master.ws.x-master.mSmallFont.StringWidth(str))/2;
double yy = int(master.ws.y-master.mSmallFont.GetHeight())/2;
Screen.DrawText(master.mSmallFont,Font.CR_FIRE,master.origin.x+xx,master.origin.y+yy,str,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
return;
}
if ( mtext.Size() <= 1 ) return;
double xx = master.ws.x-(mtext[sel].scrollbar?11:3);
double yy = master.ws.y-25;
String str = String.Format("%d \cf/\c- %d",mtext.Size()-sel,mtext.Size());
Screen.DrawText(master.mTinyFont,Font.CR_FIRE,(master.origin.x+xx)-master.mTinyFont.StringWidth(str),master.origin.y+yy,str,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
}
}