- did some cleanup and consolidation on damage factor code while converting it all to floating point.

- made armor properties floating point.
This commit is contained in:
Christoph Oelckers 2016-03-22 16:35:41 +01:00
parent 1eb106e2c5
commit af427b80bd
19 changed files with 104 additions and 112 deletions

View file

@ -1940,13 +1940,13 @@ static int PatchMisc (int dummy)
if (armor!=NULL)
{
armor->SaveAmount = 100 * deh.GreenAC;
armor->SavePercent = deh.GreenAC == 1 ? FRACUNIT/3 : FRACUNIT/2;
armor->SavePercent = deh.GreenAC == 1 ? 0.33335 : 0.5;
}
armor = static_cast<ABasicArmorPickup *> (GetDefaultByName ("BlueArmor"));
if (armor!=NULL)
{
armor->SaveAmount = 100 * deh.BlueAC;
armor->SavePercent = deh.BlueAC == 1 ? FRACUNIT/3 : FRACUNIT/2;
armor->SavePercent = deh.BlueAC == 1 ? 0.33335 : 0.5;
}
ABasicArmorBonus *barmor;

View file

@ -89,7 +89,7 @@ public:
FString Slot[10];
FName InvulMode;
FName HealingRadiusType;
fixed_t HexenArmor[5];
double HexenArmor[5];
BYTE ColorRangeStart; // Skin color range
BYTE ColorRangeEnd;
FPlayerColorSetMap ColorSets;

View file

@ -287,13 +287,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
// base the number of shards on the size of the dead thing, so bigger
// things break up into more shards than smaller things.
// An actor with _f_radius() 20 and height 64 creates ~40 chunks.
numChunks = MAX<int> (4, (self->_f_radius()>>FRACBITS)*(self->_f_height()>>FRACBITS)/32);
numChunks = MAX<int>(4, int(self->radius * self->Height)/32);
i = (pr_freeze.Random2()) % (numChunks/4);
for (i = MAX (24, numChunks + i); i >= 0; i--)
{
fixed_t xo = (((pr_freeze() - 128)*self->_f_radius()) >> 7);
fixed_t yo = (((pr_freeze() - 128)*self->_f_radius()) >> 7);
fixed_t zo = (pr_freeze()*self->_f_height() / 255);
double xo = (pr_freeze() - 128)*self->radius / 128;
double yo = (pr_freeze() - 128)*self->radius / 128;
double zo = (pr_freeze()*self->Height / 255);
mo = Spawn("IceChunk", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
if (mo)
{

View file

@ -67,8 +67,8 @@ AInventory *ABasicArmor::CreateCopy (AActor *other)
{
// BasicArmor that is in use is stored in the inventory as BasicArmor.
// BasicArmor that is in reserve is not.
ABasicArmor *copy = Spawn<ABasicArmor> (0, 0, 0, NO_REPLACE);
copy->SavePercent = SavePercent != 0 ? SavePercent : FRACUNIT/3;
ABasicArmor *copy = Spawn<ABasicArmor> ();
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;
@ -130,7 +130,7 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
}
else
{
saved = full + FixedMul (damage - full, SavePercent);
saved = full + int((damage - full) * SavePercent);
if (MaxAbsorb > 0 && saved + AbsorbCount > MaxAbsorb)
{
saved = MAX(0, MaxAbsorb - AbsorbCount);
@ -179,15 +179,10 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
// This code is taken and adapted from APowerProtection::ModifyDamage().
// The differences include not using a default value, and of course the way
// the damage factor info is obtained.
const fixed_t *pdf = NULL;
DmgFactors *df = PClass::FindActor(ArmorType)->DamageFactors;
if (df != NULL && df->CountUsed() != 0)
if (df != NULL)
{
pdf = df->CheckFactor(damageType);
if (pdf != NULL)
{
damage = newdamage = FixedMul(damage, *pdf);
}
damage = newdamage = df->Apply(damageType, damage);
}
}
if (Inventory != NULL)
@ -401,7 +396,7 @@ AInventory *AHexenArmor::CreateCopy (AActor *other)
// Like BasicArmor, HexenArmor is used in the inventory but not the map.
// health is the slot this armor occupies.
// Amount is the quantity to give (0 = normal max).
AHexenArmor *copy = Spawn<AHexenArmor> (0, 0, 0, NO_REPLACE);
AHexenArmor *copy = Spawn<AHexenArmor> ();
copy->AddArmorToSlot (other, health, Amount);
GoAwayAndDie ();
return copy;
@ -452,7 +447,7 @@ bool AHexenArmor::HandlePickup (AInventory *item)
bool AHexenArmor::AddArmorToSlot (AActor *actor, int slot, int amount)
{
APlayerPawn *ppawn;
int hits;
double hits;
if (actor->player != NULL)
{
@ -478,9 +473,9 @@ bool AHexenArmor::AddArmorToSlot (AActor *actor, int slot, int amount)
}
else
{
hits = amount * 5 * FRACUNIT;
fixed_t total = Slots[0]+Slots[1]+Slots[2]+Slots[3]+Slots[4];
fixed_t max = SlotsIncrement[0]+SlotsIncrement[1]+SlotsIncrement[2]+SlotsIncrement[3]+Slots[4]+4*5*FRACUNIT;
hits = amount * 5;
auto total = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
auto max = SlotsIncrement[0] + SlotsIncrement[1] + SlotsIncrement[2] + SlotsIncrement[3] + Slots[4] + 4 * 5;
if (total < max)
{
Slots[slot] += hits;
@ -500,13 +495,13 @@ void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
{
if (!DamageTypeDefinition::IgnoreArmor(damageType))
{
fixed_t savedPercent = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
double savedPercent = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
if (savedPercent)
{ // armor absorbed some damage
if (savedPercent > 100*FRACUNIT)
if (savedPercent > 100)
{
savedPercent = 100*FRACUNIT;
savedPercent = 100;
}
for (int i = 0; i < 4; i++)
{
@ -516,15 +511,8 @@ void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
// with the dragon skin bracers.
if (damage < 10000)
{
#if __APPLE__ && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ == 1
// -O1 optimizer bug work around. Only needed for
// GCC 4.2.1 on OS X for 10.4/10.5 tools compatibility.
volatile fixed_t tmp = 300;
Slots[i] -= ::Scale (damage, SlotsIncrement[i], tmp);
#else
Slots[i] -= ::Scale (damage, SlotsIncrement[i], 300);
#endif
if (Slots[i] < 2*FRACUNIT)
Slots[i] -= damage * SlotsIncrement[i] / 300.;
if (Slots[i] < 2)
{
Slots[i] = 0;
}
@ -535,10 +523,10 @@ void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
}
}
}
int saved = ::Scale (damage, savedPercent, 100*FRACUNIT);
if (saved > savedPercent >> (FRACBITS-1))
int saved = int(damage * savedPercent / 100.);
if (saved > savedPercent*2)
{
saved = savedPercent >> (FRACBITS-1);
saved = int(savedPercent*2);
}
newdamage -= saved;
damage = newdamage;

View file

@ -1630,25 +1630,20 @@ void APowerDamage::EndEffect( )
void APowerDamage::ModifyDamage(int damage, FName damageType, int &newdamage, bool passive)
{
static const fixed_t def = 4*FRACUNIT;
if (!passive && damage > 0)
{
const fixed_t *pdf = NULL;
int newdam;
DmgFactors *df = GetClass()->DamageFactors;
if (df != NULL && df->CountUsed() != 0)
{
pdf = df->CheckFactor(damageType);
newdam = MIN(1, df->Apply(damageType, damage));// don't allow zero damage as result of an underflow
}
else
{
pdf = &def;
}
if (pdf != NULL)
{
damage = newdamage = FixedMul(damage, *pdf);
if (*pdf > 0 && damage == 0) damage = newdamage = 1; // don't allow zero damage as result of an underflow
if (Owner != NULL && *pdf > FRACUNIT) S_Sound(Owner, 5, ActiveSound, 1.0f, ATTN_NONE);
newdam = damage * 4;
}
if (Owner != NULL && newdam > damage) S_Sound(Owner, 5, ActiveSound, 1.0f, ATTN_NONE);
newdamage = newdam;
}
if (Inventory != NULL) Inventory->ModifyDamage(damage, damageType, newdamage, passive);
}
@ -1710,22 +1705,20 @@ void APowerProtection::EndEffect( )
void APowerProtection::ModifyDamage(int damage, FName damageType, int &newdamage, bool passive)
{
static const fixed_t def = FRACUNIT/4;
if (passive && damage > 0)
{
const fixed_t *pdf = NULL;
int newdam;
DmgFactors *df = GetClass()->DamageFactors;
if (df != NULL && df->CountUsed() != 0)
{
pdf = df->CheckFactor(damageType);
newdam = MIN(0, df->Apply(damageType, damage));
}
else pdf = &def;
if (pdf != NULL)
else
{
damage = newdamage = FixedMul(damage, *pdf);
if (Owner != NULL && *pdf < FRACUNIT) S_Sound(Owner, CHAN_AUTO, ActiveSound, 1.0f, ATTN_NONE);
newdam = damage / 4;
}
if (Owner != NULL && newdam < damage) S_Sound(Owner, CHAN_AUTO, ActiveSound, 1.0f, ATTN_NONE);
newdamage = newdam;
}
if (Inventory != NULL)
{

View file

@ -456,7 +456,7 @@ public:
virtual void AbsorbDamage (int damage, FName damageType, int &newdamage);
int AbsorbCount;
fixed_t SavePercent;
double SavePercent;
int MaxAbsorb;
int MaxFullAbsorb;
int BonusCount;
@ -473,7 +473,7 @@ public:
virtual AInventory *CreateCopy (AActor *other);
virtual bool Use (bool pickup);
fixed_t SavePercent;
double SavePercent;
int MaxAbsorb;
int MaxFullAbsorb;
int SaveAmount;
@ -488,7 +488,7 @@ public:
virtual AInventory *CreateCopy (AActor *other);
virtual bool Use (bool pickup);
fixed_t SavePercent; // The default, for when you don't already have armor
double SavePercent; // The default, for when you don't already have armor
int MaxSaveAmount;
int MaxAbsorb;
int MaxFullAbsorb;
@ -510,8 +510,8 @@ public:
virtual void AbsorbDamage (int damage, FName damageType, int &newdamage);
void DepleteOrDestroy();
fixed_t Slots[5];
fixed_t SlotsIncrement[4];
double Slots[5];
double SlotsIncrement[4];
protected:
bool AddArmorToSlot (AActor *actor, int slot, int amount);

View file

@ -146,7 +146,7 @@ void ASoundSequence::PostBeginPlay ()
}
if (master == NULL)
{
master = Spawn<ASoundSequenceSlot> (0, 0, 0, NO_REPLACE);
master = Spawn<ASoundSequenceSlot> ();
master->Sequence = SN_StartSequence (master, slot, 0);
GC::WriteBarrier(master, master->Sequence);
}

View file

@ -282,7 +282,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
if (harmor->Slots[armorType] > 0 && harmor->SlotsIncrement[armorType] > 0)
{
//combine the alpha values
alpha = FixedMul(alpha, MIN<fixed_t> (OPAQUE, Scale(harmor->Slots[armorType], OPAQUE, harmor->SlotsIncrement[armorType])));
alpha = int(alpha * MIN(1., harmor->Slots[armorType] / harmor->SlotsIncrement[armorType]));
texture = statusBar->Images[image];
}
else
@ -1377,21 +1377,21 @@ class CommandDrawNumber : public CommandDrawString
case ARMORCLASS:
case SAVEPERCENT:
{
double add = 0;
AHexenArmor *harmor = statusBar->CPlayer->mo->FindInventory<AHexenArmor>();
if(harmor != NULL)
{
num = harmor->Slots[0] + harmor->Slots[1] +
add = harmor->Slots[0] + harmor->Slots[1] +
harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4];
}
//Hexen counts basic armor also so we should too.
if(statusBar->armor != NULL)
{
num += FixedMul(statusBar->armor->SavePercent, 100*FRACUNIT);
add += statusBar->armor->SavePercent * 100;
}
if(value == ARMORCLASS)
num /= (5*FRACUNIT);
else
num >>= FRACBITS;
add /= 5;
num = int(add);
break;
}
case GLOBALVAR:
@ -2770,18 +2770,19 @@ class CommandDrawBar : public SBarInfoCommand
}
case SAVEPERCENT:
{
double add = 0;
AHexenArmor *harmor = statusBar->CPlayer->mo->FindInventory<AHexenArmor>();
if(harmor != NULL)
{
value = harmor->Slots[0] + harmor->Slots[1] +
add = harmor->Slots[0] + harmor->Slots[1] +
harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4];
}
//Hexen counts basic armor also so we should too.
if(statusBar->armor != NULL)
{
value += FixedMul(statusBar->armor->SavePercent, 100*FRACUNIT);
add += statusBar->armor->SavePercent * 100;
}
value >>= FRACBITS;
value = int(add);
max = 100;
break;
}

View file

@ -313,9 +313,8 @@ static void DrawArmor(ABasicArmor * barmor, AHexenArmor * harmor, int x, int y)
if (harmor)
{
int ac = (harmor->Slots[0] + harmor->Slots[1] + harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4]);
ac >>= FRACBITS;
ap += ac;
auto ac = (harmor->Slots[0] + harmor->Slots[1] + harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4]);
ap += int(ac);
if (ac)
{

View file

@ -279,7 +279,7 @@ void FMapInfoParser::ParseGameInfo()
if (sc.CheckToken(','))
{
sc.MustGetToken(TK_FloatConst);
gameinfo.Armor2Percent = FLOAT2FIXED(sc.Float);
gameinfo.Armor2Percent = sc.Float;
sc.MustGetToken(',');
sc.MustGetToken(TK_StringConst);
gameinfo.ArmorIcon2 = sc.String;

View file

@ -135,7 +135,7 @@ struct gameinfo_t
FString ArmorIcon2;
FString PauseSign;
FString Endoom;
fixed_t Armor2Percent;
double Armor2Percent;
FString quitSound;
gameborder_t Border;
double telefogheight;

View file

@ -532,7 +532,7 @@ PClassActor *PClassActor::GetReplacee(bool lookskill)
//
//==========================================================================
void PClassActor::SetDamageFactor(FName type, fixed_t factor)
void PClassActor::SetDamageFactor(FName type, double factor)
{
if (DamageFactors == NULL)
{
@ -593,16 +593,18 @@ void PClassActor::ReplaceClassRef(PClass *oldclass, PClass *newclass)
//
//==========================================================================
fixed_t *DmgFactors::CheckFactor(FName type)
int DmgFactors::Apply(FName type, int damage)
{
fixed_t *pdf = CheckKey(type);
auto pdf = CheckKey(type);
if (pdf == NULL && type != NAME_None)
{
pdf = CheckKey(NAME_None);
}
return pdf;
if (!pdf) return damage;
return int(damage * *pdf);
}
static void SummonActor (int command, int command2, FCommandLine argv)
{
if (CheckCheatmode ())
@ -689,32 +691,33 @@ bool DamageTypeDefinition::IgnoreArmor(FName type)
//
//==========================================================================
int DamageTypeDefinition::ApplyMobjDamageFactor(int damage, FName type, DmgFactors const * const factors)
double DamageTypeDefinition::GetMobjDamageFactor(FName type, DmgFactors const * const factors)
{
if (factors)
{
// If the actor has named damage factors, look for a specific factor
fixed_t const *pdf = factors->CheckKey(type);
if (pdf) return FixedMul(damage, *pdf); // type specific damage type
auto pdf = factors->CheckKey(type);
if (pdf) return *pdf; // type specific damage type
// If this was nonspecific damage, don't fall back to nonspecific search
if (type == NAME_None) return damage;
if (type == NAME_None) return 1.;
}
// If this was nonspecific damage, don't fall back to nonspecific search
else if (type == NAME_None)
{
return damage;
return 1.;
}
else
{
// Normal is unsupplied / 1.0, so there's no difference between modifying and overriding
DamageTypeDefinition *dtd = Get(type);
return dtd ? FixedMul(damage, dtd->DefaultFactor) : damage;
return dtd ? dtd->DefaultFactor : 1.;
}
{
fixed_t const *pdf = factors->CheckKey(NAME_None);
auto pdf = factors->CheckKey(NAME_None);
DamageTypeDefinition *dtd = Get(type);
// Here we are looking for modifications to untyped damage
// If the calling actor defines untyped damage factor, that is contained in "pdf".
@ -722,15 +725,21 @@ int DamageTypeDefinition::ApplyMobjDamageFactor(int damage, FName type, DmgFacto
{
if (dtd)
{
if (dtd->ReplaceFactor) return FixedMul(damage, dtd->DefaultFactor); // use default instead of untyped factor
return FixedMul(damage, FixedMul(*pdf, dtd->DefaultFactor)); // use default as modification of untyped factor
if (dtd->ReplaceFactor) return dtd->DefaultFactor; // use default instead of untyped factor
return *pdf * dtd->DefaultFactor; // use default as modification of untyped factor
}
return FixedMul(damage, *pdf); // there was no default, so actor default is used
return *pdf; // there was no default, so actor default is used
}
else if (dtd)
{
return FixedMul(damage, dtd->DefaultFactor); // implicit untyped factor 1.0 does not need to be applied/replaced explicitly
return dtd->DefaultFactor; // implicit untyped factor 1.0 does not need to be applied/replaced explicitly
}
}
return damage;
return 1.;
}
int DamageTypeDefinition::ApplyMobjDamageFactor(int damage, FName type, DmgFactors const * const factors)
{
double factor = GetMobjDamageFactor(type, factors);
return int(damage * factor);
}

View file

@ -158,9 +158,9 @@ FArchive &operator<< (FArchive &arc, FState *&state);
#include "gametype.h"
struct DmgFactors : public TMap<FName, fixed_t>
struct DmgFactors : public TMap<FName, double>
{
fixed_t *CheckFactor(FName type);
int Apply(FName type, int damage);
};
typedef TMap<FName, int> PainChanceList;
@ -169,20 +169,21 @@ struct DamageTypeDefinition
public:
DamageTypeDefinition() { Clear(); }
fixed_t DefaultFactor;
double DefaultFactor;
bool ReplaceFactor;
bool NoArmor;
void Apply(FName type);
void Clear()
{
DefaultFactor = FRACUNIT;
DefaultFactor = 1.;
ReplaceFactor = false;
NoArmor = false;
}
static DamageTypeDefinition *Get(FName type);
static bool IgnoreArmor(FName type);
static double GetMobjDamageFactor(FName type, DmgFactors const * const factors);
static int ApplyMobjDamageFactor(int damage, FName type, DmgFactors const * const factors);
};
@ -206,7 +207,7 @@ public:
void BuildDefaults();
void ApplyDefaults(BYTE *defaults);
void RegisterIDs();
void SetDamageFactor(FName type, fixed_t factor);
void SetDamageFactor(FName type, double factor);
void SetPainChance(FName type, int chance);
size_t PropagateMark();
void InitializeNativeDefaults();

View file

@ -715,7 +715,7 @@ void cht_Give (player_t *player, const char *name, int amount)
{
ABasicArmorPickup *armor = Spawn<ABasicArmorPickup> ();
armor->SaveAmount = 100*deh.BlueAC;
armor->SavePercent = gameinfo.Armor2Percent > 0? gameinfo.Armor2Percent : FRACUNIT/2;
armor->SavePercent = gameinfo.Armor2Percent > 0? gameinfo.Armor2Percent : 0.5;
if (!armor->CallTryPickup (player->mo))
{
armor->Destroy ();

View file

@ -5080,7 +5080,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
return equippedarmor->MaxAmount;
case ARMORINFO_SAVEPERCENT:
return equippedarmor->SavePercent;
return DoubleToACS(equippedarmor->SavePercent);
case ARMORINFO_MAXABSORB:
return equippedarmor->MaxAbsorb;

View file

@ -3317,13 +3317,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst)
// base the number of shards on the size of the dead thing, so bigger
// things break up into more shards than smaller things.
// An self with _f_radius() 20 and height 64 creates ~40 chunks.
numChunks = MAX<int> (4, int(self->radius * self->Height));
numChunks = MAX<int> (4, int(self->radius * self->Height)/32);
i = (pr_burst.Random2()) % (numChunks/4);
for (i = MAX (24, numChunks + i); i >= 0; i--)
{
fixed_t xo = (((pr_burst() - 128)*self->_f_radius()) >> 7);
fixed_t yo = (((pr_burst() - 128)*self->_f_radius()) >> 7);
fixed_t zo = (pr_burst()*self->_f_height() / 255 + self->GetBobOffset());
double xo = (pr_burst() - 128) * self->radius / 128;
double yo = (pr_burst() - 128) * self->radius / 128;
double zo = (pr_burst() * self->Height / 255);
mo = Spawn(chunk, self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
if (mo)

View file

@ -1283,8 +1283,8 @@ static void ParseDamageDefinition(FScanner &sc)
if (sc.Compare("FACTOR"))
{
sc.MustGetFloat();
dtd.DefaultFactor = FLOAT2FIXED(sc.Float);
if (!dtd.DefaultFactor) dtd.ReplaceFactor = true; // Multiply by 0 yields 0: FixedMul(damage, FixedMul(factor, 0)) is more wasteful than FixedMul(factor, 0)
dtd.DefaultFactor = sc.Float;
if (dtd.DefaultFactor == 0) dtd.ReplaceFactor = true; // Multiply by 0 yields 0: FixedMul(damage, FixedMul(factor, 0)) is more wasteful than FixedMul(factor, 0)
}
else if (sc.Compare("REPLACEFACTOR"))
{

View file

@ -254,7 +254,7 @@ void HandleDeprecatedFlags(AActor *defaults, PClassActor *info, bool set, int in
defaults->Gravity = set ? 1. / 4 : 1.;
break;
case DEPF_FIRERESIST:
info->SetDamageFactor(NAME_Fire, set? FRACUNIT/2 : FRACUNIT);
info->SetDamageFactor(NAME_Fire, set ? 0.5 : 1.);
break;
// the bounce flags will set the compatibility bounce modes to remain compatible
case DEPF_HERETICBOUNCE:
@ -322,8 +322,8 @@ bool CheckDeprecatedFlags(const AActor *actor, PClassActor *info, int index)
case DEPF_FIRERESIST:
if (info->DamageFactors)
{
fixed_t *df = info->DamageFactors->CheckKey(NAME_Fire);
return df && (*df) == FRACUNIT / 2;
double *df = info->DamageFactors->CheckKey(NAME_Fire);
return df && (*df) == 0.5;
}
return false;
@ -1229,7 +1229,7 @@ DEFINE_PROPERTY(damagefactor, ZF, Actor)
if (!stricmp(str, "Normal")) dmgType = NAME_None;
else dmgType=str;
info->SetDamageFactor(dmgType, FLOAT2FIXED(id));
info->SetDamageFactor(dmgType, id);
}
}
@ -1639,9 +1639,9 @@ DEFINE_CLASS_PROPERTY(saveamount, I, Armor)
//==========================================================================
DEFINE_CLASS_PROPERTY(savepercent, F, Armor)
{
PROP_FIXED_PARM(i, 0);
PROP_DOUBLE_PARM(i, 0);
i = clamp(i, 0, 100*FRACUNIT)/100;
i = clamp(i, 0., 100.)/100.;
// Special case here because this property has to work for 2 unrelated classes
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
{
@ -2793,7 +2793,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, hexenarmor, FFFFF, PlayerPawn)
assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
for (int i = 0; i < 5; i++)
{
PROP_FIXED_PARM(val, i);
PROP_DOUBLE_PARM(val, i);
static_cast<PClassPlayerPawn *>(info)->HexenArmor[i] = val;
}
}

View file

@ -105,7 +105,7 @@ ACTOR BasicArmorBonus : Armor native
+Inventory.AUTOACTIVATE
+Inventory.ALWAYSPICKUP
Inventory.MaxAmount 0
Armor.SavePercent 0.333333
Armor.SavePercent 33.335
}