// event processing extend Class SWWMHandler { // for menu events transient Array checklist; override void ConsoleProcess( ConsoleEvent e ) { // doing it with an event because this way we can control WHEN it should be openable if ( e.Name ~== "swwmdemomenu" ) { if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') ) return; if ( !(Menu.GetCurrentMenu() is 'DemolitionistMenu') ) Menu.SetMenu('DemolitionistMenu'); } else if ( e.Name ~== "swwmzoomin" ) { if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') ) return; double val = swwm_mm_zoom; if ( val > 1. ) val = max(1.,val-.5); else val = max(.5,val-.25); CVar.FindCVar('swwm_mm_zoom').SetFloat(val); } else if ( e.Name ~== "swwmzoomout" ) { if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') ) return; double maxval = players[consoleplayer].mo.FindInventory("Omnisight")?2.:1.; double val = swwm_mm_zoom; if ( val >= 1. ) val = min(maxval,val+.5); else val = min(1.,val+.25); CVar.FindCVar('swwm_mm_zoom').SetFloat(val); } } override void NetworkProcess( ConsoleEvent e ) { static const Class cbttypes[] = {"RedShell","GreenShell","BlueShell","PurpleShell"}; if ( e.Name ~== "swwmgesture" ) { if ( (e.player == -1) || !playeringame[e.player] || !players[e.player].mo ) return; let mo = players[e.player].mo; switch( e.Args[0] ) { case 0: SWWMGesture.SetGesture(mo,GS_Wave); break; case 1: SWWMGesture.SetGesture(mo,GS_ThumbsUp); break; case 2: SWWMGesture.SetGesture(mo,GS_Victory); break; case 3: SWWMGesture.SetGesture(mo,GS_BlowKiss); break; } return; } else if ( e.Name ~== "swwmsetwalk" ) { if ( (e.player == -1) || !playeringame[e.player] || !players[e.player].mo ) return; let mo = Demolitionist(players[e.player].mo); if ( mo ) mo.bWalking = e.Args[0]; return; } else if ( e.Name ~== "swwmfixitemcaps" ) { // this command is only really needed when I update item max amounts mid-playthrough if ( multiplayer && (e.player != Net_Arbitrator) ) { if ( e.player == consoleplayer ) Console.Printf("Only the net arbitrator can call this event."); return; } for ( int i=0; i %d)",hams.GetTag(),hams.MaxAmount,hams.default.MaxAmount); hams.MaxAmount = hams.default.MaxAmount; hams.Amount = min(hams.Amount,hams.MaxAmount); } for ( Inventory inv=mo.inv; inv; inv=inv.inv ) { if ( inv is 'Ammo' ) { Ammo(inv).BackpackMaxAmount = Ammo(inv).default.BackpackMaxAmount; int newmax = inv.default.MaxAmount; if ( (hams.Amount > 0) && (Ammo(inv).BackpackMaxAmount > 0) ) { double factor = (Ammo(inv).BackpackMaxAmount-inv.default.MaxAmount)/double(hams.MaxAmount); newmax = int(inv.default.MaxAmount+hams.Amount*factor); } if ( inv.MaxAmount != newmax ) Console.Printf("Adjust %s capacity (%d -> %d)",inv.GetTag(),inv.MaxAmount,newmax); int dropme = max(0,inv.Amount-newmax); if ( dropme ) { Console.Printf("Dropped %dx %s.",dropme,inv.GetTag()); // non-SWWM ammos won't subdivide, but whatever, this is a debug command inv.CreateTossable(dropme); } inv.MaxAmount = newmax; } else if ( inv is 'MagAmmo' ) { if ( inv.MaxAmount != inv.default.MaxAmount ) Console.Printf("Adjust %s capacity (%d -> %d)",inv.GetTag(),inv.MaxAmount,inv.default.MaxAmount); // just drop the extras int dropme = max(0,inv.Amount-inv.default.MaxAmount); if ( dropme ) { Console.Printf("Dropped %dx %s.",dropme,inv.GetTag()); inv.CreateTossable(dropme); } inv.MaxAmount = inv.default.MaxAmount; } else { if ( inv.MaxAmount != inv.default.MaxAmount ) Console.Printf("Adjust %s capacity (%d -> %d)",inv.GetTag(),inv.MaxAmount,inv.default.MaxAmount); // only drop droppables (obviously) if ( !inv.bUNDROPPABLE && !inv.bUNTOSSABLE ) { int dropme = max(0,inv.Amount-inv.default.MaxAmount); if ( dropme ) { Console.Printf("Dropped %dx %s.",dropme,inv.GetTag()); for ( int j=0; j alldlg; alldlg_pack.Split(alldlg,":"); for ( int i=0; i 3 ) Console.Printf("\cg%s exceeds line limit (%d > 3)\c-",alldlg[i],l.Count()); else { if ( !e.Args[0] ) { l.Destroy(); continue; } Console.Printf("\cd%s is within line limit (%d <= 3)\c-",alldlg[i],l.Count()); } for ( int j=0; j %s",l.StringAt(j)); l.Destroy(); } return; } else if ( e.Name ~== "swwmprofilehandler" ) { if ( multiplayer && (e.player != Net_Arbitrator) ) { if ( e.player == consoleplayer ) Console.Printf("Only the net arbitrator can call this event."); return; } bprofiletics = profiletics = (e.Args[0]<=0)?10:e.Args[0]; profiling = true; worldtick_ms = 0; worldthingspawned_ms = 0; worldthingdestroyed_ms = 0; worldthingdied_ms = 0; worldthingdamaged_ms = 0; worldthingrevived_ms = 0; checkreplacement_ms = 0; checkreplacee_ms = 0; Console.Printf("Gathering data for %d tic(s)...",bprofiletics); return; } if ( e.IsManual ) return; if ( e.Name.Left(14) ~== "swwmstoregive." ) { Class item = e.Name.Mid(14); if ( !item ) return; if ( SWWMCredits.Take(players[e.Args[0]],e.Args[1]) ) { let def = GetDefaultByType(item); SWWMWeapon sw; // drop the swapweapon if we own it first if ( swwm_swapweapons && (item is 'SWWMWeapon') && (sw = SWWMWeapon(def).HasSwapWeapon(players[e.Args[0]].mo)) ) { // special case, otherwise candy gun won't drop itself if ( sw is 'CandyGun' ) CandyGun(sw).swapdrop = true; bool swapto = (sw == players[e.Args[0]].ReadyWeapon) || (sw.SisterWeapon && (sw.Sisterweapon == players[e.Args[0]].ReadyWeapon)); int ngun = sw.Amount; if ( ngun == 2 ) { // create a dual giver to drop let dg = SWWMDualWeaponGiver(Spawn("SWWMDualWeaponGiver",players[e.Args[0]].mo.pos+(0,0,10))); dg.angle = players[e.Args[0]].mo.angle; dg.VelFromAngle(5.); dg.vel.z += 1.; dg.vel += players[e.Args[0]].mo.vel; // transfer both guns dg.giveme[0] = SWWMWeapon(sw.CreateTossable(1)); dg.giveme[0].AttachToOwner(dg); dg.giveme[1] = SWWMWeapon(sw.CreateTossable(1)); dg.giveme[1].AttachToOwner(dg); dg.SetPickupState(); } else user.DropInventory(sw); // just drop it // don't autoswitch just yet (hacky) if ( swapto ) { players[e.Args[0]].ReadyWeapon = null; players[e.Args[0]].PendingWeapon = WP_NOCHANGE; } } if ( (item is 'ArmorNuggetItem') || (item is 'HealthNuggetItem') ) { // these have to be given in a loop because fun reasons for ( int i=0; i 1) ) players[e.Args[0]].mo.A_SelectWeapon("DualExplodiumGun"); else players[e.Args[0]].mo.A_SelectWeapon((Class)(item)); } } } else if ( e.Name.Left(14) ~== "swwmstoretake." ) { Class item = e.Name.Mid(14); if ( !item ) return; int amt = e.Args[2]; if ( item is 'CandyGun' ) { // check if we can sell a spare instead, for the same price int n = players[e.Args[0]].mo.CountInv('CandyGunSpares'); if ( n >= amt ) { players[e.Args[0]].mo.TakeInventory('CandyGunSpares',amt); SWWMCredits.Give(players[e.Args[0]],e.Args[1]); return; } } // if player currently has the dual wield weapon selected, switch over if ( item is 'SWWMWeapon' ) { let c = Weapon(players[e.Args[0]].mo.FindInventory(item)); if ( c.SisterWeapon && (players[e.Args[0]].ReadyWeapon == c.SisterWeapon) ) { players[e.Args[0]].ReadyWeapon = c; players[e.Args[0]].SetPSprite(PSP_WEAPON,c.FindState("Ready")); players[e.Args[0]].SetPSprite(PSP_WEAPON+1,null); // delete left weapon psprite } } // if we're selling an embiggener, we need to readjust ammo if ( item is 'HammerspaceEmbiggener' ) { let ritm = players[e.Args[0]].mo.FindInventory(item); for ( Inventory i=players[e.Args[0]].mo.Inv; i; i=i.Inv ) { if ( !(i is 'Ammo') ) continue; if ( Ammo(i).BackpackMaxAmount > 0 ) { double factor = (Ammo(i).BackpackMaxAmount-i.default.MaxAmount)/double(ritm.MaxAmount); i.MaxAmount = int(i.default.MaxAmount+(ritm.Amount-amt)*factor); } // drop excess ammo int excess = i.Amount-i.MaxAmount; if ( excess > 0 ) i.CreateTossable(excess); } } players[e.Args[0]].mo.TakeInventory(item,amt); SWWMCredits.Give(players[e.Args[0]],e.Args[1]); } else if ( e.Name.Left(10) ~== "swwmtrade." ) { Class item = e.Name.Mid(10); if ( !item ) return; let def = GetDefaultByType(item); int amt = def.Amount; // if it's an ammo, check the largest unit givable if ( item is 'Ammo' ) { for ( int i=0; i)(AllActorClasses[i]); if ( !a || (a.GetParentClass() != item) || (GetDefaultByType(a).Amount < amt) ) continue; amt = GetDefaultByType(a).Amount; } } if ( item is 'MagAmmo' ) { for ( int i=0; i)(AllActorClasses[i]); if ( !a || (a.GetParentClass() != item) || (GetDefaultByType(a).Amount < amt) ) continue; amt = GetDefaultByType(a).Amount; } } 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; bool rslt = false; Class giveitem = item; if ( item is 'HammerspaceEmbiggener' ) giveitem = 'TradedHammerspaceEmbiggener'; if ( (amt > 0) && players[e.Args[1]].mo.GiveInventory(giveitem,amt,true) ) { // if player currently has the dual wield weapon selected, switch over if ( item is 'SWWMWeapon' ) { let c = Weapon(players[e.Args[0]].mo.FindInventory(item)); if ( c.SisterWeapon && (players[e.Args[0]].ReadyWeapon == c.SisterWeapon) ) { players[e.Args[0]].ReadyWeapon = c; players[e.Args[0]].SetPSprite(PSP_WEAPON,c.FindState("Ready")); players[e.Args[0]].SetPSprite(PSP_WEAPON+1,null); // delete left weapon psprite } } // if we're trading an embiggener, we need to readjust ammo if ( item is 'HammerspaceEmbiggener' ) { let ritm = players[e.Args[0]].mo.FindInventory(item); for ( Inventory i=players[e.Args[0]].mo.Inv; i; i=i.Inv ) { if ( !(i is 'Ammo') ) continue; if ( Ammo(i).BackpackMaxAmount > 0 ) { double factor = (Ammo(i).BackpackMaxAmount-i.default.MaxAmount)/double(ritm.MaxAmount); i.MaxAmount = int(i.default.MaxAmount+(ritm.Amount-amt)*factor); } // drop excess ammo int excess = i.Amount-i.MaxAmount; if ( excess > 0 ) i.CreateTossable(excess); } } if ( item is 'CandyGun' ) { // see if we can take a fully loaded spare from us instead int n = players[e.Args[0]].mo.CountInv('CandyGunSpares'); int na = players[e.Args[0]].mo.CountInv('CandyGunAmmo'); if ( (n >= amt) && (na >= amt) ) { players[e.Args[0]].mo.TakeInventory('CandyGunSpares',amt); players[e.Args[0]].mo.TakeInventory('CandyGunAmmo',amt); } else players[e.Args[0]].mo.TakeInventory('CandyGun',amt); } else players[e.Args[0]].mo.TakeInventory(item,amt); // add to history 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()); rslt = true; } if ( e.Args[0] == consoleplayer ) { let t = new("MenuTransaction"); t.uid = e.Args[2]; t.type = MenuTransaction.TT_ITEMSEND; t.result = rslt; t.used = item; t.usedup = (players[e.Args[1]].mo.CountInv(item)<=0); checklist.Push(t); } } else if ( e.Name.Left(17) ~== "swwmmarkloreread." ) { let l = SWWMLoreLibrary.Find(players[e.Args[0]]); let idx = l.FindEntry(e.Name.Mid(17)); l.MarkRead(idx); } else if ( e.Name.Left(12) ~== "swwmuseitem." ) { Class item = e.Name.Mid(12); if ( !item ) return; let i = players[e.Args[0]].mo.FindInventory(item); if ( !i ) return; bool rslt = players[e.Args[0]].mo.UseInventory(i); if ( e.Args[0] == consoleplayer ) { let t = new("MenuTransaction"); t.uid = e.Args[1]; t.type = MenuTransaction.TT_ITEMUSE; let w = (Class)(item); if ( w ) { t.result = (players[e.Args[0]].PendingWeapon==Weapon(i)); // dual wield gun support if ( (i is 'SWWMWeapon') && (players[e.Args[0]].PendingWeapon==Weapon(i).SisterWeapon) ) t.result = true; } else t.result = rslt; t.used = item; t.usedup = (!i||(i.Amount<=0)); checklist.Push(t); } } else if ( e.Name.Left(13) ~== "swwmdropitem." ) { Class item = e.Name.Mid(13); if ( !item ) return; let i = players[e.Args[0]].mo.FindInventory(item); if ( !i ) return; int amt = i.default.Amount; // if it's an ammo, check the largest unit givable if ( i is 'Ammo' ) { for ( int i=0; i)(AllActorClasses[i]); if ( !a || (a.GetParentClass() != item) || (GetDefaultByType(a).Amount < amt) ) continue; amt = GetDefaultByType(a).Amount; } } if ( i is 'MagAmmo' ) { for ( int i=0; i)(AllActorClasses[i]); if ( !a || (a.GetParentClass() != item) || (GetDefaultByType(a).Amount < amt) ) continue; amt = GetDefaultByType(a).Amount; } } if ( amt > i.Amount ) amt = i.Amount; let drop = players[e.Args[0]].mo.DropInventory(i,amt); // add some random velocity so multiple drops don't get bunched together if ( drop ) drop.vel += (Actor.RotateVector((FRandom[Junk](-1.5,.5),FRandom[Junk](-2.5,2.5)),players[e.Args[0]].mo.angle),FRandom[Junk](2.,5.)); if ( e.Args[0] == consoleplayer ) { let t = new("MenuTransaction"); t.uid = e.Args[1]; t.type = MenuTransaction.TT_ITEMDROP; t.used = item; t.result = drop; t.usedup = (!i||(i.Amount<=0)); checklist.Push(t); } } else if ( e.Name ~== "swwmkoraxline" ) { if ( consoleplayer != e.Args[1] ) return; switch ( e.Args[0] ) { case 0: AddOneliner("koraxgreet",3,60); break; case 1: AddOneliner("koraxblood",3,150); break; case 2: AddOneliner("koraxgame",3,120); break; case 3: AddOneliner("koraxworship",3,80); break; case 4: AddOneliner("koraxmasters",3,90); break; } } else if ( e.Name.Left(17) ~== "swwmstoremessage." ) { if ( consoleplayer != e.Args[2] ) return; SWWMFullHistory.PushMessage(e.Name.Mid(17),e.Args[0],e.Args[1]); } else if ( e.Name.Left(16) ~== "swwmremoteliner." ) { if ( consoleplayer == e.Args[0] ) return; if ( !swwm_othervoice ) return; if ( swwm_mutevoice >= e.Args[1] ) return; players[e.Args[0]].mo.A_StartSound(e.Name.Mid(16),CHAN_DEMOVOICE,attenuation:.5); } else if ( e.Name.Left(19) ~== "swwmremotelinertxt." ) { if ( consoleplayer == e.Args[0] ) return; if ( !swwm_othervoice ) return; if ( swwm_mutevoice >= e.Args[1] ) return; double dist = players[consoleplayer].Camera.Distance3D(players[e.Args[0]].mo); 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.Left(8) ~== "swwmcbt." ) { // from wikipedia, the free encyclopedia if ( !playeringame[e.Args[0]] || !players[e.Args[0]].mo ) return; let cbt = Wallbuster(players[e.Args[0]].mo.FindInventory("Wallbuster")); if ( !cbt ) return; cbt.reloadqueue.Clear(); if ( e.Name.Mid(8) ~== "EMPTY" ) cbt.clearout = true; else { cbt.clearout = false; Array qs; qs.Clear(); String rite = e.Name.Mid(8); rite.Split(qs,",",TOK_SKIPEMPTY); for ( int i=0; i 3) ) continue; cbt.reloadqueue.Push(cbttypes[qi]); } } cbt.waitreload = false; } else if ( e.Name ~== "swwmcleartransaction" ) { if ( e.Args[1] != consoleplayer ) return; for ( int i=0; i= 0x61) && (e.KeyChar <= 0x7A) ) { // F if ( e.KeyChar == 0x66 ) { let demo = Demolitionist(players[consoleplayer].mo); let gone = PlayerGone(players[consoleplayer].mo); if ( (demo && (demo.Health <= 0) && (demo.deadtimer > 40)) || (gone && (gone.Health <= 0) && (gone.deadtimer > 40)) ) { // pay respects int numf = Random[FInTheChat](1,6); for ( int i=0; i