3500 lines
118 KiB
Text
3500 lines
118 KiB
Text
// internal "knowledge base" and more
|
|
Class MenuTransaction
|
|
{
|
|
enum ETransactionType
|
|
{
|
|
TT_ITEMUSE,
|
|
TT_ITEMDROP,
|
|
TT_ITEMSEND
|
|
};
|
|
|
|
int uid, type;
|
|
Class<Inventory> used;
|
|
bool result, usedup;
|
|
}
|
|
|
|
// FIXME this whole thing needs to be refactored eventually
|
|
Class DemolitionistMenu : GenericMenu
|
|
{
|
|
enum EDemoTab
|
|
{
|
|
TAB_MISSION = 0,
|
|
TAB_STATS,
|
|
TAB_INVENTORY,
|
|
TAB_KEYS,
|
|
TAB_LIBRARY,
|
|
TAB_STORE,
|
|
TAB_TRADING,
|
|
TAB_CHAT,
|
|
TAB_SECRET,
|
|
TAB_HELP
|
|
};
|
|
|
|
enum EStatsTab
|
|
{
|
|
STAT_MAIN = 0,
|
|
STAT_KILLS,
|
|
STAT_LEVEL,
|
|
STAT_ACHIEVEMENT,
|
|
};
|
|
|
|
TextureID MainWindow, TabSeparator, WindowSeparator, WindowSeparatorH,
|
|
FancyBg, Drawing[3], LoreSeparator, LoreSeparatorW;
|
|
transient Font TewiFont, MPlusFont, MiniwiFont, k6x8Font;
|
|
Array<int> tabs;
|
|
int curtab, oldtab;
|
|
// for scrolling
|
|
bool sub;
|
|
int sel0, sel1, sel2;
|
|
int ofs0, ofs1, ofs2; // usually equal to above, except when using mouse input
|
|
int drag; // when dragging with the mouse, which scroller to affect (1 = ofs0 and so on)
|
|
// mission
|
|
String missionstr;
|
|
Array<String> missionbacklog;
|
|
// stats
|
|
SWWMStats stats;
|
|
Array<String> statlist;
|
|
Array<MonsterKill> sorted_mstats; // sorted by killcount
|
|
// inventory lists
|
|
Array<Inventory> invlist;
|
|
// lore stuff
|
|
SWWMLoreLibrary lorelib;
|
|
Array<SWWMLore> lorelist;
|
|
int oldloresiz;
|
|
// store stuff
|
|
Array<Class<Inventory> > storelist;
|
|
Array<int> storeunits;
|
|
// trading
|
|
SWWMTradeHistory tradelib;
|
|
Array<int> playerlist;
|
|
// chat history total line count (includes breaks)
|
|
int chatlines;
|
|
// temporary bottom messages, such as "not enough money"
|
|
String tmsg;
|
|
int tmsgtic;
|
|
// menu keybind
|
|
int ikey[2];
|
|
String mkey[2];
|
|
// for checks (duh)
|
|
Array<MenuTransaction> checklist;
|
|
int lasttuid;
|
|
SWWMHandler hnd;
|
|
// seeeeecret
|
|
int kcode;
|
|
// crimey clock stuff
|
|
int c_year, c_month, c_day, c_hour, c_minute;
|
|
String c_tz;
|
|
// mouse stuff
|
|
Vector2 curmouse;
|
|
bool isrclick;
|
|
// somehow Drawer can be called while closing prematurely, which is big bollocks
|
|
bool isclosing;
|
|
|
|
// returns MPlus if we're playing in Japanese, otherwise returns the requested font
|
|
Font LangFont( Font req )
|
|
{
|
|
if ( language ~== "jp" ) return (req==MiniwiFont)?k6x8Font:MPlusFont;
|
|
return req;
|
|
}
|
|
|
|
int GenTUID()
|
|
{
|
|
return lasttuid++;
|
|
}
|
|
|
|
override void Init( Menu parent )
|
|
{
|
|
Super.Init(parent);
|
|
if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') )
|
|
{
|
|
// can't open this menu outside of the game or if dead
|
|
// also can't if you're not the Demolitionist
|
|
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
|
|
isclosing = true;
|
|
return;
|
|
}
|
|
TewiFont = Font.GetFont('TewiShaded');
|
|
MPlusFont = Font.GetFont('MPlusShaded');
|
|
MiniwiFont = Font.GetFont('MiniwiShaded');
|
|
k6x8Font = Font.GetFont('k6x8Shaded');
|
|
FancyBg = TexMan.CheckForTexture("graphics/tempbg.png",TexMan.Type_MiscPatch);
|
|
MainWindow = TexMan.CheckForTexture("graphics/KBase/MainWindow.png",TexMan.Type_MiscPatch);
|
|
TabSeparator = TexMan.CheckForTexture("graphics/KBase/TabSeparator.png",TexMan.Type_MiscPatch);
|
|
WindowSeparator = TexMan.CheckForTexture("graphics/KBase/WindowSeparator.png",TexMan.Type_MiscPatch);
|
|
WindowSeparatorH = TexMan.CheckForTexture("graphics/KBase/WindowSeparatorH.png",TexMan.Type_MiscPatch);
|
|
Drawing[0] = TexMan.CheckForTexture("graphics/KBase/Drawing_Saya.png",TexMan.Type_MiscPatch);
|
|
Drawing[1] = TexMan.CheckForTexture("graphics/KBase/Drawing_Ibuki.png",TexMan.Type_MiscPatch);
|
|
Drawing[2] = TexMan.CheckForTexture("graphics/KBase/Drawing_Kirin.png",TexMan.Type_MiscPatch);
|
|
LoreSeparator = TexMan.CheckForTexture("graphics/KBase/LibraryTabSeparator.png",TexMan.Type_MiscPatch);
|
|
LoreSeparatorW = TexMan.CheckForTexture("graphics/KBase/LibraryTabSeparatorJP.png",TexMan.Type_MiscPatch);
|
|
MenuSound("menu/demoopen");
|
|
[ikey[0], ikey[1]] = Bindings.GetKeysForCommand("event swwmdemomenu");
|
|
mkey[0] = Bindings.NameKeys(ikey[0],0);
|
|
mkey[1] = Bindings.NameKeys(ikey[1],0);
|
|
lorelib = SWWMLoreLibrary.Find(players[consoleplayer]);
|
|
oldloresiz = lorelib.ent.Size();
|
|
tradelib = SWWMTradeHistory.Find(players[consoleplayer]);
|
|
stats = SWWMStats.Find(players[consoleplayer]);
|
|
tmsg = "$SWWM_MAINCONTROLS";
|
|
tmsgtic = gametic+70;
|
|
lasttuid = Random[TUID]();
|
|
hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
|
// mission text
|
|
bool nrftl = false;
|
|
bool hexdd = false;
|
|
if ( (gameinfo.gametype&GAME_Doom) && SWWMUtility.IsKnownMap() )
|
|
{
|
|
int clus = level.cluster;
|
|
if ( clus == 11 ) nrftl = true;
|
|
bool eviternity = SWWMUtility.IsEviternity();
|
|
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 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 && (stats.clustervisit[i] >= 5) && (stats.clustervisit[i] != 25) ) continue;
|
|
fromdoomone = true;
|
|
break;
|
|
}
|
|
if ( !eviternity && (clus == 5) && fromdoomone )
|
|
missionstr = "$SWWM_MISSION_DOOM5_FROMDOOM1";
|
|
if ( StringTable.Localize(missionstr) ~== missionstr.Mid(1) )
|
|
missionstr = "$SWWM_MISSION_NONE";
|
|
bool firstskip = false;
|
|
for ( int i=csiz-1; i>=0; i-- )
|
|
{
|
|
if ( (stats.clustervisit[i] == clus) && !firstskip )
|
|
continue;
|
|
firstskip = true;
|
|
String xstr = String.Format(eviternity?"$SWWM_MISSION_EVITERNITY%d":"$SWWM_MISSION_DOOM%d",stats.clustervisit[i]);
|
|
if ( !eviternity && (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(missionstr) ~== missionstr.Mid(1) )
|
|
continue;
|
|
missionbacklog.Push(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";
|
|
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(missionstr) ~== missionstr.Mid(1) )
|
|
continue;
|
|
missionbacklog.Push(xstr);
|
|
}
|
|
}
|
|
else if ( (gameinfo.gametype&GAME_Hexen) && SWWMUtility.IsKnownMap() )
|
|
{
|
|
// detect deathkings in the most amazing way imaginable
|
|
int mapnamenum = level.mapname.Mid(3).ToInt(10);
|
|
if ( mapnamenum > 40 ) hexdd = true;
|
|
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";
|
|
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(missionstr) ~== missionstr.Mid(1) )
|
|
continue;
|
|
missionbacklog.Push(xstr);
|
|
}
|
|
}
|
|
else if ( gameinfo.gametype&GAME_Strife )
|
|
{
|
|
missionstr = players[consoleplayer].logtext; // just show the quest log
|
|
int csiz = stats.questbacklog.Size();
|
|
for ( int i=csiz-1; i>=0; i-- )
|
|
missionbacklog.Push(stats.questbacklog[i]);
|
|
}
|
|
else missionstr = "$SWWM_MISSION_NONE";
|
|
if ( gameinfo.gametype&GAME_Heretic )
|
|
{
|
|
// March 10th 2171, 17:34 JST
|
|
// Epoch: 6351554040
|
|
c_year = 2171;
|
|
c_month = 3;
|
|
c_day = 9;
|
|
c_hour = 17;
|
|
c_minute = 34;
|
|
c_tz = "JST";
|
|
}
|
|
else if ( gameinfo.gametype&GAME_Hexen )
|
|
{
|
|
// May 25th 2171, 16:41 JST
|
|
// Epoch: 6355438860
|
|
c_year = 2171;
|
|
c_month = 4;
|
|
c_day = 24;
|
|
c_hour = 16;
|
|
c_minute = 41;
|
|
c_tz = "JST";
|
|
if ( hexdd )
|
|
{
|
|
// deathkings happen the day after
|
|
c_day = 25;
|
|
c_hour = 10;
|
|
c_minute = 28;
|
|
}
|
|
}
|
|
else if ( gameinfo.gametype&GAME_Strife )
|
|
{
|
|
// September 13th 2173, 11:26 JST
|
|
// Epoch: 6425490360
|
|
c_year = 2173;
|
|
c_month = 7;
|
|
c_day = 12;
|
|
c_hour = 11;
|
|
c_minute = 26;
|
|
c_tz = "JST";
|
|
}
|
|
else if ( SWWMUtility.IsEviternity() )
|
|
{
|
|
// June 10th 2150, 20:09 +09
|
|
// (June 10th 2150, 20:09 JST)
|
|
// Epoch: 5694145740
|
|
c_year = 2150;
|
|
c_month = 5;
|
|
c_day = 9;
|
|
c_hour = 20;
|
|
c_minute = 9;
|
|
c_tz = "+09";
|
|
}
|
|
else // Doom
|
|
{
|
|
// June 6th 2148, 18:37 EDT
|
|
// (June 7th 2148, 07:37 JST)
|
|
// Epoch: 5630769420
|
|
c_year = 2148;
|
|
c_month = 5;
|
|
c_day = 5;
|
|
c_hour = 18;
|
|
c_minute = 37;
|
|
c_tz = "EDT";
|
|
if ( nrftl )
|
|
{
|
|
// NRFTL just happens the next day after
|
|
c_day = 6;
|
|
c_hour = 15;
|
|
c_minute = 48;
|
|
}
|
|
}
|
|
if ( (missionstr != "$SWWM_MISSION_NONE") || (missionbacklog.Size() > 0) )
|
|
tabs.Push(TAB_MISSION);
|
|
tabs.Push(TAB_STATS);
|
|
tabs.Push(TAB_INVENTORY);
|
|
tabs.Push(TAB_KEYS);
|
|
tabs.Push(TAB_LIBRARY);
|
|
tabs.Push(TAB_STORE);
|
|
for ( int i=0; i<MAXPLAYERS; i++ )
|
|
{
|
|
if ( !playeringame[i] || (i == consoleplayer) ) continue;
|
|
if ( deathmatch && (!teamplay || (players[i].GetTeam() != players[consoleplayer].GetTeam())) ) continue;
|
|
tabs.Push(TAB_TRADING);
|
|
break;
|
|
}
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( bar && (bar.FullHistory.Size() > 0) )
|
|
tabs.Push(TAB_CHAT);
|
|
int lasttab = swwm_lasttab;
|
|
for ( int i=0; i<tabs.Size(); i++ )
|
|
{
|
|
if ( tabs[i] != lasttab ) continue;
|
|
curtab = i;
|
|
break;
|
|
}
|
|
if ( tabs[curtab] == TAB_LIBRARY ) sel1 = swwm_lastloretab;
|
|
else if ( tabs[curtab] == TAB_STATS ) sel1 = swwm_laststattab;
|
|
}
|
|
|
|
// please don't look at this
|
|
private String CrimeTime()
|
|
{
|
|
// we have to do things this way because dates in this mod go beyond 32-bit unix time
|
|
static const int days_in_month[] = {31,28,31,30,31,30,31,31,30,31,30,31};
|
|
bool leap_year;
|
|
int y = c_year, m = c_month, d = c_day, h = c_hour, mn = c_minute;
|
|
int addtime = level.totaltime/GameTicRate;
|
|
while ( addtime > 0 )
|
|
{
|
|
leap_year = (!(y%4) && ((y%100) || !(y%400)));
|
|
if ( addtime >= 86400 )
|
|
{
|
|
addtime -= 86400;
|
|
d++;
|
|
int md = days_in_month[m];
|
|
if ( leap_year && (m == 1) ) md++;
|
|
if ( d >= md )
|
|
{
|
|
d = 0;
|
|
m++;
|
|
if ( m > 11 )
|
|
{
|
|
m = 0;
|
|
y++;
|
|
}
|
|
}
|
|
}
|
|
else if ( addtime >= 3600 )
|
|
{
|
|
addtime -= 3600;
|
|
h++;
|
|
if ( h > 23 )
|
|
{
|
|
h = 0;
|
|
d++;
|
|
int md = days_in_month[m];
|
|
if ( leap_year && (m == 1) ) md++;
|
|
if ( d >= md )
|
|
{
|
|
d = 0;
|
|
m++;
|
|
if ( m > 11 )
|
|
{
|
|
m = 0;
|
|
y++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( addtime >= 60 )
|
|
{
|
|
addtime -= 60;
|
|
mn++;
|
|
if ( mn > 59 )
|
|
{
|
|
mn = 0;
|
|
h++;
|
|
if ( h > 23 )
|
|
{
|
|
h = 0;
|
|
d++;
|
|
int md = days_in_month[m];
|
|
if ( leap_year && (m == 1) ) md++;
|
|
if ( d >= md )
|
|
{
|
|
d = 0;
|
|
m++;
|
|
if ( m > 11 )
|
|
{
|
|
m = 0;
|
|
y++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// we finished counting
|
|
addtime = 0;
|
|
}
|
|
}
|
|
return String.Format("%04d-%02d-%02d %02d:%02d %s",y,m+1,d+1,h,mn,c_tz);
|
|
}
|
|
|
|
override bool MenuEvent( int mkey, bool fromcontroller )
|
|
{
|
|
Font fnt = LangFont(TewiFont);
|
|
switch ( kcode )
|
|
{
|
|
case 0:
|
|
case 1:
|
|
if ( mkey == MKEY_UP ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
if ( mkey == MKEY_DOWN ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 4:
|
|
case 6:
|
|
if ( mkey == MKEY_LEFT ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 5:
|
|
case 7:
|
|
if ( mkey == MKEY_RIGHT ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 10:
|
|
if ( mkey == MKEY_ENTER )
|
|
{
|
|
MenuSound("misc/secret");
|
|
if ( tabs[curtab] >= TAB_SECRET ) tabs.Delete(curtab);
|
|
tabs.Push(TAB_SECRET);
|
|
curtab = tabs.Size()-1;
|
|
sel0 = sel1 = sel2 = 0;
|
|
ofs0 = ofs1 = ofs2 = 0;
|
|
sub = false;
|
|
}
|
|
default:
|
|
kcode = 0;
|
|
break;
|
|
}
|
|
int maxtab = multiplayer?TAB_CHAT:TAB_STORE;
|
|
switch ( mkey )
|
|
{
|
|
case MKEY_BACK:
|
|
MenuSound("menu/democlose");
|
|
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
|
|
Close();
|
|
return true;
|
|
case MKEY_PAGEUP:
|
|
MenuSound("menu/demotab");
|
|
if ( tabs[curtab] >= TAB_SECRET ) tabs.Delete(curtab); // hide this tab
|
|
if ( curtab <= 0 ) curtab = (tabs.Size()-1);
|
|
else curtab--;
|
|
CVar.FindCVar('swwm_lasttab').SetInt(tabs[curtab]);
|
|
sel0 = sel1 = sel2 = 0;
|
|
ofs0 = ofs1 = ofs2 = 0;
|
|
sub = false;
|
|
invlist.Clear();
|
|
lorelist.Clear();
|
|
storelist.Clear();
|
|
storeunits.Clear();
|
|
playerlist.Clear();
|
|
return true;
|
|
case MKEY_PAGEDOWN:
|
|
MenuSound("menu/demotab");
|
|
if ( tabs[curtab] >= TAB_SECRET ) tabs.Delete(curtab); // hide this tab
|
|
if ( curtab < (tabs.Size()-1) ) curtab++;
|
|
else curtab = 0;
|
|
CVar.FindCVar('swwm_lasttab').SetInt(tabs[curtab]);
|
|
sel0 = sel1 = sel2 = 0;
|
|
ofs0 = ofs1 = ofs2 = 0;
|
|
sub = false;
|
|
invlist.Clear();
|
|
lorelist.Clear();
|
|
storelist.Clear();
|
|
storeunits.Clear();
|
|
playerlist.Clear();
|
|
return true;
|
|
case MKEY_DOWN:
|
|
if ( tabs[curtab] == TAB_HELP )
|
|
{
|
|
String str = StringTable.Localize("$SWWM_HELPTXT");
|
|
for ( int i=0; i<MAXPLAYERS; i++ )
|
|
{
|
|
if ( !playeringame[i] || (i == consoleplayer) ) continue;
|
|
if ( deathmatch && (!teamplay || (players[i].GetTeam() != players[consoleplayer].GetTeam())) ) continue;
|
|
str = str..StringTable.Localize("$SWWM_HELPTXT_TRADING");
|
|
break;
|
|
}
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( bar && (bar.FullHistory.Size() > 0) )
|
|
str = str..StringTable.Localize("$SWWM_HELPTXT_CHAT");
|
|
BrokenLines l = fnt.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,620);
|
|
if ( (l.Count() > 28) && (sel0 < l.Count()-28) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0++;
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_MISSION )
|
|
{
|
|
String str;
|
|
if ( sel1 == 0 ) str = StringTable.Localize(missionstr);
|
|
else str = StringTable.Localize(missionbacklog[sel1-1]);
|
|
BrokenLines l = fnt.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,620);
|
|
if ( (l.Count() > 28) && (sel0 < l.Count()-28) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = ++sel0;
|
|
}
|
|
}
|
|
else if ( (tabs[curtab] == TAB_CHAT) && (StatusBar is 'SWWMStatusBar') && (sel0 > 0) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = --sel0;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_LIBRARY) && (lorelist.Size() > 1) )
|
|
{
|
|
if ( sub )
|
|
{
|
|
String str = StringTable.Localize(lorelist[sel0].text);
|
|
int ofs = (language~=="jp")?212:132;
|
|
if ( lorelist.Size() > 26 ) ofs += 8;
|
|
BrokenLines l = fnt.BreakLines(str,635-ofs);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,626-ofs);
|
|
if ( (l.Count() > 28) && (sel2 < l.Count()-28) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs2 = ++sel2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
if ( sel0 >= lorelist.Size()-1 ) ofs0 = sel0 = 0;
|
|
else
|
|
{
|
|
sel0++;
|
|
// update ofs so selection stays on-screen
|
|
int ofs = max(ofs0-26,0);
|
|
if ( sel0 < ofs ) ofs0 = sel0+26;
|
|
else if ( sel0 > ofs+26 ) ofs0 = sel0;
|
|
}
|
|
}
|
|
}
|
|
else if ( ((tabs[curtab] == TAB_INVENTORY) || (tabs[curtab] == TAB_KEYS) || ((tabs[curtab] == TAB_TRADING) && sub && (sel0 != -1))) && (invlist.Size() > 1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = ++sel0;
|
|
if ( sel0 >= invlist.Size() ) ofs0 = sel0 = 0;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STORE) && (storelist.Size() > 1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = ++sel0;
|
|
if ( sel0 >= storelist.Size() ) ofs0 = sel0 = 0;
|
|
}
|
|
else if ( tabs[curtab] == TAB_TRADING )
|
|
{
|
|
if ( !sub && (playerlist.Size() > 1) )
|
|
{
|
|
// scroll through player list
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = ++sel0;
|
|
if ( sel0 >= playerlist.Size() ) ofs0 = sel0 = 0;
|
|
}
|
|
else if ( sub && (sel0 == -1) && (sel1 < tradelib.ent.Size()-28) )
|
|
{
|
|
// scroll through trading history
|
|
MenuSound("menu/demoscroll");
|
|
ofs1 = ++sel1;
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_STATS )
|
|
{
|
|
int cnt = 0;
|
|
if ( sel1 == STAT_MAIN )
|
|
cnt = statlist.Size();
|
|
else if ( sel1 == STAT_KILLS )
|
|
cnt = sorted_mstats.Size();
|
|
else if ( sel1 == STAT_LEVEL )
|
|
cnt = stats.lstats.Size();
|
|
if ( (cnt > 22) && (sel0 < cnt-22) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = ++sel0;
|
|
}
|
|
}
|
|
return true;
|
|
case MKEY_UP:
|
|
if ( (tabs[curtab] == TAB_HELP) && (sel0 > 0) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = --sel0;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_MISSION) && (sel0 > 0) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = --sel0;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_CHAT) && (StatusBar is 'SWWMStatusBar') && (sel0 < SWWMStatusBar(StatusBar).FullHistory.Size()-1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = ++sel0;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_LIBRARY) && (lorelist.Size() > 1) )
|
|
{
|
|
if ( sub )
|
|
{
|
|
if ( sel2 > 0 )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs2 = --sel2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
if ( sel0 <= 0 ) ofs0 = sel0 = lorelist.Size()-1;
|
|
else
|
|
{
|
|
sel0--;
|
|
// update ofs so selection stays on-screen
|
|
int ofs = max(ofs0-26,0);
|
|
if ( sel0 < ofs ) ofs0 = sel0+26;
|
|
else if ( sel0 > ofs+26 ) ofs0 = sel0;
|
|
}
|
|
}
|
|
}
|
|
else if ( ((tabs[curtab] == TAB_INVENTORY) || (tabs[curtab] == TAB_KEYS) || ((tabs[curtab] == TAB_TRADING) && sub && (sel0 != -1))) && (invlist.Size() > 1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = --sel0;
|
|
if ( sel0 < 0 ) ofs0 = sel0 = invlist.Size()-1;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STORE) && (storelist.Size() > 1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = --sel0;
|
|
if ( sel0 < 0 ) ofs0 = sel0 = storelist.Size()-1;
|
|
}
|
|
else if ( tabs[curtab] == TAB_TRADING )
|
|
{
|
|
if ( !sub && (playerlist.Size() > 1) )
|
|
{
|
|
// scroll through player list
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = --sel0;
|
|
if ( sel0 < 0 ) ofs0 = sel0 = playerlist.Size()-1;
|
|
}
|
|
else if ( sub && (sel0 == -1) && (sel1 > 0) )
|
|
{
|
|
// scroll through trading history
|
|
MenuSound("menu/demoscroll");
|
|
ofs1 = --sel1;
|
|
}
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STATS) && (sel0 > 0) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = --sel0;
|
|
}
|
|
return true;
|
|
case MKEY_RIGHT:
|
|
if ( (tabs[curtab] == TAB_MISSION) && (missionbacklog.Size() > 0) )
|
|
{
|
|
if ( sel1 < missionbacklog.Size() )
|
|
{
|
|
sel0 = 0;
|
|
sel1++;
|
|
MenuSound("menu/demoscroll");
|
|
}
|
|
}
|
|
else if ( ((tabs[curtab] == TAB_INVENTORY) || (tabs[curtab] == TAB_KEYS) || ((tabs[curtab] == TAB_TRADING) && sub && (sel0 != -1))) && (invlist.Size() > 21) )
|
|
{
|
|
int oldsel = sel0;
|
|
ofs0 = sel0 += 22;
|
|
if ( sel0 >= invlist.Size() ) ofs0 = sel0 = invlist.Size()-1;
|
|
if ( sel0 != oldsel ) MenuSound("menu/demoscroll");
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STORE) && (storelist.Size() > 21) )
|
|
{
|
|
int oldsel = sel0;
|
|
ofs0 = sel0 += 22;
|
|
if ( sel0 >= storelist.Size() ) ofs0 = sel0 = storelist.Size()-1;
|
|
if ( sel0 != oldsel ) MenuSound("menu/demoscroll");
|
|
}
|
|
else if ( tabs[curtab] == TAB_LIBRARY )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = 0;
|
|
sub = false;
|
|
ofs1 = ++sel1;
|
|
if ( sel1 > LORE_LORE ) ofs1 = sel1 = LORE_ITEM;
|
|
CVar.FindCVar('swwm_lastloretab').SetInt(sel1);
|
|
}
|
|
else if ( (tabs[curtab] == TAB_TRADING) && !sub && (playerlist.Size() > 21) ) // lol is this ever going to happen
|
|
{
|
|
int oldsel = sel0;
|
|
ofs0 = sel0 += 22;
|
|
if ( sel0 >= playerlist.Size() ) ofs0 = sel0 = playerlist.Size()-1;
|
|
if ( sel0 != oldsel ) MenuSound("menu/demoscroll");
|
|
}
|
|
else if ( tabs[curtab] == TAB_STATS )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = 0;
|
|
ofs1 = ++sel1;
|
|
if ( ofs1 > STAT_ACHIEVEMENT ) ofs1 = sel1 = STAT_MAIN;
|
|
CVar.FindCVar('swwm_laststattab').SetInt(sel1);
|
|
}
|
|
return true;
|
|
case MKEY_LEFT:
|
|
if ( (tabs[curtab] == TAB_MISSION) && (missionbacklog.Size() > 0) )
|
|
{
|
|
if ( sel1 > 0 )
|
|
{
|
|
sel0 = 0;
|
|
sel1--;
|
|
MenuSound("menu/demoscroll");
|
|
}
|
|
}
|
|
else if ( ((tabs[curtab] == TAB_INVENTORY) || (tabs[curtab] == TAB_KEYS) || ((tabs[curtab] == TAB_TRADING) && sub && (sel0 != -1))) && (invlist.Size() > 21) && (sel0-22 >= 0) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 -= 22;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STORE) && (storelist.Size() > 21) && (sel0-22 >= 0) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 -= 22;
|
|
}
|
|
else if ( tabs[curtab] == TAB_LIBRARY )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = 0;
|
|
sub = false;
|
|
ofs1 = --sel1;
|
|
if ( sel1 < LORE_ITEM ) ofs1 = sel1 = LORE_LORE;
|
|
CVar.FindCVar('swwm_lastloretab').SetInt(sel1);
|
|
}
|
|
else if ( (tabs[curtab] == TAB_TRADING) && !sub && (playerlist.Size() > 21) && (sel0-22 >= 0) ) // lol is this ever going to happen
|
|
{
|
|
ofs0 = sel0 -= 22;
|
|
MenuSound("menu/demoscroll");
|
|
}
|
|
else if ( tabs[curtab] == TAB_STATS )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = 0;
|
|
ofs1 = --sel1;
|
|
if ( ofs1 < STAT_MAIN ) ofs1 = sel1 = STAT_ACHIEVEMENT;
|
|
CVar.FindCVar('swwm_laststattab').SetInt(sel1);
|
|
}
|
|
return true;
|
|
case MKEY_ENTER:
|
|
if ( (tabs[curtab] == TAB_INVENTORY) && (invlist.Size() > 0) && (sel0 < invlist.Size()) )
|
|
{
|
|
// can't use this
|
|
if ( (invlist[sel0] is 'Ammo') || (invlist[sel0] is 'MagAmmo') || (invlist[sel0] is 'SWWMCollectible')
|
|
|| (invlist[sel0] is 'HammerspaceEmbiggener') )
|
|
return true;
|
|
let t = new("MenuTransaction");
|
|
t.uid = GenTUID();
|
|
t.type = MenuTransaction.TT_ITEMUSE;
|
|
t.result = false;
|
|
// don't check weapons, always assume check succeeded
|
|
if ( invlist[sel0] is 'Weapon' ) t.result = true;
|
|
checklist.Push(t);
|
|
EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer,t.uid);
|
|
}
|
|
else if ( (tabs[curtab] == TAB_KEYS) && (invlist.Size() > 0) && (sel0 < invlist.Size()) )
|
|
{
|
|
// can't use this
|
|
if ( !(invlist[sel0] is 'SWWMKey') && !(invlist[sel0] is 'SWWMCollectible') )
|
|
return true;
|
|
let t = new("MenuTransaction");
|
|
t.uid = GenTUID();
|
|
t.type = MenuTransaction.TT_ITEMUSE;
|
|
t.result = true; // always true
|
|
checklist.Push(t);
|
|
EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer,t.uid);
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STORE) && (storelist.Size() > 0) && (sel0 < storelist.Size()) )
|
|
{
|
|
let itm = GetDefaultByType(storelist[sel0]);
|
|
let amt = storeunits[sel0];
|
|
int price = int(abs(itm.Stamina)*(1.+.75*(amt-1)));
|
|
let cur = players[consoleplayer].mo.FindInventory(storelist[sel0]);
|
|
if ( sub )
|
|
{
|
|
if ( !cur ) return true;
|
|
if ( storelist[sel0] is 'Weapon' )
|
|
{
|
|
let w = Weapon(itm);
|
|
// subtract price of given ammo, as we're only selling the weapon itself
|
|
if ( w.AmmoType1 && (w.AmmoGive1 > 0) )
|
|
{
|
|
let am1 = GetDefaultByType(w.AmmoType1);
|
|
if ( am1.Stamina > 0 ) price -= int(am1.Stamina*(1.+.75*(w.AmmoGive1-1)));
|
|
}
|
|
// candygun is a special case for secondary ammo
|
|
if ( w.AmmoType2 && (w.AmmoGive2 > 0) && (storelist[sel0] is 'CandyGun') )
|
|
{
|
|
let am2 = GetDefaultByType(w.AmmoType2);
|
|
if ( am2.Stamina > 0 ) price -= int(am2.Stamina*(1.+.75*(w.AmmoGive2-1)));
|
|
}
|
|
}
|
|
// sell at half price
|
|
if ( sub ) price /= 2;
|
|
EventHandler.SendNetworkEvent(String.Format("swwmstoretake.%s",storelist[sel0].GetClassName()),consoleplayer,price,amt);
|
|
MenuSound("menu/buyinv");
|
|
return true;
|
|
}
|
|
if ( !SWWMCredits.CanTake(players[consoleplayer],price) )
|
|
{
|
|
MenuSound("menu/noinvuse");
|
|
tmsg = StringTable.Localize("$SWWM_STOREMUNS");
|
|
tmsgtic = gametic+70;
|
|
return true;
|
|
}
|
|
int camt, max;
|
|
if ( cur )
|
|
{
|
|
camt = cur.Amount;
|
|
max = cur.MaxAmount;
|
|
}
|
|
else
|
|
{
|
|
camt = 0;
|
|
max = itm.MaxAmount;
|
|
}
|
|
if ( camt >= max )
|
|
{
|
|
MenuSound("menu/noinvuse");
|
|
tmsg = StringTable.Localize("$SWWM_STOREFULL");
|
|
tmsgtic = gametic+70;
|
|
return true;
|
|
}
|
|
EventHandler.SendNetworkEvent(String.Format("swwmstoregive.%s",storelist[sel0].GetClassName()),consoleplayer,price,amt);
|
|
MenuSound("menu/buyinv");
|
|
}
|
|
else if ( tabs[curtab] == TAB_LIBRARY )
|
|
{
|
|
if ( sub )
|
|
{
|
|
MenuSound("menu/democlose");
|
|
sub = false;
|
|
}
|
|
else if ( (lorelist.Size() > 0) && (sel0 < lorelist.Size()) )
|
|
{
|
|
// mark as read
|
|
if ( !lorelist[sel0].read )
|
|
EventHandler.SendNetworkEvent(String.Format("swwmmarkloreread.%s",lorelist[sel0].tag),consoleplayer);
|
|
MenuSound("menu/demosel");
|
|
sub = true;
|
|
ofs2 = sel2 = 0;
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_TRADING )
|
|
{
|
|
if ( !sub && (playerlist.Size() > 0) )
|
|
{
|
|
// pick a player
|
|
MenuSound("menu/demosel");
|
|
sub = true;
|
|
ofs1 = sel1 = 0;
|
|
}
|
|
else if ( sub && (sel0 != -1) && (invlist.Size() > 0) )
|
|
{
|
|
// cannot trade these
|
|
if ( ((invlist[sel1].bUNDROPPABLE || invlist[sel1].bUNTOSSABLE) && !(invlist[sel1] is 'HammerspaceEmbiggener'))
|
|
|| ((invlist[sel1] is 'CandyGunSpares') && !players[playerlist[sel0]].mo.FindInventory('CandyGun')) )
|
|
{
|
|
MenuSound("menu/noinvuse");
|
|
tmsg = StringTable.Localize("$SWWM_TRADEFAIL");
|
|
tmsgtic = gametic+70;
|
|
return true;
|
|
}
|
|
// trade item
|
|
let t = new("MenuTransaction");
|
|
t.uid = GenTUID();
|
|
t.type = MenuTransaction.TT_ITEMSEND;
|
|
t.result = false;
|
|
checklist.Push(t);
|
|
EventHandler.SendNetworkEvent(String.Format("swwmtrade.%s",invlist[sel1].GetClassName()),consoleplayer,playerlist[sel0],t.uid);
|
|
}
|
|
}
|
|
return true;
|
|
case MKEY_CLEAR:
|
|
if ( (tabs[curtab] == TAB_INVENTORY) && (invlist.Size() > 0) )
|
|
{
|
|
let t = new("MenuTransaction");
|
|
t.uid = GenTUID();
|
|
t.type = MenuTransaction.TT_ITEMDROP;
|
|
t.result = false;
|
|
checklist.Push(t);
|
|
EventHandler.SendNetworkEvent(String.Format("swwmdropitem.%s",invlist[sel0].GetClassName()),consoleplayer,t.uid);
|
|
}
|
|
else if ( (tabs[curtab] == TAB_LIBRARY) && sub )
|
|
{
|
|
MenuSound("menu/democlose");
|
|
sub = false;
|
|
}
|
|
else if ( tabs[curtab] == TAB_STORE )
|
|
{
|
|
sub = !sub;
|
|
MenuSound(sub?"menu/demosel":"menu/democlose");
|
|
}
|
|
else if ( tabs[curtab] == TAB_TRADING )
|
|
{
|
|
if ( !sub )
|
|
{
|
|
// open trading history
|
|
MenuSound("menu/demosel");
|
|
sub = true;
|
|
ofs0 = sel0 = -1;
|
|
ofs1 = sel1 = 0;
|
|
}
|
|
else if ( sub )
|
|
{
|
|
// go back
|
|
MenuSound("menu/democlose");
|
|
sub = false;
|
|
ofs0 = sel0 = 0;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return Super.MenuEvent(mkey,fromcontroller);
|
|
}
|
|
|
|
private int rnd( double num )
|
|
{
|
|
return int(num+((num<0)?-.5:.5));
|
|
}
|
|
|
|
override bool MouseEvent( int type, int mx, int my )
|
|
{
|
|
bool res = Super.MouseEvent(type,mx,my);
|
|
Font fnt = LangFont(TewiFont);
|
|
String str;
|
|
double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/400.)),1.);
|
|
Vector2 ss = (Screen.GetWidth(),Screen.GetHeight())/hs;
|
|
Vector2 origin = (ss.x-640,ss.y-400)/2.;
|
|
Vector2 mpos = (mx/hs,my/hs)-origin;
|
|
int xx, yy, len;
|
|
if ( type == MOUSE_Click )
|
|
{
|
|
if ( (mpos.x < 0) || (mpos.x >= 641) || (mpos.y < 0) || (mpos.y >= 386) ) return res; // outside clickable area, ignore
|
|
else if ( mpos.y < 14 )
|
|
{
|
|
if ( isrclick ) return res;
|
|
// check which tab we're clicking
|
|
static const string tabnames[] =
|
|
{
|
|
"$SWWM_MISSTAB", "$SWWM_STATTAB", "$SWWM_INVTAB", "$SWWM_KEYTAB",
|
|
"$SWWM_KBASETAB", "$SWWM_STORETAB", "$SWWM_TRADETAB", "$SWWM_CHATTAB",
|
|
"$SWWM_SECRETTAB", "$SWWM_HELPTAB"
|
|
};
|
|
xx = 0;
|
|
for ( int i=0; i<tabs.Size(); i++ )
|
|
{
|
|
len = fnt.StringWidth(tabnames[tabs[i]])+6;
|
|
if ( (mpos.x >= xx) && (mpos.x < xx+len) )
|
|
{
|
|
if ( curtab == i ) break;
|
|
MenuSound("menu/demotab");
|
|
if ( tabs[curtab] >= TAB_SECRET )
|
|
{
|
|
tabs.Delete(curtab);
|
|
if ( curtab < i ) i--; // account for shortening
|
|
}
|
|
curtab = i;
|
|
CVar.FindCVar('swwm_lasttab').SetInt(tabs[curtab]);
|
|
sel0 = sel1 = sel2 = 0;
|
|
ofs0 = ofs1 = ofs2 = 0;
|
|
sub = false;
|
|
invlist.Clear();
|
|
lorelist.Clear();
|
|
storelist.Clear();
|
|
storeunits.Clear();
|
|
playerlist.Clear();
|
|
break;
|
|
}
|
|
xx += len;
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_MISSION )
|
|
{
|
|
// are we clicking where the scrollbar should be?
|
|
if ( mpos.x < 632 )
|
|
{
|
|
int csiz = missionbacklog.Size();
|
|
if ( csiz <= 0 ) return res;
|
|
if ( isrclick && (sel1 < csiz) )
|
|
{
|
|
sel0 = 0;
|
|
sel1++;
|
|
MenuSound("menu/demoscroll");
|
|
}
|
|
else if ( !isrclick && (sel1 > 0) )
|
|
{
|
|
sel0 = 0;
|
|
sel1--;
|
|
MenuSound("menu/demoscroll");
|
|
}
|
|
return res;
|
|
}
|
|
if ( !isrclick )
|
|
{
|
|
String str;
|
|
if ( sel1 == 0 ) str = StringTable.Localize(missionstr);
|
|
else str = StringTable.Localize(missionbacklog[sel1-1]);
|
|
BrokenLines l = fnt.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,620);
|
|
else return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = l.Count()-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
drag = 1;
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_INVENTORY )
|
|
{
|
|
// check what item we clicked
|
|
if ( mpos.y < 377 )
|
|
{
|
|
if ( invlist.Size() <= 0 ) return res; // clicked nothing
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
|
|
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
|
|
else str = invlist[i].GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
int ofs = int(max(0,(ofs0/22)-(maxcol-1))*22);
|
|
xx = 9;
|
|
yy = 23;
|
|
int cols = 1;
|
|
for ( int i=ofs; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
// check boundary
|
|
if ( (mpos.x >= xx) && (mpos.x < xx+longest) && (mpos.y >= yy) && (mpos.y < yy+14) )
|
|
{
|
|
if ( sel0 != i ) MenuSound("menu/demoscroll");
|
|
sel0 = i;
|
|
ofs0 = (sel0/22)*22;
|
|
// drop on right click in inventory tab
|
|
if ( (tabs[curtab] == TAB_INVENTORY) && isrclick ) MenuEvent(MKEY_CLEAR,false);
|
|
else if ( !isrclick ) MenuEvent(MKEY_ENTER,false);
|
|
return res;
|
|
}
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+24;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
if ( !isrclick )
|
|
{
|
|
// check that scrollbar is present
|
|
if ( invlist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
|
|
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
|
|
else str = invlist[i].GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
drag = 1;
|
|
}
|
|
}
|
|
else if ( (tabs[curtab] == TAB_TRADING) && sub && (sel0 != -1) )
|
|
{
|
|
// check what item we clicked
|
|
if ( mpos.y < 377 )
|
|
{
|
|
if ( invlist.Size() <= 0 ) return res; // clicked nothing
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
|
|
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
|
|
else str = invlist[i].GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
int ofs = int(max(0,(ofs1/22)-(maxcol-1))*22);
|
|
xx = 9;
|
|
yy = 23;
|
|
int cols = 1;
|
|
for ( int i=ofs; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
// check boundary
|
|
if ( (mpos.x >= xx) && (mpos.x < xx+longest) && (mpos.y >= yy) && (mpos.y < yy+14) )
|
|
{
|
|
if ( sel1 != i ) MenuSound("menu/demoscroll");
|
|
sel1 = i;
|
|
ofs1 = (sel1/22)*22;
|
|
// drop on right click in inventory tab
|
|
if ( (tabs[curtab] == TAB_INVENTORY) && isrclick ) MenuEvent(MKEY_CLEAR,false);
|
|
else if ( !isrclick ) MenuEvent(MKEY_ENTER,false);
|
|
return res;
|
|
}
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+24;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
if ( !isrclick )
|
|
{
|
|
// check that scrollbar is present
|
|
if ( invlist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
|
|
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
|
|
else str = invlist[i].GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
drag = 1;
|
|
}
|
|
}
|
|
else if ( (tabs[curtab] == TAB_KEYS) && !isrclick )
|
|
{
|
|
// check what item we clicked
|
|
if ( mpos.y < 377 )
|
|
{
|
|
if ( invlist.Size() <= 0 ) return res; // clicked nothing
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
str = invlist[i].GetTag();
|
|
if ( invlist[i] is 'SWWMCollectible' )
|
|
str.AppendFormat(" (¥%d)",invlist[i].default.Stamina);
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
int ofs = int(max(0,(ofs0/22)-(maxcol-1))*22);
|
|
xx = 9;
|
|
yy = 23;
|
|
int cols = 1;
|
|
for ( int i=ofs; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
// check boundary
|
|
if ( (mpos.x >= xx) && (mpos.x < xx+longest) && (mpos.y >= yy) && (mpos.y < yy+14) )
|
|
{
|
|
if ( sel0 != i ) MenuSound("menu/demoscroll");
|
|
sel0 = i;
|
|
ofs0 = (sel0/22)*22;
|
|
// try to use it if it has any special behaviour
|
|
MenuEvent(MKEY_ENTER,false);
|
|
return res;
|
|
}
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+24;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
// check that scrollbar is present
|
|
if ( invlist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
str = invlist[i].GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
drag = 1;
|
|
}
|
|
else if ( tabs[curtab] == TAB_STORE )
|
|
{
|
|
if ( isrclick )
|
|
{
|
|
MenuEvent(MKEY_CLEAR,false);
|
|
return res;
|
|
}
|
|
// check what item we clicked
|
|
if ( mpos.y < 377 )
|
|
{
|
|
if ( storelist.Size() <= 0 ) return res; // clicked nothing
|
|
xx = 9;
|
|
yy = 23;
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<storelist.Size(); i++ )
|
|
{
|
|
if ( !storelist[i] ) continue;
|
|
let def = GetDefaultByType(storelist[i]);
|
|
if ( sub )
|
|
{
|
|
int amt = (storelist[i] is 'CandyGun')?(players[consoleplayer].mo.CountInv("CandyGunSpares")+1):players[consoleplayer].mo.CountInv(storelist[i]);
|
|
if ( (amt > 1) || (storelist[i] is 'Ammo') ) str = String.Format("(%d/%d) %s",storeunits[i],amt,def.GetTag());
|
|
else str = def.GetTag();
|
|
}
|
|
else if ( storeunits[i] > 1 ) str = String.Format("%dx %s",storeunits[i],def.GetTag());
|
|
else str = def.GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+96);
|
|
totalcol = int(ceil(storelist.Size()/22.));
|
|
// gotta check both the tag and the price for clicking
|
|
int ofs = int(max(0,(ofs0/22)-(maxcol-1))*22);
|
|
int cols = 1;
|
|
for ( int i=ofs; i<storelist.Size(); i++ )
|
|
{
|
|
if ( !storelist[i] ) continue;
|
|
// check boundary
|
|
if ( (mpos.x >= xx) && (mpos.x < xx+longest+80) && (mpos.y >= yy) && (mpos.y < yy+14) )
|
|
{
|
|
if ( sel0 != i ) MenuSound("menu/demoscroll");
|
|
sel0 = i;
|
|
ofs0 = (sel0/22)*22;
|
|
MenuEvent(MKEY_ENTER,false);
|
|
return res;
|
|
}
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+96;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
// check that scrollbar is present
|
|
if ( storelist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
xx = 9;
|
|
yy = 23;
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<storelist.Size(); i++ )
|
|
{
|
|
if ( !storelist[i] ) continue;
|
|
let def = GetDefaultByType(storelist[i]);
|
|
if ( storeunits[i] > 1 ) str = String.Format("%dx %s",storeunits[i],def.GetTag());
|
|
else str = def.GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+96);
|
|
totalcol = int(ceil(storelist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
drag = 1;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_LIBRARY) && !isrclick )
|
|
{
|
|
double midp = (language~=="jp")?206:126;
|
|
if ( mpos.x < midp )
|
|
{
|
|
if ( mpos.y < 28 )
|
|
{
|
|
// switch category
|
|
if ( mpos.x < midp/2. ) MenuEvent(MKEY_LEFT,false);
|
|
else MenuEvent(MKEY_RIGHT,false);
|
|
}
|
|
else
|
|
{
|
|
// check what item we clicked
|
|
int xx = 3;
|
|
int yy = 32;
|
|
int ofs = max(0,ofs0-26);
|
|
for ( int i=ofs; i<lorelist.Size(); i++ )
|
|
{
|
|
if ( yy > 370 ) break;
|
|
// check boundary
|
|
if ( (mpos.y >= yy) && (mpos.y < yy+14) )
|
|
{
|
|
if ( sel0 != i ) MenuSound("menu/demoscroll");
|
|
if ( (sel0 != i) || !sub )
|
|
{
|
|
sel0 = i;
|
|
sub = false;
|
|
MenuEvent(MKEY_Enter,false);
|
|
}
|
|
return res;
|
|
}
|
|
yy += 13;
|
|
}
|
|
}
|
|
}
|
|
else if ( mpos.x < midp+8 )
|
|
{
|
|
// check that scrollbar is present
|
|
if ( lorelist.Size() <= 27 ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = lorelist.Size()-27;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step ) step += 26;
|
|
if ( step != ofs0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = step;
|
|
drag = 1;
|
|
}
|
|
else if ( sub && (mpos.x >= 632) )
|
|
{
|
|
// check that scrollbar is present
|
|
str = StringTable.Localize(lorelist[sel0].text);
|
|
int ofs = (language~=="jp")?212:132;
|
|
if ( lorelist.Size() > 26 ) ofs += 8;
|
|
BrokenLines l = fnt.BreakLines(str,635-ofs);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,626-ofs);
|
|
else return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = l.Count()-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel2 ) MenuSound("menu/demoscroll");
|
|
ofs2 = sel2 = step;
|
|
drag = 3;
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_TRADING )
|
|
{
|
|
if ( isrclick )
|
|
{
|
|
MenuEvent(MKEY_CLEAR,false);
|
|
return res;
|
|
}
|
|
if ( !sub )
|
|
{
|
|
// check what item we clicked
|
|
if ( mpos.y < 377 )
|
|
{
|
|
if ( playerlist.Size() <= 0 ) return res; // clicked nothing
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<playerlist.Size(); i++ )
|
|
{
|
|
str = players[playerlist[i]].GetUserName();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(playerlist.Size()/22.));
|
|
int ofs = int(max(0,(ofs0/22)-(maxcol-1))*22);
|
|
xx = 9;
|
|
yy = 23;
|
|
int cols = 1;
|
|
for ( int i=ofs; i<playerlist.Size(); i++ )
|
|
{
|
|
str = players[playerlist[i]].GetUserName();
|
|
len = fnt.StringWidth(str);
|
|
// check text boundary
|
|
if ( (mpos.x >= xx) && (mpos.x < xx+len+1) && (mpos.y >= yy) && (mpos.y < yy+14) )
|
|
{
|
|
if ( sel0 != i ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = i;
|
|
MenuEvent(MKEY_Enter,false);
|
|
return res;
|
|
}
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+24;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
// check that scrollbar is present (will it ever be???)
|
|
if ( playerlist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<playerlist.Size(); i++ )
|
|
{
|
|
str = players[playerlist[i]].GetUserName();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(playerlist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
drag = 1;
|
|
}
|
|
else if ( sel0 == -1 )
|
|
{
|
|
// are we clicking where the scrollbar should be?
|
|
if ( mpos.x < 632 ) return res;
|
|
if ( tradelib.ent.Size() <= 28 ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = tradelib.ent.Size()-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
drag = 1;
|
|
}
|
|
}
|
|
else if ( (tabs[curtab] == TAB_CHAT) && !isrclick )
|
|
{
|
|
// are we clicking where the scrollbar should be?
|
|
if ( mpos.x < 632 ) return res;
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( !bar || (bar.FullHistory.Size() <= 1) ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = bar.FullHistory.Size()-1;
|
|
int step = szr-clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
drag = 1;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_HELP) && !isrclick )
|
|
{
|
|
// are we clicking where the scrollbar should be?
|
|
if ( mpos.x < 632 ) return res;
|
|
String kstr;
|
|
if ( mkey[1] != "" ) kstr = mkey[0].."/"..mkey[1];
|
|
else kstr = mkey[0];
|
|
str = String.Format(StringTable.Localize("$SWWM_HELPTXT"),kstr);
|
|
for ( int i=0; i<MAXPLAYERS; i++ )
|
|
{
|
|
if ( !playeringame[i] || (i == consoleplayer) ) continue;
|
|
if ( deathmatch && (!teamplay || (players[i].GetTeam() != players[consoleplayer].GetTeam())) ) continue;
|
|
str = str..StringTable.Localize("$SWWM_HELPTXT_TRADING");
|
|
break;
|
|
}
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( bar && (bar.FullHistory.Size() > 0) )
|
|
str = str..StringTable.Localize("$SWWM_HELPTXT_CHAT");
|
|
BrokenLines l = fnt.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,620);
|
|
else return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = l.Count()-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
drag = 1;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STATS) && !isrclick )
|
|
{
|
|
double midp = (language~=="jp")?206:126;
|
|
if ( mpos.x < midp )
|
|
{
|
|
// check what item we clicked
|
|
int xx = 9;
|
|
int yy = 23;
|
|
for ( int i=0; i<=STAT_ACHIEVEMENT; i++ )
|
|
{
|
|
// check boundary
|
|
if ( (mpos.y >= yy) && (mpos.y < yy+14) )
|
|
{
|
|
if ( sel1 != i )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = 0;
|
|
sel1 = i;
|
|
CVar.FindCVar('swwm_laststattab').SetInt(sel1);
|
|
}
|
|
return res;
|
|
}
|
|
yy += 16;
|
|
}
|
|
return res;
|
|
}
|
|
// are we clicking where the scrollbar should be?
|
|
if ( mpos.x < 632 ) return res;
|
|
int cnt = 0;
|
|
if ( sel1 == STAT_MAIN ) cnt = statlist.Size();
|
|
else if ( sel1 == STAT_KILLS ) cnt = stats.mstats.Size();
|
|
else if ( sel1 == STAT_LEVEL ) cnt = stats.lstats.Size();
|
|
if ( cnt <= 28 ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = cnt-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
drag = 1;
|
|
}
|
|
}
|
|
else if ( (type == MOUSE_Move) && drag ) // scroll dragging
|
|
{
|
|
if ( tabs[curtab] == TAB_MISSION )
|
|
{
|
|
String str;
|
|
if ( sel1 == 0 ) str = StringTable.Localize(missionstr);
|
|
else str = StringTable.Localize(missionbacklog[sel1-1]);
|
|
BrokenLines l = fnt.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,620);
|
|
else return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = l.Count()-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
}
|
|
else if ( (tabs[curtab] == TAB_INVENTORY) || ((tabs[curtab] == TAB_TRADING) && sub && (sel0 != -1)) )
|
|
{
|
|
// check that scrollbar is present
|
|
if ( invlist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
|
|
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
|
|
else str = invlist[i].GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
}
|
|
else if ( tabs[curtab] == TAB_KEYS )
|
|
{
|
|
// check that scrollbar is present
|
|
if ( invlist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
str = invlist[i].GetTag();
|
|
if ( invlist[i] is 'SWWMCollectible' )
|
|
str.AppendFormat(" (¥%d)",invlist[i].default.Stamina);
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
}
|
|
else if ( tabs[curtab] == TAB_STORE )
|
|
{
|
|
// check that scrollbar is present
|
|
if ( storelist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
xx = 9;
|
|
yy = 23;
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<storelist.Size(); i++ )
|
|
{
|
|
if ( !storelist[i] ) continue;
|
|
let def = GetDefaultByType(storelist[i]);
|
|
if ( sub )
|
|
{
|
|
int amt = (storelist[i] is 'CandyGun')?(players[consoleplayer].mo.CountInv("CandyGunSpares")+1):players[consoleplayer].mo.CountInv(storelist[i]);
|
|
if ( (amt > 1) || (storelist[i] is 'Ammo') ) str = String.Format("(%d/%d) %s",storeunits[i],amt,def.GetTag());
|
|
else str = def.GetTag();
|
|
}
|
|
else if ( storeunits[i] > 1 ) str = String.Format("%dx %s",storeunits[i],def.GetTag());
|
|
else str = def.GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+96);
|
|
totalcol = int(ceil(storelist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
}
|
|
else if ( tabs[curtab] == TAB_LIBRARY )
|
|
{
|
|
if ( drag == 1 )
|
|
{
|
|
// check that scrollbar is present
|
|
if ( lorelist.Size() <= 27 ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = lorelist.Size()-27;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step ) step += 26;
|
|
if ( step != ofs0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = step;
|
|
}
|
|
else if ( drag == 3 )
|
|
{
|
|
// check that scrollbar is present
|
|
str = StringTable.Localize(lorelist[sel0].text);
|
|
int ofs = (language~=="jp")?212:132;
|
|
if ( lorelist.Size() > 26 ) ofs += 8;
|
|
BrokenLines l = fnt.BreakLines(str,635-ofs);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,626-ofs);
|
|
else return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = l.Count()-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel2 ) MenuSound("menu/demoscroll");
|
|
ofs2 = sel2 = step;
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_TRADING )
|
|
{
|
|
if ( !sub )
|
|
{
|
|
// check that scrollbar is present (will it ever be???)
|
|
if ( playerlist.Size() <= 0 ) return res; // definitely no scrollbar
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<playerlist.Size(); i++ )
|
|
{
|
|
str = players[playerlist[i]].GetUserName();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
if ( maxcol >= totalcol ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = totalcol-maxcol;
|
|
int step = clamp(rnd((mpos.x-5.)/(630./szr)),0,szr);
|
|
if ( step > 0 ) step += (maxcol-1);
|
|
if ( step != (ofs0/22) ) MenuSound("menu/demoscroll");
|
|
ofs0 = step*22;
|
|
}
|
|
else if ( sel0 == -1 )
|
|
{
|
|
if ( tradelib.ent.Size() <= 28 ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = tradelib.ent.Size()-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_CHAT )
|
|
{
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( !bar || (bar.FullHistory.Size() <= 1) ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = bar.FullHistory.Size()-1;
|
|
int step = szr-clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
}
|
|
else if ( tabs[curtab] == TAB_HELP )
|
|
{
|
|
int k1, k2;
|
|
[k1, k2] = bindings.GetKeysForCommand("openmenu SWWMKnowledgeBaseMenu");
|
|
String kstr = bindings.NameKeys(k1,k2);
|
|
str = String.Format(StringTable.Localize("$SWWM_HELPTXT"),kstr);
|
|
for ( int i=0; i<MAXPLAYERS; i++ )
|
|
{
|
|
if ( !playeringame[i] || (i == consoleplayer) ) continue;
|
|
if ( deathmatch && (!teamplay || (players[i].GetTeam() != players[consoleplayer].GetTeam())) ) continue;
|
|
str = str..StringTable.Localize("$SWWM_HELPTXT_TRADING");
|
|
break;
|
|
}
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( bar && (bar.FullHistory.Size() > 0) )
|
|
str = str..StringTable.Localize("$SWWM_HELPTXT_CHAT");
|
|
BrokenLines l = fnt.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,620);
|
|
else return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = l.Count()-28;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
}
|
|
else if ( tabs[curtab] == TAB_STATS )
|
|
{
|
|
int cnt = 0;
|
|
if ( sel1 == STAT_MAIN ) cnt = statlist.Size();
|
|
else if ( sel1 == STAT_KILLS ) cnt = stats.mstats.Size();
|
|
else if ( sel1 == STAT_LEVEL ) cnt = stats.lstats.Size();
|
|
if ( cnt <= 22 ) return res; // no scrollbar
|
|
// calculate offset
|
|
int szr = cnt-22;
|
|
int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr);
|
|
if ( step != sel0 ) MenuSound("menu/demoscroll");
|
|
ofs0 = sel0 = step;
|
|
}
|
|
}
|
|
else if ( type == MOUSE_Release ) drag = 0; // stop dragging any active scrolls
|
|
return res;
|
|
}
|
|
|
|
private bool CmpInventory( Inventory a, Inventory b )
|
|
{
|
|
int ta = 0, tb = 0;
|
|
if ( a is 'Weapon' ) ta = 2;
|
|
else if ( (a is 'BackpackItem') || (a is 'HammerspaceEmbiggener') ) ta = 3;
|
|
else if ( a is 'Ammo' ) ta = 4;
|
|
else if ( a is 'MagAmmo' ) ta = 5;
|
|
else if ( (a is 'PowerupGiver') || (a is 'AmmoFabricator') || a.bBIGPOWERUP ) ta = -3;
|
|
else if ( (a is 'Health') || (a is 'HealthPickup') || (a is 'SWWMHealth') ) ta = -2;
|
|
else if ( (a is 'Armor') || (a is 'SWWMSpareArmor') ) ta = -1;
|
|
else if ( a is 'PuzzleItem' ) ta = 1;
|
|
if ( b is 'Weapon' ) tb = 2;
|
|
else if ( (b is 'BackpackItem') || (b is 'HammerspaceEmbiggener') ) tb = 3;
|
|
else if ( b is 'Ammo' ) tb = 4;
|
|
else if ( b is 'MagAmmo' ) tb = 5;
|
|
else if ( (b is 'PowerupGiver') || (b is 'AmmoFabricator') || b.bBIGPOWERUP ) tb = -3;
|
|
else if ( (b is 'Health') || (b is 'HealthPickup') || (b is 'SWWMHealth') ) tb = -2;
|
|
else if ( (b is 'Armor') || (b is 'SWWMSpareArmor') ) tb = -1;
|
|
else if ( b is 'PuzzleItem' ) tb = 1;
|
|
if ( ta == tb )
|
|
{
|
|
if ( a is 'Weapon' )
|
|
{
|
|
bool dummy;
|
|
int slota, slotb;
|
|
[dummy, slota] = players[consoleplayer].weapons.LocateWeapon(Weapon(a).GetClass());
|
|
if ( slota == 0 ) slota = 10;
|
|
[dummy, slotb] = players[consoleplayer].weapons.LocateWeapon(Weapon(b).GetClass());
|
|
if ( slotb == 0 ) slotb = 10;
|
|
if ( slota == slotb )
|
|
return (Weapon(a).SlotPriority <= Weapon(b).SlotPriority);
|
|
return slota > slotb;
|
|
}
|
|
else if ( a is 'Ammo' )
|
|
{
|
|
Class<Weapon> usesa, usesb;
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let w = (Class<Weapon>)(AllActorClasses[i]);
|
|
if ( !w ) continue;
|
|
let def = GetDefaultByType(w);
|
|
if ( w is 'SWWMWeapon' )
|
|
{
|
|
if ( SWWMWeapon(def).UsesAmmo(Ammo(a).GetClass()) )
|
|
usesa = w;
|
|
if ( SWWMWeapon(def).UsesAmmo(Ammo(b).GetClass()) )
|
|
usesb = w;
|
|
}
|
|
else
|
|
{
|
|
if ( (def.AmmoType1 == Ammo(a).GetClass()) || (def.AmmoType2 == Ammo(a).GetClass()) )
|
|
usesa = w;
|
|
if ( (def.AmmoType1 == Ammo(b).GetClass()) || (def.AmmoType2 == Ammo(b).GetClass()) )
|
|
usesb = w;
|
|
}
|
|
if ( usesa && usesb )
|
|
break;
|
|
}
|
|
if ( usesa && usesb )
|
|
{
|
|
bool dummy;
|
|
int slota, slotb;
|
|
[dummy, slota] = players[consoleplayer].weapons.LocateWeapon(usesa);
|
|
if ( slota == 0 ) slota = 10;
|
|
[dummy, slotb] = players[consoleplayer].weapons.LocateWeapon(usesb);
|
|
if ( slotb == 0 ) slotb = 10;
|
|
if ( slota == slotb )
|
|
{
|
|
// sort by unit value
|
|
int vala = abs(a.default.Stamina);
|
|
int valb = abs(b.default.Stamina);
|
|
if ( vala == valb )
|
|
{
|
|
// sort alphabetically
|
|
return a.GetTag() > b.GetTag();
|
|
}
|
|
return vala > valb;
|
|
}
|
|
return slota > slotb;
|
|
}
|
|
}
|
|
else if ( a is 'MagAmmo' )
|
|
{
|
|
// oh boy this one gets complicated
|
|
Class<Ammo> pamoa, pamob;
|
|
pamoa = MagAmmo(a).ParentAmmo;
|
|
pamob = MagAmmo(b).ParentAmmo;
|
|
Class<Weapon> usesa, usesb;
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let w = (Class<Weapon>)(AllActorClasses[i]);
|
|
if ( !w ) continue;
|
|
let def = GetDefaultByType(w);
|
|
if ( w is 'SWWMWeapon' )
|
|
{
|
|
if ( SWWMWeapon(def).UsesAmmo(pamoa) )
|
|
usesa = w;
|
|
if ( SWWMWeapon(def).UsesAmmo(pamob) )
|
|
usesb = w;
|
|
}
|
|
else
|
|
{
|
|
if ( (def.AmmoType1 == pamoa) || (def.AmmoType2 == pamoa) )
|
|
usesa = w;
|
|
if ( (def.AmmoType1 == pamob) || (def.AmmoType2 == pamob) )
|
|
usesb = w;
|
|
}
|
|
if ( usesa && usesb )
|
|
break;
|
|
}
|
|
if ( usesa && usesb )
|
|
{
|
|
bool dummy;
|
|
int slota, slotb;
|
|
[dummy, slota] = players[consoleplayer].weapons.LocateWeapon(usesa);
|
|
if ( slota == 0 ) slota = 10;
|
|
[dummy, slotb] = players[consoleplayer].weapons.LocateWeapon(usesb);
|
|
if ( slotb == 0 ) slotb = 10;
|
|
if ( slota == slotb )
|
|
{
|
|
// sort by unit value
|
|
int vala = GetDefaultByType(pamoa).Stamina;
|
|
int valb = GetDefaultByType(pamob).Stamina;
|
|
if ( vala == valb )
|
|
{
|
|
// sort alphabetically
|
|
return a.GetTag() > b.GetTag();
|
|
}
|
|
return vala > valb;
|
|
}
|
|
return slota > slotb;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// sort by unit value
|
|
int vala = abs(a.default.Stamina);
|
|
int valb = abs(b.default.Stamina);
|
|
if ( vala == valb )
|
|
{
|
|
// sort alphabetically
|
|
return a.GetTag() > b.GetTag();
|
|
}
|
|
return vala > valb;
|
|
}
|
|
}
|
|
return ta > tb;
|
|
}
|
|
|
|
private bool CmpInventoryClass( Class<Inventory> a, Class<Inventory> b )
|
|
{
|
|
int ta = 0, tb = 0;
|
|
let da = GetDefaultByType(a);
|
|
let db = GetDefaultByType(b);
|
|
if ( a is 'Weapon' ) ta = 4;
|
|
else if ( a is 'HammerspaceEmbiggener' ) ta = 3;
|
|
else if ( a is 'Ammo' ) ta = 2;
|
|
else if ( a is 'MagAmmo' ) ta = 1;
|
|
else if ( (a is 'PowerupGiver') || (a is 'AmmoFabricator') || da.bBIGPOWERUP ) ta = 5;
|
|
else if ( (a is 'Health') || (a is 'HealthPickup') || (a is 'SWWMHealth') ) ta = 7;
|
|
else if ( (a is 'Armor') || (a is 'SWWMSpareArmor') ) ta = 6;
|
|
if ( b is 'Weapon' ) tb = 4;
|
|
else if ( b is 'HammerspaceEmbiggener' ) tb = 3;
|
|
else if ( b is 'Ammo' ) tb = 2;
|
|
else if ( b is 'MagAmmo' ) ta = 1;
|
|
else if ( (b is 'PowerupGiver') || (b is 'AmmoFabricator') || db.bBIGPOWERUP ) tb = 5;
|
|
else if ( (b is 'Health') || (b is 'HealthPickup') || (b is 'SWWMHealth') ) tb = 7;
|
|
else if ( (b is 'Armor') || (b is 'SWWMSpareArmor') ) tb = 6;
|
|
if ( ta == tb )
|
|
{
|
|
// sort by unit price
|
|
if ( abs(da.Stamina) == abs(db.Stamina) )
|
|
{
|
|
// sort alphabetically
|
|
return da.GetTag() > db.GetTag();
|
|
}
|
|
return abs(da.Stamina) > abs(db.Stamina);
|
|
}
|
|
return ta < tb;
|
|
}
|
|
|
|
private int partition_inventory( Array<Inventory> a, int l, int h )
|
|
{
|
|
Inventory pv = a[h];
|
|
int i = (l-1);
|
|
for ( int j=l; j<=(h-1); j++ )
|
|
{
|
|
if ( CmpInventory(pv,a[j]) )
|
|
{
|
|
i++;
|
|
Inventory tmp = a[j];
|
|
a[j] = a[i];
|
|
a[i] = tmp;
|
|
}
|
|
}
|
|
Inventory tmp = a[h];
|
|
a[h] = a[i+1];
|
|
a[i+1] = tmp;
|
|
return i+1;
|
|
}
|
|
private void qsort_inventory( Array<Inventory> a, int l, int h )
|
|
{
|
|
if ( l >= h ) return;
|
|
int p = partition_inventory(a,l,h);
|
|
qsort_inventory(a,l,p-1);
|
|
qsort_inventory(a,p+1,h);
|
|
}
|
|
|
|
private int partition_store( Array<Class<Inventory> > a, Array<int> b, int l, int h )
|
|
{
|
|
Class<Inventory> pv = a[h];
|
|
int i = (l-1);
|
|
for ( int j=l; j<=(h-1); j++ )
|
|
{
|
|
if ( CmpInventoryClass(pv,a[j]) )
|
|
{
|
|
i++;
|
|
Class<Inventory> tmp = a[j];
|
|
a[j] = a[i];
|
|
a[i] = tmp;
|
|
int tmpi = b[j];
|
|
b[j] = b[i];
|
|
b[i] = tmpi;
|
|
}
|
|
}
|
|
Class<Inventory> tmp = a[h];
|
|
a[h] = a[i+1];
|
|
a[i+1] = tmp;
|
|
int tmpi = b[h];
|
|
b[h] = b[i+1];
|
|
b[i+1] = tmpi;
|
|
return i+1;
|
|
}
|
|
private void qsort_store( Array<Class<Inventory> > a, Array<int> b, int l, int h )
|
|
{
|
|
if ( l >= h ) return;
|
|
int p = partition_store(a,b,l,h);
|
|
qsort_store(a,b,l,p-1);
|
|
qsort_store(a,b,p+1,h);
|
|
}
|
|
|
|
private bool CmpMonsterKill( MonsterKill a, MonsterKill b )
|
|
{
|
|
if ( a.kills == b.kills )
|
|
{
|
|
// sort by name instead
|
|
String taga, tagb;
|
|
taga = GetDefaultByType(a.m).GetTag();
|
|
tagb = GetDefaultByType(b.m).GetTag();
|
|
// beautify if there's no tag
|
|
if ( taga == FallbackTag )
|
|
{
|
|
taga = a.m.GetClassName();
|
|
SWWMUtility.BeautifyClassName(taga);
|
|
}
|
|
if ( tagb == FallbackTag )
|
|
{
|
|
tagb = a.m.GetClassName();
|
|
SWWMUtility.BeautifyClassName(tagb);
|
|
}
|
|
return taga > tagb;
|
|
}
|
|
return a.kills < b.kills;
|
|
}
|
|
|
|
private int partition_mstats( Array<MonsterKill> a, int l, int h )
|
|
{
|
|
MonsterKill pv = a[h];
|
|
int i = (l-1);
|
|
for ( int j=l; j<=(h-1); j++ )
|
|
{
|
|
if ( CmpMonsterKill(pv,a[j]) )
|
|
{
|
|
i++;
|
|
MonsterKill tmp = a[j];
|
|
a[j] = a[i];
|
|
a[i] = tmp;
|
|
}
|
|
}
|
|
MonsterKill tmp = a[h];
|
|
a[h] = a[i+1];
|
|
a[i+1] = tmp;
|
|
return i+1;
|
|
}
|
|
private void qsort_mstats( Array<MonsterKill> a, int l, int h )
|
|
{
|
|
if ( l >= h ) return;
|
|
int p = partition_mstats(a,l,h);
|
|
qsort_mstats(a,l,p-1);
|
|
qsort_mstats(a,p+1,h);
|
|
}
|
|
|
|
private int partition_lore( Array<SWWMLore> a, int l, int h )
|
|
{
|
|
SWWMLore pv = a[h];
|
|
int i = (l-1);
|
|
for ( int j=l; j<=(h-1); j++ )
|
|
{
|
|
if ( StringTable.Localize(pv.tag) > StringTable.Localize(a[j].tag) )
|
|
{
|
|
i++;
|
|
SWWMLore tmp = a[j];
|
|
a[j] = a[i];
|
|
a[i] = tmp;
|
|
}
|
|
}
|
|
SWWMLore tmp = a[h];
|
|
a[h] = a[i+1];
|
|
a[i+1] = tmp;
|
|
return i+1;
|
|
}
|
|
private void qsort_lore( Array<SWWMLore> a, int l, int h )
|
|
{
|
|
if ( l >= h ) return;
|
|
int p = partition_lore(a,l,h);
|
|
qsort_lore(a,l,p-1);
|
|
qsort_lore(a,p+1,h);
|
|
}
|
|
|
|
private bool CmpCollectible( Inventory a, Inventory b )
|
|
{
|
|
if ( a.Stamina == b.Stamina )
|
|
{
|
|
// alphabetic
|
|
return a.GetTag() > b.GetTag();
|
|
}
|
|
// descending value
|
|
return a.default.Stamina < b.default.Stamina;
|
|
}
|
|
|
|
private int partition_collectible( Array<Inventory> a, int l, int h )
|
|
{
|
|
Inventory pv = a[h];
|
|
int i = (l-1);
|
|
for ( int j=l; j<=(h-1); j++ )
|
|
{
|
|
if ( CmpCollectible(pv,a[j]) )
|
|
{
|
|
i++;
|
|
Inventory tmp = a[j];
|
|
a[j] = a[i];
|
|
a[i] = tmp;
|
|
}
|
|
}
|
|
Inventory tmp = a[h];
|
|
a[h] = a[i+1];
|
|
a[i+1] = tmp;
|
|
return i+1;
|
|
}
|
|
private void qsort_collectible( Array<Inventory> a, int l, int h )
|
|
{
|
|
if ( l >= h ) return;
|
|
int p = partition_collectible(a,l,h);
|
|
qsort_collectible(a,l,p-1);
|
|
qsort_collectible(a,p+1,h);
|
|
}
|
|
|
|
override void Ticker()
|
|
{
|
|
Super.Ticker();
|
|
if ( (players[consoleplayer].Health <= 0) || isclosing )
|
|
{
|
|
// ded (or force close)
|
|
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
|
|
Close();
|
|
return;
|
|
}
|
|
if ( swwm_menupause ) menuactive = Menu.On;
|
|
else menuactive = Menu.OnNoPause;
|
|
// forcibly tick hud (mainly so interpolators can still update in the background)
|
|
if ( !multiplayer && (menuactive == Menu.On) )
|
|
StatusBar.Tick();
|
|
if ( tabs[curtab] == TAB_INVENTORY )
|
|
{
|
|
invlist.Clear();
|
|
// alphabetically sorted inventory
|
|
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.Inv )
|
|
{
|
|
if ( (inv.Amount <= 0) || !inv.SpawnState.ValidateSpriteFrame() || (inv is 'Key') || (inv is 'BasicArmor') || (inv is 'HexenArmor') || (inv is 'Powerup') || (inv is 'SWWMArmor') || (!(inv is 'Ammo') && !(inv is 'Weapon') && !inv.bINVBAR) && !(inv is 'HammerspaceEmbiggener') && !(inv is 'SWWMCollectible') && !(inv is 'MagAmmo') || (inv is 'SWWMCollectible') ) continue;
|
|
// no hidden weapons
|
|
if ( (inv is 'SWWMWeapon') && SWWMWeapon(inv).bHIDEINMENU ) continue;
|
|
String tag = inv.GetTag();
|
|
bool greater = false;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
String tag2 = invlist[i].GetTag();
|
|
if ( tag > tag2 ) continue;
|
|
greater = true;
|
|
invlist.Insert(i,inv);
|
|
break;
|
|
}
|
|
if ( greater ) continue;
|
|
invlist.Push(inv);
|
|
}
|
|
// re-sort by category
|
|
qsort_inventory(invlist,0,invlist.Size()-1);
|
|
// crop selection
|
|
if ( sel0 >= invlist.Size() ) sel0 = max(0,invlist.Size()-1);
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STATS) && (sel1 == STAT_KILLS) )
|
|
{
|
|
sorted_mstats.Copy(stats.mstats);
|
|
qsort_mstats(sorted_mstats,0,sorted_mstats.Size()-1);
|
|
}
|
|
else if ( tabs[curtab] == TAB_KEYS )
|
|
{
|
|
invlist.Clear();
|
|
// keys sorted by their index
|
|
int n = Key.GetKeyTypeCount();
|
|
for ( int i=0; i<n; i++ )
|
|
{
|
|
let k = Key(players[consoleplayer].mo.FindInventory(Key.GetKeyType(i)));
|
|
if ( !k ) continue;
|
|
invlist.Push(k);
|
|
}
|
|
// because we can't call GetReplacement from ui, let's wrangle something real ugly here to clean up replaced keys
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !(invlist[i] is 'SWWMKey') ) continue;
|
|
// remove the key this replaces
|
|
Class<Key> pc = invlist[i].Species;
|
|
if ( !pc ) continue;
|
|
for ( int j=0; j<invlist.Size(); j++ )
|
|
{
|
|
if ( invlist[j].GetClass() != pc ) continue;
|
|
invlist.Delete(j);
|
|
j--;
|
|
if ( i >= j ) i--;
|
|
}
|
|
}
|
|
// collectibles, sorted by name
|
|
Array<Inventory> cols;
|
|
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.Inv )
|
|
{
|
|
if ( inv is 'SWWMCollectible' )
|
|
cols.Push(inv);
|
|
}
|
|
qsort_collectible(cols,0,cols.Size()-1);
|
|
invlist.Append(cols);
|
|
// crop selection
|
|
if ( sel0 >= invlist.Size() ) sel0 = max(0,invlist.Size()-1);
|
|
}
|
|
else if ( tabs[curtab] == TAB_STORE )
|
|
{
|
|
Class<Inventory> lastsel = null;
|
|
if ( storelist.Size() > 0 ) lastsel = storelist[sel0];
|
|
storelist.Clear();
|
|
storeunits.Clear();
|
|
// price-sorted buyables/sellables
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let type = (Class<Inventory>)(AllActorClasses[i]);
|
|
if ( !type ) continue;
|
|
// no collectibles
|
|
if ( type is 'SWWMCollectible' ) continue;
|
|
// no Ynykron in strife (unless selling)
|
|
if ( (gameinfo.gametype&GAME_Strife) && (type is 'Ynykron') && !sub ) continue;
|
|
// can't sell candygun spares
|
|
if ( sub && (type is 'CandyGunSpares') ) continue;
|
|
let cur = players[consoleplayer].mo.FindInventory(type);
|
|
// skip items we don't own or are depleted if selling
|
|
if ( sub && (!cur || (cur.Amount <= 0)) ) continue;
|
|
else if ( !sub )
|
|
{
|
|
// skip maxed items if buying
|
|
if ( cur && (cur.Amount >= cur.MaxAmount) ) continue;
|
|
// ignore ammo for weapons not owned if buying
|
|
bool notownedammo = false;
|
|
if ( type is 'Ammo' )
|
|
{
|
|
notownedammo = true;
|
|
let amo = (Class<Ammo>)(type);
|
|
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.inv )
|
|
{
|
|
if ( !(inv is 'Weapon') ) continue;
|
|
if ( (Weapon(inv).AmmoType1 == amo) || (Weapon(inv).AmmoType2 == amo) )
|
|
{
|
|
notownedammo = false;
|
|
break;
|
|
}
|
|
if ( (inv is 'SWWMWeapon') && SWWMWeapon(inv).UsesAmmo(amo) )
|
|
{
|
|
notownedammo = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( notownedammo ) continue;
|
|
}
|
|
let inv = GetDefaultByType(type);
|
|
// skip unimplemented weapons
|
|
if ( type is 'Weapon' )
|
|
{
|
|
let ready = inv.FindState("Ready");
|
|
if ( !ready || !ready.ValidateSpriteFrame() ) continue;
|
|
}
|
|
// ignore child ammos
|
|
if ( (type is 'Ammo') && (type.GetParentClass() != 'Ammo') ) continue;
|
|
if ( inv.Stamina == 0 ) continue;
|
|
// items with negative stamina can only be sold
|
|
if ( (inv.Stamina < 0) && !sub ) continue;
|
|
int amt = inv.Amount;
|
|
int price = int(abs(inv.Stamina)*(1.+.75*(amt-1)));
|
|
if ( type is 'Ammo' )
|
|
{
|
|
int maxamt;
|
|
if ( sub ) maxamt = cur.Amount; // we can sell ALL our ammo
|
|
else maxamt = cur?(cur.MaxAmount-cur.Amount):inv.MaxAmount;
|
|
// get the largest affordable child pickup amount (that we need, or we can sell)
|
|
for ( int j=0; j<AllActorClasses.Size(); j++ )
|
|
{
|
|
let type2 = (Class<Ammo>)(AllActorClasses[j]);
|
|
if ( !type2 || (type2.GetParentClass() != type) ) continue;
|
|
let inv2 = GetDefaultByType(type2);
|
|
int cprice = int(abs(inv.Stamina)*(1.+.75*(inv2.Amount-1)));
|
|
if ( (inv2.Amount > amt) && (inv2.Amount <= maxamt) && (sub || SWWMCredits.CanTake(players[consoleplayer],cprice)) )
|
|
{
|
|
price = cprice;
|
|
amt = inv2.Amount;
|
|
}
|
|
}
|
|
}
|
|
// nuggets can be bought/sold in bulk
|
|
else if ( type is 'HealthNuggetItem' )
|
|
{
|
|
let inv2 = GetDefaultByType(SWWMHealth(inv).giveme);
|
|
int maxamt;
|
|
if ( sub ) maxamt = cur.Amount;
|
|
else
|
|
{
|
|
maxamt = (inv2.MaxAmount-players[consoleplayer].Health);
|
|
maxamt += cur?(cur.MaxAmount-cur.Amount):inv.MaxAmount;
|
|
}
|
|
for ( int j=5; j<=20; j+=5 )
|
|
{
|
|
int cprice = int(inv.Stamina*(1.+.75*(j-1)));
|
|
if ( (j <= maxamt) && (sub || SWWMCredits.CanTake(players[consoleplayer],cprice)) )
|
|
{
|
|
price = cprice;
|
|
amt = j;
|
|
}
|
|
}
|
|
}
|
|
else if ( type is 'ArmorNuggetItem' )
|
|
{
|
|
let inv2 = GetDefaultByType(SWWMSpareArmor(inv).giveme);
|
|
let cur2 = players[consoleplayer].mo.FindInventory(SWWMSpareArmor(inv).giveme);
|
|
int maxamt;
|
|
if ( sub ) maxamt = cur.Amount;
|
|
else
|
|
{
|
|
maxamt = cur2?(cur2.MaxAmount-cur2.Amount):inv2.MaxAmount;
|
|
maxamt += cur?(cur.MaxAmount-cur.Amount):inv.MaxAmount;
|
|
}
|
|
for ( int j=5; j<=20; j+=5 )
|
|
{
|
|
int cprice = int(inv.Stamina*(1.+.75*(j-1)));
|
|
if ( (j <= maxamt) && (sub || SWWMCredits.CanTake(players[consoleplayer],cprice)) )
|
|
{
|
|
price = cprice;
|
|
amt = j;
|
|
}
|
|
}
|
|
}
|
|
// sort by unit price
|
|
bool greater = false;
|
|
for ( int j=0; j<storelist.Size(); j++ )
|
|
{
|
|
let inv2 = GetDefaultByType(storelist[j]);
|
|
if ( abs(inv.Stamina) > abs(inv2.Stamina) ) continue;
|
|
greater = true;
|
|
storelist.Insert(j,type);
|
|
storeunits.Insert(j,amt);
|
|
break;
|
|
}
|
|
if ( greater ) continue;
|
|
storelist.Push(type);
|
|
storeunits.Push(amt);
|
|
}
|
|
// re-sort by category
|
|
qsort_store(storelist,storeunits,0,storelist.Size()-1);
|
|
// shift back if the last selected item was removed
|
|
if ( lastsel && (storelist.Find(lastsel)) >= storelist.Size() )
|
|
sel0 = max(0,sel0-1);
|
|
// crop selection
|
|
if ( sel0 >= storelist.Size() ) sel0 = max(0,storelist.Size()-1);
|
|
}
|
|
else if ( tabs[curtab] == TAB_LIBRARY )
|
|
{
|
|
// remember last position/size
|
|
SWWMLore oldone = null;
|
|
int oldsiz = lorelist.Size();
|
|
if ( lorelist.Size() > 0 ) oldone = lorelist[sel0];
|
|
// lore lore lore
|
|
lorelist.Clear();
|
|
for ( int i=0; i<lorelib.ent.Size(); i++ )
|
|
{
|
|
if ( lorelib.ent[i].tab != sel1 ) continue;
|
|
lorelist.Push(lorelib.ent[i]);
|
|
}
|
|
// sort
|
|
qsort_lore(lorelist,0,lorelist.Size()-1);
|
|
// readjust
|
|
if ( oldone && (lorelist.Size() != oldsiz) )
|
|
{
|
|
int idx = lorelist.Find(oldone);
|
|
if ( (idx > 0) && (idx < lorelist.Size()) )
|
|
sel0 = idx;
|
|
// update ofs so selection stays on-screen
|
|
int ofs = max(ofs0-26,0);
|
|
if ( sel0 < ofs ) ofs0 = sel0+26;
|
|
else if ( sel0 > ofs+26 ) ofs0 = sel0;
|
|
}
|
|
// add "new entries" message
|
|
if ( lorelib.ent.Size() != oldloresiz )
|
|
{
|
|
tmsg = StringTable.Localize("$SWWM_NEWLORE");
|
|
tmsgtic = gametic+70;
|
|
}
|
|
oldloresiz = lorelib.ent.Size();
|
|
}
|
|
else if ( tabs[curtab] == TAB_TRADING )
|
|
{
|
|
// build player list
|
|
playerlist.Clear();
|
|
for ( int i=0; i<MAXPLAYERS; i++ )
|
|
{
|
|
if ( !playeringame[i] || (i == consoleplayer) ) continue;
|
|
if ( deathmatch && (!teamplay || (players[i].GetTeam() != players[consoleplayer].GetTeam())) ) continue;
|
|
playerlist.Push(i);
|
|
}
|
|
// build inventory list if open
|
|
if ( sub && (sel0 != -1) )
|
|
{
|
|
invlist.Clear();
|
|
// alphabetically sorted inventory
|
|
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.Inv )
|
|
{
|
|
if ( (inv.Amount <= 0) || !inv.SpawnState.ValidateSpriteFrame() || (inv is 'Key') || (inv is 'BasicArmor') || (inv is 'HexenArmor') || (inv is 'Powerup') || (inv is 'SWWMArmor') || (!(inv is 'Ammo') && !(inv is 'Weapon') && !inv.bINVBAR) && !(inv is 'HammerspaceEmbiggener') && !(inv is 'SWWMCollectible') && !(inv is 'MagAmmo') ) continue;
|
|
// no hidden weapons
|
|
if ( (inv is 'SWWMWeapon') && SWWMWeapon(inv).bHIDEINMENU ) continue;
|
|
String tag = inv.GetTag();
|
|
bool greater = false;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
String tag2 = invlist[i].GetTag();
|
|
if ( tag > tag2 ) continue;
|
|
greater = true;
|
|
invlist.Insert(i,inv);
|
|
break;
|
|
}
|
|
if ( greater ) continue;
|
|
invlist.Push(inv);
|
|
}
|
|
// re-sort by category
|
|
qsort_inventory(invlist,0,invlist.Size()-1);
|
|
// crop selection
|
|
if ( sel1 >= invlist.Size() ) sel1 = max(0,invlist.Size()-1);
|
|
}
|
|
}
|
|
else if ( (tabs[curtab] == TAB_STATS) && (sel1 == STAT_MAIN) )
|
|
{
|
|
statlist.Clear();
|
|
// wish I could use macros for this
|
|
int thour = ((level.totaltime-stats.lastspawn)/(3600*GameTicRate));
|
|
int tmin = ((level.totaltime-stats.lastspawn)/(60*GameTicRate))%60;
|
|
int tsec = ((level.totaltime-stats.lastspawn)/GameTicRate)%60;
|
|
String str = String.Format("\cx%s\c-%02d\cu:\c-%02d\cu:\c-%02d",StringTable.Localize("$SWWM_STATUPTIME"),thour,tmin,tsec);
|
|
statlist.Push(str);
|
|
if ( stats.grounddist > 32000. ) str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATONFOOT"),stats.grounddist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
|
|
else str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATONFOOT"),stats.grounddist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
|
|
statlist.Push(str);
|
|
if ( stats.airdist > 32000. ) str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFLIGHT"),stats.airdist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
|
|
else str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFLIGHT"),stats.airdist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
|
|
statlist.Push(str);
|
|
if ( stats.swimdist > 32000. ) str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSWIM"),stats.swimdist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
|
|
else str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSWIM"),stats.swimdist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
|
|
statlist.Push(str);
|
|
if ( stats.teledist > 32000. ) str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATTELE"),stats.teledist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
|
|
else str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATTELE"),stats.teledist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATBOOST"),stats.boostcount);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDASH"),stats.dashcount);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATSTOMP"),stats.stompcount);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFUEL"),stats.fuelusage/60.,StringTable.Localize("$SWWM_UNIT_LITER"));
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSPEED"),stats.topspeed*32000./(3600*GameTicRate),StringTable.Localize("$SWWM_UNIT_KPH"));
|
|
statlist.Push(str);
|
|
thour = (stats.airtime/(3600*GameTicRate));
|
|
tmin = (stats.airtime/(60*GameTicRate))%60;
|
|
tsec = (stats.airtime/GameTicRate)%60;
|
|
str = String.Format("\cx%s\c-%02d\cu:\c-%02d\cu:\c-%02d",StringTable.Localize("$SWWM_STATAIRTIME"),thour,tmin,tsec);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATPARRY"),stats.parries);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATPPARRY"),stats.pparries);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATWPONCH"),stats.wponch);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATBUSTS"),stats.busts);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATBUTTS"),stats.buttslams);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATPATS"),stats.pats);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATKISS"),stats.smooch);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATFRIENDS"),stats.befriend);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATITEMS"),stats.items);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATSECRETS"),stats.secrets);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATKILLS"),stats.kills);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDEATHS"),stats.deaths);
|
|
statlist.Push(str);
|
|
if ( stats.hdamagedealt > 0 ) str = str = String.Format("\cx%s\c-%d%09d",StringTable.Localize("$SWWM_STATDDEALT"),stats.hdamagedealt,stats.damagedealt);
|
|
else str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDDEALT"),stats.damagedealt);
|
|
statlist.Push(str);
|
|
if ( stats.hdamagetaken > 0 ) str = String.Format("\cx%s\c-%d%09d",StringTable.Localize("$SWWM_STATDTAKEN"),stats.hdamagetaken,stats.damagetaken);
|
|
else str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDTAKEN"),stats.damagetaken);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATTDEALT"),stats.topdealt);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATTTAKEN"),stats.toptaken);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATMKILL"),stats.mkill);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATSKILL"),stats.skill);
|
|
statlist.Push(str);
|
|
str = String.Format("\cx%s\c-",StringTable.Localize("$SWWM_STATFAVWEAP"));
|
|
if ( stats.favweapon == -1 ) str = str.."N/A";
|
|
else if ( stats.wstats[stats.favweapon].w == 'SWWMWeapon' ) str = str..StringTable.Localize("$SWWM_YOURSELF");
|
|
else if ( stats.wstats[stats.favweapon].w == 'SWWMGesture' ) str = str..StringTable.Localize("$SWWM_DOKIDOKI");
|
|
else if ( stats.wstats[stats.favweapon].w == 'SWWMItemGesture' ) str = str..StringTable.Localize("$T_FROGGY");
|
|
else if ( stats.wstats[stats.favweapon].w == 'Weapon' ) str = str..StringTable.Localize("$SWWM_GRAVKILL");
|
|
else
|
|
{
|
|
let def = GetDefaultByType(stats.wstats[stats.favweapon].w);
|
|
str = str..def.GetTag();
|
|
}
|
|
statlist.Push(str);
|
|
if ( stats.hhiscore > 0 ) str = String.Format("\cx%s\cu¥\c-%d%09d",StringTable.Localize("$SWWM_STATHISCORE"),stats.hhiscore,stats.hiscore);
|
|
else str = String.Format("\cx%s\cu¥\c-%09d",StringTable.Localize("$SWWM_STATHISCORE"),stats.hiscore);
|
|
statlist.Push(str);
|
|
}
|
|
// ui->play transaction checks
|
|
for ( int i=0; i<checklist.Size(); i++ )
|
|
{
|
|
bool deleteme = false;
|
|
for ( int j=0; j<hnd.checklist.Size(); j++ )
|
|
{
|
|
if ( hnd.checklist[j].uid != checklist[i].uid ) continue;
|
|
if ( checklist[i].type == MenuTransaction.TT_ITEMUSE )
|
|
{
|
|
// check if use succeeded
|
|
if ( checklist[i].result || hnd.checklist[j].result )
|
|
{
|
|
// only play use sound if game isn't frozen
|
|
if ( !multiplayer && (menuactive == Menu.On) )
|
|
{
|
|
// if it's a weapon, play the select sound
|
|
// if it's a collectible or key, play the "hands up" sound
|
|
let w = (Class<Weapon>)(hnd.checklist[j].used);
|
|
if ( w )
|
|
{
|
|
// play if actually switching
|
|
if ( hnd.checklist[j].result )
|
|
{
|
|
String snd = GetDefaultByType(w).UpSound;
|
|
MenuSound(snd);
|
|
}
|
|
}
|
|
else if ( (hnd.checklist[j].used is 'SWWMCollectible') || (hnd.checklist[j].used is 'SWWMKey') )
|
|
MenuSound("demolitionist/handsup");
|
|
else
|
|
{
|
|
String snd = GetDefaultByType(hnd.checklist[j].used).UseSound;
|
|
MenuSound(snd);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tmsg = StringTable.Localize("$SWWM_INVFAIL");
|
|
tmsgtic = gametic+70;
|
|
MenuSound("menu/noinvuse");
|
|
}
|
|
}
|
|
else if ( checklist[i].type == MenuTransaction.TT_ITEMDROP )
|
|
{
|
|
// check if drop succeeded
|
|
if ( !hnd.checklist[j].result )
|
|
{
|
|
tmsg = StringTable.Localize("$SWWM_INVNDROP");
|
|
tmsgtic = gametic+70;
|
|
MenuSound("menu/noinvuse");
|
|
}
|
|
}
|
|
else if ( checklist[i].type == MenuTransaction.TT_ITEMSEND )
|
|
{
|
|
// check if trade succeeded
|
|
if ( !hnd.checklist[j].result )
|
|
{
|
|
tmsg = StringTable.Localize("$SWWM_TRADEFULL");
|
|
tmsgtic = gametic+70;
|
|
MenuSound("menu/noinvuse");
|
|
}
|
|
else MenuSound("menu/demosel");
|
|
}
|
|
EventHandler.SendNetworkEvent("swwmcleartransaction",checklist[i].uid,consoleplayer);
|
|
deleteme = true;
|
|
break;
|
|
}
|
|
if ( !deleteme ) continue;
|
|
checklist.Delete(i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
override bool OnUiEvent( UIEvent ev )
|
|
{
|
|
switch ( ev.type )
|
|
{
|
|
case UIEvent.Type_KeyDown:
|
|
if ( ev.keychar == UiEvent.Key_F1 )
|
|
{
|
|
if ( tabs[curtab] == TAB_HELP )
|
|
{
|
|
tabs.Delete(curtab);
|
|
curtab = oldtab;
|
|
}
|
|
else
|
|
{
|
|
if ( tabs[curtab] >= TAB_SECRET )
|
|
{
|
|
tabs.Delete(curtab);
|
|
curtab--;
|
|
}
|
|
oldtab = curtab;
|
|
tabs.Push(TAB_HELP);
|
|
curtab = tabs.Size()-1;
|
|
}
|
|
sel0 = sel1 = sel2 = 0;
|
|
ofs0 = ofs1 = ofs2 = 0;
|
|
sub = false;
|
|
invlist.Clear();
|
|
lorelist.Clear();
|
|
storelist.Clear();
|
|
storeunits.Clear();
|
|
MenuSound("menu/demotab");
|
|
return true;
|
|
}
|
|
switch ( kcode )
|
|
{
|
|
case 8:
|
|
if ( ev.keystring ~== "B" )
|
|
kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 9:
|
|
if ( ev.keystring ~== "A" ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
default:
|
|
kcode = 0;
|
|
break;
|
|
}
|
|
if( (ikey[0] && (ev.keystring == mkey[0])) || (ikey[1] && (ev.keystring == mkey[1])) )
|
|
{
|
|
MenuSound("menu/democlose");
|
|
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
|
|
Close();
|
|
return true;
|
|
}
|
|
break;
|
|
case UIEvent.Type_WheelDown:
|
|
if ( (tabs[curtab] == TAB_LIBRARY) && sub && (lorelist.Size() > 1) )
|
|
{
|
|
// special handling, need to check which side is being scrolled
|
|
double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/400.)),1.);
|
|
Vector2 ss = (Screen.GetWidth(),Screen.GetHeight())/hs;
|
|
Vector2 origin = (ss.x-640,ss.y-400)/2.;
|
|
Vector2 mpos = (curmouse/hs)-origin;
|
|
double midp = (language~=="jp")?206:126;
|
|
if ( ((lorelist.Size() > 27) && (mpos.x < midp+8)) || (mpos.x < midp) )
|
|
{
|
|
MenuSound("menu/democlose");
|
|
sub = false;
|
|
}
|
|
}
|
|
return MenuEvent(MKEY_DOWN,false);
|
|
break;
|
|
case UIEvent.Type_WheelUp:
|
|
if ( (tabs[curtab] == TAB_LIBRARY) && sub && (lorelist.Size() > 1) )
|
|
{
|
|
// special handling, need to check which side is being scrolled
|
|
double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/400.)),1.);
|
|
Vector2 ss = (Screen.GetWidth(),Screen.GetHeight())/hs;
|
|
Vector2 origin = (ss.x-640,ss.y-400)/2.;
|
|
Vector2 mpos = (curmouse/hs)-origin;
|
|
double midp = (language~=="jp")?206:126;
|
|
if ( ((lorelist.Size() > 27) && (mpos.x < midp+8)) || (mpos.x < midp) )
|
|
{
|
|
MenuSound("menu/democlose");
|
|
sub = false;
|
|
}
|
|
}
|
|
return MenuEvent(MKEY_UP,false);
|
|
break;
|
|
case UIEvent.Type_LButtonDown:
|
|
isrclick = false;
|
|
// copy over what base menus do for L click
|
|
// but ignore back button, since we don't use it
|
|
bool lres = MouseEvent(MOUSE_Click,ev.MouseX,ev.MouseY);
|
|
if ( lres ) SetCapture(true);
|
|
return lres;
|
|
break;
|
|
case UIEvent.Type_RButtonDown:
|
|
isrclick = true;
|
|
// same as L click
|
|
bool rres = MouseEvent(MOUSE_Click,ev.MouseX,ev.MouseY);
|
|
if ( rres ) SetCapture(true);
|
|
return rres;
|
|
break;
|
|
case UIEvent.Type_LButtonUp:
|
|
case UIEvent.Type_RButtonUp:
|
|
// copy over what base menus do for release
|
|
// but ignore back button, since we don't use it
|
|
if ( mMouseCapture )
|
|
{
|
|
SetCapture(false);
|
|
return MouseEvent(MOUSE_Release,ev.MouseX,ev.MouseY);
|
|
}
|
|
break;
|
|
case UIEvent.Type_MouseMove:
|
|
// store coords beforehand
|
|
curmouse = (ev.MouseX,ev.MouseY);
|
|
if ( mMouseCapture || (m_use_mouse == 1) )
|
|
return MouseEvent(MOUSE_Move,ev.MouseX,ev.MouseY);
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
override void Drawer()
|
|
{
|
|
if ( isclosing ) return;
|
|
Font fnt = LangFont(TewiFont);
|
|
String str;
|
|
double hs;
|
|
if ( (Screen.GetWidth() < 640) || (Screen.GetHeight() < 400) ) hs = max(min(floor(Screen.GetWidth()/320.),floor(Screen.GetHeight()/200.)),1.)/2.;
|
|
else hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/400.)),1.);
|
|
Vector2 ss = (Screen.GetWidth(),Screen.GetHeight())/hs;
|
|
Vector2 origin = (ss.x-640,ss.y-400)/2.;
|
|
if ( swwm_fuzz )
|
|
Screen.DrawTexture(FancyBg,false,origin.x,origin.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,.5);
|
|
Screen.DrawTexture(MainWindow,false,origin.x,origin.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// draw tabs
|
|
double xx = 3, yy = 0;
|
|
static const string tabnames[] =
|
|
{
|
|
"$SWWM_MISSTAB", "$SWWM_STATTAB", "$SWWM_INVTAB", "$SWWM_KEYTAB",
|
|
"$SWWM_KBASETAB", "$SWWM_STORETAB", "$SWWM_TRADETAB", "$SWWM_CHATTAB",
|
|
"$SWWM_SECRETTAB", "$SWWM_HELPTAB"
|
|
};
|
|
static const string ltabnames[] =
|
|
{
|
|
"$SWWM_LORETAB0", "$SWWM_LORETAB1", "$SWWM_LORETAB2"
|
|
};
|
|
static const string stabnames[] =
|
|
{
|
|
"$SWWM_STATTAB0", "$SWWM_STATTAB1", "$SWWM_STATTAB2", "$SWWM_STATTAB3"
|
|
};
|
|
for ( int i=0; i<tabs.Size(); i++ )
|
|
{
|
|
str = StringTable.Localize(tabnames[tabs[i]]);
|
|
Screen.DrawText(fnt,(curtab==i)?Font.CR_FIRE:Font.CR_DARKGRAY,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx += fnt.StringWidth(str)+2;
|
|
Screen.DrawTexture(TabSeparator,false,origin.x+xx,origin.y+yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx += 4;
|
|
}
|
|
int muns1, muns2;
|
|
[muns1, muns2] = SWWMCredits.Get(players[consoleplayer]);
|
|
str = "\cg¥\c-";
|
|
if ( muns2 > 0 ) str.AppendFormat("%d",muns2);
|
|
str.AppendFormat("%09d",muns1);
|
|
xx = 637-TewiFont.StringWidth(str);
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// draw bottom messages
|
|
yy = 386;
|
|
if ( gametic < tmsgtic ) str = StringTable.Localize(tmsg);
|
|
else str = CrimeTime();
|
|
xx = 4;
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
str = "DemolitionOS v1.0";
|
|
xx = 637-fnt.StringWidth(str);
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// draw contents
|
|
if ( tabs[curtab] == TAB_MISSION )
|
|
{
|
|
String str;
|
|
if ( sel1 == 0 ) str = StringTable.Localize(missionstr);
|
|
else str = StringTable.Localize(missionbacklog[sel1-1]);
|
|
BrokenLines l = fnt.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,620);
|
|
xx = 6;
|
|
yy = 17;
|
|
int ofs = clamp(sel0,0,max(0,l.Count()-28));
|
|
for ( int i=ofs; i<l.Count(); i++ )
|
|
{
|
|
if ( yy >= 370 ) break;
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,sel1?Color(96,0,0,0):Color(0,0,0,0));
|
|
yy += 13;
|
|
}
|
|
int csiz = missionbacklog.Size();
|
|
// scrollbar
|
|
if ( l.Count() > 28 )
|
|
{
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx = 634;
|
|
int szr = l.Count()-28;
|
|
yy = floor(ofs*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// page count
|
|
if ( csiz > 0 )
|
|
{
|
|
str = String.Format("%d \cf/\c- %d",sel1+1,csiz+1);
|
|
Screen.DrawText(MiniwiFont,Font.CR_FIRE,(origin.x+629)-MiniwiFont.StringWidth(str),origin.y+375,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( csiz > 0 )
|
|
{
|
|
str = String.Format("%d \cf/\c- %d",sel1+1,csiz+1);
|
|
Screen.DrawText(MiniwiFont,Font.CR_FIRE,(origin.x+637)-MiniwiFont.StringWidth(str),origin.y+375,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_STATS )
|
|
{
|
|
// categories
|
|
xx = 9;
|
|
yy = 23;
|
|
int twidth = (language~=="jp")?194:114;
|
|
for ( int i=0; i<=STAT_ACHIEVEMENT; i++ )
|
|
{
|
|
str = StringTable.Localize(stabnames[i]);
|
|
Screen.DrawText(fnt,(i==sel1)?Font.CR_FIRE:Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
}
|
|
xx += twidth+2;
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+xx,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// stat contents
|
|
if ( sel1 == STAT_MAIN )
|
|
{
|
|
xx += 9;
|
|
yy = 23;
|
|
int cnt = statlist.Size();
|
|
if ( cnt <= 0 )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOSTAT");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+xx+int((634-xx)-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
int ofs = clamp(sel0,0,max(0,cnt-22));
|
|
for ( int i=ofs; i<cnt; i++ )
|
|
{
|
|
if ( yy >= 370 ) break;
|
|
str = statlist[i];
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
}
|
|
// scrollbar
|
|
if ( cnt > 22 )
|
|
{
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx = 634;
|
|
int szr = cnt-22;
|
|
yy = floor(ofs*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( sel1 == STAT_KILLS )
|
|
{
|
|
xx += 9;
|
|
yy = 23;
|
|
int cnt = sorted_mstats.Size();
|
|
if ( cnt <= 0 )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOSTAT");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+xx+int((634-xx)-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
int ofs = clamp(sel0,0,max(0,cnt-22));
|
|
for ( int i=ofs; i<cnt; i++ )
|
|
{
|
|
if ( yy >= 370 ) break;
|
|
str = GetDefaultByType(sorted_mstats[i].m).GetTag(FallbackTag);
|
|
// beautify if there's no tag
|
|
if ( str == FallbackTag )
|
|
{
|
|
str = sorted_mstats[i].m.GetClassName();
|
|
SWWMUtility.BeautifyClassName(str);
|
|
}
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
str = String.Format("%d",sorted_mstats[i].kills);
|
|
int len = fnt.StringWidth(str);
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+((cnt>22)?623:631)-len,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
}
|
|
// scrollbar
|
|
if ( cnt > 22 )
|
|
{
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx = 634;
|
|
int szr = cnt-22;
|
|
yy = floor(ofs*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( sel1 == STAT_LEVEL )
|
|
{
|
|
xx += 9;
|
|
yy = 23;
|
|
int cnt = stats.lstats.Size();
|
|
if ( cnt <= 0 )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOSTAT");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+xx+int((634-xx)-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
int ofs = clamp(sel0,0,max(0,cnt-22));
|
|
let fnt2 = LangFont(MiniwiFont);
|
|
// calc lengths
|
|
int len[4], maxlen[4];
|
|
for ( int i=0; i<4; i++ ) maxlen[i] = 0;
|
|
for ( int i=0; i<cnt; i++ )
|
|
{
|
|
int sec = Thinker.Tics2Seconds(stats.lstats[i].time);
|
|
str = String.Format("T %02d:%02d:%02d",sec/3600,(sec%3600)/60,sec%60);
|
|
len[0] = fnt2.StringWidth(str);
|
|
if ( len[0] > maxlen[0] ) maxlen[0] = len[0];
|
|
str = String.Format("S %d/%d",stats.lstats[i].scount,stats.lstats[i].stotal);
|
|
len[1] = fnt2.StringWidth(str);
|
|
if ( len[1] > maxlen[1] ) maxlen[1] = len[1];
|
|
str = String.Format("I %d/%d",stats.lstats[i].icount,stats.lstats[i].itotal);
|
|
len[2] = fnt2.StringWidth(str);
|
|
if ( len[2] > maxlen[2] ) maxlen[2] = len[2];
|
|
str = String.Format("K %d/%d",stats.lstats[i].kcount,stats.lstats[i].ktotal);
|
|
len[3] = fnt2.StringWidth(str);
|
|
if ( len[3] > maxlen[3] ) maxlen[3] = len[3];
|
|
}
|
|
for ( int i=ofs; i<cnt; i++ )
|
|
{
|
|
if ( yy >= 370 ) break;
|
|
str = stats.lstats[i].hub?stats.lstats[i].levelname:String.Format("%s - %s",stats.lstats[i].mapname.MakeUpper(),stats.lstats[i].levelname);
|
|
bool smallname = fnt.StringWidth(str)>(620-(xx+maxlen[3]+maxlen[2]+maxlen[1]+maxlen[0]+24));
|
|
if ( smallname ) yy += 2;
|
|
Screen.DrawText(smallname?fnt2:fnt,Font.CR_FIRE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
if ( !smallname ) yy += 2;
|
|
int ox = ((cnt>22)?623:631);
|
|
int sec = Thinker.Tics2Seconds(stats.lstats[i].time);
|
|
str = String.Format("%02d\cu:\c-%02d\cu:\c-%02d",sec/3600,(sec%3600)/60,sec%60);
|
|
Screen.DrawText(fnt2,((stats.lstats[i].suck>0)&&(sec>=(stats.lstats[i].suck*3600)))?Font.CR_RED:(sec<=stats.lstats[i].par)?Font.CR_GOLD:Font.CR_WHITE,origin.x+ox-fnt2.StringWidth(str),origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(fnt2,Font.CR_FIRE,origin.x+ox-maxlen[0],origin.y+yy,"T",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
ox -= maxlen[0]+8;
|
|
str = String.Format("%d\cu/\c-%d",stats.lstats[i].scount,stats.lstats[i].stotal);
|
|
Screen.DrawText(fnt2,(stats.lstats[i].scount>=stats.lstats[i].stotal)?Font.CR_GOLD:Font.CR_WHITE,origin.x+ox-fnt2.StringWidth(str),origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(fnt2,Font.CR_FIRE,origin.x+ox-maxlen[1],origin.y+yy,"S",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
ox -= maxlen[1]+8;
|
|
str = String.Format("%d\cu/\c-%d",stats.lstats[i].icount,stats.lstats[i].itotal);
|
|
Screen.DrawText(fnt2,(stats.lstats[i].icount>=stats.lstats[i].itotal)?Font.CR_GOLD:Font.CR_WHITE,origin.x+ox-fnt2.StringWidth(str),origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(fnt2,Font.CR_FIRE,origin.x+ox-maxlen[2],origin.y+yy,"I",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
ox -= maxlen[2]+8;
|
|
str = String.Format("%d\cu/\c-%d",stats.lstats[i].kcount,stats.lstats[i].ktotal);
|
|
Screen.DrawText(fnt2,(stats.lstats[i].kcount>=stats.lstats[i].ktotal)?Font.CR_GOLD:Font.CR_WHITE,origin.x+ox-fnt2.StringWidth(str),origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(fnt2,Font.CR_FIRE,origin.x+ox-maxlen[3],origin.y+yy,"K",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 14;
|
|
}
|
|
// scrollbar
|
|
if ( cnt > 22 )
|
|
{
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx = 634;
|
|
int szr = cnt-22;
|
|
yy = floor(ofs*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( sel1 == STAT_ACHIEVEMENT )
|
|
{
|
|
xx += 9;
|
|
yy = 23;
|
|
str = StringTable.Localize("$SWWM_COMINGSOON");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+xx+int((631-xx)-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( (tabs[curtab] == TAB_INVENTORY) || ((tabs[curtab] == TAB_TRADING) && sub && (sel0 != -1)) )
|
|
{
|
|
if ( invlist.Size() <= 0 )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOINV");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
xx = 9;
|
|
yy = 23;
|
|
int longest, len;
|
|
int maxcol, totalcol, cols = 1;
|
|
// first pass, calculate longest item name
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
|
|
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
|
|
else str = invlist[i].GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
int ofs = int(max(0,(ofs0/22)-(maxcol-1))*22);
|
|
for ( int i=ofs; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
|
|
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
|
|
else str = invlist[i].GetTag();
|
|
int clscol = Font.CR_WHITE;
|
|
if ( invlist[i] is 'Weapon' ) clscol = Font.CR_GOLD;
|
|
else if ( invlist[i] is 'MagAmmo' ) clscol = Font.CR_TAN;
|
|
else if ( (invlist[i] is 'BackpackItem') || (invlist[i] is 'HammerspaceEmbiggener') ) clscol = Font.CR_DARKBROWN;
|
|
else if ( invlist[i] is 'Ammo' ) clscol = Font.CR_BROWN;
|
|
else if ( (invlist[i] is 'PowerupGiver') || (invlist[i] is 'AmmoFabricator') || invlist[i].bBIGPOWERUP ) clscol = Font.CR_PURPLE;
|
|
else if ( (invlist[i] is 'Health') || (invlist[i] is 'HealthPickup') || (invlist[i] is 'SWWMHealth') ) clscol = Font.CR_RED;
|
|
else if ( (invlist[i] is 'Armor') || (invlist[i] is 'SWWMSpareArmor') ) clscol = Font.CR_GREEN;
|
|
else if ( invlist[i] is 'PuzzleItem' ) clscol = Font.CR_LIGHTBLUE;
|
|
else if ( invlist[i] is 'SWWMCollectible' ) clscol = Font.CR_FIRE;
|
|
Screen.DrawText(fnt,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0));
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+24;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
if ( maxcol < totalcol )
|
|
{
|
|
// draw scrollbar
|
|
int szr = totalcol-maxcol;
|
|
xx = floor((ofs/22.)*(630./szr))+2.;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+373,"▬",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawTexture(WindowSeparatorH,false,origin.x,origin.y+377,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_KEYS )
|
|
{
|
|
if ( invlist.Size() <= 0 )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOKEYS");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
xx = 9;
|
|
yy = 23;
|
|
int longest = 0, len;
|
|
int maxcol, totalcol, cols = 1;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
str = invlist[i].GetTag();
|
|
if ( invlist[i] is 'SWWMCollectible' )
|
|
str.AppendFormat(" (¥%d)",invlist[i].default.Stamina);
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+24);
|
|
totalcol = int(ceil(invlist.Size()/22.));
|
|
int ofs = int(max(0,(ofs0/22)-(maxcol-1))*22);
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
str = invlist[i].GetTag();
|
|
if ( invlist[i] is 'SWWMCollectible' )
|
|
str.AppendFormat(" \cj(\cg¥\cf%d\cj)\c-",invlist[i].default.Stamina);
|
|
Screen.DrawText(fnt,(invlist[i] is 'SWWMCollectible')?Font.CR_PURPLE:Font.CR_UNTRANSLATED,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0));
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+24;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
if ( maxcol < totalcol )
|
|
{
|
|
// draw scrollbar
|
|
int szr = totalcol-maxcol;
|
|
xx = floor((ofs/22.)*(630./szr))+2.;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+373,"▬",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawTexture(WindowSeparatorH,false,origin.x,origin.y+377,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_LIBRARY )
|
|
{
|
|
xx = 3;
|
|
yy = 14;
|
|
// draw the category
|
|
int twidth = (language~=="jp")?200:120;
|
|
str = StringTable.Localize(ltabnames[sel1]);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,"<",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx+twidth-6,origin.y+yy,">",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+xx+(twidth-fnt.StringWidth(str))/2,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// draw "unread" indicators on sides
|
|
int ltab = sel1-1;
|
|
if ( ltab < 0 ) ltab = 2;
|
|
int rtab = sel1+1;
|
|
if ( rtab > 2 ) rtab = 0;
|
|
bool lunread = false, runread = false;
|
|
for ( int i=0; i<lorelib.ent.Size(); i++ )
|
|
{
|
|
if ( lorelib.ent[i].tab == ltab ) lunread |= !lorelib.ent[i].read;
|
|
if ( lorelib.ent[i].tab == rtab ) runread |= !lorelib.ent[i].read;
|
|
}
|
|
if ( lunread ) Screen.DrawText(TewiFont,Font.CR_GOLD,origin.x+xx+6,origin.y+yy,"‼",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
if ( runread ) Screen.DrawText(TewiFont,Font.CR_GOLD,origin.x+xx+twidth-12,origin.y+yy,"‼",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawTexture((language~=="jp")?LoreSeparatorW:LoreSeparator,false,origin.x,origin.y+27,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 18;
|
|
// draw the current entries
|
|
int ofs = max(0,ofs0-26);
|
|
for ( int i=ofs; i<lorelist.Size(); i++ )
|
|
{
|
|
if ( yy > 370 ) break;
|
|
str = StringTable.Localize(lorelist[i].tag);
|
|
int len = fnt.StringWidth(str);
|
|
Screen.DrawText(fnt,(i==sel0)?Font.CR_FIRE:Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
if ( !lorelist[i].read )
|
|
Screen.DrawText(TewiFont,Font.CR_GOLD,origin.x+xx+len,origin.y+yy," ‼",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 13;
|
|
}
|
|
xx += twidth+2;
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+xx,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx += 3;
|
|
// scrollbar
|
|
if ( lorelist.Size() > 27 )
|
|
{
|
|
int szr = lorelist.Size()-27;
|
|
yy = floor((ofs)*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx += 5;
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+xx,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx += 3;
|
|
}
|
|
xx += 4;
|
|
// draw the entry text (if open)
|
|
if ( !sub )
|
|
{
|
|
str = StringTable.Localize("$SWWM_LOREUNSEL");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+xx+int((634-xx)-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
str = StringTable.Localize(lorelist[sel0].text);
|
|
BrokenLines l = fnt.BreakLines(str,int(635-xx));
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,int(626-xx));
|
|
yy = 17;
|
|
ofs = clamp(sel2,0,max(0,l.Count()-28));
|
|
for ( int i=ofs; i<l.Count(); i++ )
|
|
{
|
|
if ( yy > 370 ) break;
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 13;
|
|
}
|
|
// scrollbar
|
|
if ( l.Count() > 28 )
|
|
{
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx = 634;
|
|
int szr = l.Count()-28;
|
|
yy = floor(ofs*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_STORE )
|
|
{
|
|
if ( storelist.Size() <= 0 )
|
|
{
|
|
str = StringTable.Localize(sub?"$SWWM_NOSTORESELL":"$SWWM_NOSTORE");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
// draw all the stuff in the store
|
|
xx = 9;
|
|
yy = 23;
|
|
int longest = 0, len;
|
|
int maxcol, totalcol;
|
|
for ( int i=0; i<storelist.Size(); i++ )
|
|
{
|
|
if ( !storelist[i] ) continue;
|
|
let def = GetDefaultByType(storelist[i]);
|
|
if ( sub )
|
|
{
|
|
int amt = (storelist[i] is 'CandyGun')?(players[consoleplayer].mo.CountInv("CandyGunSpares")+1):players[consoleplayer].mo.CountInv(storelist[i]);
|
|
if ( (amt > 1) || (storelist[i] is 'Ammo') ) str = String.Format("(%d/%d) %s",storeunits[i],amt,def.GetTag());
|
|
else str = def.GetTag();
|
|
}
|
|
else if ( (storeunits[i] > 1) || (storelist[i] is 'Ammo') ) str = String.Format("%dx %s",storeunits[i],def.GetTag());
|
|
else str = def.GetTag();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
}
|
|
maxcol = 622/(longest+96);
|
|
totalcol = int(ceil(storelist.Size()/22.));
|
|
int ofs = int(max(0,(ofs0/22)-(maxcol-1))*22);
|
|
int cols = 1;
|
|
for ( int i=ofs; i<storelist.Size(); i++ )
|
|
{
|
|
if ( !storelist[i] ) continue;
|
|
let def = GetDefaultByType(storelist[i]);
|
|
if ( sub )
|
|
{
|
|
int amt = (storelist[i] is 'CandyGun')?(players[consoleplayer].mo.CountInv("CandyGunSpares")+1):players[consoleplayer].mo.CountInv(storelist[i]);
|
|
if ( (amt > 1) || (storelist[i] is 'Ammo') ) str = String.Format("(%d/%d) %s",storeunits[i],amt,def.GetTag());
|
|
else str = def.GetTag();
|
|
}
|
|
else if ( (storeunits[i] > 1) || (storelist[i] is 'Ammo') ) str = String.Format("%dx %s",storeunits[i],def.GetTag());
|
|
else str = def.GetTag();
|
|
int clscol = Font.CR_WHITE;
|
|
if ( storelist[i] is 'Weapon' ) clscol = Font.CR_GOLD;
|
|
else if ( storelist[i] is 'MagAmmo' ) clscol = Font.CR_TAN;
|
|
else if ( (storelist[i] is 'BackpackItem') || (storelist[i] is 'HammerspaceEmbiggener') ) clscol = Font.CR_DARKBROWN;
|
|
else if ( storelist[i] is 'Ammo' ) clscol = Font.CR_BROWN;
|
|
else if ( (storelist[i] is 'PowerupGiver') || (storelist[i] is 'AmmoFabricator') || def.bBIGPOWERUP ) clscol = Font.CR_PURPLE;
|
|
else if ( (storelist[i] is 'Health') || (storelist[i] is 'HealthPickup') || (storelist[i] is 'SWWMHealth') ) clscol = Font.CR_RED;
|
|
else if ( (storelist[i] is 'Armor') || (storelist[i] is 'SWWMSpareArmor') ) clscol = Font.CR_GREEN;
|
|
Screen.DrawText(fnt,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0));
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+96;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
xx = 9;
|
|
yy = 23;
|
|
cols = 1;
|
|
for ( int i=ofs; i<storelist.Size(); i++ )
|
|
{
|
|
if ( !storelist[i] ) continue;
|
|
let def = GetDefaultByType(storelist[i]);
|
|
int price = int(abs(def.Stamina)*(1.+.75*(storeunits[i]-1)));
|
|
if ( sub && (storelist[i] is 'Weapon') )
|
|
{
|
|
let w = Weapon(def);
|
|
// subtract price of given ammo, as we're only selling the weapon itself
|
|
if ( w.AmmoType1 && (w.AmmoGive1 > 0) )
|
|
{
|
|
let am1 = GetDefaultByType(w.AmmoType1);
|
|
if ( am1.Stamina > 0 ) price -= int(am1.Stamina*(1.+.75*(w.AmmoGive1-1)));
|
|
}
|
|
// candygun is a special case for secondary ammo
|
|
if ( w.AmmoType2 && (w.AmmoGive2 > 0) && (storelist[i] is 'CandyGun') )
|
|
{
|
|
let am2 = GetDefaultByType(w.AmmoType2);
|
|
if ( am2.Stamina > 0 ) price -= int(am2.Stamina*(1.+.75*(w.AmmoGive2-1)));
|
|
}
|
|
}
|
|
// sell at half price
|
|
if ( sub ) price /= 2;
|
|
str = String.Format("¥%d",price);
|
|
len = TewiFont.StringWidth(str);
|
|
int clscol = Font.CR_FIRE;
|
|
if ( sub ) clscol = Font.CR_GREEN;
|
|
else if ( (price > muns1) && (muns2 <= 0) ) clscol = Font.CR_BLACK;
|
|
Screen.DrawText(TewiFont,clscol,origin.x+xx+longest+80-len,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0));
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+96;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > maxcol ) break;
|
|
}
|
|
}
|
|
if ( maxcol < totalcol )
|
|
{
|
|
// draw scrollbar
|
|
int szr = totalcol-maxcol;
|
|
xx = floor((ofs/22.)*(630./szr))+2.;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+373,"▬",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawTexture(WindowSeparatorH,false,origin.x,origin.y+377,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_TRADING )
|
|
{
|
|
if ( !sub )
|
|
{
|
|
if ( playerlist.Size() <= 0 )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOTRADE");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
xx = 9;
|
|
yy = 23;
|
|
int longest = 0, len;
|
|
int ofs = int(floor(max(0,sel0-44)/22.)*22);
|
|
int cols = 1;
|
|
for ( int i=ofs; i<playerlist.Size(); i++ )
|
|
{
|
|
str = players[playerlist[i]].GetUserName();
|
|
len = fnt.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0));
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+24;
|
|
yy = 23;
|
|
longest = 0;
|
|
cols++;
|
|
if ( cols > 3 ) break;
|
|
}
|
|
}
|
|
if ( playerlist.Size() > 65 )
|
|
{
|
|
// draw scrollbar
|
|
int szr = (playerlist.Size()/22)-2;
|
|
xx = floor((ofs/22)*(630./szr))+2;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+373,"▬",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawTexture(WindowSeparatorH,false,origin.x,origin.y+377,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( sub )
|
|
{
|
|
if ( sel0 == -1 )
|
|
{
|
|
if ( tradelib.ent.Size() <= 0 )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOTRADEHIST");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
xx = 6;
|
|
yy = 17;
|
|
int ofs = clamp(sel1,0,max(0,tradelib.ent.Size()-28));
|
|
for ( int i=ofs; i<tradelib.ent.Size(); i++ )
|
|
{
|
|
if ( yy >= 370 ) break;
|
|
let ent = tradelib.ent[tradelib.ent.Size()-(i+1)];
|
|
int thour = (ent.timestamp/(3600*GameTicRate));
|
|
int tmin = (ent.timestamp/(60*GameTicRate))%60;
|
|
int tsec = (ent.timestamp/GameTicRate)%60;
|
|
str = String.Format("\cu[\cc%02d\cu:\cc%02d\cu:\cc%02d\cu]\c- ",thour,tmin,tsec);
|
|
str.AppendFormat("\cd%s %s\cd: \cj%dx \cf%s\c-",ent.type?StringTable.Localize("$SWWM_TRADEFROM"):StringTable.Localize("$SWWM_TRADETO"),ent.other,ent.amt,GetDefaultByType(ent.what).GetTag());
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 13;
|
|
}
|
|
// scrollbar
|
|
if ( tradelib.ent.Size() > 28 )
|
|
{
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx = 634;
|
|
int szr = tradelib.ent.Size()-28;
|
|
yy = floor(ofs*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_CHAT )
|
|
{
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( !bar || (bar.FullHistory.Size() <= 0) )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOCHAT");
|
|
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
int margin = TewiFont.StringWidth("[00:00:00] ");
|
|
int ofs = bar.FullHistory.Size()-(1+sel0);
|
|
xx = 3;
|
|
yy = 379;
|
|
for ( int i=ofs; i>=0; i-- )
|
|
{
|
|
int col = (bar.FullHistory[i].type==PRINT_TEAMCHAT)?msg4color:msg3color;
|
|
int thour = (bar.FullHistory[i].tic/(3600*GameTicRate));
|
|
int tmin = (bar.FullHistory[i].tic/(60*GameTicRate))%60;
|
|
int tsec = (bar.FullHistory[i].tic/GameTicRate)%60;
|
|
str = String.Format("\cu[\c-%02d\cu:\c-%02d\cu:\c-%02d\cu]\c- ",thour,tmin,tsec);
|
|
BrokenLines l = fnt.BreakLines(bar.FullHistory[i].str,626-margin);
|
|
double by = yy-13*l.Count();
|
|
if ( by < 17 ) break;
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+by,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
for ( int j=0; j<l.Count(); j++ )
|
|
Screen.DrawText(fnt,col,origin.x+xx+margin,origin.y+by+j*13,l.StringAt(j),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy = by;
|
|
}
|
|
// scrollbar
|
|
if ( bar.FullHistory.Size() > 1 )
|
|
{
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx = 634;
|
|
int szr = bar.FullHistory.Size()-1;
|
|
yy = floor((szr-sel0)*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_SECRET )
|
|
{
|
|
if ( gameinfo.gametype&(GAME_Strife|GAME_Hexen) )
|
|
{
|
|
Screen.DrawTexture(Drawing[2],false,origin.x+20,origin.y+40,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
str = StringTable.Localize("$SWWM_KIRINPOEM");
|
|
BrokenLines l = fnt.BreakLines(str,300);
|
|
int mxlen = 0;
|
|
for ( int i=0; i<l.Count(); i++ )
|
|
{
|
|
if ( l.StringWidth(i) > mxlen ) mxlen = l.StringWidth(i);
|
|
xx = (i<l.Count()-1)?350:(350+mxlen-l.StringWidth(i));
|
|
Screen.DrawText(fnt,Font.CR_GOLD,origin.x+xx,origin.y+43+i*14,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
str = StringTable.Localize("$SWWM_FROMKIRIN");
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+350,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
else if ( gameinfo.gametype&GAME_Heretic )
|
|
{
|
|
Screen.DrawTexture(Drawing[1],false,origin.x+20,origin.y+40,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
str = StringTable.Localize("$SWWM_CUTIECLUB");
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+350,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
else
|
|
{
|
|
Screen.DrawTexture(Drawing[0],false,origin.x+20,origin.y+40,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
str = StringTable.Localize("$SWWM_TODEMO");
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+(640-fnt.StringWidth(str))/2,origin.y+350,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
else if ( tabs[curtab] == TAB_HELP )
|
|
{
|
|
// help tab
|
|
String kstr;
|
|
if ( mkey[1] != "" ) kstr = mkey[0].."/"..mkey[1];
|
|
else kstr = mkey[0];
|
|
str = String.Format(StringTable.Localize("$SWWM_HELPTXT"),kstr);
|
|
for ( int i=0; i<MAXPLAYERS; i++ )
|
|
{
|
|
if ( !playeringame[i] || (i == consoleplayer) ) continue;
|
|
if ( deathmatch && (!teamplay || (players[i].GetTeam() != players[consoleplayer].GetTeam())) ) continue;
|
|
str = str..StringTable.Localize("$SWWM_HELPTXT_TRADING");
|
|
break;
|
|
}
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( bar && (bar.FullHistory.Size() > 0) )
|
|
str = str..StringTable.Localize("$SWWM_HELPTXT_CHAT");
|
|
BrokenLines l = fnt.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = fnt.BreakLines(str,620);
|
|
xx = 6;
|
|
yy = 17;
|
|
int ofs = clamp(sel0,0,max(0,l.Count()-28));
|
|
for ( int i=ofs; i<l.Count(); i++ )
|
|
{
|
|
if ( yy >= 370 ) break;
|
|
Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 13;
|
|
}
|
|
// scrollbar
|
|
if ( l.Count() > 28 )
|
|
{
|
|
Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx = 634;
|
|
int szr = l.Count()-28;
|
|
yy = floor(ofs*(353./szr))+17;
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
}
|
|
}
|