qzdoom-gpl/wadsrc/static/zscript/inventory/armor.txt

459 lines
12 KiB
Text

/*
** armor.txt
** Implements all variations of armor objects
**
**---------------------------------------------------------------------------
** Copyright 2002-2016 Randy Heit
** Copyright 2006-2017 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
class Armor : Inventory native
{
Default
{
Inventory.PickupSound "misc/armor_pkup";
}
}
//===========================================================================
//
//
// BasicArmor
//
//
//===========================================================================
class BasicArmor : Armor native
{
native int AbsorbCount;
native double SavePercent;
native int MaxAbsorb;
native int MaxFullAbsorb;
native int BonusCount;
native Name ArmorType;
native int ActualSaveAmount;
Default
{
+Inventory.KEEPDEPLETED
}
//===========================================================================
//
// ABasicArmor :: Tick
//
// If BasicArmor is given to the player by means other than a
// BasicArmorPickup, then it may not have an icon set. Fix that here.
//
//===========================================================================
override void Tick ()
{
Super.Tick ();
AbsorbCount = 0;
if (!Icon.isValid())
{
String icontex = gameinfo.ArmorIcon1;
if (SavePercent >= gameinfo.Armor2Percent && gameinfo.ArmorIcon2.Length() != 0)
icontex = gameinfo.ArmorIcon2;
if (icontex.Length() != 0)
Icon = TexMan.CheckForTexture (icontex, TexMan.TYPE_Any);
}
}
//===========================================================================
//
// ABasicArmor :: CreateCopy
//
//===========================================================================
override Inventory CreateCopy (Actor other)
{
// BasicArmor that is in use is stored in the inventory as BasicArmor.
// BasicArmor that is in reserve is not.
let copy = BasicArmor(Spawn("BasicArmor"));
copy.SavePercent = SavePercent != 0 ? SavePercent : 0.33335; // slightly more than 1/3 to avoid roundoff errors.
copy.Amount = Amount;
copy.MaxAmount = MaxAmount;
copy.Icon = Icon;
copy.BonusCount = BonusCount;
copy.ArmorType = ArmorType;
copy.ActualSaveAmount = ActualSaveAmount;
GoAwayAndDie ();
return copy;
}
//===========================================================================
//
// ABasicArmor :: HandlePickup
//
//===========================================================================
override bool HandlePickup (Inventory item)
{
if (item.GetClass() == "BasicArmor")
{
// You shouldn't be picking up BasicArmor anyway.
return true;
}
if (!item.bIgnoreSkill)
{
if (item is "BasicArmorBonus")
{
let armor = BasicArmorBonus(item);
armor.SaveAmount = int(armor.SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
}
else if (item is "BasicArmorPickup")
{
let armor = BasicArmorPickup(item);
armor.SaveAmount = int(armor.SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
}
}
return false;
}
//===========================================================================
//
// ABasicArmor :: AbsorbDamage
//
//===========================================================================
override void AbsorbDamage (int damage, Name damageType, out int newdamage)
{
int saved;
if (!DamageTypeDefinition.IgnoreArmor(damageType))
{
int full = MAX(0, MaxFullAbsorb - AbsorbCount);
if (damage < full)
{
saved = damage;
}
else
{
saved = full + int((damage - full) * SavePercent);
if (MaxAbsorb > 0 && saved + AbsorbCount > MaxAbsorb)
{
saved = MAX(0, MaxAbsorb - AbsorbCount);
}
}
if (Amount < saved)
{
saved = Amount;
}
newdamage -= saved;
Amount -= saved;
AbsorbCount += saved;
if (Amount == 0)
{
// The armor has become useless
SavePercent = 0;
ArmorType = 'None'; // Not NAME_BasicArmor.
// Now see if the player has some more armor in their inventory
// and use it if so. As in Strife, the best armor is used up first.
BasicArmorPickup best = null;
Inventory probe = Owner.Inv;
while (probe != null)
{
let inInv = BasicArmorPickup(probe);
if (inInv != null)
{
if (best == null || best.SavePercent < inInv.SavePercent)
{
best = inInv;
}
}
probe = probe.Inv;
}
if (best != null)
{
Owner.UseInventory (best);
}
}
damage = newdamage;
}
// Once the armor has absorbed its part of the damage, then apply its damage factor, if any, to the player
if ((damage > 0) && (ArmorType != 'None')) // BasicArmor is not going to have any damage factor, so skip it.
{
ApplyDamageFactors(ArmorType, damageType, damage, damage);
}
}
}
//===========================================================================
//
//
// BasicArmorBonus
//
//
//===========================================================================
class BasicArmorBonus : Armor
{
double SavePercent; // The default, for when you don't already have armor
int MaxSaveAmount;
int MaxAbsorb;
int MaxFullAbsorb;
int SaveAmount;
int BonusCount;
int BonusMax;
property prefix: Armor;
property MaxSaveAmount: MaxSaveAmount;
property SaveAmount : SaveAmount;
property SavePercent: SavePercent;
property MaxAbsorb: MaxAbsorb;
property MaxFullAbsorb: MaxFullAbsorb;
property MaxBonus: BonusCount;
property MaxBonusMax: BonusMax;
Default
{
+Inventory.AUTOACTIVATE
+Inventory.ALWAYSPICKUP
Inventory.MaxAmount 0;
Armor.SavePercent 33.335;
}
//===========================================================================
//
// ABasicArmorBonus :: CreateCopy
//
//===========================================================================
override Inventory CreateCopy (Actor other)
{
let copy = BasicArmorBonus(Super.CreateCopy (other));
if (!bIgnoreSkill)
{
SaveAmount = int(SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
}
copy.SavePercent = SavePercent;
copy.SaveAmount = SaveAmount;
copy.MaxSaveAmount = MaxSaveAmount;
copy.BonusCount = BonusCount;
copy.BonusMax = BonusMax;
copy.MaxAbsorb = MaxAbsorb;
copy.MaxFullAbsorb = MaxFullAbsorb;
return copy;
}
//===========================================================================
//
// ABasicArmorBonus :: Use
//
// Tries to add to the amount of BasicArmor a player has.
//
//===========================================================================
override bool Use (bool pickup)
{
let armor = BasicArmor(Owner.FindInventory("BasicArmor"));
bool result = false;
// This should really never happen but let's be prepared for a broken inventory.
if (armor == null)
{
armor = BasicArmor(Spawn("BasicArmor"));
armor.BecomeItem ();
armor.Amount = 0;
armor.MaxAmount = MaxSaveAmount;
Owner.AddInventory (armor);
}
if (BonusCount > 0 && armor.BonusCount < BonusMax)
{
armor.BonusCount = min(armor.BonusCount + BonusCount, BonusMax);
result = true;
}
int saveAmount = min(SaveAmount, MaxSaveAmount);
if (saveAmount <= 0)
{ // If it can't give you anything, it's as good as used.
return BonusCount > 0 ? result : true;
}
// If you already have more armor than this item can give you, you can't
// use it.
if (armor.Amount >= MaxSaveAmount + armor.BonusCount)
{
return result;
}
if (armor.Amount <= 0)
{ // Should never be less than 0, but might as well check anyway
armor.Amount = 0;
armor.Icon = Icon;
armor.SavePercent = clamp(SavePercent, 0, 100) / 100;
armor.MaxAbsorb = MaxAbsorb;
armor.ArmorType = GetClassName();
armor.MaxFullAbsorb = MaxFullAbsorb;
armor.ActualSaveAmount = MaxSaveAmount;
}
armor.Amount = min(armor.Amount + saveAmount, MaxSaveAmount + armor.BonusCount);
armor.MaxAmount = max(armor.MaxAmount, MaxSaveAmount);
return true;
}
}
//===========================================================================
//
//
// BasicArmorPickup
//
//
//===========================================================================
class BasicArmorPickup : Armor
{
double SavePercent;
int MaxAbsorb;
int MaxFullAbsorb;
int SaveAmount;
property prefix: Armor;
property SaveAmount : SaveAmount;
property SavePercent: SavePercent;
property MaxAbsorb: MaxAbsorb;
property MaxFullAbsorb: MaxFullAbsorb;
Default
{
+Inventory.AUTOACTIVATE;
Inventory.MaxAmount 0;
}
//===========================================================================
//
// ABasicArmorPickup :: CreateCopy
//
//===========================================================================
override Inventory CreateCopy (Actor other)
{
let copy = BasicArmorPickup(Super.CreateCopy (other));
if (!bIgnoreSkill)
{
SaveAmount = int(SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
}
copy.SavePercent = SavePercent;
copy.SaveAmount = SaveAmount;
copy.MaxAbsorb = MaxAbsorb;
copy.MaxFullAbsorb = MaxFullAbsorb;
return copy;
}
//===========================================================================
//
// ABasicArmorPickup :: Use
//
// Either gives you new armor or replaces the armor you already have (if
// the SaveAmount is greater than the amount of armor you own). When the
// item is auto-activated, it will only be activated if its max amount is 0
// or if you have no armor active already.
//
//===========================================================================
override bool Use (bool pickup)
{
let armor = BasicArmor(Owner.FindInventory("BasicArmor"));
// This should really never happen but let's be prepared for a broken inventory.
if (armor == null)
{
armor = BasicArmor(Spawn("BasicArmor"));
armor.BecomeItem ();
Owner.AddInventory (armor);
}
else
{
// If you already have more armor than this item gives you, you can't
// use it.
if (armor.Amount >= SaveAmount + armor.BonusCount)
{
return false;
}
// Don't use it if you're picking it up and already have some.
if (pickup && armor.Amount > 0 && MaxAmount > 0)
{
return false;
}
}
armor.SavePercent = clamp(SavePercent, 0, 100) / 100;
armor.Amount = SaveAmount + armor.BonusCount;
armor.MaxAmount = SaveAmount;
armor.Icon = Icon;
armor.MaxAbsorb = MaxAbsorb;
armor.MaxFullAbsorb = MaxFullAbsorb;
armor.ArmorType = GetClassName();
armor.ActualSaveAmount = SaveAmount;
return true;
}
}
//===========================================================================
//
//
// HexenArmor
//
//
//===========================================================================
class HexenArmor : Armor native
{
native double Slots[5];
native double SlotsIncrement[4];
Default
{
+Inventory.KEEPDEPLETED
+Inventory.UNTOSSABLE
}
}