swwmgz_m/zscript/handler/swwm_handler_process.zsc
Marisa the Magician 5488bfce5d Remove code built on incorrect assumptions about UI events.
That is, remove code for closing menus with the key that's bound to open them.
As it turns out, UIEvent.keystring isn't 1:1 with key binds for a command.
This SEEMINGLY worked since the Demolitionist Menu is by default bound to Q,
and pressing Q does send an UIEvent to the menu with the string "Q". But if,
for example, the menu had been bound to Tab, this would fall apart because then
the key string sent is "	" (a literal tab character).
If there is a way to do this properly, I don't know about it. I've looked
everywhere in GZDoom's code for a solution, something that would let me do what
I need, but alas, there is nothing there. Better to get rid of this in its
entirety than keep the flaky code in the mod until someone with a special
setup that breaks it shows up to complain.
2022-08-13 14:28:09 +02:00

634 lines
19 KiB
Text

// event processing
extend Class SWWMHandler
{
// for menu events
transient Array<MenuTransaction> 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') )
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<Ammo> 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<MAXPLAYERS; i++ )
{
if ( !playeringame[i] || !players[i].mo ) continue;
let mo = players[i].mo;
Inventory hams = mo.FindInventory("HammerspaceEmbiggener");
if ( hams )
{
if ( hams.MaxAmount != hams.default.MaxAmount )
Console.Printf("Adjust %s capacity (%d -> %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<dropme; j++ ) inv.CreateTossable(j);
}
}
inv.MaxAmount = inv.default.MaxAmount;
inv.Amount = min(inv.Amount,inv.MaxAmount);
}
}
}
}
else if ( e.Name ~== "swwmupdateshadows" )
{
if ( multiplayer && (e.player != Net_Arbitrator) )
{
if ( e.player == consoleplayer )
Console.Printf("Only the net arbitrator can call this event.");
return;
}
if ( !swwm_shadows )
{
let ti = ThinkerIterator.Create("SWWMShadow");
SWWMShadow s;
int n = 0;
while ( s = SWWMShadow(ti.Next()) )
{
n++;
s.Destroy();
}
Console.Printf("%d shadows removed.",n);
return;
}
// build list of actors that already have shadows
Array<Actor> 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<Actor> 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 ~== "swwmupdatetrackers" )
{
if ( multiplayer && (e.player != Net_Arbitrator) )
{
if ( e.player == consoleplayer )
Console.Printf("Only the net arbitrator can call this event.");
return;
}
if ( swwm_notrack )
{
int n = trackers_cnt;
while ( trackers )
{
let next = trackers.next;
trackers.Destroy(); // wow that's simple, all in one line
trackers = next;
}
trackers_cnt = 0;
Console.Printf("%d trackers removed.",n);
return;
}
int n = trackers_cnt;
let ti = ThinkerIterator.Create("Actor");
Actor a;
while ( a = Actor(ti.Next()) )
{
if ( (!a.bSHOOTABLE && !a.bISMONSTER) || (a is 'LampMoth') || (a is 'CompanionLamp') ) continue;
let trk = SWWMCombatTracker.Spawn(self,a,true);
if ( !a.player ) trk.maxhealth = max(a.health,a.GetSpawnHealth());
}
n = (trackers_cnt-n);
Console.Printf("%d trackers added.",n);
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; i<suckableactors.Size(); i++ )
{
if ( suckableactors[i] && (suckableactors[i].bSHOOTABLE || suckableactors[i].bMISSILE) ) continue;
suckableactors.Delete(i);
i--;
n++;
}
Console.Printf("%d suckable actors trimmed.",n);
return;
}
else if ( e.Name ~== "swwmcleareffects" )
{
if ( multiplayer && (e.player != Net_Arbitrator) )
{
if ( e.player == consoleplayer )
Console.Printf("Only the net arbitrator can call this event.");
return;
}
int n = casings_cnt+chips_cnt+blods_cnt+meats_cnt;
CleanQueues();
Console.Printf("%d effects cleared.",n);
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;
for ( int i=0; i<8; i++ )
{
prof_ms[i] = 0;
prof_avg[i] = 0;
prof_calls[i] = 0;
}
Console.Printf("Gathering data for %d tic%s...",bprofiletics,(bprofiletics>1)?"s":"");
return;
}
if ( e.IsManual ) return;
if ( e.Name.Left(14) ~== "swwmstoregive." )
{
Class<Inventory> 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<e.Args[2]; i++ )
players[e.Args[0]].mo.GiveInventory(item,1,true);
}
else players[e.Args[0]].mo.GiveInventory(item,e.Args[2],true);
// fucky workaround
let inv = players[e.Args[0]].mo.FindInventory(item);
if ( inv && (inv.Amount <= 0) && !inv.bKEEPDEPLETED ) inv.Destroy();
if ( item is 'Weapon' )
{
// special case, select dual guns if we bought a second one
if ( (item is 'ExplodiumGun') && (players[e.Args[0]].mo.CountInv("ExplodiumGun") > 1) )
players[e.Args[0]].mo.A_SelectWeapon("DualExplodiumGun");
else players[e.Args[0]].mo.A_SelectWeapon((Class<Weapon>)(item));
}
}
}
else if ( e.Name.Left(14) ~== "swwmstoretake." )
{
Class<Inventory> 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<Inventory> 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<Weapon>)(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<Inventory> 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.Size(); i++ )
{
let a = (Class<Ammo>)(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.Size(); i++ )
{
let a = (Class<MagAmmo>)(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<String> qs;
qs.Clear();
String rite = e.Name.Mid(8);
rite.Split(qs,",",TOK_SKIPEMPTY);
for ( int i=0; i<qs.Size(); i++ )
{
int qi = qs[i].ToInt();
if ( (qi < 0) || (qi > 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<checklist.Size(); i++ )
{
if ( checklist[i].uid != e.Args[0] ) continue;
checklist.Delete(i);
i--;
}
}
else if ( e.Name ~== "swwmclearalltransactions" )
{
if ( e.Args[0] != consoleplayer ) return;
checklist.Clear();
}
else if ( e.Name ~== "swwmstorepuzzlecnt" )
{
let s = SWWMStats.Find(players[e.Args[0]]);
if ( s )
{
s.puzzlecnt = e.Args[1];
s.realpuzzlecnt = e.Args[2];
}
}
else if ( e.Name ~== "swwmsetoldcheat" )
{
let s = SWWMStats.Find(players[e.Args[0]]);
if ( s ) s.oldcheat = true;
}
else if ( e.Name ~== "swwmgamelore" )
SWWMLoreLibrary.Add(players[e.Args[0]],"Madcat");
else if ( e.Name ~== "swwmweaponreceive" )
{
if ( e.Args[1] != consoleplayer ) return;
if ( (e.Args[0] < 0) || (e.Args[0] > 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;
// 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<numf; i++ )
{
let f = PayRespects.PressF();
StatusBar.AttachMessage(f,0,layer:StatusBar.HUDMSGLayer_OverHUD);
}
}
}
// cheats
if ( (e.KeyChar >= 0x61) && (e.KeyChar <= 0x7A) )
{
if ( CheatInput(e) )
return true;
}
return false;
}
}