mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-29 15:06:42 +00:00
Some cleanup - move definitions to implementation file
This commit is contained in:
parent
c04a8afc8b
commit
525ce2f042
6 changed files with 197 additions and 181 deletions
|
@ -3,8 +3,15 @@
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/actionequip.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
#include "../mwmechanics/spells.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "../mwgui/inventorywindow.hpp"
|
#include "../mwgui/inventorywindow.hpp"
|
||||||
#include "../mwgui/bookwindow.hpp"
|
#include "../mwgui/bookwindow.hpp"
|
||||||
#include "../mwgui/scrollwindow.hpp"
|
#include "../mwgui/scrollwindow.hpp"
|
||||||
|
@ -17,8 +24,8 @@ namespace
|
||||||
{
|
{
|
||||||
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
|
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
|
||||||
{
|
{
|
||||||
int cmp = MWWorld::Class::get(left).getName(left).compare(
|
int cmp = left.getClass().getName(left).compare(
|
||||||
MWWorld::Class::get(right).getName(right));
|
right.getClass().getName(right));
|
||||||
return cmp < 0;
|
return cmp < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,10 +341,7 @@ namespace MWGui
|
||||||
// equip, if it can be equipped
|
// equip, if it can be equipped
|
||||||
if (!MWWorld::Class::get(item).getEquipmentSlots(item).first.empty())
|
if (!MWWorld::Class::get(item).getEquipmentSlots(item).first.empty())
|
||||||
{
|
{
|
||||||
// Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping
|
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item);
|
||||||
|
|
||||||
MWWorld::ActionEquip action(item);
|
|
||||||
action.execute (MWBase::Environment::get().getWorld ()->getPlayerPtr());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store.setSelectedEnchantItem(it);
|
store.setSelectedEnchantItem(it);
|
||||||
|
|
|
@ -3,13 +3,17 @@
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
#include "../mwmechanics/spells.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "tooltips.hpp"
|
#include "tooltips.hpp"
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/actionequip.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
#include "../mwmechanics/spells.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "spellicons.hpp"
|
#include "spellicons.hpp"
|
||||||
#include "inventorywindow.hpp"
|
#include "inventorywindow.hpp"
|
||||||
|
@ -231,8 +235,7 @@ namespace MWGui
|
||||||
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
|
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
|
||||||
|
|
||||||
float enchantCost = enchant->mData.mCost;
|
float enchantCost = enchant->mData.mCost;
|
||||||
MWMechanics::NpcStats &stats = player.getClass().getNpcStats(player);
|
int eSkill = player.getClass().getSkill(player, ESM::Skill::Enchant);
|
||||||
int eSkill = stats.getSkill(ESM::Skill::Enchant).getModified();
|
|
||||||
int castCost = std::max(1.f, enchantCost - (enchantCost / 100) * (eSkill - 10));
|
int castCost = std::max(1.f, enchantCost - (enchantCost / 100) * (eSkill - 10));
|
||||||
|
|
||||||
std::string cost = boost::lexical_cast<std::string>(castCost);
|
std::string cost = boost::lexical_cast<std::string>(castCost);
|
||||||
|
@ -316,13 +319,7 @@ namespace MWGui
|
||||||
if (_sender->getUserString("Equipped") == "false"
|
if (_sender->getUserString("Equipped") == "false"
|
||||||
&& !MWWorld::Class::get(item).getEquipmentSlots(item).first.empty())
|
&& !MWWorld::Class::get(item).getEquipmentSlots(item).first.empty())
|
||||||
{
|
{
|
||||||
// Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping
|
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item);
|
||||||
|
|
||||||
MWWorld::ActionEquip action(item);
|
|
||||||
action.execute (MWBase::Environment::get().getWorld ()->getPlayerPtr());
|
|
||||||
|
|
||||||
// since we changed equipping status, update the inventory window
|
|
||||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store.setSelectedEnchantItem(it);
|
store.setSelectedEnchantItem(it);
|
||||||
|
|
|
@ -1,20 +1,182 @@
|
||||||
#include "spellcasting.hpp"
|
#include "spellcasting.hpp"
|
||||||
|
|
||||||
|
#include <cfloat>
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
#include "../mwworld/actionteleport.hpp"
|
#include "../mwworld/actionteleport.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
|
|
||||||
|
#include "magiceffects.hpp"
|
||||||
|
#include "npcstats.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
|
||||||
|
ESM::Skill::SkillEnum spellSchoolToSkill(int school)
|
||||||
|
{
|
||||||
|
std::map<int, ESM::Skill::SkillEnum> schoolSkillMap; // maps spell school to skill id
|
||||||
|
schoolSkillMap[0] = ESM::Skill::Alteration;
|
||||||
|
schoolSkillMap[1] = ESM::Skill::Conjuration;
|
||||||
|
schoolSkillMap[3] = ESM::Skill::Illusion;
|
||||||
|
schoolSkillMap[2] = ESM::Skill::Destruction;
|
||||||
|
schoolSkillMap[4] = ESM::Skill::Mysticism;
|
||||||
|
schoolSkillMap[5] = ESM::Skill::Restoration;
|
||||||
|
assert(schoolSkillMap.find(school) != schoolSkillMap.end());
|
||||||
|
return schoolSkillMap[school];
|
||||||
|
}
|
||||||
|
|
||||||
|
float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool)
|
||||||
|
{
|
||||||
|
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
|
||||||
|
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).mMagnitude)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
float y = FLT_MAX;
|
||||||
|
float lowestSkill = 0;
|
||||||
|
|
||||||
|
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it)
|
||||||
|
{
|
||||||
|
float x = it->mDuration;
|
||||||
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(
|
||||||
|
it->mEffectID);
|
||||||
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage))
|
||||||
|
x = std::max(1.f, x);
|
||||||
|
x *= 0.1 * magicEffect->mData.mBaseCost;
|
||||||
|
x *= 0.5 * (it->mMagnMin + it->mMagnMax);
|
||||||
|
x *= it->mArea * 0.05 * magicEffect->mData.mBaseCost;
|
||||||
|
if (magicEffect->mData.mFlags & ESM::MagicEffect::CastTarget)
|
||||||
|
x *= 1.5;
|
||||||
|
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
|
"fEffectCostMult")->getFloat();
|
||||||
|
x *= fEffectCostMult;
|
||||||
|
|
||||||
|
float s = 2 * actor.getClass().getSkill(actor, spellSchoolToSkill(magicEffect->mData.mSchool));
|
||||||
|
if (s - x < y)
|
||||||
|
{
|
||||||
|
y = s - x;
|
||||||
|
if (effectiveSchool)
|
||||||
|
*effectiveSchool = magicEffect->mData.mSchool;
|
||||||
|
lowestSkill = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
|
return 100;
|
||||||
|
|
||||||
|
if (spell->mData.mFlags & ESM::Spell::F_Always)
|
||||||
|
return 100;
|
||||||
|
|
||||||
|
int castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).mMagnitude;
|
||||||
|
|
||||||
|
int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
|
||||||
|
int actorLuck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||||
|
|
||||||
|
float castChance = (lowestSkill - spell->mData.mCost + castBonus + 0.2 * actorWillpower + 0.1 * actorLuck) * stats.getFatigueTerm();
|
||||||
|
if (MWBase::Environment::get().getWorld()->getGodModeState() && actor.getRefData().getHandle() == "player")
|
||||||
|
castChance = 100;
|
||||||
|
|
||||||
|
return std::max(0.f, std::min(100.f, castChance));
|
||||||
|
}
|
||||||
|
|
||||||
|
float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor, int* effectiveSchool)
|
||||||
|
{
|
||||||
|
const ESM::Spell* spell =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
||||||
|
return getSpellSuccessChance(spell, actor, effectiveSchool);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
int school = 0;
|
||||||
|
getSpellSuccessChance(spellId, actor, &school);
|
||||||
|
return school;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
int school = 0;
|
||||||
|
getSpellSuccessChance(spell, actor, &school);
|
||||||
|
return school;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell)
|
||||||
|
{
|
||||||
|
const ESM::MagicEffect *magicEffect =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
|
||||||
|
effectId);
|
||||||
|
|
||||||
|
const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
|
||||||
|
float resisted = 0;
|
||||||
|
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful)
|
||||||
|
{
|
||||||
|
|
||||||
|
short resistanceEffect = ESM::MagicEffect::getResistanceEffect(effectId);
|
||||||
|
short weaknessEffect = ESM::MagicEffect::getWeaknessEffect(effectId);
|
||||||
|
|
||||||
|
float resistance = 0;
|
||||||
|
if (resistanceEffect != -1)
|
||||||
|
resistance += stats.getMagicEffects().get(resistanceEffect).mMagnitude;
|
||||||
|
if (weaknessEffect != -1)
|
||||||
|
resistance -= stats.getMagicEffects().get(weaknessEffect).mMagnitude;
|
||||||
|
|
||||||
|
|
||||||
|
float willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
|
||||||
|
float luck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||||
|
float x = (willpower + 0.1 * luck) * stats.getFatigueTerm();
|
||||||
|
|
||||||
|
// This makes spells that are easy to cast harder to resist and vice versa
|
||||||
|
if (spell != NULL && caster.getClass().isActor())
|
||||||
|
{
|
||||||
|
float castChance = getSpellSuccessChance(spell, caster);
|
||||||
|
if (castChance > 0)
|
||||||
|
x *= 50 / castChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
float roll = static_cast<float>(std::rand()) / RAND_MAX * 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);
|
||||||
|
|
||||||
|
resisted = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resisted;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell)
|
||||||
|
{
|
||||||
|
float resistance = getEffectResistance(effectId, actor, caster, spell);
|
||||||
|
if (resistance >= 0)
|
||||||
|
return 1 - resistance / 100.f;
|
||||||
|
else
|
||||||
|
return -(resistance-100) / 100.f;
|
||||||
|
}
|
||||||
|
|
||||||
CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target)
|
CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target)
|
||||||
: mCaster(caster)
|
: mCaster(caster)
|
||||||
, mTarget(target)
|
, mTarget(target)
|
||||||
|
@ -230,7 +392,7 @@ namespace MWMechanics
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(caster, target, MWBase::MechanicsManager::OT_Assault);
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(caster, target, MWBase::MechanicsManager::OT_Assault);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, MWMechanics::EffectKey effect, float magnitude)
|
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const MWMechanics::EffectKey& effect, float magnitude)
|
||||||
{
|
{
|
||||||
short effectId = effect.mId;
|
short effectId = effect.mId;
|
||||||
if (!target.getClass().isActor())
|
if (!target.getClass().isActor())
|
||||||
|
|
|
@ -1,33 +1,13 @@
|
||||||
#ifndef MWMECHANICS_SPELLSUCCESS_H
|
#ifndef MWMECHANICS_SPELLSUCCESS_H
|
||||||
#define MWMECHANICS_SPELLSUCCESS_H
|
#define MWMECHANICS_SPELLSUCCESS_H
|
||||||
|
|
||||||
#include <cfloat>
|
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
|
||||||
#include "../mwbase/environment.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
|
||||||
|
|
||||||
#include "npcstats.hpp"
|
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
inline ESM::Skill::SkillEnum spellSchoolToSkill(int school)
|
class EffectKey;
|
||||||
{
|
|
||||||
std::map<int, ESM::Skill::SkillEnum> schoolSkillMap; // maps spell school to skill id
|
ESM::Skill::SkillEnum spellSchoolToSkill(int school);
|
||||||
schoolSkillMap[0] = ESM::Skill::Alteration;
|
|
||||||
schoolSkillMap[1] = ESM::Skill::Conjuration;
|
|
||||||
schoolSkillMap[3] = ESM::Skill::Illusion;
|
|
||||||
schoolSkillMap[2] = ESM::Skill::Destruction;
|
|
||||||
schoolSkillMap[4] = ESM::Skill::Mysticism;
|
|
||||||
schoolSkillMap[5] = ESM::Skill::Restoration;
|
|
||||||
assert(schoolSkillMap.find(school) != schoolSkillMap.end());
|
|
||||||
return schoolSkillMap[school];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param spell spell to cast
|
* @param spell spell to cast
|
||||||
|
@ -36,147 +16,16 @@ namespace MWMechanics
|
||||||
* @attention actor has to be an NPC and not a creature!
|
* @attention actor has to be an NPC and not a creature!
|
||||||
* @return success chance from 0 to 100 (in percent)
|
* @return success chance from 0 to 100 (in percent)
|
||||||
*/
|
*/
|
||||||
inline float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool = NULL)
|
float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool = NULL);
|
||||||
{
|
float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor, int* effectiveSchool = NULL);
|
||||||
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
|
||||||
|
|
||||||
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).mMagnitude)
|
int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor);
|
||||||
return 0;
|
int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
float y = FLT_MAX;
|
|
||||||
float lowestSkill = 0;
|
|
||||||
|
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it)
|
|
||||||
{
|
|
||||||
float x = it->mDuration;
|
|
||||||
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(
|
|
||||||
it->mEffectID);
|
|
||||||
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage))
|
|
||||||
x = std::max(1.f, x);
|
|
||||||
x *= 0.1 * magicEffect->mData.mBaseCost;
|
|
||||||
x *= 0.5 * (it->mMagnMin + it->mMagnMax);
|
|
||||||
x *= it->mArea * 0.05 * magicEffect->mData.mBaseCost;
|
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::CastTarget)
|
|
||||||
x *= 1.5;
|
|
||||||
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
|
||||||
"fEffectCostMult")->getFloat();
|
|
||||||
x *= fEffectCostMult;
|
|
||||||
|
|
||||||
float s = 2 * actor.getClass().getSkill(actor, spellSchoolToSkill(magicEffect->mData.mSchool));
|
|
||||||
if (s - x < y)
|
|
||||||
{
|
|
||||||
y = s - x;
|
|
||||||
if (effectiveSchool)
|
|
||||||
*effectiveSchool = magicEffect->mData.mSchool;
|
|
||||||
lowestSkill = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
|
||||||
return 100;
|
|
||||||
|
|
||||||
if (spell->mData.mFlags & ESM::Spell::F_Always)
|
|
||||||
return 100;
|
|
||||||
|
|
||||||
int castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).mMagnitude;
|
|
||||||
|
|
||||||
int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
|
|
||||||
int actorLuck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
|
||||||
|
|
||||||
float castChance = (lowestSkill - spell->mData.mCost + castBonus + 0.2 * actorWillpower + 0.1 * actorLuck) * stats.getFatigueTerm();
|
|
||||||
if (MWBase::Environment::get().getWorld()->getGodModeState() && actor.getRefData().getHandle() == "player")
|
|
||||||
castChance = 100;
|
|
||||||
|
|
||||||
return std::max(0.f, std::min(100.f, castChance));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor, int* effectiveSchool = NULL)
|
|
||||||
{
|
|
||||||
const ESM::Spell* spell =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
|
||||||
return getSpellSuccessChance(spell, actor, effectiveSchool);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor)
|
|
||||||
{
|
|
||||||
int school = 0;
|
|
||||||
getSpellSuccessChance(spellId, actor, &school);
|
|
||||||
return school;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor)
|
|
||||||
{
|
|
||||||
int school = 0;
|
|
||||||
getSpellSuccessChance(spell, actor, &school);
|
|
||||||
return school;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @return >=100 for fully resisted. can also return negative value for damage amplification.
|
/// @return >=100 for fully resisted. can also return negative value for damage amplification.
|
||||||
inline float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell = NULL)
|
float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell = NULL);
|
||||||
{
|
|
||||||
const ESM::MagicEffect *magicEffect =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
|
|
||||||
effectId);
|
|
||||||
|
|
||||||
const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
|
||||||
|
|
||||||
float resisted = 0;
|
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful)
|
|
||||||
{
|
|
||||||
|
|
||||||
short resistanceEffect = ESM::MagicEffect::getResistanceEffect(effectId);
|
|
||||||
short weaknessEffect = ESM::MagicEffect::getWeaknessEffect(effectId);
|
|
||||||
|
|
||||||
float resistance = 0;
|
|
||||||
if (resistanceEffect != -1)
|
|
||||||
resistance += stats.getMagicEffects().get(resistanceEffect).mMagnitude;
|
|
||||||
if (weaknessEffect != -1)
|
|
||||||
resistance -= stats.getMagicEffects().get(weaknessEffect).mMagnitude;
|
|
||||||
|
|
||||||
|
|
||||||
float willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
|
|
||||||
float luck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
|
||||||
float x = (willpower + 0.1 * luck) * stats.getFatigueTerm();
|
|
||||||
|
|
||||||
// This makes spells that are easy to cast harder to resist and vice versa
|
|
||||||
if (spell != NULL && caster.getClass().isActor())
|
|
||||||
{
|
|
||||||
float castChance = getSpellSuccessChance(spell, caster);
|
|
||||||
if (castChance > 0)
|
|
||||||
x *= 50 / castChance;
|
|
||||||
}
|
|
||||||
|
|
||||||
float roll = static_cast<float>(std::rand()) / RAND_MAX * 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);
|
|
||||||
|
|
||||||
resisted = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
return resisted;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell = NULL)
|
|
||||||
{
|
|
||||||
float resistance = getEffectResistance(effectId, actor, caster, spell);
|
|
||||||
if (resistance >= 0)
|
|
||||||
return 1 - resistance / 100.f;
|
|
||||||
else
|
|
||||||
return -(resistance-100) / 100.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell = NULL);
|
||||||
|
|
||||||
class CastSpell
|
class CastSpell
|
||||||
{
|
{
|
||||||
|
@ -202,7 +51,7 @@ namespace MWMechanics
|
||||||
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
||||||
const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false);
|
const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false);
|
||||||
|
|
||||||
void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, MWMechanics::EffectKey effect, float magnitude);
|
void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace MWMechanics
|
||||||
/// \brief Spell list
|
/// \brief Spell list
|
||||||
///
|
///
|
||||||
/// This class manages known spells as well as abilities, powers and permanent negative effects like
|
/// This class manages known spells as well as abilities, powers and permanent negative effects like
|
||||||
/// diseaes.
|
/// diseases.
|
||||||
class Spells
|
class Spells
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue