forked from mirror/openmw-tes3mp
Move spell magicka cost calculation to standalone function
This commit is contained in:
parent
143fdae6fe
commit
3ba0a336b7
5 changed files with 83 additions and 41 deletions
|
@ -440,22 +440,11 @@ namespace MWGui
|
||||||
|
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
|
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
|
||||||
{
|
{
|
||||||
float x = 0.5f * (it->mMagnMin + it->mMagnMax);
|
const ESM::ENAMstruct& effect = *it;
|
||||||
|
|
||||||
const ESM::MagicEffect* effect =
|
y += std::max(1.f, MWMechanics::calcEffectCost(effect));
|
||||||
store.get<ESM::MagicEffect>().find(it->mEffectID);
|
|
||||||
|
|
||||||
x *= 0.1f * effect->mData.mBaseCost;
|
if (effect.mRange == ESM::RT_Target)
|
||||||
x *= 1 + it->mDuration;
|
|
||||||
x += 0.05f * std::max(1, it->mArea) * effect->mData.mBaseCost;
|
|
||||||
|
|
||||||
float fEffectCostMult =
|
|
||||||
store.get<ESM::GameSetting>().find("fEffectCostMult")->getFloat();
|
|
||||||
|
|
||||||
y += x * fEffectCostMult;
|
|
||||||
y = std::max(1.f,y);
|
|
||||||
|
|
||||||
if (it->mRange == ESM::RT_Target)
|
|
||||||
y *= 1.5;
|
y *= 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,8 +464,10 @@ namespace MWGui
|
||||||
|
|
||||||
mPriceLabel->setCaption(MyGUI::utility::toString(int(price)));
|
mPriceLabel->setCaption(MyGUI::utility::toString(int(price)));
|
||||||
|
|
||||||
float chance = MWMechanics::getSpellSuccessChance(&mSpell, MWMechanics::getPlayer());
|
float chance = MWMechanics::calcSpellBaseSuccessChance(&mSpell, MWMechanics::getPlayer(), NULL);
|
||||||
mSuccessChance->setCaption(MyGUI::utility::toString(int(chance)));
|
|
||||||
|
int intChance = std::min(100, int(chance));
|
||||||
|
mSuccessChance->setCaption(MyGUI::utility::toString(intChance));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -593,16 +593,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rating *= ((effect.mMagnMin + effect.mMagnMax) * (effect.mDuration > 0 ? effect.mDuration : 1) + effect.mArea);
|
rating *= calcEffectCost(effect);
|
||||||
rating *= magicEffect->mData.mBaseCost;
|
|
||||||
|
|
||||||
if (effect.mRange == ESM::RT_Target)
|
|
||||||
rating *= 1.5f;
|
|
||||||
|
|
||||||
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
|
||||||
"fEffectCostMult")->getFloat();
|
|
||||||
|
|
||||||
rating *= fEffectCostMult * 0.05;
|
|
||||||
|
|
||||||
// Currently treating all "on target" or "on touch" effects to target the enemy actor.
|
// Currently treating all "on target" or "on touch" effects to target the enemy actor.
|
||||||
// Combat AI is egoistic, so doesn't consider applying positive effects to friendly actors.
|
// Combat AI is egoistic, so doesn't consider applying positive effects to friendly actors.
|
||||||
|
@ -619,6 +610,9 @@ namespace MWMechanics
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it)
|
for (std::vector<ESM::ENAMstruct>::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it)
|
||||||
{
|
{
|
||||||
rating += rateEffect(*it, actor, enemy);
|
rating += rateEffect(*it, actor, enemy);
|
||||||
|
|
||||||
|
if (it->mRange == ESM::RT_Target)
|
||||||
|
rating *= 1.5f;
|
||||||
}
|
}
|
||||||
return rating;
|
return rating;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "autocalcspell.hpp"
|
#include "autocalcspell.hpp"
|
||||||
|
#include "spellcasting.hpp"
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -255,27 +256,39 @@ namespace MWMechanics
|
||||||
|
|
||||||
void calcWeakestSchool (const ESM::Spell* spell, const int* actorSkills, int& effectiveSchool, float& skillTerm)
|
void calcWeakestSchool (const ESM::Spell* spell, const int* actorSkills, int& effectiveSchool, float& skillTerm)
|
||||||
{
|
{
|
||||||
|
// Morrowind for some reason uses a formula slightly different from magicka cost calculation
|
||||||
float minChance = std::numeric_limits<float>::max();
|
float minChance = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
const ESM::EffectList& effects = spell->mEffects;
|
const ESM::EffectList& effects = spell->mEffects;
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator it = effects.mList.begin(); it != effects.mList.end(); ++it)
|
for (std::vector<ESM::ENAMstruct>::const_iterator it = effects.mList.begin(); it != effects.mList.end(); ++it)
|
||||||
{
|
{
|
||||||
const ESM::ENAMstruct& effect = *it;
|
const ESM::ENAMstruct& effect = *it;
|
||||||
float x = static_cast<float>(effect.mDuration);
|
|
||||||
|
|
||||||
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
|
||||||
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage))
|
|
||||||
x = std::max(1.f, x);
|
|
||||||
|
|
||||||
x *= 0.1f * magicEffect->mData.mBaseCost;
|
int minMagn = 1;
|
||||||
x *= 0.5f * (effect.mMagnMin + effect.mMagnMax);
|
int maxMagn = 1;
|
||||||
x += effect.mArea * 0.05f * magicEffect->mData.mBaseCost;
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
|
||||||
|
{
|
||||||
|
minMagn = effect.mMagnMin;
|
||||||
|
maxMagn = effect.mMagnMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
int duration = 0;
|
||||||
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
||||||
|
duration = effect.mDuration;
|
||||||
|
|
||||||
|
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore()
|
||||||
|
.get<ESM::GameSetting>().find("fEffectCostMult")->getFloat();
|
||||||
|
|
||||||
|
float x = 0.5 * (std::max(1, minMagn) + std::max(1, maxMagn));
|
||||||
|
x *= 0.1 * magicEffect->mData.mBaseCost;
|
||||||
|
x *= 1 + duration;
|
||||||
|
x += 0.05 * std::max(1, effect.mArea) * magicEffect->mData.mBaseCost;
|
||||||
|
x *= fEffectCostMult;
|
||||||
|
|
||||||
if (effect.mRange == ESM::RT_Target)
|
if (effect.mRange == ESM::RT_Target)
|
||||||
x *= 1.5f;
|
x *= 1.5f;
|
||||||
|
|
||||||
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fEffectCostMult")->getFloat();
|
|
||||||
x *= fEffectCostMult;
|
|
||||||
|
|
||||||
float s = 2.f * actorSkills[mapSchoolToSkill(magicEffect->mData.mSchool)];
|
float s = 2.f * actorSkills[mapSchoolToSkill(magicEffect->mData.mSchool)];
|
||||||
if (s - x < minChance)
|
if (s - x < minChance)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,8 +44,36 @@ namespace MWMechanics
|
||||||
return schoolSkillMap[school];
|
return schoolSkillMap[school];
|
||||||
}
|
}
|
||||||
|
|
||||||
float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool, bool cap)
|
float calcEffectCost(const ESM::ENAMstruct& effect)
|
||||||
{
|
{
|
||||||
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
|
||||||
|
|
||||||
|
int minMagn = 1;
|
||||||
|
int maxMagn = 1;
|
||||||
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
|
||||||
|
{
|
||||||
|
minMagn = effect.mMagnMin;
|
||||||
|
maxMagn = effect.mMagnMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
int duration = 0;
|
||||||
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
||||||
|
duration = effect.mDuration;
|
||||||
|
|
||||||
|
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore()
|
||||||
|
.get<ESM::GameSetting>().find("fEffectCostMult")->getFloat();
|
||||||
|
|
||||||
|
float x = 0.5 * (std::max(1, minMagn) + std::max(1, maxMagn));
|
||||||
|
x *= 0.1 * magicEffect->mData.mBaseCost;
|
||||||
|
x *= 1 + duration;
|
||||||
|
x += 0.05 * std::max(1, effect.mArea) * magicEffect->mData.mBaseCost;
|
||||||
|
|
||||||
|
return x * fEffectCostMult;
|
||||||
|
}
|
||||||
|
|
||||||
|
float calcSpellBaseSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool)
|
||||||
|
{
|
||||||
|
// Morrowind for some reason uses a formula slightly different from magicka cost calculation
|
||||||
float y = std::numeric_limits<float>::max();
|
float y = std::numeric_limits<float>::max();
|
||||||
float lowestSkill = 0;
|
float lowestSkill = 0;
|
||||||
|
|
||||||
|
@ -54,8 +82,10 @@ namespace MWMechanics
|
||||||
float x = static_cast<float>(it->mDuration);
|
float x = static_cast<float>(it->mDuration);
|
||||||
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(
|
||||||
it->mEffectID);
|
it->mEffectID);
|
||||||
|
|
||||||
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage))
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage))
|
||||||
x = std::max(1.f, x);
|
x = std::max(1.f, x);
|
||||||
|
|
||||||
x *= 0.1f * magicEffect->mData.mBaseCost;
|
x *= 0.1f * magicEffect->mData.mBaseCost;
|
||||||
x *= 0.5f * (it->mMagnMin + it->mMagnMax);
|
x *= 0.5f * (it->mMagnMin + it->mMagnMax);
|
||||||
x *= it->mArea * 0.05f * magicEffect->mData.mBaseCost;
|
x *= it->mArea * 0.05f * magicEffect->mData.mBaseCost;
|
||||||
|
@ -75,6 +105,18 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
|
||||||
|
int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
|
||||||
|
int actorLuck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||||
|
|
||||||
|
float castChance = (lowestSkill - spell->mData.mCost + 0.2f * actorWillpower + 0.1f * actorLuck);
|
||||||
|
|
||||||
|
return castChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool, bool cap)
|
||||||
|
{
|
||||||
bool godmode = actor == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
|
bool godmode = actor == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
|
||||||
|
|
||||||
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
@ -98,10 +140,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
float castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude();
|
float castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude();
|
||||||
|
|
||||||
int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
|
float castChance = calcSpellBaseSuccessChance(spell, actor, effectiveSchool) + castBonus;
|
||||||
int actorLuck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
castChance *= stats.getFatigueTerm();
|
||||||
|
|
||||||
float castChance = (lowestSkill - spell->mData.mCost + castBonus + 0.2f * actorWillpower + 0.1f * actorLuck) * stats.getFatigueTerm();
|
|
||||||
|
|
||||||
if (!cap)
|
if (!cap)
|
||||||
return std::max(0.f, castChance);
|
return std::max(0.f, castChance);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef MWMECHANICS_SPELLSUCCESS_H
|
#ifndef MWMECHANICS_SPELLSUCCESS_H
|
||||||
#define MWMECHANICS_SPELLSUCCESS_H
|
#define MWMECHANICS_SPELLSUCCESS_H
|
||||||
|
|
||||||
|
#include <components/esm/effectlist.hpp>
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
@ -21,6 +22,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
ESM::Skill::SkillEnum spellSchoolToSkill(int school);
|
ESM::Skill::SkillEnum spellSchoolToSkill(int school);
|
||||||
|
|
||||||
|
float calcEffectCost(const ESM::ENAMstruct& effect);
|
||||||
|
|
||||||
bool isSummoningEffect(int effectId);
|
bool isSummoningEffect(int effectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,6 +65,7 @@ namespace MWMechanics
|
||||||
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);
|
||||||
|
float calcSpellBaseSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool);
|
||||||
|
|
||||||
/// Apply a magic effect that is applied in tick intervals until its remaining time ends or it is removed
|
/// Apply a magic effect that is applied in tick intervals until its remaining time ends or it is removed
|
||||||
/// @return Was the effect a tickable effect with a magnitude?
|
/// @return Was the effect a tickable effect with a magnitude?
|
||||||
|
|
Loading…
Reference in a new issue