283 lines
9.2 KiB
Text
283 lines
9.2 KiB
Text
// inventory functions
|
|
extend Class Demolitionist
|
|
{
|
|
override void GiveDefaultInventory()
|
|
{
|
|
if ( !player ) return;
|
|
bInDefaultInventory = true; // prevent default inventory from adding lore entries (fixes lore library disappearing when loading saves WHILE DEAD)
|
|
// we don't need hexen or basic armors
|
|
// we can simplify the code a lot here since no handling of many special conditions is needed
|
|
let sc = Inventory(Spawn('SayaCollar'));
|
|
if ( !sc.CallTryPickup(self) ) sc.Destroy();
|
|
let ap = Inventory(Spawn('AlmasteelPlating'));
|
|
if ( !ap.CallTryPickup(self) ) ap.Destroy();
|
|
let dp = Inventory(Spawn('DeepImpact'));
|
|
if ( !dp.CallTryPickup(self) ) dp.Destroy();
|
|
let eg = ExplodiumGun(Spawn('ExplodiumGun'));
|
|
eg.firstselect = true;
|
|
if ( !eg.CallTryPickup(self) ) eg.Destroy();
|
|
else player.ReadyWeapon = player.PendingWeapon = eg;
|
|
// in hexdd, we start with the chaos sphere in our grasp
|
|
if ( SWWMUtility.IsDeathkings() && SWWMUtility.CheckMD5List("vanillahexen.list") )
|
|
{
|
|
let cs = Inventory(Spawn('SWWMChaosSphere'));
|
|
if ( !cs.CallTryPickup(self) ) cs.Destroy();
|
|
}
|
|
// in deathmatch, we start with 8 embiggeners
|
|
if ( deathmatch )
|
|
{
|
|
let em = Inventory(Spawn('TradedHammerspaceEmbiggener'));
|
|
em.Amount = em.MaxAmount;
|
|
if ( !em.CallTryPickup(self) ) em.Destroy();
|
|
}
|
|
bInDefaultInventory = false;
|
|
}
|
|
|
|
override void ClearInventory()
|
|
{
|
|
Super.ClearInventory();
|
|
// remove some specific "undroppable" items
|
|
Actor last = self;
|
|
while ( last.inv )
|
|
{
|
|
let i = last.inv;
|
|
if ( ((i is 'SWWMArmor') && !i.bUNCLEARABLE) || (i is 'HammerspaceEmbiggener') )
|
|
{
|
|
i.DepleteOrDestroy();
|
|
if ( !i.bDestroyed ) last = i;
|
|
}
|
|
else last = i;
|
|
}
|
|
// clean up the "got weapons" so their obtain lines are played again
|
|
if ( mystats ) mystats.CleanGotWeapons();
|
|
}
|
|
|
|
override void RemoveInventory( Inventory item )
|
|
{
|
|
// stop any looping sounds our current weapon had
|
|
if ( (item is 'SWWMWeapon') && player && (SWWMWeapon(item) == player.ReadyWeapon) )
|
|
{
|
|
A_StopSound(CHAN_WEAPONEXTRA);
|
|
A_StopSound(CHAN_WEAPONEXTRA2);
|
|
A_StopSound(CHAN_WEAPONEXTRA3);
|
|
}
|
|
Super.RemoveInventory(item);
|
|
}
|
|
|
|
// skull keys, random chance of "alas poor yorick" line
|
|
private clearscope bool IsSkullKey( Inventory item )
|
|
{
|
|
String cname = item.GetClassName();
|
|
cname.MakeLower();
|
|
return (cname.IndexOf("skull") != -1);
|
|
}
|
|
|
|
override void AddInventory( Inventory item )
|
|
{
|
|
Super.AddInventory(item);
|
|
if ( !player ) return;
|
|
String cn = item.GetClassName();
|
|
if ( !bInDefaultInventory && (level.maptime > 0) && (!(item is 'SWWMWeapon') || !(cn.Left(4) ~== "Dual")) ) // dual weapons are ignored here, as they're handled separately
|
|
{
|
|
// add lore if any
|
|
SWWMLoreLibrary.Add(player,cn);
|
|
// weapon get oneliner
|
|
if ( (item is 'Weapon') && !(item is 'SWWMGesture') && !(item is 'SWWMItemGesture') && mystats && !mystats.GotWeapon(Weapon(item).GetClass()) && (player == players[consoleplayer]) && !ingivecheat )
|
|
{
|
|
if ( (item is 'HeavyMahSheenGun') && !Random[DemoLines](0,2) && SWWMHandler.AddOneliner("sheenspecial",2,20) )
|
|
{
|
|
A_StartSound("sheen/specialpick",CHAN_ITEM,CHANF_OVERLAP,1.,.5);
|
|
A_StartSound("sheen/specialpick",CHAN_ITEM,CHANF_OVERLAP,1.,.5);
|
|
}
|
|
else if ( (item is 'SWWMWeapon') && (SWWMWeapon(item).GetLine != "") )
|
|
{
|
|
// fall back to generic weapon get if voicepack lacks weapon-specific lines
|
|
if ( !SWWMHandler.AddOneliner(SWWMWeapon(item).GetLine,2) )
|
|
SWWMHandler.AddOneliner("getweapon",2);
|
|
}
|
|
else SWWMHandler.AddOneliner("getweapon",2);
|
|
facegrin = true;
|
|
}
|
|
}
|
|
if ( (item is 'Key') && !ingivecheat && !deathmatch && !bInDefaultInventory )
|
|
{
|
|
// score
|
|
int score = 100;
|
|
if ( player == players[consoleplayer] ) Console.Printf(StringTable.Localize("$SWWM_FINDKEY"),item.GetTag(),score);
|
|
else Console.Printf(StringTable.Localize("$SWWM_FINDKEYREM"),player.GetUserName(),item.GetTag(),score);
|
|
SWWMCredits.Give(player,score);
|
|
if ( player == players[consoleplayer] ) SWWMScoreObj.SpawnAtActorBunch(100,self);
|
|
if ( !Random[DemoLines](0,5) && IsSkullKey(item) )
|
|
{
|
|
if ( !SWWMHandler.AddOneliner("skullget",2) )
|
|
SWWMHandler.AddOneliner("keyget",2);
|
|
}
|
|
else SWWMHandler.AddOneliner("keyget",2);
|
|
facegrin = true;
|
|
}
|
|
// add collectible to stats
|
|
if ( item is 'SWWMCollectible' )
|
|
{
|
|
let col = SWWMCollectible(item);
|
|
if ( !ingivecheat )
|
|
{
|
|
SWWMHandler.AddOneliner(col.GetLine,2);
|
|
facegrin = true;
|
|
}
|
|
if ( !mystats ) return;
|
|
let cls = col.GetClass();
|
|
if ( (mystats.ownedcollectibles.Size() > 0) && (mystats.ownedcollectibles.Find(cls) < mystats.ownedcollectibles.Size()) ) return;
|
|
mystats.ownedcollectibles.Push(cls);
|
|
}
|
|
// yorick
|
|
if ( (item is 'PuzzSkull') && mystats && !mystats.gotyorick && !ingivecheat )
|
|
{
|
|
mystats.gotyorick = true;
|
|
SWWMHandler.AddOneliner("skullget",2);
|
|
facegrin = true;
|
|
}
|
|
// notify key obtained to flash icon
|
|
if ( item is 'Key' )
|
|
EventHandler.SendInterfaceEvent(consoleplayer,"swwmkeyget."..item.GetClassName(),PlayerNumber());
|
|
}
|
|
|
|
override bool UseInventory( Inventory item )
|
|
{
|
|
if ( (player.cheats&CF_TOTALLYFROZEN) || isFrozen() ) return false;
|
|
if ( !Actor.UseInventory(item) )
|
|
{
|
|
if ( player == players[consoleplayer] )
|
|
{
|
|
if ( !(item is 'Weapon') && !(item is 'SWWMCollectible') && !(item is 'Key') )
|
|
A_StartSound("menu/noinvuse",CHAN_ITEMEXTRA);
|
|
if ( item is 'PuzzleItem' )
|
|
SWWMHandler.AddOneliner("puzzfail",2,20);
|
|
}
|
|
return false;
|
|
}
|
|
// use sounds of big powerups are heard by other players
|
|
if ( (player == players[consoleplayer]) || item.bBIGPOWERUP )
|
|
A_StartSound(item.UseSound,CHAN_ITEMEXTRA);
|
|
if ( (player == players[consoleplayer]) && (item is 'PuzzleItem') )
|
|
SWWMHandler.AddOneliner("puzzsucc",2,10);
|
|
return true;
|
|
}
|
|
|
|
// the default PickWeapon code breaks when dual weapons are involved
|
|
// so we gotta roll out our own here
|
|
//
|
|
// we also need to override PickNextWeapon and PickPrevWeapon due to quirks of
|
|
// gestures
|
|
private Weapon TraverseSlot( int slot, bool checkammo, int start, int end, Weapon cur )
|
|
{
|
|
for ( int i=start; i>=end; i-- )
|
|
{
|
|
let type = player.weapons.GetWeapon(slot,i);
|
|
let w = Weapon(player.mo.FindInventory(type));
|
|
if ( !w || (w == cur) || (cur && cur.bPOWERED_UP && (w == cur.SisterWeapon)) )
|
|
continue;
|
|
String sn = w.GetClassName();
|
|
bool dual = ((type is 'SWWMWeapon') && (sn.Left(4) ~== "Dual"));
|
|
if ( (!checkammo && (!dual || (w.SisterWeapon && (w.SisterWeapon.Amount > 1))))
|
|
|| w.CheckAmmo(Weapon.EitherFire,false) )
|
|
return w;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
override Weapon PickWeapon( int slot, bool checkammo )
|
|
{
|
|
int slotsize = player.weapons.SlotSize(slot);
|
|
let cur = player.ReadyWeapon;
|
|
bool found = false;
|
|
int cs, ci;
|
|
if ( cur )
|
|
{
|
|
if ( cur is 'SWWMGesture' ) [found, cs, ci] = player.weapons.LocateWeapon(SWWMGesture(cur).formerweapon.GetClass());
|
|
else if ( cur is 'SWWMItemGesture' ) [found, cs, ci] = player.weapons.LocateWeapon(SWWMItemGesture(cur).gest.formerweapon.GetClass());
|
|
else [found, cs, ci] = player.weapons.LocateWeapon(cur.GetClass());
|
|
}
|
|
if ( found && (cs == slot) )
|
|
{
|
|
// traverse the slot down from current index
|
|
let w = TraverseSlot(slot,checkammo,ci-1,0,cur);
|
|
if ( !w ) w = TraverseSlot(slot,checkammo,slotsize-1,ci+1,cur);
|
|
return w?w:cur;
|
|
}
|
|
let w = TraverseSlot(slot,checkammo,slotsize-1,0,cur);
|
|
return w?w:cur;
|
|
}
|
|
|
|
// we have to reimplement this because of gestures
|
|
private bool, int, int FindMostRecentWeaponSWWM()
|
|
{
|
|
let cur = player.ReadyWeapon;
|
|
if ( player.PendingWeapon != WP_NOCHANGE ) cur = player.PendingWeapon;
|
|
if ( cur )
|
|
{
|
|
bool found = false;
|
|
int cs, ci;
|
|
if ( cur is 'SWWMGesture' ) [found, cs, ci] = player.weapons.LocateWeapon(SWWMGesture(cur).formerweapon.GetClass());
|
|
else if ( cur is 'SWWMItemGesture' ) [found, cs, ci] = player.weapons.LocateWeapon(SWWMItemGesture(cur).gest.formerweapon.GetClass());
|
|
else [found, cs, ci] = player.weapons.LocateWeapon(cur.GetClass());
|
|
return found, cs, ci;
|
|
}
|
|
return false, 0 ,0;
|
|
}
|
|
|
|
private Weapon PickPNWeapon( bool bPrev = false )
|
|
{
|
|
let [found, sslot, sidx] = FindMostRecentWeaponSWWM();
|
|
let cur = player.ReadyWeapon;
|
|
if ( cur is 'SWWMGesture' ) cur = SWWMGesture(cur).formerweapon;
|
|
else if ( cur is 'SWWMItemGesture' ) cur = SWWMItemGesture(cur).gest.formerweapon;
|
|
if ( !cur || found )
|
|
{
|
|
int slot, idx;
|
|
if ( !cur )
|
|
{
|
|
sslot = bPrev?0:(NUM_WEAPON_SLOTS-1);
|
|
sidx = bPrev?0:player.Weapons.SlotSize(sslot);
|
|
}
|
|
slot = sslot;
|
|
idx = sidx;
|
|
int checked = 0;
|
|
do
|
|
{
|
|
if ( bPrev )
|
|
{
|
|
if ( --idx < 0 )
|
|
{
|
|
checked++;
|
|
if ( --slot < 0 ) slot = NUM_WEAPON_SLOTS-1;
|
|
idx = player.Weapons.SlotSize(slot)-1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ++idx >= player.Weapons.SlotSize(slot) )
|
|
{
|
|
idx = 0;
|
|
checked++;
|
|
if ( ++slot >= NUM_WEAPON_SLOTS ) slot = 0;
|
|
}
|
|
}
|
|
let type = player.Weapons.GetWeapon(slot,idx);
|
|
let w = Weapon(FindInventory(type));
|
|
if ( w && w.CheckAmmo(Weapon.EitherFire,false) )
|
|
return w;
|
|
}
|
|
while ( ((slot != sslot) || (idx != sidx)) && (checked <= NUM_WEAPON_SLOTS) );
|
|
}
|
|
return player.ReadyWeapon;
|
|
}
|
|
|
|
override Weapon PickPrevWeapon()
|
|
{
|
|
return PickPNWeapon(true);
|
|
}
|
|
override Weapon PickNextWeapon()
|
|
{
|
|
return PickPNWeapon();
|
|
}
|
|
}
|