As of this commit, do not consider the experience when playing that new expansion to be complete. I've only partially written some of the mission texts and rudimentarily enhanced some boss fights. Currently there is one major limitation in that the intermission texts cannot be replaced, as they're hardcoded inside the UMAPINFO. I don't know if I can work around that.
318 lines
10 KiB
Text
318 lines
10 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 lor = 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;
|
|
lor = SWWMUtility.IsLegacyOfRust();
|
|
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);
|
|
}
|
|
else if ( lor )
|
|
{
|
|
// legacy of rust has its quirks, as with umapinfo there are
|
|
// technically no clusters
|
|
if ( (level.levelnum <= 7) || (level.levelnum == 15) ) clus = 28;
|
|
else if ( (level.levelnum <= 14) || (level.levelnum == 16) ) clus = 29;
|
|
missionstr = String.Format("$SWWM_MISSION_DOOM%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));
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
|