swwmgz_m/zscript/handler/swwm_handler_process.zsc

600 lines
18 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 ~== "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;
}
}