620 lines
19 KiB
Text
620 lines
19 KiB
Text
// shoppin'
|
|
|
|
Class DemolitionistStoreTab : DemolitionistMenuTab
|
|
{
|
|
DemolitionistMenuList invlist[2];
|
|
bool bDisabled;
|
|
bool bSell;
|
|
int ofs, maxofs, maxw;
|
|
double smofs;
|
|
bool drag;
|
|
|
|
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 = 8;
|
|
else if ( (a is 'Armor') || (a is 'SWWMSpareArmor') ) ta = 7;
|
|
else if ( da.bINVBAR ) 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 = 8;
|
|
else if ( (b is 'Armor') || (b is 'SWWMSpareArmor') ) tb = 7;
|
|
else if ( db.bINVBAR ) 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_store( Array<DemolitionistMenuListItem> a, int l, int h )
|
|
{
|
|
DemolitionistMenuListItem pv = a[h];
|
|
int i = (l-1);
|
|
for ( int j=l; j<=(h-1); j++ )
|
|
{
|
|
if ( CmpInventoryClass(DemolitionistMenuStoreItem(pv).inv,DemolitionistMenuStoreItem(a[j]).inv) )
|
|
{
|
|
i++;
|
|
DemolitionistMenuListItem tmp = a[j];
|
|
a[j] = a[i];
|
|
a[i] = tmp;
|
|
}
|
|
}
|
|
DemolitionistMenuListItem tmp = a[h];
|
|
a[h] = a[i+1];
|
|
a[i+1] = tmp;
|
|
return i+1;
|
|
}
|
|
private void qsort_store( Array<DemolitionistMenuListItem> a, int l, int h )
|
|
{
|
|
if ( l >= h ) return;
|
|
int p = partition_store(a,l,h);
|
|
qsort_store(a,l,p-1);
|
|
qsort_store(a,p+1,h);
|
|
}
|
|
|
|
override DemolitionistMenuTab Init( DemolitionistMenu master )
|
|
{
|
|
title = StringTable.Localize("$SWWM_STORETAB");
|
|
bDisabled = (deathmatch||(G_SkillPropertyInt(SKILLP_ACSReturn)>=4)||master.hnd.gdat.disablestore);
|
|
return Super.Init(master);
|
|
}
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( invlist[0] ) invlist[0].Destroy();
|
|
if ( invlist[1] ) invlist[1].Destroy();
|
|
}
|
|
|
|
override void OnSelect()
|
|
{
|
|
bSell = master.shnd.menustate.At("WasSelling").ToInt();
|
|
smofs = ofs;
|
|
}
|
|
override void OnDeselect()
|
|
{
|
|
master.shnd.menustate.Insert("WasSelling",String.Format("%d",bSell));
|
|
smofs = ofs;
|
|
}
|
|
|
|
private bool FilterStore( Class<Inventory> type, Inventory cur, readonly<Inventory> inv )
|
|
{
|
|
// no collectibles
|
|
if ( type is 'SWWMCollectible' ) return true;
|
|
// no barriers outside doom
|
|
if ( !(gameinfo.gametype&GAME_DOOM) && (type is 'EBarrier') ) return true;
|
|
// no gravity/tether outside raven
|
|
if ( !(gameinfo.gametype&GAME_RAVEN) && ((type is 'GravitySuppressor') || (type is 'SafetyTether')) ) return true;
|
|
// can't sell candygun spares if we already own a Candy Gun
|
|
if ( bSell && (type is 'CandyGunSpares') && players[consoleplayer].mo.FindInventory("CandyGun") ) return true;
|
|
// skip items we don't own or are depleted if selling
|
|
if ( bSell && (!cur || (cur.Amount <= 0)) ) return true;
|
|
else if ( !bSell )
|
|
{
|
|
// skip maxed items if buying
|
|
if ( cur && (cur.Amount >= cur.MaxAmount) ) return true;
|
|
// 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 ) return true;
|
|
}
|
|
// skip unimplemented weapons
|
|
if ( type is 'Weapon' )
|
|
{
|
|
let ready = inv.FindState("Ready");
|
|
if ( !ready || !ready.ValidateSpriteFrame() ) return true;
|
|
}
|
|
// ignore child ammos
|
|
if ( (type is 'Ammo') && (type.GetParentClass() != 'SWWMAmmo') ) return true;
|
|
if ( (type is 'MagAmmo') && (type.GetParentClass() != 'MagAmmo') ) return true;
|
|
// items must have a set price
|
|
if ( inv.Stamina == 0 ) return true;
|
|
// items with negative stamina can only be sold
|
|
if ( (inv.Stamina < 0) && !bSell ) return true;
|
|
return false;
|
|
}
|
|
|
|
override void Ticker()
|
|
{
|
|
if ( bDisabled ) return; // do nothing
|
|
bool mustsort = false;
|
|
bool skipsel = false;
|
|
// only update active list to reduce perf hit
|
|
if ( !invlist[bSell] )
|
|
{
|
|
mustsort = true;
|
|
skipsel = true;
|
|
// initialize
|
|
invlist[bSell] = new("DemolitionistMenuList");
|
|
invlist[bSell].master = master;
|
|
invlist[bSell].selected = 0;
|
|
}
|
|
// check if current entries must be deleted
|
|
for ( int i=0; i<invlist[bSell].items.Size(); i++ )
|
|
{
|
|
let type = DemolitionistMenuStoreItem(invlist[bSell].items[i]).inv;
|
|
let cur = players[consoleplayer].mo.FindInventory(type);
|
|
let inv = GetDefaultByType(type);
|
|
if ( !FilterStore(type,cur,inv) ) continue;
|
|
invlist[bSell].items[i].Destroy();
|
|
invlist[bSell].items.Delete(i);
|
|
if ( invlist[bSell].selected > i ) invlist[bSell].selected = max(0,invlist[bSell].selected-1);
|
|
i--;
|
|
}
|
|
foreach ( cls:AllActorClasses )
|
|
{
|
|
let type = (Class<Inventory>)(cls);
|
|
if ( !type ) continue;
|
|
let cur = players[consoleplayer].mo.FindInventory(type);
|
|
let inv = GetDefaultByType(type);
|
|
if ( FilterStore(type,cur,inv) ) continue;
|
|
// skip if it's already there
|
|
bool skipme = false;
|
|
foreach ( i:invlist[bSell].items )
|
|
{
|
|
if ( DemolitionistMenuStoreItem(i).inv != type ) continue;
|
|
skipme = true;
|
|
break;
|
|
}
|
|
if ( skipme ) continue;
|
|
// insert sorted by unit price
|
|
bool greater = false;
|
|
for ( int j=0; j<invlist[bSell].items.Size(); j++ )
|
|
{
|
|
let inv2 = GetDefaultByType(DemolitionistMenuStoreItem(invlist[bSell].items[j]).inv);
|
|
if ( abs(inv.Stamina) > abs(inv2.Stamina) ) continue;
|
|
greater = true;
|
|
invlist[bSell].items.Insert(j,new("DemolitionistMenuStoreItem").Init(master,type,bSell));
|
|
mustsort = true;
|
|
break;
|
|
}
|
|
if ( greater ) continue;
|
|
invlist[bSell].items.Push(new("DemolitionistMenuStoreItem").Init(master,type,bSell));
|
|
mustsort = true;
|
|
}
|
|
// don't do anything if empty
|
|
if ( invlist[bSell].items.Size() <= 0 ) return;
|
|
// sort inventory
|
|
if ( mustsort )
|
|
{
|
|
DemolitionistMenuListItem csel = invlist[bSell].items[invlist[bSell].selected];
|
|
qsort_store(invlist[bSell].items,0,invlist[bSell].items.Size()-1);
|
|
let idx = invlist[bSell].items.Find(csel);
|
|
if ( !skipsel && (idx != invlist[bSell].items.Size()) && (idx != invlist[bSell].selected) )
|
|
invlist[bSell].selected = idx;
|
|
}
|
|
// rearrange all item positions
|
|
maxofs = 0;
|
|
maxw = 0;
|
|
foreach ( i:invlist[bSell].items )
|
|
{
|
|
let fw = DemolitionistMenuStoreItem(i).GetFullWidth();
|
|
if ( fw > maxw ) maxw = fw;
|
|
}
|
|
int xx = 0;
|
|
int yy = 0;
|
|
foreach ( i:invlist[bSell].items )
|
|
{
|
|
maxofs = max(maxofs,xx+maxw-16);
|
|
DemolitionistMenuStoreItem(i).width = maxw;
|
|
i.xpos = xx;
|
|
i.ypos = yy;
|
|
yy += 16;
|
|
if ( yy > (master.ws.y-62) )
|
|
{
|
|
xx += maxw;
|
|
yy = 0;
|
|
}
|
|
}
|
|
maxofs = max(0,maxofs-int(master.ws.x-18));
|
|
if ( ofs > maxofs ) smofs = ofs = maxofs;
|
|
// update smooth scroll
|
|
smofs = (smofs*.6)+(ofs*.4);
|
|
if ( abs(smofs-ofs) < (1./master.hs) ) smofs = ofs;
|
|
// tick the list
|
|
invlist[bSell].Ticker();
|
|
}
|
|
|
|
// called when sending a scroll input
|
|
// returns true if the position actually changed
|
|
// speed: how many pixels to move (either back or forward)
|
|
bool Scroll( int speed )
|
|
{
|
|
if ( maxofs <= 0 ) return false;
|
|
int oldofs = ofs;
|
|
ofs = clamp(ofs+speed,0,maxofs);
|
|
return (ofs != oldofs);
|
|
}
|
|
// called when clicking on our scrollbar
|
|
// returns true if the position actually changed
|
|
// x: relative click position
|
|
bool SetOffset( double x )
|
|
{
|
|
if ( maxofs <= 0 ) return false;
|
|
int oldofs = ofs;
|
|
ofs = clamp(int(round((x-5.)/((master.ws.x-10.)/maxofs))),0,maxofs);
|
|
return (ofs != oldofs);
|
|
}
|
|
// called when keyboard scrolling
|
|
void KBScroll()
|
|
{
|
|
if ( maxofs <= 0 ) return;
|
|
int minx = (invlist[bSell].items[invlist[bSell].selected].xpos+maxw-16)-int(master.ws.x-18);
|
|
int maxx = invlist[bSell].items[invlist[bSell].selected].xpos;
|
|
if ( ofs < minx ) ofs = clamp(minx,0,maxofs);
|
|
else if ( ofs > maxx ) ofs = clamp(maxx,0,maxofs);
|
|
}
|
|
|
|
override void MenuInput( int key )
|
|
{
|
|
if ( bDisabled ) return; // do nothing
|
|
if ( key == MK_BACK )
|
|
{
|
|
bSell = !bSell;
|
|
master.MenuSound(bSell?"menu/demosel":"menu/democlose");
|
|
if ( invlist[bSell] && (invlist[bSell].items.Size() > 0) )
|
|
{
|
|
invlist[bSell].selected = 0;
|
|
KBScroll();
|
|
}
|
|
return;
|
|
}
|
|
if ( !invlist[bSell] || (invlist[bSell].items.Size() <= 0) ) return;
|
|
switch ( key )
|
|
{
|
|
case MK_LEFT:
|
|
int prev = max(0,invlist[bSell].selected-22);
|
|
if ( prev == invlist[bSell].selected ) break;
|
|
invlist[bSell].selected = prev;
|
|
master.MenuSound("menu/demoscroll");
|
|
KBScroll();
|
|
break;
|
|
case MK_RIGHT:
|
|
int next = min(invlist[bSell].items.Size()-1,invlist[bSell].selected+22);
|
|
if ( next == invlist[bSell].selected ) break;
|
|
invlist[bSell].selected = next;
|
|
master.MenuSound("menu/demoscroll");
|
|
KBScroll();
|
|
break;
|
|
case MK_DOWN:
|
|
if ( invlist[bSell].selected < invlist[bSell].items.Size()-1 )
|
|
{
|
|
invlist[bSell].selected++;
|
|
master.MenuSound("menu/demoscroll");
|
|
KBScroll();
|
|
}
|
|
break;
|
|
case MK_UP:
|
|
if ( invlist[bSell].selected > 0 )
|
|
{
|
|
invlist[bSell].selected--;
|
|
master.MenuSound("menu/demoscroll");
|
|
KBScroll();
|
|
}
|
|
break;
|
|
case MK_ENTER:
|
|
if ( invlist[bSell].selected >= invlist[bSell].items.Size() ) break;
|
|
DemolitionistMenuStoreItem(invlist[bSell].items[invlist[bSell].selected]).BuySellItem();
|
|
break;
|
|
}
|
|
}
|
|
override void MouseInput( Vector2 pos, int btn )
|
|
{
|
|
if ( bDisabled ) return; // do nothing
|
|
if ( btn == MB_RIGHT )
|
|
{
|
|
// just toggle buy/sell
|
|
MenuInput(MK_BACK);
|
|
return;
|
|
}
|
|
if ( !invlist[bSell] || (invlist[bSell].items.Size() <= 0) ) return;
|
|
switch ( btn )
|
|
{
|
|
case MB_LEFT:
|
|
// see if we're clicking the scrollbar (if it exists)
|
|
if ( pos.y > (master.ws.y-21) )
|
|
{
|
|
if ( SetOffset(pos.x) )
|
|
{
|
|
master.MenuSound("menu/demoscroll");
|
|
drag = true;
|
|
}
|
|
break;
|
|
}
|
|
// find which element we clicked
|
|
for ( int i=0; i<invlist[bSell].items.Size(); i++ )
|
|
{
|
|
if ( !invlist[bSell].items[i].CheckBounds((pos.x-9)+smofs,pos.y-23) )
|
|
continue;
|
|
invlist[bSell].selected = i;
|
|
KBScroll();
|
|
// buy/sell it
|
|
MenuInput(MK_ENTER);
|
|
break;
|
|
}
|
|
break;
|
|
case MB_WHEELUP:
|
|
if ( Scroll(-maxw/16) ) master.MenuSound("menu/demoscroll");
|
|
break;
|
|
case MB_WHEELDOWN:
|
|
if ( Scroll(maxw/16) ) master.MenuSound("menu/demoscroll");
|
|
break;
|
|
case MB_DRAG:
|
|
if ( drag ) SetOffset(pos.x);
|
|
break;
|
|
case MB_RELEASE:
|
|
drag = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
override void Drawer( double fractic )
|
|
{
|
|
if ( bDisabled )
|
|
{
|
|
String str = StringTable.Localize("$SWWM_NOSTORE");
|
|
double xx = int(master.ws.x-master.mSmallFont.StringWidth(str))/2;
|
|
double yy = int(master.ws.y-master.mSmallFont.GetHeight())/2;
|
|
Screen.DrawText(master.mSmallFont,Font.CR_FIRE,master.origin.x+xx,master.origin.y+yy,str,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
if ( !invlist[bSell] || (invlist[bSell].items.Size() <= 0) )
|
|
{
|
|
String str = StringTable.Localize(bSell?"$SWWM_NOSTORESELL":"$SWWM_NOSTOREBUY");
|
|
double xx = int(master.ws.x-master.mSmallFont.StringWidth(str))/2;
|
|
double yy = int(master.ws.y-master.mSmallFont.GetHeight())/2;
|
|
Screen.DrawText(master.mSmallFont,Font.CR_FIRE,master.origin.x+xx,master.origin.y+yy,str,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
double xx = 9;
|
|
double yy = 23;
|
|
Screen.SetClipRect(int((master.origin.x+9)*master.hs),int((master.origin.y+23)*master.hs),int((master.ws.x-18)*master.hs),int((master.ws.y-46)*master.hs));
|
|
double ssmofs = (smofs~==ofs)?smofs:(smofs*(1.-fractic)+((smofs*.6)+(ofs*.4))*fractic);
|
|
invlist[bSell].Drawer((xx-ssmofs,yy));
|
|
Screen.ClearClipRect();
|
|
if ( maxofs <= 0 ) return;
|
|
yy = master.ws.y-21;
|
|
master.DrawHSeparator(0,yy,master.ws.x);
|
|
yy -= 4;
|
|
xx = floor(ssmofs*((master.ws.x-10)/maxofs))+2;
|
|
Screen.DrawText(master.mSmallFont,Font.CR_FIRE,master.origin.x+xx,master.origin.y+yy,"▬",DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
|
|
// store item (buy/sell)
|
|
Class DemolitionistMenuStoreItem : DemolitionistMenuListItem
|
|
{
|
|
Class<Inventory> inv;
|
|
int col;
|
|
bool bSell;
|
|
String pricelabel;
|
|
int width;
|
|
|
|
DemolitionistMenuStoreItem Init( DemolitionistMenu master, Class<Inventory> i, bool bSell = false )
|
|
{
|
|
Super.Init(master,"");
|
|
inv = i;
|
|
col = Font.CR_WHITE;
|
|
let def = GetDefaultByType(i);
|
|
if ( i is 'Weapon' ) col = SWWMUtility.IsVIPItemClass(i)?Font.FindFontColor('VIPGold'):Font.CR_GOLD;
|
|
else if ( i is 'MagAmmo' ) col = SWWMUtility.IsVIPItemClass(i)?Font.FindFontColor('VIPTan'):Font.CR_TAN;
|
|
else if ( (i is 'BackpackItem') || (i is 'HammerspaceEmbiggener') ) col = Font.CR_DARKBROWN;
|
|
else if ( i is 'Ammo' ) col = SWWMUtility.IsVIPItemClass(i)?Font.FindFontColor('VIPBrown'):Font.CR_BROWN;
|
|
else if ( (i is 'PowerupGiver') || (i is 'AmmoFabricator') || def.bBIGPOWERUP ) col = SWWMUtility.IsVIPItemClass(i)?Font.FindFontColor('VIPPurple'):Font.CR_PURPLE;
|
|
else if ( (i is 'Health') || (i is 'HealthPickup') || (i is 'SWWMHealth') ) col = Font.CR_RED;
|
|
else if ( (i is 'Armor') || (i is 'SWWMSpareArmor') ) col = Font.CR_GREEN;
|
|
else if ( def.bINVBAR ) col = Font.CR_CYAN;
|
|
self.bSell = bSell;
|
|
UpdateLabel();
|
|
return self;
|
|
}
|
|
|
|
// used for the store display calculation
|
|
int GetFullWidth()
|
|
{
|
|
return master.mSmallFont.StringWidth(label)+96+master.mSmallFont.StringWidth(pricelabel);
|
|
}
|
|
|
|
// so the prices don't get cut off
|
|
override Vector2 GetDrawBounds()
|
|
{
|
|
return (width-16,GetHeight());
|
|
}
|
|
|
|
// also checks for clicking on the price
|
|
override bool CheckBounds( double x, double y )
|
|
{
|
|
if ( Super.CheckBounds(x,y) ) return true;
|
|
int ofs = (width-16)-master.mSmallFont.StringWidth(pricelabel);
|
|
if ( x < xpos+ofs ) return false;
|
|
if ( y < ypos ) return false;
|
|
if ( x > xpos+width ) return false;
|
|
if ( y > ypos+GetHeight() ) return false;
|
|
return true;
|
|
}
|
|
|
|
// get the score to pay/receive and the units to buy/sell
|
|
int, int GetPriceUnits()
|
|
{
|
|
let def = GetDefaultByType(inv);
|
|
let cur = players[consoleplayer].mo.FindInventory(inv);
|
|
int amt = def.Amount;
|
|
int price = int(abs(def.Stamina)*(1.+.75*(amt-1)));
|
|
if ( inv is 'Ammo' )
|
|
{
|
|
int maxamt;
|
|
if ( bSell ) maxamt = cur.Amount; // we can sell ALL our ammo
|
|
else maxamt = cur?(cur.MaxAmount-cur.Amount):def.MaxAmount;
|
|
// get the largest affordable child pickup amount (that we need, or we can sell)
|
|
foreach ( cls:AllActorClasses )
|
|
{
|
|
let inv2 = (Class<Ammo>)(cls);
|
|
if ( !inv2 || (inv2.GetParentClass() != inv) ) continue;
|
|
let def2 = GetDefaultByType(inv2);
|
|
int cprice = int(abs(def.Stamina)*(1.+.75*(def2.Amount-1)));
|
|
if ( (def2.Amount > amt) && (def2.Amount <= maxamt) && (bSell || SWWMCredits.CanTake(players[consoleplayer],cprice)) )
|
|
{
|
|
price = cprice;
|
|
amt = def2.Amount;
|
|
}
|
|
}
|
|
}
|
|
else if ( inv is 'MagAmmo' )
|
|
{
|
|
// never bought, only sold
|
|
int maxamt = cur.Amount;
|
|
// get the largest affordable child pickup amount (that we can sell)
|
|
foreach ( cls:AllActorClasses )
|
|
{
|
|
let inv2 = (Class<MagAmmo>)(cls);
|
|
if ( !inv2 || (inv2.GetParentClass() != inv) ) continue;
|
|
let def2 = GetDefaultByType(inv2);
|
|
int cprice = int(abs(def.Stamina)*(1.+.75*(def2.Amount-1)));
|
|
if ( (def2.Amount > amt) && (def2.Amount <= maxamt) )
|
|
{
|
|
price = cprice;
|
|
amt = def2.Amount;
|
|
}
|
|
}
|
|
}
|
|
if ( bSell && (inv is 'Weapon') )
|
|
{
|
|
let w = GetDefaultByType((Class<Weapon>)(inv));
|
|
// 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(abs(am1.Stamina)*(1.+.75*(w.AmmoGive1-1)));
|
|
}
|
|
if ( w.AmmoType2 && (w.AmmoGive2 > 0) )
|
|
{
|
|
let am2 = GetDefaultByType(w.AmmoType2);
|
|
if ( am2.Stamina != 0 ) price -= int(abs(am2.Stamina)*(1.+.75*(w.AmmoGive2-1)));
|
|
}
|
|
}
|
|
// sell at half price
|
|
if ( bSell ) price = int(abs(def.Stamina)*amt)/2;
|
|
return price, amt;
|
|
}
|
|
|
|
// formatted name
|
|
private void UpdateLabel()
|
|
{
|
|
int price, amt;
|
|
[price, amt] = GetPriceUnits();
|
|
let def = GetDefaultByType(inv);
|
|
if ( bSell )
|
|
{
|
|
pricelabel = String.Format("\cd¥%d\c-",price);
|
|
int cur = (inv is 'CandyGun')?(players[consoleplayer].mo.CountInv("CandyGunSpares")+1):players[consoleplayer].mo.CountInv(inv);
|
|
if ( (cur > 1) || (inv is 'Ammo') || (inv is 'MagAmmo') ) label = String.Format("%s (%d/%d)",def.GetTag(),amt,cur);
|
|
else label = def.GetTag();
|
|
}
|
|
else
|
|
{
|
|
if ( price > master.muns ) pricelabel = String.Format("\cm¥%d\c-",price);
|
|
else pricelabel = String.Format("\cx¥%d\cx",price);
|
|
if ( (amt > 1) || (inv is 'Ammo') || (inv is 'MagAmmo') ) label = String.Format("%dx %s",amt,def.GetTag());
|
|
else label = def.GetTag();
|
|
}
|
|
}
|
|
|
|
override void Ticker()
|
|
{
|
|
UpdateLabel();
|
|
}
|
|
|
|
override void Drawer( Vector2 pos, bool selected )
|
|
{
|
|
Screen.DrawText(master.mSmallFont,col,master.origin.x+pos.x,master.origin.y+pos.y,label,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,selected?Color(0,0,0,0):Color(96,0,0,0));
|
|
Screen.DrawText(master.mSmallFont,Font.CR_UNTRANSLATED,master.origin.x+pos.x+(width-16)-master.mSmallFont.StringWidth(pricelabel),master.origin.y+pos.y,pricelabel,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,selected?Color(0,0,0,0):Color(96,0,0,0));
|
|
}
|
|
|
|
void BuySellItem()
|
|
{
|
|
int price, amt;
|
|
[price, amt] = GetPriceUnits();
|
|
if ( bSell )
|
|
{
|
|
EventHandler.SendNetworkEvent(String.Format("swwmstoretake.%s",inv.GetClassName()),consoleplayer,price,amt);
|
|
master.MenuSound("menu/buyinv");
|
|
return;
|
|
}
|
|
if ( !SWWMCredits.CanTake(players[consoleplayer],price) )
|
|
{
|
|
master.MenuSound("menu/noinvuse");
|
|
master.tmsg = StringTable.Localize("$SWWM_STOREMUNS");
|
|
master.tmsgtic = Menu.MenuTime()+70;
|
|
return;
|
|
}
|
|
if ( (inv is 'SWWMWeapon') && swwm_swapweapons )
|
|
{
|
|
// check swapweapon
|
|
let wpn = GetDefaultByType((Class<SWWMWeapon>)(inv));
|
|
let sw = wpn.HasSwapWeapon(players[consoleplayer].mo);
|
|
if ( sw )
|
|
{
|
|
master.MenuSound("menu/noinvuse");
|
|
master.tmsg = String.Format(StringTable.Localize("$SWWM_STORESWAP"),sw.GetTag());
|
|
master.tmsgtic = Menu.MenuTime()+70;
|
|
return;
|
|
}
|
|
}
|
|
let cur = players[consoleplayer].mo.FindInventory(inv);
|
|
int camt, max;
|
|
if ( cur )
|
|
{
|
|
camt = cur.Amount;
|
|
max = cur.MaxAmount;
|
|
}
|
|
else
|
|
{
|
|
camt = 0;
|
|
max = GetDefaultByType(inv).MaxAmount;
|
|
}
|
|
if ( (max > 0) && (camt >= max) )
|
|
{
|
|
master.MenuSound("menu/noinvuse");
|
|
master.tmsg = StringTable.Localize("$SWWM_STOREFULL");
|
|
master.tmsgtic = Menu.MenuTime()+70;
|
|
return;
|
|
}
|
|
EventHandler.SendNetworkEvent(String.Format("swwmstoregive.%s",inv.GetClassName()),consoleplayer,price,amt);
|
|
master.MenuSound("menu/buyinv");
|
|
}
|
|
}
|