mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-05 13:45:35 +00:00
Separate spell resistance
This commit is contained in:
parent
5973285446
commit
db13984db0
8 changed files with 134 additions and 98 deletions
|
@ -83,7 +83,7 @@ add_openmw_dir (mwclass
|
||||||
add_openmw_dir (mwmechanics
|
add_openmw_dir (mwmechanics
|
||||||
mechanicsmanagerimp stat creaturestats magiceffects movement actorutil
|
mechanicsmanagerimp stat creaturestats magiceffects movement actorutil
|
||||||
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe
|
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe
|
||||||
aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance
|
||||||
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
|
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
|
||||||
character actors objects aistate coordinateconverter trading weaponpriority spellpriority weapontype
|
character actors objects aistate coordinateconverter trading weaponpriority spellpriority weapontype
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "npcstats.hpp"
|
#include "npcstats.hpp"
|
||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
#include "spellcasting.hpp"
|
#include "spellcasting.hpp"
|
||||||
|
#include "spellresistance.hpp"
|
||||||
#include "difficultyscaling.hpp"
|
#include "difficultyscaling.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
#include "pathfinding.hpp"
|
#include "pathfinding.hpp"
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "aifollow.hpp"
|
#include "aifollow.hpp"
|
||||||
#include "weapontype.hpp"
|
#include "weapontype.hpp"
|
||||||
#include "summoning.hpp"
|
#include "summoning.hpp"
|
||||||
|
#include "spellresistance.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
@ -168,83 +169,6 @@ namespace MWMechanics
|
||||||
return spell && spellIncreasesSkill(spell);
|
return spell && spellIncreasesSkill(spell);
|
||||||
}
|
}
|
||||||
|
|
||||||
float getEffectResistanceAttribute (short effectId, const MagicEffects* actorEffects)
|
|
||||||
{
|
|
||||||
short resistanceEffect = ESM::MagicEffect::getResistanceEffect(effectId);
|
|
||||||
short weaknessEffect = ESM::MagicEffect::getWeaknessEffect(effectId);
|
|
||||||
|
|
||||||
float resistance = 0;
|
|
||||||
if (resistanceEffect != -1)
|
|
||||||
resistance += actorEffects->get(resistanceEffect).getMagnitude();
|
|
||||||
if (weaknessEffect != -1)
|
|
||||||
resistance -= actorEffects->get(weaknessEffect).getMagnitude();
|
|
||||||
|
|
||||||
if (effectId == ESM::MagicEffect::FireDamage)
|
|
||||||
resistance += actorEffects->get(ESM::MagicEffect::FireShield).getMagnitude();
|
|
||||||
if (effectId == ESM::MagicEffect::ShockDamage)
|
|
||||||
resistance += actorEffects->get(ESM::MagicEffect::LightningShield).getMagnitude();
|
|
||||||
if (effectId == ESM::MagicEffect::FrostDamage)
|
|
||||||
resistance += actorEffects->get(ESM::MagicEffect::FrostShield).getMagnitude();
|
|
||||||
|
|
||||||
return resistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
|
|
||||||
const ESM::Spell* spell, const MagicEffects* effects)
|
|
||||||
{
|
|
||||||
const ESM::MagicEffect *magicEffect =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
|
|
||||||
effectId);
|
|
||||||
|
|
||||||
const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
|
||||||
const MWMechanics::MagicEffects* magicEffects = &stats.getMagicEffects();
|
|
||||||
if (effects)
|
|
||||||
magicEffects = effects;
|
|
||||||
|
|
||||||
// Effects with no resistance attribute belonging to them can not be resisted
|
|
||||||
if (ESM::MagicEffect::getResistanceEffect(effectId) == -1)
|
|
||||||
return 0.f;
|
|
||||||
|
|
||||||
float resistance = getEffectResistanceAttribute(effectId, magicEffects);
|
|
||||||
|
|
||||||
int willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
|
|
||||||
float luck = static_cast<float>(stats.getAttribute(ESM::Attribute::Luck).getModified());
|
|
||||||
float x = (willpower + 0.1f * luck) * stats.getFatigueTerm();
|
|
||||||
|
|
||||||
// This makes spells that are easy to cast harder to resist and vice versa
|
|
||||||
float castChance = 100.f;
|
|
||||||
if (spell != nullptr && !caster.isEmpty() && caster.getClass().isActor())
|
|
||||||
{
|
|
||||||
castChance = getSpellSuccessChance(spell, caster, nullptr, false, false); // Uncapped casting chance
|
|
||||||
}
|
|
||||||
if (castChance > 0)
|
|
||||||
x *= 50 / castChance;
|
|
||||||
|
|
||||||
float roll = Misc::Rng::rollClosedProbability() * 100;
|
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)
|
|
||||||
roll -= resistance;
|
|
||||||
|
|
||||||
if (x <= roll)
|
|
||||||
x = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)
|
|
||||||
x = 100;
|
|
||||||
else
|
|
||||||
x = roll / std::min(x, 100.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
x = std::min(x + resistance, 100.f);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
|
|
||||||
const ESM::Spell* spell, const MagicEffects* effects)
|
|
||||||
{
|
|
||||||
float resistance = getEffectResistance(effectId, actor, caster, spell, effects);
|
|
||||||
return 1 - resistance / 100.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the given effect can be applied to the target. If \a castByPlayer, emits a message box on failure.
|
/// Check if the given effect can be applied to the target. If \a castByPlayer, emits a message box on failure.
|
||||||
bool checkEffectTarget (int effectId, const MWWorld::Ptr& target, const MWWorld::Ptr& caster, bool castByPlayer)
|
bool checkEffectTarget (int effectId, const MWWorld::Ptr& target, const MWWorld::Ptr& caster, bool castByPlayer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef MWMECHANICS_SPELLSUCCESS_H
|
#ifndef MWMECHANICS_SPELLCASTING_H
|
||||||
#define MWMECHANICS_SPELLSUCCESS_H
|
#define MWMECHANICS_SPELLCASTING_H
|
||||||
|
|
||||||
#include <components/esm/effectlist.hpp>
|
#include <components/esm/effectlist.hpp>
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
@ -46,24 +46,6 @@ namespace MWMechanics
|
||||||
bool spellIncreasesSkill(const ESM::Spell* spell);
|
bool spellIncreasesSkill(const ESM::Spell* spell);
|
||||||
bool spellIncreasesSkill(const std::string& spellId);
|
bool spellIncreasesSkill(const std::string& spellId);
|
||||||
|
|
||||||
/// Get the resistance attribute against an effect for a given actor. This will add together
|
|
||||||
/// ResistX and Weakness to X effects relevant against the given effect.
|
|
||||||
float getEffectResistanceAttribute (short effectId, const MagicEffects* actorEffects);
|
|
||||||
|
|
||||||
/// Get the effective resistance against an effect casted by the given actor in the given spell (optional).
|
|
||||||
/// @return >=100 for fully resisted. can also return negative value for damage amplification.
|
|
||||||
/// @param effects Override the actor's current magicEffects. Useful if there are effects currently
|
|
||||||
/// being applied (but not applied yet) that should also be considered.
|
|
||||||
float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
|
|
||||||
const ESM::Spell* spell = nullptr, const MagicEffects* effects = nullptr);
|
|
||||||
|
|
||||||
/// Get an effect multiplier for applying an effect cast by the given actor in the given spell (optional).
|
|
||||||
/// @return effect multiplier from 0 to 2. (100% net resistance to 100% net weakness)
|
|
||||||
/// @param effects Override the actor's current magicEffects. Useful if there are effects currently
|
|
||||||
/// being applied (but not applied yet) that should also be considered.
|
|
||||||
float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
|
|
||||||
const ESM::Spell* spell = nullptr, const MagicEffects* effects = nullptr);
|
|
||||||
|
|
||||||
bool checkEffectTarget (int effectId, const MWWorld::Ptr& target, const MWWorld::Ptr& caster, bool castByPlayer);
|
bool checkEffectTarget (int effectId, const MWWorld::Ptr& target, const MWWorld::Ptr& caster, bool castByPlayer);
|
||||||
|
|
||||||
int getEffectiveEnchantmentCastCost (float castCost, const MWWorld::Ptr& actor);
|
int getEffectiveEnchantmentCastCost (float castCost, const MWWorld::Ptr& actor);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "creaturestats.hpp"
|
#include "creaturestats.hpp"
|
||||||
#include "spellcasting.hpp"
|
#include "spellcasting.hpp"
|
||||||
|
#include "spellresistance.hpp"
|
||||||
#include "weapontype.hpp"
|
#include "weapontype.hpp"
|
||||||
#include "combat.hpp"
|
#include "combat.hpp"
|
||||||
#include "summoning.hpp"
|
#include "summoning.hpp"
|
||||||
|
|
90
apps/openmw/mwmechanics/spellresistance.cpp
Normal file
90
apps/openmw/mwmechanics/spellresistance.cpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#include "spellresistance.hpp"
|
||||||
|
|
||||||
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include "creaturestats.hpp"
|
||||||
|
#include "spellcasting.hpp"
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
|
||||||
|
float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
|
||||||
|
const ESM::Spell* spell, const MagicEffects* effects)
|
||||||
|
{
|
||||||
|
float resistance = getEffectResistance(effectId, actor, caster, spell, effects);
|
||||||
|
return 1 - resistance / 100.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
|
||||||
|
const ESM::Spell* spell, const MagicEffects* effects)
|
||||||
|
{
|
||||||
|
// Effects with no resistance attribute belonging to them can not be resisted
|
||||||
|
if (ESM::MagicEffect::getResistanceEffect(effectId) == -1)
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
const auto magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effectId);
|
||||||
|
|
||||||
|
const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
const MWMechanics::MagicEffects* magicEffects = &stats.getMagicEffects();
|
||||||
|
if (effects)
|
||||||
|
magicEffects = effects;
|
||||||
|
|
||||||
|
float resistance = getEffectResistanceAttribute(effectId, magicEffects);
|
||||||
|
|
||||||
|
int willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
|
||||||
|
float luck = static_cast<float>(stats.getAttribute(ESM::Attribute::Luck).getModified());
|
||||||
|
float x = (willpower + 0.1f * luck) * stats.getFatigueTerm();
|
||||||
|
|
||||||
|
// This makes spells that are easy to cast harder to resist and vice versa
|
||||||
|
float castChance = 100.f;
|
||||||
|
if (spell != nullptr && !caster.isEmpty() && caster.getClass().isActor())
|
||||||
|
castChance = getSpellSuccessChance(spell, caster, nullptr, false, false); // Uncapped casting chance
|
||||||
|
if (castChance > 0)
|
||||||
|
x *= 50 / castChance;
|
||||||
|
|
||||||
|
float roll = Misc::Rng::rollClosedProbability() * 100;
|
||||||
|
if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)
|
||||||
|
roll -= resistance;
|
||||||
|
|
||||||
|
if (x <= roll)
|
||||||
|
x = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)
|
||||||
|
x = 100;
|
||||||
|
else
|
||||||
|
x = roll / std::min(x, 100.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
x = std::min(x + resistance, 100.f);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getEffectResistanceAttribute (short effectId, const MagicEffects* actorEffects)
|
||||||
|
{
|
||||||
|
short resistanceEffect = ESM::MagicEffect::getResistanceEffect(effectId);
|
||||||
|
short weaknessEffect = ESM::MagicEffect::getWeaknessEffect(effectId);
|
||||||
|
|
||||||
|
float resistance = 0;
|
||||||
|
if (resistanceEffect != -1)
|
||||||
|
resistance += actorEffects->get(resistanceEffect).getMagnitude();
|
||||||
|
if (weaknessEffect != -1)
|
||||||
|
resistance -= actorEffects->get(weaknessEffect).getMagnitude();
|
||||||
|
|
||||||
|
if (effectId == ESM::MagicEffect::FireDamage)
|
||||||
|
resistance += actorEffects->get(ESM::MagicEffect::FireShield).getMagnitude();
|
||||||
|
if (effectId == ESM::MagicEffect::ShockDamage)
|
||||||
|
resistance += actorEffects->get(ESM::MagicEffect::LightningShield).getMagnitude();
|
||||||
|
if (effectId == ESM::MagicEffect::FrostDamage)
|
||||||
|
resistance += actorEffects->get(ESM::MagicEffect::FrostShield).getMagnitude();
|
||||||
|
|
||||||
|
return resistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
apps/openmw/mwmechanics/spellresistance.hpp
Normal file
37
apps/openmw/mwmechanics/spellresistance.hpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef MWMECHANICS_SPELLRESISTANCE_H
|
||||||
|
#define MWMECHANICS_SPELLRESISTANCE_H
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct Spell;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
class MagicEffects;
|
||||||
|
|
||||||
|
/// Get an effect multiplier for applying an effect cast by the given actor in the given spell (optional).
|
||||||
|
/// @return effect multiplier from 0 to 2. (100% net resistance to 100% net weakness)
|
||||||
|
/// @param effects Override the actor's current magicEffects. Useful if there are effects currently
|
||||||
|
/// being applied (but not applied yet) that should also be considered.
|
||||||
|
float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
|
||||||
|
const ESM::Spell* spell = nullptr, const MagicEffects* effects = nullptr);
|
||||||
|
|
||||||
|
/// Get the effective resistance against an effect casted by the given actor in the given spell (optional).
|
||||||
|
/// @return >=100 for fully resisted. can also return negative value for damage amplification.
|
||||||
|
/// @param effects Override the actor's current magicEffects. Useful if there are effects currently
|
||||||
|
/// being applied (but not applied yet) that should also be considered.
|
||||||
|
float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
|
||||||
|
const ESM::Spell* spell = nullptr, const MagicEffects* effects = nullptr);
|
||||||
|
|
||||||
|
/// Get the resistance attribute against an effect for a given actor. This will add together
|
||||||
|
/// ResistX and Weakness to X effects relevant against the given effect.
|
||||||
|
float getEffectResistanceAttribute (short effectId, const MagicEffects* actorEffects);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
#include "../mwmechanics/spellresistance.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
#include "../mwmechanics/weapontype.hpp"
|
#include "../mwmechanics/weapontype.hpp"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue