mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-02 01:45:31 +00:00
Implement correct armor mitigation mechanics
This commit is contained in:
parent
804f1a5e59
commit
5629803a08
3 changed files with 20 additions and 6 deletions
|
@ -394,6 +394,9 @@ namespace MWClass
|
||||||
if (damage > 0.0f && !object.isEmpty())
|
if (damage > 0.0f && !object.isEmpty())
|
||||||
MWMechanics::resistNormalWeapon(ptr, attacker, object, damage);
|
MWMechanics::resistNormalWeapon(ptr, attacker, object, damage);
|
||||||
|
|
||||||
|
if (damage < 0.001f)
|
||||||
|
damage = 0;
|
||||||
|
|
||||||
if (damage > 0.f)
|
if (damage > 0.f)
|
||||||
{
|
{
|
||||||
// Check for knockdown
|
// Check for knockdown
|
||||||
|
@ -409,6 +412,8 @@ namespace MWClass
|
||||||
else
|
else
|
||||||
getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur?
|
getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur?
|
||||||
|
|
||||||
|
damage = std::max(1.f, damage);
|
||||||
|
|
||||||
if(ishealth)
|
if(ishealth)
|
||||||
{
|
{
|
||||||
if (!attacker.isEmpty())
|
if (!attacker.isEmpty())
|
||||||
|
@ -639,6 +644,7 @@ namespace MWClass
|
||||||
|
|
||||||
float Creature::getArmorRating (const MWWorld::Ptr& ptr) const
|
float Creature::getArmorRating (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
|
// Note this is currently unused. Creatures do not use armor mitigation.
|
||||||
return getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).mMagnitude;
|
return getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).mMagnitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -280,6 +280,7 @@ namespace MWClass
|
||||||
gmst.iKnockDownOddsBase = store.find("iKnockDownOddsBase");
|
gmst.iKnockDownOddsBase = store.find("iKnockDownOddsBase");
|
||||||
gmst.fDamageStrengthBase = store.find("fDamageStrengthBase");
|
gmst.fDamageStrengthBase = store.find("fDamageStrengthBase");
|
||||||
gmst.fDamageStrengthMult = store.find("fDamageStrengthMult");
|
gmst.fDamageStrengthMult = store.find("fDamageStrengthMult");
|
||||||
|
gmst.fCombatArmorMinMult = store.find("fCombatArmorMinMult");
|
||||||
|
|
||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
|
@ -706,6 +707,9 @@ namespace MWClass
|
||||||
if (damage > 0.0f && !object.isEmpty())
|
if (damage > 0.0f && !object.isEmpty())
|
||||||
MWMechanics::resistNormalWeapon(ptr, attacker, object, damage);
|
MWMechanics::resistNormalWeapon(ptr, attacker, object, damage);
|
||||||
|
|
||||||
|
if (damage < 0.001f)
|
||||||
|
damage = 0;
|
||||||
|
|
||||||
if(damage > 0.0f)
|
if(damage > 0.0f)
|
||||||
{
|
{
|
||||||
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
|
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
|
||||||
|
@ -734,7 +738,7 @@ namespace MWClass
|
||||||
else
|
else
|
||||||
getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur?
|
getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur?
|
||||||
|
|
||||||
if(ishealth && !attacker.isEmpty()) // Don't use armor mitigation for fall damage
|
if(damage > 0 && ishealth && !attacker.isEmpty()) // Don't use armor mitigation for fall damage
|
||||||
{
|
{
|
||||||
// Hit percentages:
|
// Hit percentages:
|
||||||
// cuirass = 30%
|
// cuirass = 30%
|
||||||
|
@ -754,9 +758,12 @@ namespace MWClass
|
||||||
};
|
};
|
||||||
int hitslot = hitslots[(int)(::rand()/(RAND_MAX+1.0)*20.0)];
|
int hitslot = hitslots[(int)(::rand()/(RAND_MAX+1.0)*20.0)];
|
||||||
|
|
||||||
float damagediff = damage;
|
float unmitigatedDamage = damage;
|
||||||
damage /= std::min(1.0f + getArmorRating(ptr)/std::max(1.0f, damage), 4.0f);
|
float x = damage / (damage + getArmorRating(ptr));
|
||||||
damagediff -= damage;
|
damage *= std::max(gmst.fCombatArmorMinMult->getFloat(), x);
|
||||||
|
int damageDiff = unmitigatedDamage - damage;
|
||||||
|
if (damage < 1)
|
||||||
|
damage = 1;
|
||||||
|
|
||||||
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
||||||
MWWorld::ContainerStoreIterator armorslot = inv.getSlot(hitslot);
|
MWWorld::ContainerStoreIterator armorslot = inv.getSlot(hitslot);
|
||||||
|
@ -764,13 +771,13 @@ namespace MWClass
|
||||||
if(!armor.isEmpty() && armor.getTypeName() == typeid(ESM::Armor).name())
|
if(!armor.isEmpty() && armor.getTypeName() == typeid(ESM::Armor).name())
|
||||||
{
|
{
|
||||||
int armorhealth = armor.getClass().getItemHealth(armor);
|
int armorhealth = armor.getClass().getItemHealth(armor);
|
||||||
armorhealth -= std::min(std::max(1, (int)damagediff),
|
armorhealth -= std::min(std::max(1, damageDiff),
|
||||||
armorhealth);
|
armorhealth);
|
||||||
armor.getCellRef().setCharge(armorhealth);
|
armor.getCellRef().setCharge(armorhealth);
|
||||||
|
|
||||||
// Armor broken? unequip it
|
// Armor broken? unequip it
|
||||||
if (armorhealth == 0)
|
if (armorhealth == 0)
|
||||||
inv.unequipItem(armor, ptr);
|
armor = *inv.unequipItem(armor, ptr);
|
||||||
|
|
||||||
if (ptr.getRefData().getHandle() == "player")
|
if (ptr.getRefData().getHandle() == "player")
|
||||||
skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0);
|
skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0);
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace MWClass
|
||||||
const ESM::GameSetting *iKnockDownOddsBase;
|
const ESM::GameSetting *iKnockDownOddsBase;
|
||||||
const ESM::GameSetting *fDamageStrengthBase;
|
const ESM::GameSetting *fDamageStrengthBase;
|
||||||
const ESM::GameSetting *fDamageStrengthMult;
|
const ESM::GameSetting *fDamageStrengthMult;
|
||||||
|
const ESM::GameSetting *fCombatArmorMinMult;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const GMST& getGmst();
|
static const GMST& getGmst();
|
||||||
|
|
Loading…
Reference in a new issue