diff --git a/TODO.md b/TODO.md index cad6e686b..68d842ea0 100644 --- a/TODO.md +++ b/TODO.md @@ -1,12 +1,10 @@ Fundamental things: - - Eviscerator - Hellblazer - Sparkster - Silver Bullet - Ynykron - Wallbuster - Custom intermission - - Trading tab Extra things: - Art for custom intermission diff --git a/language.def b/language.def index cb2d661db..6cc82ae56 100644 --- a/language.def +++ b/language.def @@ -143,7 +143,6 @@ SWWM_STOREMUNS = "You don't have enough money"; SWWM_NOSTORE = "(there is nothing left to buy)"; SWWM_TRADETAB = "Trading"; SWWM_TRADEFULL = "They can't hold more of that"; -SWWM_TRADEHIST = "History"; SWWM_TRADETO = "Sent to"; SWWM_TRADEFROM = "Received from"; SWWM_NOTRADE = "(there is no one to trade with)"; @@ -207,7 +206,8 @@ SWWM_HELPTXT = "\cx---------------------------\c-\n" "\n" "\cfUp/Down:\c- Navigate\n" -"\cfEnter:\c- Select option\n" +"\cfEnter:\c- Select recipient\n" +"\cfBackspace:\c- History\n" "\n" "\cxTrading Tab - Controls (Trade)\c-\n" "\cx----------------------------\c-\n" diff --git a/language.es b/language.es index 2bc5f797c..e3a1d397c 100644 --- a/language.es +++ b/language.es @@ -139,7 +139,6 @@ SWWM_STOREMUNS = "No tienes suficiente dinero"; SWWM_NOSTORE = "(no queda nada que comprar)"; SWWM_TRADETAB = "Intercambio"; SWWM_TRADEFULL = "No puede llevar más de eso"; -SWWM_TRADEHIST = "Historial"; SWWM_TRADETO = "Enviado a"; SWWM_TRADEFROM = "Recibido de"; SWWM_NOTRADE = "(no hay nadie con quien intercambiar)"; @@ -203,7 +202,8 @@ SWWM_HELPTXT = "\cx---------------------------\c-\n" "\n" "\cfArriba/Abajo:\c- Navegar\n" -"\cfEnter:\c- Elegir opción\n" +"\cfEnter:\c- Elegir destinatario\n" +"\cfRetroceso:\c- Historial\n" "\n" "\cxPestaña de Intercambio - Controles (Intercambio)\c-\n" "\cx----------------------------\c-\n" diff --git a/modeldef.misc b/modeldef.misc new file mode 100644 index 000000000..006277688 --- /dev/null +++ b/modeldef.misc @@ -0,0 +1,14 @@ +Model "ReflectedBullet" +{ + Path "models" + + Model 0 "Boolet_d.3d" + Skin 0 "Boolet.png" + Scale 0.003 0.003 0.003 + USEACTORPITCH + USEACTORROLL + AngleOffset -90 + ZOffset 1 + + FrameIndex XZW1 A 0 0 +} diff --git a/zscript/swwm_common.zsc b/zscript/swwm_common.zsc index ee45e0f8c..7ecf17086 100644 --- a/zscript/swwm_common.zsc +++ b/zscript/swwm_common.zsc @@ -182,8 +182,9 @@ Class SWWMCredits : Thinker // Trading history between players Class SWWMTrade { - int timestamp, type; - String other, what; + int timestamp, type, amt; + String other; + Class what; } Class SWWMTradeHistory : Thinker @@ -191,26 +192,28 @@ Class SWWMTradeHistory : Thinker PlayerInfo myplayer; Array ent; - static void RegisterSend( PlayerInfo p, PlayerInfo other, String what ) + static void RegisterSend( PlayerInfo p, PlayerInfo other, Class what, int amt ) { let th = Find(p); if ( !th ) return; SWWMTrade t = new("SWWMTrade"); - t.timestamp = gametic; + t.timestamp = level.totaltime; t.type = 0; t.other = other.GetUserName(); t.what = what; + t.amt = amt; th.ent.Push(t); } - static void RegisterReceive( PlayerInfo p, PlayerInfo other, String what ) + static void RegisterReceive( PlayerInfo p, PlayerInfo other, Class what, int amt ) { let th = Find(p); if ( !th ) return; SWWMTrade t = new("SWWMTrade"); - t.timestamp = gametic; + t.timestamp = level.totaltime; t.type = 1; t.other = other.GetUserName(); t.what = what; + t.amt = amt; th.ent.Push(t); } @@ -659,6 +662,59 @@ Class SWWMCombatTracker : Thinker } } +// Press F to Pay Respects +Class PayRespects : HUDMessageBase +{ + Vector2 basepos; + int lifespan, initialspan, starttic; + transient Font TewiFont; + double scale; + Vector2 hs, ss; + int seed, seed2; + + static PayRespects PressF() + { + let f = new("PayRespects"); + f.basepos = (FRandom[FInTheChat](0.,1.),FRandom[FInTheChat](1.02,1.05)); + f.scale = FRandom[FInTheChat](.5,2.); + f.lifespan = f.initialspan = Random[FInTheChat](20,80); + f.starttic = level.maptime; + f.seed = Random[FInTheChat](); + f.seed2 = Random[FInTheChat](); + f.ScreenSizeChanged(); + return f; + } + + override bool Tick() + { + lifespan--; + return (lifespan<=0); + } + + override void ScreenSizeChanged() + { + hs = StatusBar.GetHUDScale()*scale; + ss = (Screen.GetWidth()/hs.x,Screen.GetHeight()/hs.y); + } + + override void Draw( int bottom, int visibility ) + { + Vector2 realpos = (basepos.x*ss.x,basepos.y*ss.y); + if ( !TewiFont ) TewiFont = Font.GetFont('TewiShaded'); + Vector2 fo = (TewiFont.StringWidth("F")/2.,-TewiFont.GetHeight()); + // F rise up + int initspd = (128-seed); + if ( (initspd >= 0) && (initspd < 32) ) initspd = 32; + if ( (initspd < 0) && (initspd > -32) ) initspd = -32; + int boostup = 32+(seed2/4); + double fractic = SWWMStatusBar(statusbar)?SWWMStatusBar(statusbar).fractic:0; + fo.x += (.15*initspd)*((initialspan-(lifespan-fractic))**.6); + fo.y += ((initialspan-(lifespan-fractic))**1.6)-boostup*sin((90./initialspan)*(level.maptime+fractic-starttic)); + double alph = clamp((lifespan+fractic)/double(initialspan),0.,1.); + Screen.DrawText(TewiFont,Font.CR_GREEN,realpos.x-fo.x,realpos.y-fo.y,"F",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph); + } +} + // One-liners Class SWWMOneLiner : HUDMessageBase { @@ -1393,6 +1449,8 @@ Class SWWMHandler : EventHandler int multilevel[MAXPLAYERS]; int lastitemcount[MAXPLAYERS]; bool allkills, allitems, allsecrets; + // for money cheat + transient ui int kcode; // heal/armor flashes need to be handled here so they don't stack transient int hflash[MAXPLAYERS], aflash[MAXPLAYERS]; @@ -2003,6 +2061,41 @@ Class SWWMHandler : EventHandler } } + override bool InputProcess( InputEvent e ) + { + if ( e.Type == InputEvent.TYPE_KeyDown ) // assuming that's the F key on all keyboards (hopefully) + { + static const int lods[] = {38,24,32,31,24,33,18,50,24,49,18}; + // what's that spell? + // loadsamoney! ... probably + if ( e.KeyScan == lods[kcode] ) + { + kcode++; + if ( kcode >= 11 ) + { + SendNetworkEvent("swwmmoneycheat",consoleplayer); + kcode = 0; + } + } + else kcode = 0; + if ( e.KeyScan == 33 ) + { + let demo = Demolitionist(players[consoleplayer].mo); + if ( demo && (demo.Health <= 0) && (demo.deadtimer > 40) ) + { + // pay respects + int numf = Random[FInTheChat](1,6); + for ( int i=0; i ramt ) amt = ramt; - if ( players[e.Args[1]].mo.GiveInventory(item,amt) ) + Inventory ritm = players[e.Args[1]].mo.FindInventory(item); + if ( ritm ) + { + int maxgive = ritm.MaxAmount-ritm.Amount; + if ( amt > maxgive ) amt = maxgive; + } + else if ( amt > def.MaxAmount ) amt = def.MaxAmount; + if ( (amt > 0) && players[e.Args[1]].mo.GiveInventory(item,amt) ) { players[e.Args[0]].mo.TakeInventory(item,amt); // add to history - SWWMTradeHistory.RegisterSend(players[e.Args[0]],players[e.Args[1]],def.GetTag()); - SWWMTradeHistory.RegisterReceive(players[e.Args[1]],players[e.Args[0]],def.GetTag()); + SWWMTradeHistory.RegisterSend(players[e.Args[0]],players[e.Args[1]],item,amt); + SWWMTradeHistory.RegisterReceive(players[e.Args[1]],players[e.Args[0]],item,amt); // add messages if ( e.Args[0] == consoleplayer ) Console.Printf(StringTable.Localize("$SWWM_MSGSENT"),amt,def.GetTag(),players[e.Args[1]].GetUserName()); if ( e.Args[1] == consoleplayer ) Console.Printf(StringTable.Localize("$SWWM_MSGRECV"),players[e.Args[0]].GetUserName(),amt,def.GetTag()); @@ -2381,6 +2479,16 @@ Class SWWMHandler : EventHandler if ( dist < 2000 ) Console.Printf("\cx%s\cx: %s\c-",players[e.Args[0]].GetUserName(),StringTable.Localize(e.Name.Mid(19))); } + else if ( e.Name ~== "swwmmoneycheat" ) + { + if ( consoleplayer == e.Args[0] ) + { + Console.Printf("\cfLOADSAMONEY!\c-"); + S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI); + S_StartSound("misc/emone",CHAN_VOICE,CHANF_UI); + } + SWWMCredits.Give(players[e.Args[0]],999999999); + } } // stuff for hud diff --git a/zscript/swwm_hud.zsc b/zscript/swwm_hud.zsc index dd509cf7f..61797122e 100644 --- a/zscript/swwm_hud.zsc +++ b/zscript/swwm_hud.zsc @@ -99,7 +99,7 @@ Class SWWMStatusBar : BaseStatusBar let m = new("MsgLine"); m.str = outline.Left(outline.Length()-1); // strip newline m.type = printlevel; - m.tic = level.maptime; + m.tic = level.totaltime; m.rep = 1; // append chat messages to full history if ( (printlevel == PRINT_CHAT) || (printlevel == PRINT_TEAMCHAT) ) @@ -202,14 +202,14 @@ Class SWWMStatusBar : BaseStatusBar // prune old messages for ( int i=0; i PRINT_HIGH) && (level.maptime < (MainQueue[i].tic+35*chatduration.GetInt())) ) continue; + if ( (MainQueue[i].type <= PRINT_HIGH) && (level.totaltime < (MainQueue[i].tic+35*msgduration.GetInt())) ) continue; + else if ( (MainQueue[i].type > PRINT_HIGH) && (level.totaltime < (MainQueue[i].tic+35*chatduration.GetInt())) ) continue; MainQueue.Delete(i); i--; } @@ -363,7 +363,7 @@ Class SWWMStatusBar : BaseStatusBar mMiniwiFont = HUDFont.Create("MiniwiShaded"); mMPlusFont = HUDFont.Create("MPlusShaded"); HealthInter = DynamicValueInterpolator.Create(100,.1,1,100); - ScoreInter = DynamicValueInterpolator.Create(0,.1,1,1000); + ScoreInter = DynamicValueInterpolator.Create(0,.1,1,999999999); FuelInter = DynamicValueInterpolator.Create(120,.5,1,100); DashInter = DynamicValueInterpolator.Create(120,.5,1,40); gl_proj = new("swwmLe__GLScreen"); @@ -755,7 +755,7 @@ Class SWWMStatusBar : BaseStatusBar else if ( MainQueue[i].type == PRINT_TEAMCHAT ) col = teamcol.GetInt(); String cstr = MainQueue[i].str; if ( MainQueue[i].rep > 1 ) cstr.AppendFormat(" (x%d)",MainQueue[i].rep); - int curtime = MainQueue[i].tic-level.maptime; + int curtime = MainQueue[i].tic-level.totaltime; if ( MainQueue[i].type < PRINT_CHAT ) curtime += 35*msgduration.GetInt(); else curtime += 35*chatduration.GetInt(); double alph = clamp(curtime/20.,0.,1.); @@ -780,7 +780,7 @@ Class SWWMStatusBar : BaseStatusBar { String cstr = PickupQueue[i].str; if ( PickupQueue[i].rep > 1 ) cstr.AppendFormat(" (x%d)",PickupQueue[i].rep); - int curtime = (PickupQueue[i].tic+35*pickduration.GetInt())-level.maptime; + int curtime = (PickupQueue[i].tic+35*pickduration.GetInt())-level.totaltime; double alph = clamp(curtime/20.,0.,1.); Font fnt = LangFont(mTewiFont); BrokenLines l = fnt.BreakLines(cstr,int(ss.x*.75)); diff --git a/zscript/swwm_inventory.zsc b/zscript/swwm_inventory.zsc index e6ae19cfb..517ea1e73 100644 --- a/zscript/swwm_inventory.zsc +++ b/zscript/swwm_inventory.zsc @@ -447,6 +447,8 @@ Class BigPunchImpact : Actor } } +Class ReflectedBullet : SWWMCasing {} + Class ParryField : Actor { Default @@ -516,12 +518,40 @@ Class ParryField : Actor { if ( (flags&DMG_INFLICTOR_IS_PUFF) && (source != master) ) { - // TODO deflect hitscan - // three options: - // 1. just block the bullet, making it bounce off - // 2. ricochet in random direction - // 3. ricochet directly back to source + Vector3 vdir = (cos(angle),sin(angle),0); + Vector3 vpos = inflictor.pos; // puff goes here + bool raging = !!master.FindInventory("RagekitPower"); + let i = Spawn(raging?"BigPunchImpact":"PunchImpact",vpos); + i.angle = angle+180; + // deflect hitscan + A_StartSound("misc/ricochet",CHAN_VOICE,CHANF_OVERLAP,.7); A_StartSound("demolitionist/parry",CHAN_VOICE,CHANF_OVERLAP,.4); + // three options: + switch ( Random[Parry](0,7) ) + { + case 0: + case 1: + case 2: + // 1. just block the bullet, making it bounce off + let b = Spawn("ReflectedBullet",vpos); + b.angle = angle; + b.target = self; + b.vel = (-vdir+(FRandom[Parry](-.2,.2),FRandom[Parry](-.2,.2),FRandom[Parry](-.2,.2))).unit()*FRandom[Parry](raging?9:3,raging?20:8); + break; + case 3: + case 4: + case 5: + // 2. ricochet in random direction + Vector3 rdir = (-vdir+(FRandom[Parry](-.4,.4),FRandom[Parry](-.4,.4),FRandom[Parry](-.4,.4))).unit(); + LineAttack(atan2(rdir.y,rdir.x),8000,asin(-rdir.z),raging?(damage*8):damage,mod,inflictor.GetClass(),LAF_ABSPOSITION,null,vpos.z,vpos.x,vpos.y); + break; + case 6: + case 7: + // 3. ricochet directly back to source + Vector3 tdir = source?(level.Vec3Diff(vpos,source.Vec3Offset(0,0,source.height/2))):(-vdir); + LineAttack(atan2(tdir.y,tdir.x),8000,asin(-tdir.z),raging?(damage*8):damage,mod,inflictor.GetClass(),LAF_ABSPOSITION,null,vpos.z,vpos.x,vpos.y); + break; + } } return 0; } diff --git a/zscript/swwm_menu.zsc b/zscript/swwm_menu.zsc index 31b9c49e4..47759a00e 100644 --- a/zscript/swwm_menu.zsc +++ b/zscript/swwm_menu.zsc @@ -36,6 +36,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu Array storeunits; // trading SWWMTradeHistory tradelib; + Array playerlist; // chat history total line count (includes breaks) int chatlines; // temporary bottom messages, such as "not enough money" @@ -51,6 +52,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu int lastuseamt; int checkuse; int checkdrop; + int checksend; // seeeeecret int kcode; @@ -91,9 +93,10 @@ Class SWWMKnowledgeBaseMenu : GenericMenu tcol = CVar.GetCVar("msg4color",players[consoleplayer]); 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; + tmsgtic = gametic+140; } override bool MenuEvent( int mkey, bool fromcontroller ) @@ -150,6 +153,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu lorelist.Clear(); storelist.Clear(); storeunits.Clear(); + playerlist.Clear(); return true; case MKEY_PAGEDOWN: MenuSound("menu/demotab"); @@ -162,6 +166,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu lorelist.Clear(); storelist.Clear(); storeunits.Clear(); + playerlist.Clear(); return true; case MKEY_DOWN: if ( curtab == TAB_HELP ) @@ -231,6 +236,34 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if ( sel0 >= storelist.Size() ) sel0 = 0; } + else if ( curtab == TAB_TRADING ) + { + if ( !sub && (playerlist.Size() > 1) ) + { + // scroll through player list + MenuSound("menu/demoscroll"); + sel0++; + if ( sel0 >= playerlist.Size() ) + sel0 = 0; + } + else if ( sub ) + { + if ( (sel0 == -1) && (sel1 < tradelib.ent.Size()-28) ) + { + // scroll through trading history + MenuSound("menu/demoscroll"); + sel1++; + } + else if ( invlist.Size() > 1 ) + { + // scroll through inventory + MenuSound("menu/demoscroll"); + sel1++; + if ( sel1 >= invlist.Size() ) + sel1 = 0; + } + } + } return true; case MKEY_UP: if ( curtab == TAB_HELP ) @@ -286,6 +319,34 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if ( sel0 < 0 ) sel0 = storelist.Size()-1; } + else if ( curtab == TAB_TRADING ) + { + if ( !sub && (playerlist.Size() > 1) ) + { + // scroll through player list + MenuSound("menu/demoscroll"); + sel0--; + if ( sel0 < 0 ) + sel0 = playerlist.Size()-1; + } + else if ( sub ) + { + if ( (sel0 == -1) && (sel1 > 0) ) + { + // scroll through trading history + MenuSound("menu/demoscroll"); + sel1--; + } + else if ( invlist.Size() > 1 ) + { + // scroll through inventory + MenuSound("menu/demoscroll"); + sel1--; + if ( sel1 < 0 ) + sel1 = invlist.Size()-1; + } + } + } return true; case MKEY_RIGHT: if ( ((curtab == TAB_INVENTORY) || (curtab == TAB_KEYS)) && (invlist.Size() > 21) ) @@ -311,6 +372,23 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if ( sel1 > LORE_LORE ) sel1 = LORE_ITEM; } + else if ( curtab == TAB_TRADING ) + { + if ( !sub && (playerlist.Size() > 21) ) // lol is this ever going to happen + { + int oldsel = sel0; + sel0 += 22; + if ( sel0 >= playerlist.Size() ) sel0 = playerlist.Size()-1; + if ( sel0 != oldsel ) MenuSound("menu/demoscroll"); + } + else if ( sub && (sel0 != -1) ) + { + int oldsel = sel1; + sel1 += 22; + if ( sel1 >= invlist.Size() ) sel1 = invlist.Size()-1; + if ( sel1 != oldsel ) MenuSound("menu/demoscroll"); + } + } return true; case MKEY_LEFT: if ( ((curtab == TAB_INVENTORY) || (curtab == TAB_KEYS)) && (invlist.Size() > 21) ) @@ -338,6 +416,25 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if ( sel1 < LORE_ITEM ) sel1 = LORE_LORE; } + else if ( curtab == TAB_TRADING ) + { + if ( !sub && (playerlist.Size() > 21) ) // lol is this ever going to happen + { + if ( sel0-22 >= 0 ) + { + sel0 -= 22; + MenuSound("menu/demoscroll"); + } + } + else if ( sub && (sel0 != -1) ) + { + if ( sel1-22 >= 0 ) + { + sel1 -= 22; + MenuSound("menu/demoscroll"); + } + } + } return true; case MKEY_ENTER: if ( (curtab == TAB_INVENTORY) && (invlist.Size() > 0) && (sel0 < invlist.Size()) ) @@ -348,7 +445,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu lastuseamt = invlist[sel0].Amount; // don't check weapons (or the lamp) if ( !(invlist[sel0] is 'Weapon') && !(invlist[sel0] is 'SWWMLamp') ) - checkuse = gametic+1; + checkuse = gametic+(multiplayer?5:1); EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer); } else if ( (curtab == TAB_STORE) && (storelist.Size() > 0) && (sel0 < storelist.Size()) ) @@ -361,7 +458,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu { MenuSound("menu/noinvuse"); tmsg = StringTable.Localize("$SWWM_STOREMUNS"); - tmsgtic = gametic+35; + tmsgtic = gametic+70; return true; } let cur = players[consoleplayer].mo.FindInventory(storelist[sel0]); @@ -380,10 +477,11 @@ Class SWWMKnowledgeBaseMenu : GenericMenu { MenuSound("menu/noinvuse"); tmsg = StringTable.Localize("$SWWM_STOREFULL"); - tmsgtic = gametic+35; + tmsgtic = gametic+70; return true; } EventHandler.SendNetworkEvent(String.Format("swwmstoregive.%s",storelist[sel0].GetClassName()),consoleplayer,price,amt); + if ( (camt+amt) >= max ) sel0 = max(0,sel0-1); MenuSound("menu/buyinv"); } else if ( curtab == TAB_LIBRARY ) @@ -403,13 +501,31 @@ Class SWWMKnowledgeBaseMenu : GenericMenu sel2 = 0; } } + else if ( curtab == TAB_TRADING ) + { + if ( !sub && (playerlist.Size() > 0) ) + { + // pick a player + MenuSound("menu/demosel"); + sub = true; + sel1 = 0; + } + else if ( sub && (sel0 != -1) && (invlist.Size() > 0) ) + { + // trade item + lastuse = invlist[sel1].GetClass(); + lastuseamt = invlist[sel1].Amount; + checksend = gametic+(multiplayer?5:1); + EventHandler.SendNetworkEvent(String.Format("swwmtrade.%s",invlist[sel1].GetClassName()),consoleplayer,playerlist[sel0]); + } + } return true; case MKEY_CLEAR: if ( (curtab == TAB_INVENTORY) && (invlist.Size() > 0) ) { lastuse = invlist[sel0].GetClass(); lastuseamt = invlist[sel0].Amount; - checkdrop = gametic+1; + checkdrop = gametic+(multiplayer?5:1); EventHandler.SendNetworkEvent(String.Format("swwmdropitem.%s",invlist[sel0].GetClassName()),consoleplayer); } else if ( (curtab == TAB_LIBRARY) && sub ) @@ -417,6 +533,24 @@ Class SWWMKnowledgeBaseMenu : GenericMenu MenuSound("menu/democlose"); sub = false; } + else if ( curtab == TAB_TRADING ) + { + if ( !sub ) + { + // open trading history + MenuSound("menu/demosel"); + sub = true; + sel0 = -1; + sel1 = 0; + } + else if ( sub ) + { + // go back + MenuSound("menu/democlose"); + sub = false; + sel0 = 0; + } + } return true; } return Super.MenuEvent(mkey,fromcontroller); @@ -647,10 +781,59 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if ( lorelib.ent.Size() != oldloresiz ) { tmsg = StringTable.Localize("$SWWM_NEWLORE"); - tmsgtic = gametic+35; + tmsgtic = gametic+70; } oldloresiz = lorelib.ent.Size(); } + else if ( curtab == TAB_TRADING ) + { + // build player list + playerlist.Clear(); + for ( int i=0; i tag2 ) continue; + greater = true; + invlist.Insert(i,inv); + break; + } + if ( greater ) continue; + invlist.Push(inv); + } + // re-sort by category + for ( int i=0; i 0) && CmpInventory(invlist[k-1],invlist[k]) ) + { + Inventory tmp = invlist[k]; + invlist[k] = invlist[k-1]; + invlist[k-1] = tmp; + k--; + } + j++; + } + } + } + } // check if use succeeded if ( checkuse && (gametic > checkuse) ) { @@ -659,7 +842,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if ( amt == lastuseamt ) { tmsg = StringTable.Localize("$SWWM_INVFAIL"); - tmsgtic = gametic+35; + tmsgtic = gametic+70; MenuSound("menu/noinvuse"); } else @@ -677,12 +860,30 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if ( amt == lastuseamt ) { tmsg = StringTable.Localize("$SWWM_INVNDROP"); - tmsgtic = gametic+35; + tmsgtic = gametic+70; MenuSound("menu/noinvuse"); } else if ( (amt == 0) && (sel0 >= invlist.Size()) ) sel0 = max(0,sel0-1); } + // check if trade succeeded + if ( checksend && (gametic > checksend) ) + { + checksend = 0; + int amt = players[consoleplayer].mo.CountInv(lastuse); + if ( amt == lastuseamt ) + { + tmsg = StringTable.Localize("$SWWM_TRADEFULL"); + tmsgtic = gametic+70; + MenuSound("menu/noinvuse"); + } + else + { + MenuSound("menu/demosel"); + if ( (amt == 0) && (sel1 >= invlist.Size()) ) + sel1 = max(0,sel1-1); + } + } } override bool OnUiEvent( UIEvent ev ) @@ -1117,8 +1318,109 @@ Class SWWMKnowledgeBaseMenu : GenericMenu } else if ( curtab == TAB_TRADING ) { - str = StringTable.Localize("$SWWM_COMINGSOON"); - Screen.DrawText(fnt,Font.CR_FIRE,(ss.x-fnt.StringWidth(str))/2.,(ss.y-fnt.GetHeight())/2.,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + if ( !sub ) + { + 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 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(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 ( 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 ) + { + xx = 6; + yy = 17; + int ofs = clamp(sel1,0,max(0,tradelib.ent.Size()-28)); + for ( int i=ofs; i= 370 ) break; + let ent = tradelib.ent[tradelib.ent.Size()-(i+1)]; + int thour = (ent.timestamp/(3600*Thinker.TICRATE)); + int tmin = (ent.timestamp/(60*Thinker.TICRATE))%60; + int tsec = (ent.timestamp/Thinker.TICRATE)%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 + { + xx = 9; + yy = 23; + int longest = 0, len; + int ofs = int(floor(max(0,sel1-44)/22.)*22); + int cols = 1; + for ( int i=ofs; i 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 = fnt.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(fnt,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel1)?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_CHAT ) {