swwmgz_m/zscript/items/swwm_basearmor.zsc

187 lines
5.5 KiB
Text

// Base class for all SWWM Armors
Class SWWMArmor : Armor abstract
{
meta int priority;
meta String drainmsg;
meta Class<SWWMSpareArmor> parent;
private int SArmorFlags;
Property ArmorPriority : priority;
Property DrainMessage : drainmsg;
Property GiverArmor : parent;
FlagDef NoHitFlash : SArmorFlags, 0; // doesn't flash when taking damage
FlagDef NoHitSound : SArmorFlags, 1; // doesn't play a sound when taking damage
FlagDef NoDrain : SArmorFlags, 2; // amount is not drained, will always reduce as long as amount is non-zero
// useful for powerup-given armors
transient int lastautousetic; // accumulated damage can make the use sounds stack
transient int lasthittic; // same here
Default
{
+INVENTORY.AUTOACTIVATE;
+INVENTORY.UNTOSSABLE;
+INVENTORY.UNDROPPABLE;
+INVENTORY.KEEPDEPLETED;
+INVENTORY.ALWAYSPICKUP;
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
// find last armor that's better than us
Inventory found = null;
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( !(i is 'SWWMArmor') || (i == self) || (SWWMArmor(i).priority < priority) ) continue;
found = i;
}
if ( !found )
{
// find first item with an armor worse than us after it
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( (i == self) || !(i.Inv is 'SWWMArmor') ) continue;
if ( SWWMArmor(i.Inv).priority > priority ) continue;
found = i;
break;
}
}
if ( !found )
{
// check if first item in inventory is health or a sandwich
if ( (other.Inv is 'SWWMHealth') || (other.Inv is 'GrilledCheeseSandwich') )
{
// we're good
return;
}
// find first item with health or sandwich after it
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( (i == self) || (!(i.Inv is 'SWWMHealth' ) && !(i.Inv is 'GrilledCheeseSandwich')) ) continue;
found = i;
break;
}
}
if ( !found ) return;
// place ourselves right after it
Inventory saved = found.Inv;
found.Inv = self;
other.Inv = Inv;
Inv = saved;
}
// for subclasses
virtual int HandleDamage( int damage, Name damageType, int flags )
{
return damage;
}
override void AbsorbDamage( int damage, Name damageType, out int newdamage, Actor inflictor, Actor source, int flags )
{
int saved;
if ( (amount <= 0) || DamageTypeDefinition.IgnoreArmor(damageType) || (damage <= 0) )
return;
if ( !bNOHITFLASH ) SWWMHandler.DoFlash(Owner,Color(int(clamp(damage*.15,1,16)),255,224,192),3);
if ( !bNOHITSOUND && (lasthittic < gametic) )
{
Owner.A_StartSound("armor/hit",CHAN_DAMAGE,CHANF_OVERLAP,clamp(damage*.03,0.,1.),2.5);
lasthittic = gametic;
}
saved = HandleDamage(damage,damageType,flags);
int healed = max(0,saved-damage);
saved = min(saved,damage);
if ( !bNODRAIN && (amount <= saved) ) saved = amount;
newdamage -= saved;
if ( healed > 0 ) Owner.GiveBody(healed);
if ( (swwm_strictuntouchable == 1) && (saved > 0) && Owner.player )
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd ) hnd.tookdamage[Owner.PlayerNumber()] = true;
}
if ( !bNODRAIN ) amount -= saved;
damage = newdamage;
if ( (amount <= (MaxAmount-default.Amount)) && (Owner.CountInv(parent) > 0) )
{
if ( GetDefaultByType(parent).UseSound && (lastautousetic < gametic) )
{
Owner.A_StartSound(GetDefaultByType(parent).UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP,.6);
lastautousetic = gametic;
}
int tgive = 0;
while ( (amount <= (MaxAmount-default.Amount)) && (Owner.CountInv(parent) > 0) )
{
Amount += default.Amount;
Owner.TakeInventory(parent,1);
// absorb the extra damage too
saved = HandleDamage(damage,damageType,flags);
healed = max(0,saved-damage);
saved = min(saved,damage);
if ( amount <= saved ) saved = amount;
newdamage -= saved;
if ( healed > 0 ) Owner.GiveBody(healed);
amount -= saved;
damage = newdamage;
}
}
else if ( amount <= 0 )
{
if ( Owner.CheckLocalView() && (drainmsg != "") ) Console.Printf(StringTable.Localize(drainmsg));
DepleteOrDestroy();
return;
}
}
}
// gives armor when used
Class SWWMSpareArmor : Inventory abstract
{
Mixin SWWMAutoUseFix;
Mixin SWWMUseToPickup;
Mixin SWWMOverlapPickupSound;
Mixin SWWMRespawn;
Mixin SWWMRotatingPickup;
Mixin SWWMPickupGlow;
meta Class<SWWMArmor> giveme;
Property GiveArmor : giveme;
override bool Use( bool pickup )
{
let cur = Owner.FindInventory(giveme);
if ( !cur || (!pickup && (cur.Amount < cur.MaxAmount)) || (GetDefaultByType(giveme).Amount+cur.Amount <= cur.MaxAmount) || ((default.MaxAmount <= 0) && (cur.Amount < cur.MaxAmount)) )
{
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) )
{
bool bPlayMe = true;
if ( self is 'ArmorNuggetItem' )
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd )
{
if ( hnd.lastnuggettic[Owner.PlayerNumber()] == gametic )
bPlayMe = false; // don't play if picked up on the same exact tic (overlapping items)
hnd.lastnuggettic[Owner.PlayerNumber()] = gametic;
}
}
if ( bPlayMe ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
}
Owner.GiveInventory(giveme,GetDefaultByType(giveme).Amount);
SWWMHandler.ArmorFlash(Owner.PlayerNumber());
return true;
}
return false;
}
Default
{
+INVENTORY.INVBAR;
+INVENTORY.ISARMOR;
+INVENTORY.AUTOACTIVATE;
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMGreenPickupFlash";
+FLOATBOB;
+DONTGIB;
FloatBobStrength 0.25;
}
}