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.
745 lines
24 KiB
Text
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;
|
|
}
|
|
}
|