Tweaks here and there to other stuff. Refined wall jumping/climbing, also works on actors (including other players). Refined how boosting/dashing handles falling speeds. Added improved air control. It was very much needed. Added "kick" sounds to wall jumps. Add option to hear other player's voices in mp. Fix some broken localization. Fix invulnerable monsters bleeding from some attacks. Fix desync when jumping on top of another player with prediction enabled. Make moths immune to your damage, so you can stop accidentally killing them. Make normal ammo buyable in Hexen again.
1311 lines
No EOL
44 KiB
Text
1311 lines
No EOL
44 KiB
Text
// internal "knowledge base" and more
|
|
Class SWWMKnowledgeBaseMenu : GenericMenu
|
|
{
|
|
enum EDemoTab
|
|
{
|
|
TAB_MISSION = 0,
|
|
TAB_STATS,
|
|
TAB_INVENTORY,
|
|
TAB_KEYS,
|
|
TAB_LIBRARY,
|
|
TAB_STORE,
|
|
TAB_TRADING,
|
|
TAB_CHAT,
|
|
TAB_SECRET
|
|
};
|
|
|
|
TextureID MainWindow, TabSeparator, WindowSeparator, WindowSeparatorH,
|
|
FancyBg, EasterEgg, LoreSeparator;
|
|
Font TewiFont;
|
|
int curtab;
|
|
// for scrolling
|
|
bool sub;
|
|
int sel0, sel1, sel2;
|
|
// stats
|
|
SWWMStats stats;
|
|
// 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;
|
|
// 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];
|
|
// color for chat
|
|
CVar ccol, tcol;
|
|
// for checks (duh)
|
|
Class<Inventory> lastuse;
|
|
int lastuseamt;
|
|
int checkuse;
|
|
int checkdrop;
|
|
// seeeeecret
|
|
int kcode;
|
|
|
|
override void Init( Menu parent )
|
|
{
|
|
Super.Init(parent);
|
|
if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) )
|
|
{
|
|
// can't open this menu outside of the game or if dead
|
|
Close();
|
|
return;
|
|
}
|
|
TewiFont = Font.GetFont('TewiShaded');
|
|
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);
|
|
EasterEgg = TexMan.CheckForTexture("graphics/KBase/Drawing.png",TexMan.Type_MiscPatch);
|
|
LoreSeparator = TexMan.CheckForTexture("graphics/KBase/LibraryTabSeparator.png",TexMan.Type_MiscPatch);
|
|
curtab = CVar.GetCVar('swwm_lasttab',players[consoleplayer]).GetInt();
|
|
if ( (curtab < 0) || (curtab > 7) ) curtab = 0;
|
|
MenuSound("menu/demoopen");
|
|
[ikey[0], ikey[1]] = Bindings.GetKeysForCommand("openmenu SWWMKnowledgeBaseMenu");
|
|
mkey[0] = Bindings.NameKeys(ikey[0],0);
|
|
mkey[1] = Bindings.NameKeys(ikey[1],0);
|
|
ccol = CVar.GetCVar("msg3color",players[consoleplayer]);
|
|
tcol = CVar.GetCVar("msg4color",players[consoleplayer]);
|
|
lorelib = SWWMLoreLibrary.Find(players[consoleplayer]);
|
|
oldloresiz = lorelib.ent.Size();
|
|
stats = SWWMStats.Find(players[consoleplayer]);
|
|
}
|
|
|
|
override bool MenuEvent( int mkey, bool fromcontroller )
|
|
{
|
|
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");
|
|
curtab = TAB_SECRET;
|
|
sel0 = sel1 = sel2 = 0;
|
|
sub = false;
|
|
}
|
|
default:
|
|
kcode = 0;
|
|
break;
|
|
}
|
|
switch ( mkey )
|
|
{
|
|
case MKEY_BACK:
|
|
MenuSound("menu/democlose");
|
|
Close();
|
|
return true;
|
|
case MKEY_PAGEUP:
|
|
MenuSound("menu/demotab");
|
|
if ( (curtab <= 0) || (curtab > 7) ) curtab = 7;
|
|
else curtab--;
|
|
CVar.GetCVar('swwm_lasttab',players[consoleplayer]).SetInt(curtab);
|
|
sel0 = sel1 = sel2 = 0;
|
|
sub = false;
|
|
invlist.Clear();
|
|
lorelist.Clear();
|
|
storelist.Clear();
|
|
storeunits.Clear();
|
|
return true;
|
|
case MKEY_PAGEDOWN:
|
|
MenuSound("menu/demotab");
|
|
if ( curtab < 7 ) curtab++;
|
|
else curtab = 0;
|
|
CVar.GetCVar('swwm_lasttab',players[consoleplayer]).SetInt(curtab);
|
|
sel0 = sel1 = sel2 = 0;
|
|
sub = false;
|
|
invlist.Clear();
|
|
lorelist.Clear();
|
|
storelist.Clear();
|
|
storeunits.Clear();
|
|
return true;
|
|
case MKEY_DOWN:
|
|
if ( curtab == TAB_MISSION )
|
|
{
|
|
String str = StringTable.Localize("$SWWM_MISSION_NONE");
|
|
if ( gameinfo.gametype&GAME_Doom ) str = StringTable.Localize("$SWWM_MISSION_DOOM");
|
|
else if ( gameinfo.gametype&GAME_Heretic ) str = StringTable.Localize("$SWWM_MISSION_HERETIC");
|
|
else if ( gameinfo.gametype&GAME_Hexen ) str = StringTable.Localize("$SWWM_MISSION_HEXEN");
|
|
BrokenLines l = TewiFont.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = TewiFont.BreakLines(str,620);
|
|
if ( (l.Count() > 28) && (sel0 < l.Count()-28) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0++;
|
|
}
|
|
}
|
|
else if ( (curtab == TAB_CHAT) && (StatusBar is 'SWWMStatusBar') && (sel0 > 0) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0--;
|
|
}
|
|
else if ( (curtab == TAB_LIBRARY) && (lorelist.Size() > 1) )
|
|
{
|
|
if ( sub )
|
|
{
|
|
int ofs = TewiFont.StringWidth("********************")+12;
|
|
if ( lorelist.Size() > 26 ) ofs += 8;
|
|
String str = StringTable.Localize(lorelist[sel0].text);
|
|
BrokenLines l = TewiFont.BreakLines(str,635-ofs);
|
|
if ( l.Count() > 28 ) l = TewiFont.BreakLines(str,626-ofs);
|
|
if ( (l.Count() > 28) && (sel2 < l.Count()-28) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel2++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0++;
|
|
if ( sel0 >= lorelist.Size() )
|
|
sel0 = 0;
|
|
}
|
|
}
|
|
else if ( ((curtab == TAB_INVENTORY) || (curtab == TAB_KEYS)) && (invlist.Size() > 1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0++;
|
|
if ( sel0 >= invlist.Size() )
|
|
sel0 = 0;
|
|
}
|
|
else if ( (curtab == TAB_STORE) && (storelist.Size() > 1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0++;
|
|
if ( sel0 >= storelist.Size() )
|
|
sel0 = 0;
|
|
}
|
|
return true;
|
|
case MKEY_UP:
|
|
if ( curtab == TAB_MISSION )
|
|
{
|
|
if ( sel0 > 0 )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0--;
|
|
}
|
|
}
|
|
else if ( (curtab == TAB_CHAT) && (StatusBar is 'SWWMStatusBar') && (sel0 < SWWMStatusBar(StatusBar).FullHistory.Size()-1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0++;
|
|
}
|
|
else if ( (curtab == TAB_LIBRARY) && (lorelist.Size() > 1) )
|
|
{
|
|
if ( sub )
|
|
{
|
|
if ( sel2 > 0 )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel2--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0--;
|
|
if ( sel0 < 0 )
|
|
sel0 = lorelist.Size()-1;
|
|
}
|
|
}
|
|
else if ( ((curtab == TAB_INVENTORY) || (curtab == TAB_KEYS)) && (invlist.Size() > 1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0--;
|
|
if ( sel0 < 0 )
|
|
sel0 = invlist.Size()-1;
|
|
}
|
|
else if ( (curtab == TAB_STORE) && (storelist.Size() > 1) )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0--;
|
|
if ( sel0 < 0 )
|
|
sel0 = storelist.Size()-1;
|
|
}
|
|
return true;
|
|
case MKEY_RIGHT:
|
|
if ( ((curtab == TAB_INVENTORY) || (curtab == TAB_KEYS)) && (invlist.Size() > 21) )
|
|
{
|
|
int oldsel = sel0;
|
|
sel0 += 22;
|
|
if ( sel0 >= invlist.Size() ) sel0 = invlist.Size()-1;
|
|
if ( sel0 != oldsel ) MenuSound("menu/demoscroll");
|
|
}
|
|
else if ( (curtab == TAB_STORE) && (storelist.Size() > 21) )
|
|
{
|
|
int oldsel = sel0;
|
|
sel0 += 22;
|
|
if ( sel0 >= storelist.Size() ) sel0 = storelist.Size()-1;
|
|
if ( sel0 != oldsel ) MenuSound("menu/demoscroll");
|
|
}
|
|
else if ( curtab == TAB_LIBRARY )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0 = 0;
|
|
sub = false;
|
|
sel1++;
|
|
if ( sel1 > LORE_LORE )
|
|
sel1 = LORE_ITEM;
|
|
}
|
|
return true;
|
|
case MKEY_LEFT:
|
|
if ( ((curtab == TAB_INVENTORY) || (curtab == TAB_KEYS)) && (invlist.Size() > 21) )
|
|
{
|
|
if ( sel0-22 >= 0 )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0 -= 22;
|
|
}
|
|
}
|
|
else if ( (curtab == TAB_STORE) && (storelist.Size() > 21) )
|
|
{
|
|
if ( sel0-22 >= 0 )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0 -= 22;
|
|
}
|
|
}
|
|
else if ( curtab == TAB_LIBRARY )
|
|
{
|
|
MenuSound("menu/demoscroll");
|
|
sel0 = 0;
|
|
sub = false;
|
|
sel1--;
|
|
if ( sel1 < LORE_ITEM )
|
|
sel1 = LORE_LORE;
|
|
}
|
|
return true;
|
|
case MKEY_ENTER:
|
|
if ( (curtab == TAB_INVENTORY) && (invlist.Size() > 0) )
|
|
{
|
|
// can't use this
|
|
if ( invlist[sel0] is 'Ammo' ) return true;
|
|
lastuse = invlist[sel0].GetClass();
|
|
lastuseamt = invlist[sel0].Amount;
|
|
// don't check weapons (or the lamp)
|
|
if ( !(invlist[sel0] is 'Weapon') && !(invlist[sel0] is 'SWWMLamp') )
|
|
checkuse = gametic+1;
|
|
EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer);
|
|
}
|
|
else if ( (curtab == TAB_STORE) && (storelist.Size() > 0) )
|
|
{
|
|
int moni = SWWMCredits.Get(players[consoleplayer]);
|
|
let itm = GetDefaultByType(storelist[sel0]);
|
|
let amt = storeunits[sel0];
|
|
int price = int(itm.Stamina*(1.+.5*(amt-1)));
|
|
if ( moni < price )
|
|
{
|
|
MenuSound("menu/noinvuse");
|
|
tmsg = StringTable.Localize("$SWWM_STOREMUNS");
|
|
tmsgtic = gametic+35;
|
|
return true;
|
|
}
|
|
let cur = players[consoleplayer].mo.FindInventory(storelist[sel0]);
|
|
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+35;
|
|
return true;
|
|
}
|
|
EventHandler.SendNetworkEvent(String.Format("swwmstoregive.%s",storelist[sel0].GetClassName()),consoleplayer,price,amt);
|
|
MenuSound("menu/buyinv");
|
|
}
|
|
else if ( curtab == TAB_LIBRARY )
|
|
{
|
|
if ( sub )
|
|
{
|
|
MenuSound("menu/democlose");
|
|
sub = false;
|
|
}
|
|
else if ( lorelist.Size() > 0 )
|
|
{
|
|
// mark as read
|
|
if ( !lorelist[sel0].read )
|
|
EventHandler.SendNetworkEvent(String.Format("swwmmarkloreread.%s",lorelist[sel0].tag),consoleplayer);
|
|
MenuSound("menu/demosel");
|
|
sub = true;
|
|
sel2 = 0;
|
|
}
|
|
}
|
|
return true;
|
|
case MKEY_CLEAR:
|
|
if ( (curtab == TAB_INVENTORY) && (invlist.Size() > 0) )
|
|
{
|
|
lastuse = invlist[sel0].GetClass();
|
|
lastuseamt = invlist[sel0].Amount;
|
|
checkdrop = gametic+1;
|
|
EventHandler.SendNetworkEvent(String.Format("swwmdropitem.%s",invlist[sel0].GetClassName()),consoleplayer);
|
|
}
|
|
else if ( (curtab == TAB_LIBRARY) && sub )
|
|
{
|
|
MenuSound("menu/democlose");
|
|
sub = false;
|
|
}
|
|
return true;
|
|
}
|
|
return Super.MenuEvent(mkey,fromcontroller);
|
|
}
|
|
|
|
private bool CmpInventory( Inventory a, Inventory b )
|
|
{
|
|
int ta = 0, tb = 0;
|
|
if ( a is 'Weapon' ) ta = 2;
|
|
else if ( (a is 'Ammo') || (a is 'BackpackItem') || (a is 'HammerspaceEmbiggener') ) ta = 3;
|
|
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 'Ammo') || (b is 'BackpackItem') || (b is 'HammerspaceEmbiggener') ) tb = 3;
|
|
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;
|
|
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 = 2;
|
|
else if ( a is 'Ammo' ) ta = 1;
|
|
else if ( (a is 'PowerupGiver') || (a is 'AmmoFabricator') || da.bBIGPOWERUP ) ta = 3;
|
|
else if ( (a is 'Health') || (a is 'HealthPickup') || (a is 'SWWMHealth') ) ta = 5;
|
|
else if ( (a is 'Armor') || (a is 'SWWMSpareArmor') ) ta = 4;
|
|
if ( b is 'Weapon' ) tb = 2;
|
|
else if ( b is 'Ammo' ) tb = 1;
|
|
else if ( (b is 'PowerupGiver') || (b is 'AmmoFabricator') || db.bBIGPOWERUP ) tb = 3;
|
|
else if ( (b is 'Health') || (b is 'HealthPickup') || (b is 'SWWMHealth') ) tb = 5;
|
|
else if ( (b is 'Armor') || (b is 'SWWMSpareArmor') ) tb = 4;
|
|
return ta < tb;
|
|
}
|
|
|
|
override void Ticker()
|
|
{
|
|
Super.Ticker();
|
|
if ( players[consoleplayer].Health <= 0 )
|
|
{
|
|
// ded
|
|
MenuSound("menu/democlose");
|
|
Close();
|
|
return;
|
|
}
|
|
if ( 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') ) 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
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
int j = 1;
|
|
while ( j < invlist.Size() )
|
|
{
|
|
int k = j;
|
|
while ( (k > 0) && CmpInventory(invlist[k-1],invlist[k]) )
|
|
{
|
|
Inventory tmp = invlist[k];
|
|
invlist[k] = invlist[k-1];
|
|
invlist[k-1] = tmp;
|
|
k--;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
else if ( curtab == TAB_KEYS )
|
|
{
|
|
invlist.Clear();
|
|
// alphabetically sorted keys
|
|
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.Inv )
|
|
{
|
|
if ( !(inv is 'Key') ) 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);
|
|
}
|
|
}
|
|
else if ( curtab == TAB_STORE )
|
|
{
|
|
storelist.Clear();
|
|
storeunits.Clear();
|
|
// price-sorted buyables
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let type = (Class<Inventory>)(AllActorClasses[i]);
|
|
if ( !type ) continue;
|
|
// skip chanceboxes, since they're not yet implemented
|
|
if ( type is 'Chancebox' ) continue;
|
|
// no fabricators outside of hexen
|
|
if ( !(gameinfo.gametype&GAME_Hexen) && (type is 'AmmoFabricator') ) continue;
|
|
// skip maxed items
|
|
let cur = players[consoleplayer].mo.FindInventory(type);
|
|
if ( cur && (cur.Amount >= cur.MaxAmount) ) continue;
|
|
// ignore ammo for weapons not owned
|
|
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;
|
|
int amt = inv.Amount;
|
|
if ( type is 'Ammo' )
|
|
{
|
|
// get the largest child pickup amount
|
|
for ( int j=0; j<AllActorClasses.Size(); j++ )
|
|
{
|
|
let type2 = (Class<Ammo>)(AllActorClasses[j]);
|
|
if ( !type2 || (type2.GetParentClass() != type) ) continue;
|
|
let inv2 = GetDefaultByType(type2);
|
|
if ( inv2.Amount > amt ) amt = inv2.Amount;
|
|
}
|
|
}
|
|
int price = int(inv.Stamina*(1.+.5*(amt-1)));
|
|
bool greater = false;
|
|
for ( int j=0; j<storelist.Size(); j++ )
|
|
{
|
|
let inv2 = GetDefaultByType(storelist[j]);
|
|
int price2 = int(inv2.Stamina*(1.+.5*(storeunits[j]-1)));
|
|
if ( price > price2 ) 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
|
|
for ( int i=0; i<storelist.Size(); i++ )
|
|
{
|
|
int j = 1;
|
|
while ( j < storelist.Size() )
|
|
{
|
|
int k = j;
|
|
while ( (k > 0) && CmpInventoryClass(storelist[k-1],storelist[k]) )
|
|
{
|
|
Class<Inventory> tmp = storelist[k];
|
|
storelist[k] = storelist[k-1];
|
|
storelist[k-1] = tmp;
|
|
int tmpi = storeunits[k];
|
|
storeunits[k] = storeunits[k-1];
|
|
storeunits[k-1] = tmpi;
|
|
k--;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
else if ( 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]);
|
|
}
|
|
// readjust
|
|
if ( oldone && (lorelist.Size() != oldsiz) )
|
|
{
|
|
int idx = lorelist.Find(oldone);
|
|
if ( (idx > 0) && (idx < lorelist.Size()) )
|
|
sel0 = idx;
|
|
}
|
|
// add "new entries" message
|
|
if ( lorelib.ent.Size() != oldloresiz )
|
|
{
|
|
tmsg = StringTable.Localize("$SWWM_NEWLORE");
|
|
tmsgtic = gametic+35;
|
|
}
|
|
oldloresiz = lorelib.ent.Size();
|
|
}
|
|
// check if use succeeded
|
|
if ( checkuse && (gametic > checkuse) )
|
|
{
|
|
checkuse = 0;
|
|
int amt = players[consoleplayer].mo.CountInv(lastuse);
|
|
if ( amt == lastuseamt )
|
|
{
|
|
tmsg = StringTable.Localize("$SWWM_INVFAIL");
|
|
tmsgtic = gametic+35;
|
|
MenuSound("menu/noinvuse");
|
|
}
|
|
else
|
|
{
|
|
MenuSound(GetDefaultByType(lastuse).UseSound);
|
|
if ( (amt == 0) && (sel0 >= invlist.Size()) )
|
|
sel0 = max(0,sel0-1);
|
|
}
|
|
}
|
|
// check if drop succeeded
|
|
if ( checkdrop && (gametic > checkdrop) )
|
|
{
|
|
checkdrop = 0;
|
|
int amt = players[consoleplayer].mo.CountInv(lastuse);
|
|
if ( amt == lastuseamt )
|
|
{
|
|
tmsg = StringTable.Localize("$SWWM_INVNDROP");
|
|
tmsgtic = gametic+35;
|
|
MenuSound("menu/noinvuse");
|
|
}
|
|
else if ( (amt == 0) && (sel0 >= invlist.Size()) )
|
|
sel0 = max(0,sel0-1);
|
|
}
|
|
}
|
|
|
|
override bool OnUiEvent( UIEvent ev )
|
|
{
|
|
switch ( ev.type )
|
|
{
|
|
case UIEvent.Type_KeyDown:
|
|
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");
|
|
Close();
|
|
return true;
|
|
}
|
|
break;
|
|
case UIEvent.Type_WheelDown:
|
|
return MenuEvent(MKEY_DOWN,false);
|
|
break;
|
|
case UIEvent.Type_WheelUp:
|
|
return MenuEvent(MKEY_UP,false);
|
|
break;
|
|
}
|
|
return Super.OnUIEvent(ev);
|
|
}
|
|
|
|
override void Drawer()
|
|
{
|
|
Super.Drawer();
|
|
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.;
|
|
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"
|
|
};
|
|
static const string ltabnames[] =
|
|
{
|
|
"$SWWM_LORETAB0", "$SWWM_LORETAB1", "$SWWM_LORETAB2"
|
|
};
|
|
int mx = (curtab==TAB_SECRET)?9:8;
|
|
for ( int i=0; i<mx; i++ )
|
|
{
|
|
str = StringTable.Localize(tabnames[i]);
|
|
Screen.DrawText(TewiFont,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 += TewiFont.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 muns = SWWMCredits.Get(players[consoleplayer]);
|
|
str = String.Format("\cg¥\c-%09d",muns);
|
|
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
|
|
if ( gametic < tmsgtic ) str = StringTable.Localize(tmsg);
|
|
else
|
|
{
|
|
str = StringTable.Localize("$SWWM_MAINCONTROLS");
|
|
switch ( curtab )
|
|
{
|
|
case TAB_INVENTORY:
|
|
str = str..StringTable.Localize("$SWWM_LISTCONTROLS")..StringTable.Localize("$SWWM_INVCONTROLS");
|
|
break;
|
|
case TAB_KEYS:
|
|
str = str..StringTable.Localize("$SWWM_LISTCONTROLS");
|
|
break;
|
|
case TAB_MISSION:
|
|
case TAB_CHAT:
|
|
str = str..StringTable.Localize("$SWWM_TEXTCONTROLS");
|
|
break;
|
|
case TAB_STORE:
|
|
str = str..StringTable.Localize("$SWWM_LISTCONTROLS")..StringTable.Localize("$SWWM_STRCONTROLS");
|
|
break;
|
|
case TAB_TRADING:
|
|
if ( sub )
|
|
{
|
|
if ( sel1 == -1 ) str = str..StringTable.Localize("$SWWM_TEXTCONTROLS")..StringTable.Localize("$SWWM_TRADECONTROLS2");
|
|
else str = str..StringTable.Localize("$SWWM_LISTCONTROLS")..StringTable.Localize("$SWWM_TRADECONTROLS1");
|
|
}
|
|
else str = str..StringTable.Localize("$SWWM_TEXTCONTROLS")..StringTable.Localize("$SWWM_TRADECONTROLS0");
|
|
break;
|
|
case TAB_LIBRARY:
|
|
if ( sub ) str = str..StringTable.Localize("$SWWM_TEXTCONTROLS")..StringTable.Localize("$SWWM_LORECONTROLS1");
|
|
else str = str..StringTable.Localize("$SWWM_TEXTCONTROLS")..StringTable.Localize("$SWWM_LORECONTROLS0");
|
|
break;
|
|
}
|
|
}
|
|
xx = 4;
|
|
yy = 386;
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
str = String.Format("DemolitionOS %s",StringTable.Localize("$SWWM_MODVER"));
|
|
xx = 637-TewiFont.StringWidth(str);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// draw contents
|
|
if ( curtab == TAB_MISSION )
|
|
{
|
|
if ( gameinfo.gametype&GAME_Doom ) str = StringTable.Localize("$SWWM_MISSION_DOOM");
|
|
else if ( gameinfo.gametype&GAME_Heretic ) str = StringTable.Localize("$SWWM_MISSION_HERETIC");
|
|
else if ( gameinfo.gametype&GAME_Hexen ) str = StringTable.Localize("$SWWM_MISSION_HEXEN");
|
|
else str = StringTable.Localize("$SWWM_MISSION_NONE");
|
|
BrokenLines l = TewiFont.BreakLines(str,629);
|
|
if ( l.Count() > 28 ) l = TewiFont.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(TewiFont,Font.CR_GREEN,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 ( curtab == TAB_STATS )
|
|
{
|
|
xx = 9;
|
|
yy = 23;
|
|
// wish I could use macros for this
|
|
int thour = ((gametic-stats.lastspawn)/(3600*Thinker.TICRATE));
|
|
int tmin = ((gametic-stats.lastspawn)/(60*Thinker.TICRATE))%60;
|
|
int tsec = ((gametic-stats.lastspawn)/Thinker.TICRATE)%60;
|
|
str = String.Format("\cx%s\c-%02d\cu:\c-%02d\cu:\c-%02d",StringTable.Localize("$SWWM_STATUPTIME"),thour,tmin,tsec);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
if ( stats.grounddist > 32000. ) str = String.Format("\cx%s\c-%g\cukm\c-",StringTable.Localize("$SWWM_STATONFOOT"),stats.grounddist/32000.);
|
|
else str = String.Format("\cx%s\c-%g\cum\c-",StringTable.Localize("$SWWM_STATONFOOT"),stats.grounddist/32.);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
if ( stats.airdist > 32000. ) str = String.Format("\cx%s\c-%g\cukm\c-",StringTable.Localize("$SWWM_STATFLIGHT"),stats.airdist/32000.);
|
|
else str = String.Format("\cx%s\c-%g\cum\c-",StringTable.Localize("$SWWM_STATFLIGHT"),stats.airdist/32.);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATBOOST"),stats.boostcount);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDASH"),stats.dashcount);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATSTOMP"),stats.stompcount);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%g\cul\c-",StringTable.Localize("$SWWM_STATFUEL"),stats.fuelusage/6.);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%g\cukm/h\c-",StringTable.Localize("$SWWM_STATSPEED"),stats.topspeed*32000./(3600*Thinker.TICRATE));
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
thour = (stats.airtime/(3600*Thinker.TICRATE));
|
|
tmin = (stats.airtime/(60*Thinker.TICRATE))%60;
|
|
tsec = (stats.airtime/Thinker.TICRATE)%60;
|
|
str = String.Format("\cx%s\c-%02d\cu:\c-%02d\cu:\c-%02d",StringTable.Localize("$SWWM_STATAIRTIME"),thour,tmin,tsec);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATKILLS"),stats.kills);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDEATHS"),stats.deaths);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDDEALT"),stats.damagedealt);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDTAKEN"),stats.damagetaken);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATTDEALT"),stats.topdealt);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATTTAKEN"),stats.toptaken);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATMKILL"),stats.mkill);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\c-",StringTable.Localize("$SWWM_STATFAVWEAP"));
|
|
if ( stats.favweapon == -1 ) str = str.."N/A";
|
|
else
|
|
{
|
|
let def = GetDefaultByType(stats.wstats[stats.favweapon].w);
|
|
str = str..def.GetTag();
|
|
}
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
str = String.Format("\cx%s\cu¥\c-%09d",StringTable.Localize("$SWWM_STATHISCORE"),stats.hiscore);
|
|
Screen.DrawText(TewiFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy += 16;
|
|
}
|
|
else if ( curtab == TAB_INVENTORY )
|
|
{
|
|
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<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
if ( (invlist[i] is 'Ammo') || (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
|
|
else str = invlist[i].GetTag();
|
|
len = TewiFont.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
int clscol = Font.CR_WHITE;
|
|
if ( invlist[i] is 'Weapon' ) clscol = Font.CR_GOLD;
|
|
else if ( (invlist[i] is 'Ammo') || (invlist[i] is 'BackpackItem') || (invlist[i] is 'HammerspaceEmbiggener') ) 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;
|
|
Screen.DrawText(TewiFont,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(128,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 ( invlist.Size() > 65 )
|
|
{
|
|
// draw scrollbar
|
|
int szr = (invlist.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 ( curtab == TAB_KEYS )
|
|
{
|
|
xx = 9;
|
|
yy = 23;
|
|
int longest = 0, len;
|
|
int ofs = int(floor(max(0,sel0-44)/22.)*22);
|
|
int cols = 1;
|
|
for ( int i=0; i<invlist.Size(); i++ )
|
|
{
|
|
if ( !invlist[i] ) continue;
|
|
str = invlist[i].GetTag();
|
|
len = TewiFont.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
Screen.DrawText(TewiFont,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(128,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 ( invlist.Size() > 65 )
|
|
{
|
|
// draw scrollbar
|
|
int szr = (invlist.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 ( curtab == TAB_LIBRARY )
|
|
{
|
|
xx = 3;
|
|
yy = 14;
|
|
// draw the category
|
|
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_FIRE,origin.x+xx+(TewiFont.StringWidth("********************")-TewiFont.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,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,origin.y+yy," ‼ ",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
Screen.DrawTexture(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,sel0-26);
|
|
for ( int i=ofs; i<lorelist.Size(); i++ )
|
|
{
|
|
if ( yy > 370 ) break;
|
|
str = StringTable.Localize(lorelist[i].tag);
|
|
if ( !lorelist[i].read ) str = str.." \cf‼\c-";
|
|
Screen.DrawText(TewiFont,(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);
|
|
yy += 13;
|
|
}
|
|
xx += TewiFont.StringWidth("********************")+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() > 26 )
|
|
{
|
|
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(TewiFont,Font.CR_FIRE,origin.x+xx+((634-xx)-TewiFont.StringWidth(str))/2.,(ss.y-TewiFont.GetHeight())/2.,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
str = StringTable.Localize(lorelist[sel0].text);
|
|
BrokenLines l = TewiFont.BreakLines(str,int(635-xx));
|
|
if ( l.Count() > 28 ) l = TewiFont.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(TewiFont,Font.CR_GREEN,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 ( curtab == TAB_STORE )
|
|
{
|
|
if ( storelist.Size() <= 0 )
|
|
{
|
|
str = StringTable.Localize("$SWWM_NOSTORE");
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,(ss.x-TewiFont.StringWidth(str))/2.,(ss.y-TewiFont.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 ofs = int(floor(max(0,sel0-22)/22.)*22);
|
|
int cols = 1;
|
|
int collen[2];
|
|
for ( int i=ofs; 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 = TewiFont.StringWidth(str);
|
|
if ( len > longest ) longest = len;
|
|
collen[cols-1] = longest;
|
|
int clscol = Font.CR_WHITE;
|
|
if ( storelist[i] is 'Weapon' ) clscol = Font.CR_GOLD;
|
|
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(TewiFont,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(128,0,0,0):Color(0,0,0,0));
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += longest+96;
|
|
yy = 23;
|
|
longest = 0;
|
|
cols++;
|
|
if ( cols > 2 ) 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(def.Stamina*(1.+.5*(storeunits[i]-1)));
|
|
str = String.Format("¥%d",price);
|
|
len = TewiFont.StringWidth(str);
|
|
int clscol = Font.CR_FIRE;
|
|
if ( price > muns ) clscol = Font.CR_BLACK;
|
|
Screen.DrawText(TewiFont,clscol,origin.x+xx+collen[cols-1]+80-len,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(128,0,0,0):Color(0,0,0,0));
|
|
yy += 16;
|
|
if ( yy >= 370 )
|
|
{
|
|
xx += collen[cols-1]+96;
|
|
yy = 23;
|
|
cols++;
|
|
if ( cols > 2 ) break;
|
|
}
|
|
}
|
|
if ( storelist.Size() > 43 )
|
|
{
|
|
// draw scrollbar
|
|
int szr = (storelist.Size()/22)-1;
|
|
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 ( curtab == TAB_TRADING )
|
|
{
|
|
str = StringTable.Localize("$SWWM_COMINGSOON");
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,(ss.x-TewiFont.StringWidth(str))/2.,(ss.y-TewiFont.GetHeight())/2.,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
else if ( curtab == TAB_CHAT )
|
|
{
|
|
if ( !(StatusBar is 'SWWMStatusBar') ) return;
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
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)?tcol.GetInt():ccol.GetInt();
|
|
int thour = (bar.FullHistory[i].tic/(3600*Thinker.TICRATE));
|
|
int tmin = (bar.FullHistory[i].tic/(60*Thinker.TICRATE))%60;
|
|
int tsec = (bar.FullHistory[i].tic/Thinker.TICRATE)%60;
|
|
str = String.Format("\cu[\c-%02d\cu:\c-%02d\cu:\c-%02d\cu]\c- ",thour,tmin,tsec);
|
|
BrokenLines l = TewiFont.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(TewiFont,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 ( curtab == TAB_SECRET )
|
|
{
|
|
// hidden secret tab
|
|
Screen.DrawTexture(EasterEgg,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(TewiFont,Font.CR_FIRE,origin.x+(640-TewiFont.StringWidth(str))/2.,origin.y+350,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// voice selector
|
|
Class OptionMenuItemSWWMVoiceOption : OptionMenuItemOptionBase
|
|
{
|
|
CVar mCVar;
|
|
Array<String> types;
|
|
|
|
OptionMenuItemSWWMVoiceOption Init( String label, Name command, CVar graycheck = null, int center = 0 )
|
|
{
|
|
Super.Init(label,command,'',graycheck,center);
|
|
mCVar = CVar.FindCVar(mAction);
|
|
int lmp;
|
|
for ( lmp = Wads.FindLump("swwmvoicepack.txt"); lmp > 0; lmp = Wads.FindLump("swwmvoicepack.txt",lmp+1) )
|
|
{
|
|
Array<String> lst;
|
|
lst.Clear();
|
|
String dat = Wads.ReadLump(lmp);
|
|
dat.Split(lst,"\n",0);
|
|
for ( int i=0; i<lst.Size(); i++ )
|
|
{
|
|
if ( (lst[i].Length() <= 0) || (lst[i].GetNextCodePoint(0) == 0) || (lst[i].Left(1) == "\n") || (lst[i].Left(1) == "#") ) continue;
|
|
types.Push(lst[i]);
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
override bool SetString( int i, String newtext )
|
|
{
|
|
if ( i == OP_VALUES )
|
|
{
|
|
int cnt = types.Size();
|
|
if ( cnt >= 0 )
|
|
{
|
|
mValues = newtext;
|
|
int s = GetSelection();
|
|
if ( (s >= cnt) || (s < 0) ) s = 0;
|
|
SetSelection(s);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
override int GetSelection()
|
|
{
|
|
int Selection = -1;
|
|
int cnt = types.Size();
|
|
if ( (cnt > 0) && mCVar )
|
|
{
|
|
String cv = mCVar.GetString();
|
|
for( int i=0; i<cnt; i++ )
|
|
{
|
|
if ( cv ~== types[i] )
|
|
{
|
|
Selection = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return Selection;
|
|
}
|
|
|
|
override void SetSelection( int Selection )
|
|
{
|
|
int cnt = types.Size();
|
|
if ( (cnt > 0) && mCVar )
|
|
mCVar.SetString(types[Selection]);
|
|
}
|
|
|
|
override int Draw( OptionMenuDescriptor desc, int y, int indent, bool selected )
|
|
{
|
|
if ( mCenter ) indent = (screen.GetWidth()/2);
|
|
drawLabel(indent,y,selected?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,isGrayed());
|
|
int Selection = GetSelection();
|
|
String loc;
|
|
if ( Selection == -1 ) loc = "Unknown";
|
|
else
|
|
{
|
|
String uptxt = types[Selection];
|
|
uptxt.MakeUpper();
|
|
String str = String.Format("SWWM_VOICENAME_%s",uptxt);
|
|
loc = StringTable.Localize(str,false);
|
|
if ( str == loc ) loc = types[Selection];
|
|
}
|
|
drawValue(indent,y,OptionMenuSettings.mFontColorValue,loc,isGrayed());
|
|
return indent;
|
|
}
|
|
|
|
override bool MenuEvent( int mkey, bool fromcontroller )
|
|
{
|
|
int cnt = types.Size();
|
|
if ( cnt > 0 )
|
|
{
|
|
int Selection = GetSelection();
|
|
if ( mkey == Menu.MKEY_Left )
|
|
{
|
|
if ( Selection == -1 ) Selection = 0;
|
|
else if ( --Selection < 0 ) Selection = cnt-1;
|
|
}
|
|
else if ( (mkey == Menu.MKEY_Right) || (mkey == Menu.MKEY_Enter) )
|
|
{
|
|
if ( ++Selection >= cnt ) Selection = 0;
|
|
}
|
|
else return OptionMenuItem.MenuEvent(mkey,fromcontroller);
|
|
SetSelection(Selection);
|
|
Menu.MenuSound("menu/change");
|
|
}
|
|
else return OptionMenuItem.MenuEvent(mkey,fromcontroller);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// option menu /w tooltips
|
|
Class SWWMOptionMenu : OptionMenu
|
|
{
|
|
private String ttip;
|
|
|
|
override void Ticker()
|
|
{
|
|
Super.Ticker();
|
|
// fetch the tooltip for whatever's selected (if any)
|
|
if ( mDesc.mSelectedItem == -1 ) return;
|
|
String mcvar = mDesc.mItems[mDesc.mSelectedItem].GetAction();
|
|
mcvar.Replace(" ","_"); // need to strip whitespace for command actions
|
|
String locstr = String.Format("TOOLTIP_%s",mcvar);
|
|
ttip = StringTable.Localize(locstr,false);
|
|
if ( ttip == locstr ) ttip = "";
|
|
}
|
|
override void Drawer()
|
|
{
|
|
Super.Drawer();
|
|
if ( ttip == "" ) return;
|
|
// re-evaluate y to check where the cursor is
|
|
int cy = 0;
|
|
int y = mDesc.mPosition;
|
|
if ( y <= 0 )
|
|
{
|
|
let font = generic_ui||!mDesc.mFont?NewSmallFont:mDesc.mFont;
|
|
if ( font && (mDesc.mTitle.Length() > 0) )
|
|
y = -y+font.GetHeight();
|
|
else y = -y;
|
|
}
|
|
int fontheight = OptionMenuSettings.mLinespacing*CleanYfac_1;
|
|
y *= CleanYfac_1;
|
|
int lastrow = Screen.GetHeight()-OptionHeight()*CleanYfac_1;
|
|
for ( int i=0; ((i < mDesc.mItems.Size()) && (y <= lastrow)); i++ )
|
|
{
|
|
// Don't scroll the uppermost items
|
|
if ( i == mDesc.mScrollTop )
|
|
{
|
|
i += mDesc.mScrollPos;
|
|
if ( i >= mDesc.mItems.Size() ) break; // skipped beyond end of menu
|
|
}
|
|
y += fontheight;
|
|
if ( mDesc.mSelectedItem == i )
|
|
{
|
|
cy = y;
|
|
break;
|
|
}
|
|
}
|
|
let fnt = Font.GetFont('Tewi');
|
|
let lines = fnt.BreakLines(ttip,CleanWidth_1-8);
|
|
int height = (8+fnt.GetHeight()*lines.Count())*CleanYFac_1;
|
|
// draw at the bottom unless the selected option could is covered by the tooltip
|
|
int ypos = Screen.GetHeight()-height;
|
|
if ( cy >= ypos ) ypos = 0;
|
|
Screen.Dim("Black",.75,0,ypos,Screen.GetWidth(),height);
|
|
ypos += 4*CleanYFac_1;
|
|
for ( int i=0; i<lines.Count(); i++ )
|
|
{
|
|
Screen.DrawText(fnt,Font.CR_WHITE,4*CleanXFac_1,ypos,lines.StringAt(i),DTA_CleanNoMove_1,true);
|
|
ypos += fnt.GetHeight()*CleanYFac_1;
|
|
}
|
|
}
|
|
} |