swwmgz_m/zscript/handler/swwm_handler_process.zsc
Marisa the Magician cf17e889d8 Use InterfaceEvents instead of PostUiTick for oneliners, more reliable.
Due to some arbitrary change in GZDoom, which was later merged into VKDoom as
well, PostUiTick no longer consistently gets called after WorldTick.
This is kind of funny and also disappointing and sad because I intentionally
designed that feature this way, on purpose, and now it no longer works as
intended. Who knows how many other mods are affected by this now.
2025-08-21 01:31:55 +02:00

745 lines
24 KiB
Text

// event processing
extend Class SWWMHandler
{
// for the compact hud
transient int WeaponFlash[10];
// weapon selector
ui SWWMWeaponSelect wsel;
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;
let bar = SWWMStatusBar(StatusBar);
if ( !bar ) return;
bar.mm_zoom = max(.5,bar.mm_zoom-.25);
}
else if ( e.Name ~== "swwmzoomout" )
{
if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') )
return;
let bar = SWWMStatusBar(StatusBar);
if ( !bar ) return;
bar.mm_zoom = min(1.,bar.mm_zoom+.25);
}
else if ( e.Name ~== "swwmstepclear" )
{
Console.Printf("Cleared %d steps.",traced_stepnum);
traced_steppos = 0;
traced_stepnum = 0;
}
else if ( e.Name ~== "swwmstepcount" )
{
double cmdist = 0.;
int startpos = traced_steppos-traced_stepnum;
if ( startpos < 0 ) startpos += MAX_TRACED_BUFSZ;
for ( int i=1; i<traced_stepnum; i++ )
{
int idx1 = (startpos+(i-1))%MAX_TRACED_BUFSZ;
int idx2 = (startpos+i)%MAX_TRACED_BUFSZ;
// skip if vectors are NaN, for safety
if ( (traced_steps[idx1] != traced_steps[idx1])
|| (traced_steps[idx2] != traced_steps[idx2]) ) continue;
double sdist = level.Vec2Diff(traced_steps[idx1],traced_steps[idx2]).length();
cmdist += sdist;
}
Console.Printf("%d steps, %g map units total.",traced_stepnum,cmdist);
}
}
private ui void CheckPlayerStep()
{
if ( swwm_mm_steptrace && !do_trace_steps )
{
// begin tracing now
traced_steppos = 0;
traced_stepnum = 0;
oldplayerpos = (double.nan,double.nan);
do_trace_steps = true;
}
else if ( !swwm_mm_steptrace && do_trace_steps )
{
// just stop tracing, don't touch the data
do_trace_steps = false;
}
}
private ui void DoPlayerStep( Vector2 playerpos, bool ignoremindist = false )
{
// ignore if current position is NaN
if ( playerpos != playerpos ) return;
// clamp into map bounds to avoid weirdness
playerpos.x = clamp(playerpos.x,-32768.,32767.);
playerpos.y = clamp(playerpos.y,-32768.,32767.);
double clamped_mdist = clamp(swwm_mm_minstep,8.,256.);
double mindistsq = clamped_mdist*clamped_mdist;
if ( !ignoremindist && (oldplayerpos == oldplayerpos) && ((oldplayerpos-playerpos).lengthsquared() < mindistsq) )
return;
oldplayerpos = playerpos;
traced_steps[traced_steppos] = playerpos;
traced_steppos = (traced_steppos+1)%MAX_TRACED_BUFSZ;
traced_stepnum = min(traced_stepnum+1,clamp(swwm_mm_maxsteps,2,MAX_TRACED_BUFSZ));
}
override void InterfaceProcess( ConsoleEvent e )
{
if ( e.IsManual ) return;
if ( e.Name.Left(16) ~== "swwmsetdialogue." )
SWWMDialogues.StartSeq(e.Name.Mid(16));
if ( e.Name.Left(17) ~== "swwmmessageliner." )
{
String theline = e.Name.Mid(17);
int linelevel = e.Args[0];
int linespan = e.Args[1];
if ( (theline == "") || (players[consoleplayer].health <= 0) ) return;
if ( linelevel > swwm_mutevoice )
{
let l = SWWMOneLiner.Make(theline,linespan);
StatusBar.AttachMessage(l,-3473);
if ( swwm_voicelog )
{
String txt = StringTable.Localize(theline);
txt.Replace("\c-","\c*"); // fix color reset escapes
Console.PrintfEx(PRINT_CHAT|PRINT_NONOTIFY,"\cd"..(multiplayer?players[consoleplayer].GetUserName():"Demo").."\c*: "..txt.."\c*");
}
}
SendNetworkEvent("swwmremotelinertxt."..theline,consoleplayer,linelevel);
}
else if ( e.Name.Left(11) ~== "swwmkeyget." )
{
let bar = SWWMStatusBar(StatusBar);
if ( !bar || (bar.CPlayer != players[e.Args[0]]) ) return;
String kname = e.Name.Mid(11);
Class<Key> k = kname;
if ( k )
{
let kg = new('KeyGet');
kg.got = k;
kg.flashtime = gametic+25;
bar.keyflash.Push(kg);
}
}
else if ( e.Name.Left(15) ~== "swwmwpntooltip." )
{
let bar = SWWMStatusBar(StatusBar);
if ( !bar ) return;
String wname = e.Name.Mid(15);
Class<SWWMWeapon> w = wname;
if ( w )
{
let tt = new("SWWMWeaponTooltip").Init(w);
bool appended = false;
for ( SWWMWeaponTooltip t=bar.ctip; t; t=t.next )
{
if ( t.next ) continue;
appended = true;
t.next = tt;
break;
}
if ( !appended )
{
bar.ctip = tt;
bar.AttachMessage(tt,-2910);
}
}
}
else if ( e.Name.Left(15) ~== "swwmwpnswaptip." )
{
let bar = SWWMStatusBar(StatusBar);
if ( !bar ) return;
// network IDs finally becoming useful here
uint ida = e.Name.Mid(15,8).ToInt(16);
uint idb = e.Name.Mid(23,8).ToInt(16);
let wa = Inventory(Object.GetNetworkEntity(ida));
let wb = Inventory(Object.GetNetworkEntity(idb));
if ( !wa || !wb ) return;
if ( e.Args[0] )
{
// force to expire
if ( bar.cstip ) bar.cstip.Expire(wa,wb);
return;
}
if ( bar.cstip )
{
bar.cstip.Poke(wa,wb);
return;
}
let tt = new('SWWMWeaponSwapTip').Init(wa,wb);
bar.cstip = tt;
bar.AttachMessage(tt,-2911);
}
else if ( e.Name.Left(12) ~== "swwmnametag." )
{
let bar = SWWMStatusBar(StatusBar);
if ( !bar ) return;
bar.ntagstr = StringTable.Localize(e.Name.Mid(12));
bar.ntagtic = level.totaltime;
bar.ntagcol = nametagcolor;
}
else if ( e.Name ~== "swwmdoflash" )
{
GenericFlash gf = new('GenericFlash').Setup(flash_camera,flash_color,flash_duration);
StatusBar.AttachMessage(gf,0,BaseStatusBar.HUDMSGLayer_UnderHUD);
}
else if ( e.Name ~== "swwmsendplayerstep" )
{
CheckPlayerStep();
let demo = Demolitionist(players[consoleplayer].mo);
if ( !demo || !do_trace_steps ) return;
DoPlayerStep(demo.pos.xy);
}
else if ( e.Name ~== "swwmsendplayertele" )
{
CheckPlayerStep();
let demo = Demolitionist(players[consoleplayer].mo);
if ( !demo || !do_trace_steps ) return;
// send the position we had before teleporting
DoPlayerStep(demo.pretelepos.xy,true);
// to indicate that the player has teleported, we write a NaN into the buffer (yup)
oldplayerpos = (double.nan,double.nan);
traced_steps[traced_steppos] = (double.nan,double.nan);
traced_steppos = (traced_steppos+1)%MAX_TRACED_BUFSZ;
traced_stepnum = min(traced_stepnum+1,clamp(swwm_mm_maxsteps,2,MAX_TRACED_BUFSZ));
// send the post-teleport position
DoPlayerStep(demo.pos.xy,true);
}
else if ( e.Name ~== "swwmhudgivescore" )
{
let bar = SWWMStatusBar(StatusBar);
if ( !bar ) return;
if ( bar.cummscoreup+e.Args[0] < bar.cummscoreup ) bar.cummscoreup = 999999999;
else bar.cummscoreup = min(999999999,bar.cummscoreup+e.Args[0]);
bar.cummspanup = 20+35*int(Log10(clamp(bar.cummscoreup,1,999999999)));
bar.cummflashup = 15;
}
else if ( e.Name ~== "swwmhudtakescore" )
{
let bar = SWWMStatusBar(StatusBar);
if ( !bar ) return;
if ( bar.cummscoredn+e.Args[0] < bar.cummscoredn ) bar.cummscoredn = 999999999;
else bar.cummscoredn = min(999999999,bar.cummscoredn+e.Args[0]);
bar.cummspandn = 20+35*int(Log10(clamp(bar.cummscoredn,1,999999999)));
bar.cummflashdn = 15;
}
else if ( e.Name ~== "swwmitemused" )
{
// report back to kbase menu that the item got (or did not get) used
int uid = e.Args[0];
bool rslt = e.Args[1];
bool usedup = e.Args[2];
let kbase = DemolitionistMenu(Menu.GetCurrentMenu());
if ( kbase ) kbase.ItemUsed(uid,rslt,usedup);
}
else if ( e.Name ~== "swwmitemdropped" )
{
// report back to kbase menu that the item got (or did not get) dropped
int uid = e.Args[0];
bool rslt = e.Args[1];
bool usedup = e.Args[2];
let kbase = DemolitionistMenu(Menu.GetCurrentMenu());
if ( kbase ) kbase.ItemDropped(uid,rslt,usedup);
}
}
override void NetworkCommandProcess( NetworkCommand cmd )
{
if ( cmd.Command == 'swwmuseitem' )
{
// kbase menu wants us to use a specific item
int uid = cmd.ReadInt();
int pid = cmd.ReadInt();
uint iid = cmd.ReadInt();
let p = players[pid];
let i = Inventory(GetNetworkEntity(iid));
if ( (i.Owner != p.mo) )
ThrowAbortException("swwmuseitem: attempted to use item '%s' not owned by player '%s'",i.GetTag(),p.GetUserName());
bool rslt = p.mo.UseInventory(i);
let w = Weapon(i);
if ( w )
{
rslt = (p.PendingWeapon==Weapon(i));
// dual wield gun support
if ( (i is 'SWWMWeapon') && (p.PendingWeapon==Weapon(i).SisterWeapon) )
rslt = true;
}
else if ( (i is 'Key') || (i is 'SWWMCollectible') ) rslt = true;
SendInterfaceEvent(pid,"swwmitemused",uid,rslt,(!i||(i.Amount<=0)));
}
else if ( cmd.Command == 'swwmdropitem' )
{
// kbase menu wants us to drop a specific item
int uid = cmd.ReadInt();
int pid = cmd.ReadInt();
uint iid = cmd.ReadInt();
let p = players[pid];
let i = Inventory(GetNetworkEntity(iid));
if ( (i.Owner != p.mo) )
ThrowAbortException("swwmdropitem: attempted to drop item '%s' not owned by player '%s'",i.GetTag(),p.GetUserName());
int amt = i.default.Amount;
// if it's an ammo, check the largest unit givable
if ( i is 'MagAmmo' )
{
foreach ( cls:AllActorClasses )
{
let a = (Class<MagAmmo>)(cls);
if ( !a || (a.GetParentClass() != i.GetClass()) || (GetDefaultByType(a).Amount < amt) ) continue;
amt = GetDefaultByType(a).Amount;
}
}
else if ( i is 'Ammo' )
{
foreach ( cls:AllActorClasses )
{
let a = (Class<Ammo>)(cls);
if ( !a || (a.GetParentClass() != i.GetClass()) || (GetDefaultByType(a).Amount < amt) ) continue;
amt = GetDefaultByType(a).Amount;
}
}
if ( amt > i.Amount ) amt = i.Amount;
let drop = p.mo.DropInventory(i,amt);
// randomize movement direction so multiple drops don't get bunched together
if ( drop )
{
Vector2 vel2d = drop.vel.xy;
drop.vel.xy = Actor.RotateVector(vel2d,FRandom[Junk](-15,15));
drop.vel.xy *= FRandom[Junk](.9,1.1);
}
SendInterfaceEvent(pid,"swwmitemdropped",uid,!!drop,(!i||(i.Amount<=0)));
}
}
override void NetworkProcess( ConsoleEvent e )
{
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 ~== "swwmsetradius" )
{
if ( multiplayer && (e.player != Net_Arbitrator) )
{
if ( e.player == consoleplayer )
Console.Printf("Only the net arbitrator can call this event.");
return;
}
let mo = players[e.player].mo;
if ( !mo ) return;
FLineTraceData d;
mo.LineTrace(mo.angle,10000.,mo.pitch,TRF_ABSPOSITION|TRF_THRUBLOCK|TRF_THRUHITSCAN|TRF_ALLACTORS,mo.player.viewz,mo.pos.x,mo.pos.y,d);
if ( d.HitType != TRACE_HitActor ) return;
Console.Printf("Change %s radius from %g to %g.",d.HitActor.GetTag(),d.HitActor.radius,e.Args[0]);
d.HitActor.A_SetSize(e.Args[0],-1);
}
else if ( e.Name ~== "swwmsetheight" )
{
if ( multiplayer && (e.player != Net_Arbitrator) )
{
if ( e.player == consoleplayer )
Console.Printf("Only the net arbitrator can call this event.");
return;
}
let mo = players[e.player].mo;
if ( !mo ) return;
FLineTraceData d;
mo.LineTrace(mo.angle,10000.,mo.pitch,TRF_ABSPOSITION|TRF_THRUBLOCK|TRF_THRUHITSCAN|TRF_ALLACTORS,mo.player.viewz,mo.pos.x,mo.pos.y,d);
if ( d.HitType != TRACE_HitActor ) return;
Console.Printf("Change %s height from %g to %g.",d.HitActor.GetTag(),d.HitActor.height,e.Args[0]);
d.HitActor.A_SetSize(-1,e.Args[0]);
}
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 ~== "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+pools_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);
// workaround for some items
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 ~== "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(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 )
{
String txt = StringTable.Localize(e.Name.Mid(19));
txt.Replace("\c-","\c*"); // fix color reset escapes
Console.PrintfEx(PRINT_CHAT,"\cx%s\cx: %s\c-",players[e.Args[0]].GetUserName(),txt);
}
}
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 ~== "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.Left(14) ~== "swwmselweapon." )
{
Class<Weapon> wpn = e.Name.Mid(14);
if ( !wpn ) return;
let w = Weapon(players[e.player].mo.FindInventory(wpn));
if ( !w ) return;
if ( !w.CheckAmmo(Weapon.EitherFire,false) )
{
S_StartSound("menu/democlose",CHAN_AUTO,CHANF_UI);
return;
}
players[e.player].mo.UseInventory(w);
if ( e.player != consoleplayer ) return;
bool rslt = (players[e.player].PendingWeapon == w);
if ( (w is 'SWWMWeapon') && (players[e.player].PendingWeapon == w.SisterWeapon) )
rslt = true; // switching to dual gun
S_StartSound(rslt?"menu/demosel":"menu/democlose",CHAN_AUTO,CHANF_UI);
}
else if ( e.Name ~== "swwmlustysuns" )
{
if ( consoleplayer != e.Args[0] ) return;
AddOneliner("lustysuns",3,15);
}
// 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
String cmd = Bindings.GetBinding(e.KeyScan);
if ( paused )
{
if ( (cmd ~== "invprev") || (cmd ~== "invnext") ) return true;
// skip the rest of this function
return false;
}
// weapon selector is active
int WeapSel = 0;
if ( cmd ~== "weapnext" ) WeapSel = 1;
else if ( cmd ~== "weapprev" ) WeapSel = -1;
if ( wsel && (wsel.stage < 2) )
{
// pov/dpad takes priority
if ( (e.KeyScan == InputEvent.Key_JoyPOV1_Up) || (e.KeyScan == InputEvent.Key_Pad_DPad_Up) )
WeapSel = -1;
else if ( (e.KeyScan == InputEvent.Key_JoyPOV1_Down) || (e.KeyScan == InputEvent.Key_Pad_DPad_Down) )
WeapSel = 1;
if ( WeapSel == 1 )
{
wsel.WeapNext();
return true;
}
if ( WeapSel == -1 )
{
wsel.WeapPrev();
return true;
}
// Joy1 should be the same thing as the A button (usually)
if ( (e.KeyScan == InputEvent.Key_Joy1) || (e.KeyScan == InputEvent.Key_Pad_A) || (cmd ~== "+attack") )
{
wsel.WeapSel();
return true;
}
// ditto for Joy2
if ( (e.KeyScan == InputEvent.Key_Joy2) || (e.KeyScan == InputEvent.Key_Pad_B) || (cmd ~== "+altattack") )
{
wsel.WeapCancel();
return true;
}
}
else if ( WeapSel && swwm_useweaponbar && !paused && (players[consoleplayer].playerstate == PST_LIVE) && players[consoleplayer].mo && (gamestate == GS_LEVEL) )
{
// special case: ignore if we used the mousewheel and the automap is active
if ( (automapactive && !viewactive) && ((e.KeyScan == InputEvent.Key_MWheelUp) || (e.KeyScan == InputEvent.Key_MWheelDown)) )
return false;
// only if player owns any selectable weapons
if ( !wsel && SWWMWeaponSelect.PlayerHasWeapons(players[consoleplayer].mo) )
{
wsel = new('SWWMWeaponSelect').Init(players[consoleplayer].mo);
StatusBar.AttachMessage(wsel,-2920,layer:StatusBar.HUDMSGLayer_UnderHUD);
if ( WeapSel == 1 ) wsel.WeapNext();
else if ( WeapSel == -1 ) wsel.WeapPrev();
}
return true;
}
// 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) && !paused )
{
if ( CheatInput(e) )
return true;
}
return false;
}
}