// event processing extend Class SWWMHandler { // for menu events transient Array checklist; // for the compact hud transient int WeaponFlash[10]; 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') || paused ) 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 = level.allmap?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 shaded; let ti = ThinkerIterator.Create("Actor"); Actor a; while ( a = Actor(ti.Next()) ) { if ( !(a is 'SWWMShadow') ) continue; shaded.Push(a.target); } int n = 0; ti.Reinit(); while ( a = Actor(ti.Next()) ) { if ( (a is 'LampMoth') || !(a.bSHOOTABLE || a.bISMONSTER || (a is 'Inventory') || (a is 'CompanionLamp')) || !((a is 'Demolitionist') || (a.SpawnState.sprite == a.GetSpriteIndex('XZW1'))) ) continue; if ( shaded.Find(a) < shaded.Size() ) continue; if ( !SWWMShadow.Track(a) ) continue; n++; } Console.Printf("%d shadows added.",n); return; } else if ( e.Name ~== "swwmupdateglows" ) { if ( multiplayer && (e.player != Net_Arbitrator) ) { if ( e.player == consoleplayer ) Console.Printf("Only the net arbitrator can call this event."); return; } if ( !swwm_itemglows ) { let ti = ThinkerIterator.Create("SWWMPickupFlash"); SWWMPickupFlash f; int n = 0; while ( f = SWWMPickupFlash(ti.Next()) ) { if ( f.CurState != f.FindState('Pickup') ) continue; n++; f.Destroy(); } Console.Printf("%d glows removed.",n); return; } // build list of items that already have glows Array glowed; let ti = ThinkerIterator.Create("Actor"); Actor a; while ( a = Actor(ti.Next()) ) { if ( !(a is 'SWWMPickupFlash') || (a.CurState != a.FindState('Pickup')) ) continue; glowed.Push(a.target); } int n = 0; ti.Reinit(); while ( a = Actor(ti.Next()) ) { if ( !(a is 'Inventory') || Inventory(a).Owner || !(Inventory(a).PickupFlash is 'SWWMPickupFlash') ) continue; if ( glowed.Find(a) < glowed.Size() ) continue; let p = Actor.Spawn(Inventory(a).PickupFlash,a.Vec3Offset(0,0,16)); p.target = a; p.SetStateLabel("Pickup"); n++; } Console.Printf("%d glows added.",n); return; } else if ( e.Name ~== "swwmupdatehitboxes" ) { if ( multiplayer && (e.player != Net_Arbitrator) ) { if ( e.player == consoleplayer ) Console.Printf("Only the net arbitrator can call this event."); return; } if ( !swwm_extendedpickup ) { let ti = ThinkerIterator.Create("SWWMExtendedItemHitbox"); SWWMExtendedItemHitbox h; int n = 0; while ( h = SWWMExtendedItemHitbox(ti.Next()) ) { n++; h.Destroy(); } Console.Printf("%d hitboxes removed.",n); return; } Console.Printf("Extended hitboxes can't be re-enabled at runtime. Please restart the map."); return; } else if ( e.Name ~== "swwmtrimsuckables" ) { if ( multiplayer && (e.player != Net_Arbitrator) ) { if ( e.player == consoleplayer ) Console.Printf("Only the net arbitrator can call this event."); return; } int n = 0; for ( int i=0; i1)?"s":""); 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); 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 && 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(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 if ( (i is 'Key') || (i is 'SWWMCollectible') ) 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_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_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))); if ( swwm_voicelog ) SWWMFullHistory.PushMessage("\cd"..players[e.Args[0]].GetUserName().."\c-: "..StringTable.Localize(e.Name.Mid(19)),level.totaltime,PRINT_CHAT); } } 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 9) ) return; WeaponFlash[e.Args[0]] = gametic+25; } else if ( e.Name ~== "swwmccstart" ) gdat.ccstartonce = true; else if ( e.Name ~== "swwmcclilith" ) gdat.cclilithonce = true; // cheats go here else CheatEvent(e); } override bool InputProcess( InputEvent e ) { if ( e.Type != InputEvent.TYPE_KeyDown ) return false; // block invprev/next inputs when paused if ( paused ) { String cmd = Bindings.GetBinding(e.KeyScan); if ( (cmd ~== "invprev") || (cmd ~== "invnext") ) return true; // skip the rest of this function return false; } // 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= 0x61) && (e.KeyChar <= 0x7A) && !paused ) { if ( CheatInput(e) ) return true; } return false; } }