mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-27 06:41:37 +00:00
Merge branch 'lua-activeeffects' into 'master'
Lua: Actor api for active effects and active spells See merge request OpenMW/openmw!3036
This commit is contained in:
commit
d3ed04c551
41 changed files with 1077 additions and 524 deletions
|
@ -73,9 +73,9 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
float weight = getContainerStore(ptr).getWeight();
|
float weight = getContainerStore(ptr).getWeight();
|
||||||
const MWMechanics::MagicEffects& effects = getCreatureStats(ptr).getMagicEffects();
|
const MWMechanics::MagicEffects& effects = getCreatureStats(ptr).getMagicEffects();
|
||||||
weight -= effects.get(MWMechanics::EffectKey(ESM::MagicEffect::Feather)).getMagnitude();
|
weight -= effects.getOrDefault(MWMechanics::EffectKey(ESM::MagicEffect::Feather)).getMagnitude();
|
||||||
if (ptr != MWMechanics::getPlayer() || !MWBase::Environment::get().getWorld()->getGodModeState())
|
if (ptr != MWMechanics::getPlayer() || !MWBase::Environment::get().getWorld()->getGodModeState())
|
||||||
weight += effects.get(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).getMagnitude();
|
weight += effects.getOrDefault(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).getMagnitude();
|
||||||
return (weight < 0) ? 0.0f : weight;
|
return (weight < 0) ? 0.0f : weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace MWClass
|
||||||
float getSwimSpeedImpl(const MWWorld::Ptr& ptr, const GMST& gmst, const MWMechanics::MagicEffects& mageffects,
|
float getSwimSpeedImpl(const MWWorld::Ptr& ptr, const GMST& gmst, const MWMechanics::MagicEffects& mageffects,
|
||||||
float baseSpeed) const
|
float baseSpeed) const
|
||||||
{
|
{
|
||||||
return baseSpeed * (1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude())
|
return baseSpeed * (1.0f + 0.01f * mageffects.getOrDefault(ESM::MagicEffect::SwiftSwim).getMagnitude())
|
||||||
* (gmst.fSwimRunBase->mValue.getFloat()
|
* (gmst.fSwimRunBase->mValue.getFloat()
|
||||||
+ 0.01f * getSkill(ptr, ESM::Skill::Athletics) * gmst.fSwimRunAthleticsMult->mValue.getFloat());
|
+ 0.01f * getSkill(ptr, ESM::Skill::Athletics) * gmst.fSwimRunAthleticsMult->mValue.getFloat());
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,11 +555,11 @@ namespace MWClass
|
||||||
if (getEncumbrance(ptr) > getCapacity(ptr))
|
if (getEncumbrance(ptr) > getCapacity(ptr))
|
||||||
moveSpeed = 0.0f;
|
moveSpeed = 0.0f;
|
||||||
else if (canFly(ptr)
|
else if (canFly(ptr)
|
||||||
|| (mageffects.get(ESM::MagicEffect::Levitate).getMagnitude() > 0 && world->isLevitationEnabled()))
|
|| (mageffects.getOrDefault(ESM::MagicEffect::Levitate).getMagnitude() > 0 && world->isLevitationEnabled()))
|
||||||
{
|
{
|
||||||
float flySpeed = 0.01f
|
float flySpeed = 0.01f
|
||||||
* (stats.getAttribute(ESM::Attribute::Speed).getModified()
|
* (stats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||||
+ mageffects.get(ESM::MagicEffect::Levitate).getMagnitude());
|
+ mageffects.getOrDefault(ESM::MagicEffect::Levitate).getMagnitude());
|
||||||
flySpeed = gmst.fMinFlySpeed->mValue.getFloat()
|
flySpeed = gmst.fMinFlySpeed->mValue.getFloat()
|
||||||
+ flySpeed * (gmst.fMaxFlySpeed->mValue.getFloat() - gmst.fMinFlySpeed->mValue.getFloat());
|
+ flySpeed * (gmst.fMaxFlySpeed->mValue.getFloat() - gmst.fMinFlySpeed->mValue.getFloat());
|
||||||
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
|
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
|
||||||
|
@ -614,7 +614,7 @@ namespace MWClass
|
||||||
float Creature::getArmorRating(const MWWorld::Ptr& ptr) const
|
float Creature::getArmorRating(const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
// Equipment armor rating is deliberately ignored.
|
// Equipment armor rating is deliberately ignored.
|
||||||
return getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).getMagnitude();
|
return getCreatureStats(ptr).getMagicEffects().getOrDefault(ESM::MagicEffect::Shield).getMagnitude();
|
||||||
}
|
}
|
||||||
|
|
||||||
float Creature::getCapacity(const MWWorld::Ptr& ptr) const
|
float Creature::getCapacity(const MWWorld::Ptr& ptr) const
|
||||||
|
|
|
@ -1021,11 +1021,11 @@ namespace MWClass
|
||||||
float moveSpeed;
|
float moveSpeed;
|
||||||
if (getEncumbrance(ptr) > getCapacity(ptr))
|
if (getEncumbrance(ptr) > getCapacity(ptr))
|
||||||
moveSpeed = 0.0f;
|
moveSpeed = 0.0f;
|
||||||
else if (mageffects.get(ESM::MagicEffect::Levitate).getMagnitude() > 0 && world->isLevitationEnabled())
|
else if (mageffects.getOrDefault(ESM::MagicEffect::Levitate).getMagnitude() > 0 && world->isLevitationEnabled())
|
||||||
{
|
{
|
||||||
float flySpeed = 0.01f
|
float flySpeed = 0.01f
|
||||||
* (stats.getAttribute(ESM::Attribute::Speed).getModified()
|
* (stats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||||
+ mageffects.get(ESM::MagicEffect::Levitate).getMagnitude());
|
+ mageffects.getOrDefault(ESM::MagicEffect::Levitate).getMagnitude());
|
||||||
flySpeed = gmst.fMinFlySpeed->mValue.getFloat()
|
flySpeed = gmst.fMinFlySpeed->mValue.getFloat()
|
||||||
+ flySpeed * (gmst.fMaxFlySpeed->mValue.getFloat() - gmst.fMinFlySpeed->mValue.getFloat());
|
+ flySpeed * (gmst.fMaxFlySpeed->mValue.getFloat() - gmst.fMinFlySpeed->mValue.getFloat());
|
||||||
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat() * normalizedEncumbrance;
|
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat() * normalizedEncumbrance;
|
||||||
|
@ -1071,7 +1071,7 @@ namespace MWClass
|
||||||
float x = gmst.fJumpAcrobaticsBase->mValue.getFloat()
|
float x = gmst.fJumpAcrobaticsBase->mValue.getFloat()
|
||||||
+ std::pow(a / 15.0f, gmst.fJumpAcroMultiplier->mValue.getFloat());
|
+ std::pow(a / 15.0f, gmst.fJumpAcroMultiplier->mValue.getFloat());
|
||||||
x += 3.0f * b * gmst.fJumpAcroMultiplier->mValue.getFloat();
|
x += 3.0f * b * gmst.fJumpAcroMultiplier->mValue.getFloat();
|
||||||
x += mageffects.get(ESM::MagicEffect::Jump).getMagnitude() * 64;
|
x += mageffects.getOrDefault(ESM::MagicEffect::Jump).getMagnitude() * 64;
|
||||||
x *= encumbranceTerm;
|
x *= encumbranceTerm;
|
||||||
|
|
||||||
if (stats.getStance(MWMechanics::CreatureStats::Stance_Run))
|
if (stats.getStance(MWMechanics::CreatureStats::Stance_Run))
|
||||||
|
@ -1217,7 +1217,7 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float shield = stats.getMagicEffects().get(ESM::MagicEffect::Shield).getMagnitude();
|
float shield = stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Shield).getMagnitude();
|
||||||
|
|
||||||
return ratings[MWWorld::InventoryStore::Slot_Cuirass] * 0.3f
|
return ratings[MWWorld::InventoryStore::Slot_Cuirass] * 0.3f
|
||||||
+ (ratings[MWWorld::InventoryStore::Slot_CarriedLeft] + ratings[MWWorld::InventoryStore::Slot_Helmet]
|
+ (ratings[MWWorld::InventoryStore::Slot_CarriedLeft] + ratings[MWWorld::InventoryStore::Slot_Helmet]
|
||||||
|
|
|
@ -582,7 +582,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
||||||
return player.getClass()
|
return player.getClass()
|
||||||
.getCreatureStats(player)
|
.getCreatureStats(player)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::Corprus)
|
.getOrDefault(ESM::MagicEffect::Corprus)
|
||||||
.getMagnitude()
|
.getMagnitude()
|
||||||
!= 0;
|
!= 0;
|
||||||
|
|
||||||
|
@ -601,7 +601,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
||||||
return player.getClass()
|
return player.getClass()
|
||||||
.getCreatureStats(player)
|
.getCreatureStats(player)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::Vampirism)
|
.getOrDefault(ESM::MagicEffect::Vampirism)
|
||||||
.getMagnitude()
|
.getMagnitude()
|
||||||
> 0;
|
> 0;
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ namespace
|
||||||
const MWWorld::Store<ESM::GameSetting>& gmst
|
const MWWorld::Store<ESM::GameSetting>& gmst
|
||||||
= MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>();
|
= MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>();
|
||||||
|
|
||||||
return gmst.find(ESM::MagicEffect::effectIdToString(id1))->mValue.getString()
|
return gmst.find(ESM::MagicEffect::indexToGmstString(id1))->mValue.getString()
|
||||||
< gmst.find(ESM::MagicEffect::effectIdToString(id2))->mValue.getString();
|
< gmst.find(ESM::MagicEffect::indexToGmstString(id2))->mValue.getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(ESM::ENAMstruct& effect)
|
void init(ESM::ENAMstruct& effect)
|
||||||
|
@ -196,7 +196,7 @@ namespace MWGui
|
||||||
mEffectImage->setImageTexture(Misc::ResourceHelpers::correctIconPath(
|
mEffectImage->setImageTexture(Misc::ResourceHelpers::correctIconPath(
|
||||||
effect->mIcon, MWBase::Environment::get().getResourceSystem()->getVFS()));
|
effect->mIcon, MWBase::Environment::get().getResourceSystem()->getVFS()));
|
||||||
|
|
||||||
mEffectName->setCaptionWithReplacing("#{" + ESM::MagicEffect::effectIdToString(effect->mIndex) + "}");
|
mEffectName->setCaptionWithReplacing("#{" + ESM::MagicEffect::indexToGmstString(effect->mIndex) + "}");
|
||||||
|
|
||||||
mEffect.mEffectID = effect->mIndex;
|
mEffect.mEffectID = effect->mIndex;
|
||||||
|
|
||||||
|
@ -552,7 +552,7 @@ namespace MWGui
|
||||||
mAvailableEffectsList->addItem(MWBase::Environment::get()
|
mAvailableEffectsList->addItem(MWBase::Environment::get()
|
||||||
.getESMStore()
|
.getESMStore()
|
||||||
->get<ESM::GameSetting>()
|
->get<ESM::GameSetting>()
|
||||||
.find(ESM::MagicEffect::effectIdToString(effectId))
|
.find(ESM::MagicEffect::indexToGmstString(effectId))
|
||||||
->mValue.getString());
|
->mValue.getString());
|
||||||
mButtonMapping[i] = effectId;
|
mButtonMapping[i] = effectId;
|
||||||
++i;
|
++i;
|
||||||
|
@ -565,7 +565,7 @@ namespace MWGui
|
||||||
const std::string& name = MWBase::Environment::get()
|
const std::string& name = MWBase::Environment::get()
|
||||||
.getESMStore()
|
.getESMStore()
|
||||||
->get<ESM::GameSetting>()
|
->get<ESM::GameSetting>()
|
||||||
.find(ESM::MagicEffect::effectIdToString(effectId))
|
.find(ESM::MagicEffect::indexToGmstString(effectId))
|
||||||
->mValue.getString();
|
->mValue.getString();
|
||||||
MyGUI::Widget* w = mAvailableEffectsList->getItemWidget(name);
|
MyGUI::Widget* w = mAvailableEffectsList->getItemWidget(name);
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ namespace MWGui
|
||||||
image->setImageTexture(Misc::ResourceHelpers::correctIconPath(
|
image->setImageTexture(Misc::ResourceHelpers::correctIconPath(
|
||||||
effect->mIcon, MWBase::Environment::get().getResourceSystem()->getVFS()));
|
effect->mIcon, MWBase::Environment::get().getResourceSystem()->getVFS()));
|
||||||
|
|
||||||
const std::string& name = ESM::MagicEffect::effectIdToString(effectId);
|
const std::string& name = ESM::MagicEffect::indexToGmstString(effectId);
|
||||||
|
|
||||||
ToolTipInfo tooltipInfo;
|
ToolTipInfo tooltipInfo;
|
||||||
tooltipInfo.caption = "#{" + name + "}";
|
tooltipInfo.caption = "#{" + name + "}";
|
||||||
|
|
|
@ -954,7 +954,7 @@ namespace MWGui
|
||||||
void ToolTips::createMagicEffectToolTip(MyGUI::Widget* widget, short id)
|
void ToolTips::createMagicEffectToolTip(MyGUI::Widget* widget, short id)
|
||||||
{
|
{
|
||||||
const ESM::MagicEffect* effect = MWBase::Environment::get().getESMStore()->get<ESM::MagicEffect>().find(id);
|
const ESM::MagicEffect* effect = MWBase::Environment::get().getESMStore()->get<ESM::MagicEffect>().find(id);
|
||||||
const std::string& name = ESM::MagicEffect::effectIdToString(id);
|
const std::string& name = ESM::MagicEffect::indexToGmstString(id);
|
||||||
|
|
||||||
std::string icon = effect->mIcon;
|
std::string icon = effect->mIcon;
|
||||||
int slashPos = icon.rfind('\\');
|
int slashPos = icon.rfind('\\');
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwmechanics/activespells.hpp"
|
#include "../mwmechanics/activespells.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
#include "../mwmechanics/magiceffects.hpp"
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwmechanics/spellutil.hpp"
|
#include "../mwmechanics/spellutil.hpp"
|
||||||
#include "../mwworld/action.hpp"
|
#include "../mwworld/action.hpp"
|
||||||
|
@ -27,11 +28,95 @@
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
// class returned via 'types.Actor.spells(obj)' in Lua
|
template <typename Store>
|
||||||
struct ActorSpells
|
struct ActorStore
|
||||||
{
|
{
|
||||||
const ObjectVariant mActor;
|
using Collection = typename Store::Collection;
|
||||||
|
using Iterator = typename Collection::const_iterator;
|
||||||
|
|
||||||
|
ActorStore(const sol::object& actor)
|
||||||
|
: mActor(actor)
|
||||||
|
, mIterator()
|
||||||
|
, mIndex(0)
|
||||||
|
{
|
||||||
|
if (!isActor())
|
||||||
|
throw std::runtime_error("Actor expected");
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isActor() const { return !mActor.ptr().isEmpty() && mActor.ptr().getClass().isActor(); }
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
mIndex = 0;
|
||||||
|
auto* store = getStore();
|
||||||
|
if (store)
|
||||||
|
mIterator = store->begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEnd() const
|
||||||
|
{
|
||||||
|
auto* store = getStore();
|
||||||
|
if (store)
|
||||||
|
return mIterator == store->end();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void advance()
|
||||||
|
{
|
||||||
|
auto* store = getStore();
|
||||||
|
if (store)
|
||||||
|
{
|
||||||
|
mIterator++;
|
||||||
|
mIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Store* getStore() const;
|
||||||
|
|
||||||
|
ObjectVariant mActor;
|
||||||
|
Iterator mIterator;
|
||||||
|
int mIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
MWMechanics::Spells* ActorStore<MWMechanics::Spells>::getStore() const
|
||||||
|
{
|
||||||
|
if (!isActor())
|
||||||
|
return nullptr;
|
||||||
|
const MWWorld::Ptr& ptr = mActor.ptr();
|
||||||
|
return &ptr.getClass().getCreatureStats(ptr).getSpells();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
MWMechanics::MagicEffects* ActorStore<MWMechanics::MagicEffects>::getStore() const
|
||||||
|
{
|
||||||
|
if (!isActor())
|
||||||
|
return nullptr;
|
||||||
|
const MWWorld::Ptr& ptr = mActor.ptr();
|
||||||
|
return &ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
MWMechanics::ActiveSpells* ActorStore<MWMechanics::ActiveSpells>::getStore() const
|
||||||
|
{
|
||||||
|
if (!isActor())
|
||||||
|
return nullptr;
|
||||||
|
const MWWorld::Ptr& ptr = mActor.ptr();
|
||||||
|
return &ptr.getClass().getCreatureStats(ptr).getActiveSpells();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ActiveEffect
|
||||||
|
{
|
||||||
|
MWMechanics::EffectKey key;
|
||||||
|
MWMechanics::EffectParam param;
|
||||||
|
};
|
||||||
|
// class returned via 'types.Actor.spells(obj)' in Lua
|
||||||
|
using ActorSpells = ActorStore<MWMechanics::Spells>;
|
||||||
|
// class returned via 'types.Actor.activeEffects(obj)' in Lua
|
||||||
|
using ActorActiveEffects = ActorStore<MWMechanics::MagicEffects>;
|
||||||
|
// class returned via 'types.Actor.activeSpells(obj)' in Lua
|
||||||
|
using ActorActiveSpells = ActorStore<MWMechanics::ActiveSpells>;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace sol
|
namespace sol
|
||||||
|
@ -52,14 +137,22 @@ namespace sol
|
||||||
struct is_automagical<ESM::MagicEffect> : std::false_type
|
struct is_automagical<ESM::MagicEffect> : std::false_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
template <>
|
template <typename T>
|
||||||
struct is_automagical<MWLua::ActorSpells> : std::false_type
|
struct is_automagical<MWLua::ActorStore<T>> : std::false_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
|
static ESM::RefId toSpellId(const sol::object& spellOrId)
|
||||||
|
{
|
||||||
|
if (spellOrId.is<ESM::Spell>())
|
||||||
|
return spellOrId.as<const ESM::Spell*>()->mId;
|
||||||
|
else
|
||||||
|
return ESM::RefId::deserializeText(LuaUtil::cast<std::string_view>(spellOrId));
|
||||||
|
}
|
||||||
|
|
||||||
sol::table initCoreMagicBindings(const Context& context)
|
sol::table initCoreMagicBindings(const Context& context)
|
||||||
{
|
{
|
||||||
sol::state_view& lua = context.mLua->sol();
|
sol::state_view& lua = context.mLua->sol();
|
||||||
|
@ -89,6 +182,13 @@ namespace MWLua
|
||||||
{ "Power", ESM::Spell::ST_Power },
|
{ "Power", ESM::Spell::ST_Power },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
sol::table effect(context.mLua->sol(), sol::create);
|
||||||
|
magicApi["EFFECT_TYPE"] = LuaUtil::makeStrictReadOnly(effect);
|
||||||
|
for (const auto& name : ESM::MagicEffect::sIndexNames)
|
||||||
|
{
|
||||||
|
effect[name] = Misc::StringUtils::lowerCase(name);
|
||||||
|
}
|
||||||
|
|
||||||
// Spell store
|
// Spell store
|
||||||
using SpellStore = MWWorld::Store<ESM::Spell>;
|
using SpellStore = MWWorld::Store<ESM::Spell>;
|
||||||
const SpellStore* spellStore = &MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>();
|
const SpellStore* spellStore = &MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>();
|
||||||
|
@ -156,7 +256,7 @@ namespace MWLua
|
||||||
auto effectParamsT = lua.new_usertype<ESM::ENAMstruct>("ESM3_EffectParams");
|
auto effectParamsT = lua.new_usertype<ESM::ENAMstruct>("ESM3_EffectParams");
|
||||||
effectParamsT[sol::meta_function::to_string] = [magicEffectStore](const ESM::ENAMstruct& params) {
|
effectParamsT[sol::meta_function::to_string] = [magicEffectStore](const ESM::ENAMstruct& params) {
|
||||||
const ESM::MagicEffect* const rec = magicEffectStore->find(params.mEffectID);
|
const ESM::MagicEffect* const rec = magicEffectStore->find(params.mEffectID);
|
||||||
return "ESM3_EffectParams[" + ESM::MagicEffect::effectIdToString(rec->mIndex) + "]";
|
return "ESM3_EffectParams[" + ESM::MagicEffect::indexToGmstString(rec->mIndex) + "]";
|
||||||
};
|
};
|
||||||
effectParamsT["effect"]
|
effectParamsT["effect"]
|
||||||
= sol::readonly_property([magicEffectStore](const ESM::ENAMstruct& params) -> const ESM::MagicEffect* {
|
= sol::readonly_property([magicEffectStore](const ESM::ENAMstruct& params) -> const ESM::MagicEffect* {
|
||||||
|
@ -189,15 +289,18 @@ namespace MWLua
|
||||||
auto magicEffectT = context.mLua->sol().new_usertype<ESM::MagicEffect>("ESM3_MagicEffect");
|
auto magicEffectT = context.mLua->sol().new_usertype<ESM::MagicEffect>("ESM3_MagicEffect");
|
||||||
|
|
||||||
magicEffectT[sol::meta_function::to_string] = [](const ESM::MagicEffect& rec) {
|
magicEffectT[sol::meta_function::to_string] = [](const ESM::MagicEffect& rec) {
|
||||||
return "ESM3_MagicEffect[" + ESM::MagicEffect::effectIdToString(rec.mIndex) + "]";
|
return "ESM3_MagicEffect[" + ESM::MagicEffect::indexToGmstString(rec.mIndex) + "]";
|
||||||
};
|
};
|
||||||
magicEffectT["id"] = sol::readonly_property([](const ESM::MagicEffect& rec) -> int { return rec.mIndex; });
|
magicEffectT["id"] = sol::readonly_property([](const ESM::MagicEffect& rec) -> std::string {
|
||||||
|
auto name = ESM::MagicEffect::indexToName(rec.mIndex);
|
||||||
|
return Misc::StringUtils::lowerCase(name);
|
||||||
|
});
|
||||||
magicEffectT["name"] = sol::readonly_property([](const ESM::MagicEffect& rec) -> std::string_view {
|
magicEffectT["name"] = sol::readonly_property([](const ESM::MagicEffect& rec) -> std::string_view {
|
||||||
return MWBase::Environment::get()
|
return MWBase::Environment::get()
|
||||||
.getWorld()
|
.getWorld()
|
||||||
->getStore()
|
->getStore()
|
||||||
.get<ESM::GameSetting>()
|
.get<ESM::GameSetting>()
|
||||||
.find(ESM::MagicEffect::effectIdToString(rec.mIndex))
|
.find(ESM::MagicEffect::indexToGmstString(rec.mIndex))
|
||||||
->mValue.getString();
|
->mValue.getString();
|
||||||
});
|
});
|
||||||
magicEffectT["school"]
|
magicEffectT["school"]
|
||||||
|
@ -214,26 +317,69 @@ namespace MWLua
|
||||||
// magicEffectT["projectileSpeed"]
|
// magicEffectT["projectileSpeed"]
|
||||||
// = sol::readonly_property([](const ESM::MagicEffect& rec) -> float { return rec.mData.mSpeed; });
|
// = sol::readonly_property([](const ESM::MagicEffect& rec) -> float { return rec.mData.mSpeed; });
|
||||||
|
|
||||||
|
auto activeEffectT = context.mLua->sol().new_usertype<ActiveEffect>("ActiveEffect");
|
||||||
|
|
||||||
|
activeEffectT[sol::meta_function::to_string] = [](const ActiveEffect& effect) {
|
||||||
|
return "ActiveEffect[" + ESM::MagicEffect::indexToGmstString(effect.key.mId) + "]";
|
||||||
|
};
|
||||||
|
activeEffectT["id"] = sol::readonly_property([](const ActiveEffect& effect) -> std::string {
|
||||||
|
auto name = ESM::MagicEffect::indexToName(effect.key.mId);
|
||||||
|
return Misc::StringUtils::lowerCase(name);
|
||||||
|
});
|
||||||
|
activeEffectT["name"]
|
||||||
|
= sol::readonly_property([](const ActiveEffect& effect) -> std::string { return effect.key.toString(); });
|
||||||
|
|
||||||
|
activeEffectT["affectedSkill"]
|
||||||
|
= sol::readonly_property([magicEffectStore](const ActiveEffect& effect) -> sol::optional<std::string> {
|
||||||
|
auto* rec = magicEffectStore->find(effect.key.mId);
|
||||||
|
if ((rec->mData.mFlags & ESM::MagicEffect::TargetSkill) && effect.key.mArg >= 0
|
||||||
|
&& effect.key.mArg < ESM::Skill::Length)
|
||||||
|
return Misc::StringUtils::lowerCase(ESM::Skill::sSkillNames[effect.key.mArg]);
|
||||||
|
else
|
||||||
|
return sol::nullopt;
|
||||||
|
});
|
||||||
|
activeEffectT["affectedAttribute"]
|
||||||
|
= sol::readonly_property([magicEffectStore](const ActiveEffect& effect) -> sol::optional<std::string> {
|
||||||
|
auto* rec = magicEffectStore->find(effect.key.mId);
|
||||||
|
if ((rec->mData.mFlags & ESM::MagicEffect::TargetAttribute) && effect.key.mArg >= 0
|
||||||
|
&& effect.key.mArg < ESM::Attribute::Length)
|
||||||
|
return Misc::StringUtils::lowerCase(ESM::Attribute::sAttributeNames[effect.key.mArg]);
|
||||||
|
else
|
||||||
|
return sol::nullopt;
|
||||||
|
});
|
||||||
|
|
||||||
|
activeEffectT["magnitude"]
|
||||||
|
= sol::readonly_property([](const ActiveEffect& effect) { return effect.param.getMagnitude(); });
|
||||||
|
activeEffectT["magnitudeBase"]
|
||||||
|
= sol::readonly_property([](const ActiveEffect& effect) { return effect.param.getBase(); });
|
||||||
|
activeEffectT["magnitudeModifier"]
|
||||||
|
= sol::readonly_property([](const ActiveEffect& effect) { return effect.param.getModifier(); });
|
||||||
|
|
||||||
return LuaUtil::makeReadOnly(magicApi);
|
return LuaUtil::makeReadOnly(magicApi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addActorMagicBindings(sol::table& actor, const Context& context)
|
void addActorMagicBindings(sol::table& actor, const Context& context)
|
||||||
{
|
{
|
||||||
auto toSpellId = [](const sol::object& spellOrId) -> ESM::RefId {
|
|
||||||
if (spellOrId.is<ESM::Spell>())
|
|
||||||
return spellOrId.as<const ESM::Spell*>()->mId;
|
|
||||||
else
|
|
||||||
return ESM::RefId::deserializeText(LuaUtil::cast<std::string_view>(spellOrId));
|
|
||||||
};
|
|
||||||
|
|
||||||
const MWWorld::Store<ESM::Spell>* spellStore
|
const MWWorld::Store<ESM::Spell>* spellStore
|
||||||
= &MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>();
|
= &MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>();
|
||||||
|
|
||||||
// types.Actor.spells(o)
|
// types.Actor.spells(o)
|
||||||
actor["spells"] = [](const sol::object actor) { return ActorSpells{ ObjectVariant(actor) }; };
|
actor["spells"] = [](const sol::object& actor) { return ActorSpells{ actor }; };
|
||||||
auto spellsT = context.mLua->sol().new_usertype<ActorSpells>("ActorSpells");
|
auto spellsT = context.mLua->sol().new_usertype<ActorSpells>("ActorSpells");
|
||||||
spellsT[sol::meta_function::to_string]
|
spellsT[sol::meta_function::to_string]
|
||||||
= [](const ActorSpells& spells) { return "ActorSpells[" + spells.mActor.object().toString(); };
|
= [](const ActorSpells& spells) { return "ActorSpells[" + spells.mActor.object().toString() + "]"; };
|
||||||
|
|
||||||
|
actor["activeSpells"] = [](const sol::object& actor) { return ActorActiveSpells{ actor }; };
|
||||||
|
auto activeSpellsT = context.mLua->sol().new_usertype<ActorActiveSpells>("ActorActiveSpells");
|
||||||
|
activeSpellsT[sol::meta_function::to_string] = [](const ActorActiveSpells& spells) {
|
||||||
|
return "ActorActiveSpells[" + spells.mActor.object().toString() + "]";
|
||||||
|
};
|
||||||
|
|
||||||
|
actor["activeEffects"] = [](const sol::object& actor) { return ActorActiveEffects{ actor }; };
|
||||||
|
auto activeEffectsT = context.mLua->sol().new_usertype<ActorActiveEffects>("ActorActiveEffects");
|
||||||
|
activeEffectsT[sol::meta_function::to_string] = [](const ActorActiveEffects& effects) {
|
||||||
|
return "ActorActiveEffects[" + effects.mActor.object().toString() + "]";
|
||||||
|
};
|
||||||
|
|
||||||
actor["getSelectedSpell"] = [spellStore](const Object& o) -> sol::optional<const ESM::Spell*> {
|
actor["getSelectedSpell"] = [spellStore](const Object& o) -> sol::optional<const ESM::Spell*> {
|
||||||
const MWWorld::Ptr& ptr = o.ptr();
|
const MWWorld::Ptr& ptr = o.ptr();
|
||||||
|
@ -250,56 +396,59 @@ namespace MWLua
|
||||||
else
|
else
|
||||||
return spellStore->find(spellId);
|
return spellStore->find(spellId);
|
||||||
};
|
};
|
||||||
actor["setSelectedSpell"]
|
actor["setSelectedSpell"] = [context, spellStore](const SelfObject& o, const sol::object& spellOrId) {
|
||||||
= [context, spellStore, toSpellId](const SelfObject& o, const sol::object& spellOrId) {
|
const MWWorld::Ptr& ptr = o.ptr();
|
||||||
const MWWorld::Ptr& ptr = o.ptr();
|
const MWWorld::Class& cls = ptr.getClass();
|
||||||
const MWWorld::Class& cls = ptr.getClass();
|
if (!cls.isActor())
|
||||||
if (!cls.isActor())
|
throw std::runtime_error("Actor expected");
|
||||||
throw std::runtime_error("Actor expected");
|
ESM::RefId spellId;
|
||||||
ESM::RefId spellId;
|
if (spellOrId != sol::nil)
|
||||||
if (spellOrId != sol::nil)
|
{
|
||||||
{
|
spellId = toSpellId(spellOrId);
|
||||||
spellId = toSpellId(spellOrId);
|
const ESM::Spell* spell = spellStore->find(spellId);
|
||||||
const ESM::Spell* spell = spellStore->find(spellId);
|
if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power)
|
||||||
if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power)
|
throw std::runtime_error("Ability or disease can not be casted: " + spellId.toDebugString());
|
||||||
throw std::runtime_error("Ability or disease can not be casted: " + spellId.toDebugString());
|
}
|
||||||
}
|
context.mLuaManager->addAction([obj = Object(ptr), spellId]() {
|
||||||
context.mLuaManager->addAction([obj = Object(ptr), spellId]() {
|
const MWWorld::Ptr& ptr = obj.ptr();
|
||||||
const MWWorld::Ptr& ptr = obj.ptr();
|
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
if (!stats.getSpells().hasSpell(spellId))
|
||||||
if (!stats.getSpells().hasSpell(spellId))
|
throw std::runtime_error("Actor doesn't know spell " + spellId.toDebugString());
|
||||||
throw std::runtime_error("Actor doesn't know spell " + spellId.toDebugString());
|
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||||
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
{
|
||||||
{
|
int chance = 0;
|
||||||
int chance = 0;
|
if (!spellId.empty())
|
||||||
if (!spellId.empty())
|
chance = MWMechanics::getSpellSuccessChance(spellId, ptr);
|
||||||
chance = MWMechanics::getSpellSuccessChance(spellId, ptr);
|
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, chance);
|
||||||
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, chance);
|
}
|
||||||
}
|
else
|
||||||
else
|
ptr.getClass().getCreatureStats(ptr).getSpells().setSelectedSpell(spellId);
|
||||||
ptr.getClass().getCreatureStats(ptr).getSpells().setSelectedSpell(spellId);
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// #(types.Actor.spells(o))
|
// #(types.Actor.spells(o))
|
||||||
spellsT[sol::meta_function::length] = [](const ActorSpells& spells) -> size_t {
|
spellsT[sol::meta_function::length] = [](const ActorSpells& spells) -> size_t {
|
||||||
const MWWorld::Ptr& ptr = spells.mActor.ptr();
|
if (auto* store = spells.getStore())
|
||||||
return ptr.getClass().getCreatureStats(ptr).getSpells().count();
|
return store->count();
|
||||||
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// types.Actor.spells(o)[i]
|
// types.Actor.spells(o)[i]
|
||||||
spellsT[sol::meta_function::index] = sol::overload(
|
spellsT[sol::meta_function::index] = sol::overload(
|
||||||
[](const ActorSpells& spells, size_t index) -> const ESM::Spell* {
|
[](const ActorSpells& spells, size_t index) -> sol::optional<const ESM::Spell*> {
|
||||||
const MWWorld::Ptr& ptr = spells.mActor.ptr();
|
if (auto* store = spells.getStore())
|
||||||
return ptr.getClass().getCreatureStats(ptr).getSpells().at(index - 1);
|
if (index <= store->count())
|
||||||
|
return store->at(index - 1);
|
||||||
|
return sol::nullopt;
|
||||||
},
|
},
|
||||||
[spellStore](const ActorSpells& spells, std::string_view spellId) -> sol::optional<const ESM::Spell*> {
|
[spellStore](const ActorSpells& spells, std::string_view spellId) -> sol::optional<const ESM::Spell*> {
|
||||||
const MWWorld::Ptr& ptr = spells.mActor.ptr();
|
if (auto* store = spells.getStore())
|
||||||
const ESM::Spell* spell = spellStore->find(ESM::RefId::deserializeText(spellId));
|
{
|
||||||
if (ptr.getClass().getCreatureStats(ptr).getSpells().hasSpell(spell))
|
const ESM::Spell* spell = spellStore->find(ESM::RefId::deserializeText(spellId));
|
||||||
return spell;
|
if (store->hasSpell(spell))
|
||||||
else
|
return spell;
|
||||||
return sol::nullopt;
|
}
|
||||||
|
return sol::nullopt;
|
||||||
});
|
});
|
||||||
|
|
||||||
// pairs(types.Actor.spells(o))
|
// pairs(types.Actor.spells(o))
|
||||||
|
@ -309,22 +458,24 @@ namespace MWLua
|
||||||
spellsT[sol::meta_function::ipairs] = context.mLua->sol()["ipairsForArray"].template get<sol::function>();
|
spellsT[sol::meta_function::ipairs] = context.mLua->sol()["ipairsForArray"].template get<sol::function>();
|
||||||
|
|
||||||
// types.Actor.spells(o):add(id)
|
// types.Actor.spells(o):add(id)
|
||||||
spellsT["add"] = [context, toSpellId](const ActorSpells& spells, const sol::object& spellOrId) {
|
spellsT["add"] = [context](const ActorSpells& spells, const sol::object& spellOrId) {
|
||||||
if (spells.mActor.isLObject())
|
if (spells.mActor.isLObject())
|
||||||
throw std::runtime_error("Local scripts can modify only spells of the actor they are attached to.");
|
throw std::runtime_error("Local scripts can modify only spells of the actor they are attached to.");
|
||||||
context.mLuaManager->addAction([obj = spells.mActor.object(), id = toSpellId(spellOrId)]() {
|
context.mLuaManager->addAction([obj = spells.mActor.object(), id = toSpellId(spellOrId)]() {
|
||||||
const MWWorld::Ptr& ptr = obj.ptr();
|
const MWWorld::Ptr& ptr = obj.ptr();
|
||||||
ptr.getClass().getCreatureStats(ptr).getSpells().add(id);
|
if (ptr.getClass().isActor())
|
||||||
|
ptr.getClass().getCreatureStats(ptr).getSpells().add(id);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// types.Actor.spells(o):remove(id)
|
// types.Actor.spells(o):remove(id)
|
||||||
spellsT["remove"] = [context, toSpellId](const ActorSpells& spells, const sol::object& spellOrId) {
|
spellsT["remove"] = [context](const ActorSpells& spells, const sol::object& spellOrId) {
|
||||||
if (spells.mActor.isLObject())
|
if (spells.mActor.isLObject())
|
||||||
throw std::runtime_error("Local scripts can modify only spells of the actor they are attached to.");
|
throw std::runtime_error("Local scripts can modify only spells of the actor they are attached to.");
|
||||||
context.mLuaManager->addAction([obj = spells.mActor.object(), id = toSpellId(spellOrId)]() {
|
context.mLuaManager->addAction([obj = spells.mActor.object(), id = toSpellId(spellOrId)]() {
|
||||||
const MWWorld::Ptr& ptr = obj.ptr();
|
const MWWorld::Ptr& ptr = obj.ptr();
|
||||||
ptr.getClass().getCreatureStats(ptr).getSpells().remove(id);
|
if (ptr.getClass().isActor())
|
||||||
|
ptr.getClass().getCreatureStats(ptr).getSpells().remove(id);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -334,8 +485,90 @@ namespace MWLua
|
||||||
throw std::runtime_error("Local scripts can modify only spells of the actor they are attached to.");
|
throw std::runtime_error("Local scripts can modify only spells of the actor they are attached to.");
|
||||||
context.mLuaManager->addAction([obj = spells.mActor.object()]() {
|
context.mLuaManager->addAction([obj = spells.mActor.object()]() {
|
||||||
const MWWorld::Ptr& ptr = obj.ptr();
|
const MWWorld::Ptr& ptr = obj.ptr();
|
||||||
ptr.getClass().getCreatureStats(ptr).getSpells().clear();
|
if (ptr.getClass().isActor())
|
||||||
|
ptr.getClass().getCreatureStats(ptr).getSpells().clear();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// pairs(types.Actor.activeSpells(o))
|
||||||
|
// Note that the indexes are fake, and only for consistency with other lua pairs interfaces. You can't use them
|
||||||
|
// for anything.
|
||||||
|
activeSpellsT["__pairs"] = [](sol::this_state ts, ActorActiveSpells& self) {
|
||||||
|
sol::state_view lua(ts);
|
||||||
|
self.reset();
|
||||||
|
return sol::as_function([lua, &self]() mutable -> std::pair<sol::object, sol::object> {
|
||||||
|
if (!self.isEnd())
|
||||||
|
{
|
||||||
|
auto result = sol::make_object(lua, self.mIterator->getId());
|
||||||
|
auto index = sol::make_object(lua, self.mIndex + 1);
|
||||||
|
self.advance();
|
||||||
|
return { index, result };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return { sol::lua_nil, sol::lua_nil };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// types.Actor.activeSpells(o):isSpellActive(id)
|
||||||
|
activeSpellsT["isSpellActive"] = [](const ActorActiveSpells& spells, const sol::object& spellOrId) -> bool {
|
||||||
|
auto id = toSpellId(spellOrId);
|
||||||
|
if (auto* store = spells.getStore())
|
||||||
|
return store->isSpellActive(id);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// pairs(types.Actor.activeEffects(o))
|
||||||
|
// Note that the indexes are fake, and only for consistency with other lua pairs interfaces. You can't use them
|
||||||
|
// for anything.
|
||||||
|
activeEffectsT["__pairs"] = [](sol::this_state ts, ActorActiveEffects& self) {
|
||||||
|
sol::state_view lua(ts);
|
||||||
|
self.reset();
|
||||||
|
return sol::as_function([lua, &self]() mutable -> std::pair<sol::object, sol::object> {
|
||||||
|
if (!self.isEnd())
|
||||||
|
{
|
||||||
|
ActiveEffect effect = ActiveEffect{ self.mIterator->first, self.mIterator->second };
|
||||||
|
auto result = sol::make_object(lua, effect);
|
||||||
|
|
||||||
|
auto key = sol::make_object(lua, self.mIterator->first.toString());
|
||||||
|
self.advance();
|
||||||
|
return { key, result };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return { sol::lua_nil, sol::lua_nil };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// types.Actor.activeEffects(o):getEffect(id, ?arg)
|
||||||
|
activeEffectsT["getEffect"] = [](const ActorActiveEffects& effects, std::string_view idStr,
|
||||||
|
sol::optional<std::string_view> argStr) -> sol::optional<ActiveEffect> {
|
||||||
|
if (!effects.isActor())
|
||||||
|
return sol::nullopt;
|
||||||
|
|
||||||
|
auto id = ESM::MagicEffect::indexNameToIndex(idStr);
|
||||||
|
auto* rec = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(id);
|
||||||
|
|
||||||
|
MWMechanics::EffectKey key = MWMechanics::EffectKey(id);
|
||||||
|
|
||||||
|
if (argStr.has_value()
|
||||||
|
&& (rec->mData.mFlags & (ESM::MagicEffect::TargetAttribute | ESM::MagicEffect::TargetSkill)))
|
||||||
|
{
|
||||||
|
// MWLua exposes attributes and skills as strings, so we have to convert them back to IDs here
|
||||||
|
if (rec->mData.mFlags & ESM::MagicEffect::TargetAttribute)
|
||||||
|
key = MWMechanics::EffectKey(id, ESM::Attribute::stringToAttributeId(argStr.value()));
|
||||||
|
|
||||||
|
if (rec->mData.mFlags & ESM::MagicEffect::TargetSkill)
|
||||||
|
key = MWMechanics::EffectKey(id, ESM::Skill::stringToSkillId(argStr.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<MWMechanics::EffectParam> param;
|
||||||
|
if (auto* store = effects.getStore())
|
||||||
|
if (store->get(key, param))
|
||||||
|
return ActiveEffect{ key, param.value() };
|
||||||
|
return sol::nullopt;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,7 +374,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
ESM::MagicEffect::Effects effect
|
ESM::MagicEffect::Effects effect
|
||||||
= ptr.getClass().isNpc() ? ESM::MagicEffect::CalmHumanoid : ESM::MagicEffect::CalmCreature;
|
= ptr.getClass().isNpc() ? ESM::MagicEffect::CalmHumanoid : ESM::MagicEffect::CalmCreature;
|
||||||
if (creatureStats.getMagicEffects().get(effect).getMagnitude() > 0.f)
|
if (creatureStats.getMagicEffects().getOrDefault(effect).getMagnitude() > 0.f)
|
||||||
creatureStats.getAiSequence().stopCombat();
|
creatureStats.getAiSequence().stopCombat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,8 @@ namespace MWMechanics
|
||||||
void resetWorsenings();
|
void resetWorsenings();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<ActiveSpellParams>::const_iterator TIterator;
|
typedef std::list<ActiveSpellParams> Collection;
|
||||||
|
typedef Collection::const_iterator TIterator;
|
||||||
|
|
||||||
void readState(const ESM::ActiveSpells& state);
|
void readState(const ESM::ActiveSpells& state);
|
||||||
void writeState(ESM::ActiveSpells& state) const;
|
void writeState(ESM::ActiveSpells& state) const;
|
||||||
|
|
|
@ -158,7 +158,7 @@ namespace
|
||||||
void soulTrap(const MWWorld::Ptr& creature)
|
void soulTrap(const MWWorld::Ptr& creature)
|
||||||
{
|
{
|
||||||
const auto& stats = creature.getClass().getCreatureStats(creature);
|
const auto& stats = creature.getClass().getCreatureStats(creature);
|
||||||
if (!stats.getMagicEffects().get(ESM::MagicEffect::Soultrap).getMagnitude())
|
if (!stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Soultrap).getMagnitude())
|
||||||
return;
|
return;
|
||||||
const int creatureSoulValue = creature.get<ESM::Creature>()->mBase->mData.mSoul;
|
const int creatureSoulValue = creature.get<ESM::Creature>()->mBase->mData.mSoul;
|
||||||
if (creatureSoulValue == 0)
|
if (creatureSoulValue == 0)
|
||||||
|
@ -668,7 +668,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creatureStats2.getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude() > 0)
|
if (creatureStats2.getMagicEffects().getOrDefault(ESM::MagicEffect::Invisibility).getMagnitude() > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Stop here if target is unreachable
|
// Stop here if target is unreachable
|
||||||
|
@ -828,7 +828,8 @@ namespace MWMechanics
|
||||||
stats.setHealth(stat);
|
stats.setHealth(stat);
|
||||||
|
|
||||||
double restoreHours = hours;
|
double restoreHours = hours;
|
||||||
const bool stunted = stats.getMagicEffects().get(ESM::MagicEffect::StuntedMagicka).getMagnitude() > 0;
|
const bool stunted
|
||||||
|
= stats.getMagicEffects().getOrDefault(ESM::MagicEffect::StuntedMagicka).getMagnitude() > 0;
|
||||||
if (stunted)
|
if (stunted)
|
||||||
{
|
{
|
||||||
// Stunted Magicka effect should be taken into account.
|
// Stunted Magicka effect should be taken into account.
|
||||||
|
@ -954,7 +955,7 @@ namespace MWMechanics
|
||||||
const bool knockedOutUnderwater
|
const bool knockedOutUnderwater
|
||||||
= (isKnockedOut && world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3())));
|
= (isKnockedOut && world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3())));
|
||||||
if ((world->isSubmerged(ptr) || knockedOutUnderwater)
|
if ((world->isSubmerged(ptr) || knockedOutUnderwater)
|
||||||
&& stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).getMagnitude() == 0)
|
&& stats.getMagicEffects().getOrDefault(ESM::MagicEffect::WaterBreathing).getMagnitude() == 0)
|
||||||
{
|
{
|
||||||
float timeLeft = 0.0f;
|
float timeLeft = 0.0f;
|
||||||
if (knockedOutUnderwater)
|
if (knockedOutUnderwater)
|
||||||
|
@ -1110,7 +1111,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (actorClass.isClass(ptr, "Guard") && !creatureStats.getAiSequence().isInPursuit()
|
if (actorClass.isClass(ptr, "Guard") && !creatureStats.getAiSequence().isInPursuit()
|
||||||
&& !creatureStats.getAiSequence().isInCombat()
|
&& !creatureStats.getAiSequence().isInCombat()
|
||||||
&& creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid).getMagnitude() == 0)
|
&& creatureStats.getMagicEffects().getOrDefault(ESM::MagicEffect::CalmHumanoid).getMagnitude() == 0)
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore& esmStore = world->getStore();
|
const MWWorld::ESMStore& esmStore = world->getStore();
|
||||||
static const int cutoff = esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->mValue.getInteger();
|
static const int cutoff = esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->mValue.getInteger();
|
||||||
|
@ -1814,7 +1815,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
// Reset magic effects and recalculate derived effects
|
// Reset magic effects and recalculate derived effects
|
||||||
// One case where we need this is to make sure bound items are removed upon death
|
// One case where we need this is to make sure bound items are removed upon death
|
||||||
const float vampirism = stats.getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude();
|
const float vampirism
|
||||||
|
= stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Vampirism).getMagnitude();
|
||||||
stats.getActiveSpells().clear(actor.getPtr());
|
stats.getActiveSpells().clear(actor.getPtr());
|
||||||
// Make sure spell effects are removed
|
// Make sure spell effects are removed
|
||||||
purgeSpellEffects(stats.getActorId());
|
purgeSpellEffects(stats.getActorId());
|
||||||
|
@ -2002,7 +2004,7 @@ namespace MWMechanics
|
||||||
const auto [healthPerHour, magickaPerHour] = getRestorationPerHourOfSleep(ptr);
|
const auto [healthPerHour, magickaPerHour] = getRestorationPerHourOfSleep(ptr);
|
||||||
|
|
||||||
CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
const bool stunted = stats.getMagicEffects().get(ESM::MagicEffect::StuntedMagicka).getMagnitude() > 0;
|
const bool stunted = stats.getMagicEffects().getOrDefault(ESM::MagicEffect::StuntedMagicka).getMagnitude() > 0;
|
||||||
|
|
||||||
const float healthHours = healthPerHour > 0
|
const float healthHours = healthPerHour > 0
|
||||||
? (stats.getHealth().getModified() - stats.getHealth().getCurrent()) / healthPerHour
|
? (stats.getHealth().getModified() - stats.getHealth().getCurrent()) / healthPerHour
|
||||||
|
|
|
@ -32,13 +32,13 @@ namespace MWMechanics
|
||||||
bool hasWaterWalking(const MWWorld::Ptr& actor)
|
bool hasWaterWalking(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
const MWMechanics::MagicEffects& effects = actor.getClass().getCreatureStats(actor).getMagicEffects();
|
const MWMechanics::MagicEffects& effects = actor.getClass().getCreatureStats(actor).getMagicEffects();
|
||||||
return effects.get(ESM::MagicEffect::WaterWalking).getMagnitude() > 0;
|
return effects.getOrDefault(ESM::MagicEffect::WaterWalking).getMagnitude() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTargetMagicallyHidden(const MWWorld::Ptr& actor)
|
bool isTargetMagicallyHidden(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
const MagicEffects& magicEffects = actor.getClass().getCreatureStats(actor).getMagicEffects();
|
const MagicEffects& magicEffects = actor.getClass().getCreatureStats(actor).getMagicEffects();
|
||||||
return (magicEffects.get(ESM::MagicEffect::Invisibility).getMagnitude() > 0)
|
return (magicEffects.getOrDefault(ESM::MagicEffect::Invisibility).getMagnitude() > 0)
|
||||||
|| (magicEffects.get(ESM::MagicEffect::Chameleon).getMagnitude() > 75);
|
|| (magicEffects.getOrDefault(ESM::MagicEffect::Chameleon).getMagnitude() > 75);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,7 +464,7 @@ namespace MWMechanics
|
||||||
if (enemy.getClass()
|
if (enemy.getClass()
|
||||||
.getCreatureStats(enemy)
|
.getCreatureStats(enemy)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::Levitate)
|
.getOrDefault(ESM::MagicEffect::Levitate)
|
||||||
.getMagnitude()
|
.getMagnitude()
|
||||||
> 0)
|
> 0)
|
||||||
{
|
{
|
||||||
|
@ -484,7 +484,11 @@ namespace MWMechanics
|
||||||
if (!actor.getClass().canWalk(actor) && !actor.getClass().isBipedal(actor))
|
if (!actor.getClass().canWalk(actor) && !actor.getClass().isBipedal(actor))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::Levitate).getMagnitude()
|
if (actor.getClass()
|
||||||
|
.getCreatureStats(actor)
|
||||||
|
.getMagicEffects()
|
||||||
|
.getOrDefault(ESM::MagicEffect::Levitate)
|
||||||
|
.getMagnitude()
|
||||||
> 0)
|
> 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -284,8 +284,11 @@ namespace
|
||||||
if (fallHeight >= fallDistanceMin)
|
if (fallHeight >= fallDistanceMin)
|
||||||
{
|
{
|
||||||
const float acrobaticsSkill = static_cast<float>(ptr.getClass().getSkill(ptr, ESM::Skill::Acrobatics));
|
const float acrobaticsSkill = static_cast<float>(ptr.getClass().getSkill(ptr, ESM::Skill::Acrobatics));
|
||||||
const float jumpSpellBonus
|
const float jumpSpellBonus = ptr.getClass()
|
||||||
= ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Jump).getMagnitude();
|
.getCreatureStats(ptr)
|
||||||
|
.getMagicEffects()
|
||||||
|
.getOrDefault(ESM::MagicEffect::Jump)
|
||||||
|
.getMagnitude();
|
||||||
const float fallAcroBase = store.find("fFallAcroBase")->mValue.getFloat();
|
const float fallAcroBase = store.find("fFallAcroBase")->mValue.getFloat();
|
||||||
const float fallAcroMult = store.find("fFallAcroMult")->mValue.getFloat();
|
const float fallAcroMult = store.find("fFallAcroMult")->mValue.getFloat();
|
||||||
const float fallDistanceBase = store.find("fFallDistanceBase")->mValue.getFloat();
|
const float fallDistanceBase = store.find("fFallDistanceBase")->mValue.getFloat();
|
||||||
|
@ -2387,7 +2390,11 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
if (cls.getCreatureStats(mPtr).isDead()
|
if (cls.getCreatureStats(mPtr).isDead()
|
||||||
|| (!godmode
|
|| (!godmode
|
||||||
&& cls.getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Paralyze).getModifier() > 0))
|
&& cls.getCreatureStats(mPtr)
|
||||||
|
.getMagicEffects()
|
||||||
|
.getOrDefault(ESM::MagicEffect::Paralyze)
|
||||||
|
.getModifier()
|
||||||
|
> 0))
|
||||||
{
|
{
|
||||||
moved.z() = 1.0;
|
moved.z() = 1.0;
|
||||||
}
|
}
|
||||||
|
@ -2644,7 +2651,7 @@ namespace MWMechanics
|
||||||
|| mPtr.getClass()
|
|| mPtr.getClass()
|
||||||
.getCreatureStats(mPtr)
|
.getCreatureStats(mPtr)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(MWMechanics::EffectKey(effectId))
|
.getOrDefault(MWMechanics::EffectKey(effectId))
|
||||||
.getMagnitude()
|
.getMagnitude()
|
||||||
<= 0)
|
<= 0)
|
||||||
mAnimation->removeEffect(effectId);
|
mAnimation->removeEffect(effectId);
|
||||||
|
@ -2656,16 +2663,22 @@ namespace MWMechanics
|
||||||
if (!mPtr.getClass().isActor())
|
if (!mPtr.getClass().isActor())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float light
|
float light = mPtr.getClass()
|
||||||
= mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Light).getMagnitude();
|
.getCreatureStats(mPtr)
|
||||||
|
.getMagicEffects()
|
||||||
|
.getOrDefault(ESM::MagicEffect::Light)
|
||||||
|
.getMagnitude();
|
||||||
mAnimation->setLightEffect(light);
|
mAnimation->setLightEffect(light);
|
||||||
|
|
||||||
// If you're dead you don't care about whether you've started/stopped being a vampire or not
|
// If you're dead you don't care about whether you've started/stopped being a vampire or not
|
||||||
if (mPtr.getClass().getCreatureStats(mPtr).isDead())
|
if (mPtr.getClass().getCreatureStats(mPtr).isDead())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool vampire
|
bool vampire = mPtr.getClass()
|
||||||
= mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude()
|
.getCreatureStats(mPtr)
|
||||||
|
.getMagicEffects()
|
||||||
|
.getOrDefault(ESM::MagicEffect::Vampirism)
|
||||||
|
.getMagnitude()
|
||||||
> 0.0f;
|
> 0.0f;
|
||||||
mAnimation->setVampire(vampire);
|
mAnimation->setVampire(vampire);
|
||||||
}
|
}
|
||||||
|
@ -2679,7 +2692,7 @@ namespace MWMechanics
|
||||||
if (mPtr.getClass()
|
if (mPtr.getClass()
|
||||||
.getCreatureStats(mPtr)
|
.getCreatureStats(mPtr)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::Invisibility)
|
.getOrDefault(ESM::MagicEffect::Invisibility)
|
||||||
.getModifier()) // Ignore base magnitude (see bug #3555).
|
.getModifier()) // Ignore base magnitude (see bug #3555).
|
||||||
{
|
{
|
||||||
if (mPtr == getPlayer())
|
if (mPtr == getPlayer())
|
||||||
|
@ -2690,7 +2703,7 @@ namespace MWMechanics
|
||||||
float chameleon = mPtr.getClass()
|
float chameleon = mPtr.getClass()
|
||||||
.getCreatureStats(mPtr)
|
.getCreatureStats(mPtr)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::Chameleon)
|
.getOrDefault(ESM::MagicEffect::Chameleon)
|
||||||
.getMagnitude();
|
.getMagnitude();
|
||||||
if (chameleon)
|
if (chameleon)
|
||||||
{
|
{
|
||||||
|
|
|
@ -185,8 +185,8 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const MWMechanics::MagicEffects& effects = actor.getClass().getCreatureStats(actor).getMagicEffects();
|
const MWMechanics::MagicEffects& effects = actor.getClass().getCreatureStats(actor).getMagicEffects();
|
||||||
const float resistance = effects.get(ESM::MagicEffect::ResistNormalWeapons).getMagnitude() / 100.f;
|
const float resistance = effects.getOrDefault(ESM::MagicEffect::ResistNormalWeapons).getMagnitude() / 100.f;
|
||||||
const float weakness = effects.get(ESM::MagicEffect::WeaknessToNormalWeapons).getMagnitude() / 100.f;
|
const float weakness = effects.getOrDefault(ESM::MagicEffect::WeaknessToNormalWeapons).getMagnitude() / 100.f;
|
||||||
|
|
||||||
damage *= 1.f - std::min(1.f, resistance - weakness);
|
damage *= 1.f - std::min(1.f, resistance - weakness);
|
||||||
|
|
||||||
|
@ -313,15 +313,17 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
static const float fCombatInvisoMult = gmst.find("fCombatInvisoMult")->mValue.getFloat();
|
static const float fCombatInvisoMult = gmst.find("fCombatInvisoMult")->mValue.getFloat();
|
||||||
defenseTerm += std::min(100.f,
|
defenseTerm += std::min(100.f,
|
||||||
fCombatInvisoMult * victimStats.getMagicEffects().get(ESM::MagicEffect::Chameleon).getMagnitude());
|
fCombatInvisoMult
|
||||||
|
* victimStats.getMagicEffects().getOrDefault(ESM::MagicEffect::Chameleon).getMagnitude());
|
||||||
defenseTerm += std::min(100.f,
|
defenseTerm += std::min(100.f,
|
||||||
fCombatInvisoMult * victimStats.getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude());
|
fCombatInvisoMult
|
||||||
|
* victimStats.getMagicEffects().getOrDefault(ESM::MagicEffect::Invisibility).getMagnitude());
|
||||||
}
|
}
|
||||||
float attackTerm = skillValue + (stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f)
|
float attackTerm = skillValue + (stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f)
|
||||||
+ (stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
+ (stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||||
attackTerm *= stats.getFatigueTerm();
|
attackTerm *= stats.getFatigueTerm();
|
||||||
attackTerm += mageffects.get(ESM::MagicEffect::FortifyAttack).getMagnitude()
|
attackTerm += mageffects.getOrDefault(ESM::MagicEffect::FortifyAttack).getMagnitude()
|
||||||
- mageffects.get(ESM::MagicEffect::Blind).getMagnitude();
|
- mageffects.getOrDefault(ESM::MagicEffect::Blind).getMagnitude();
|
||||||
|
|
||||||
return round(attackTerm - defenseTerm);
|
return round(attackTerm - defenseTerm);
|
||||||
}
|
}
|
||||||
|
@ -338,7 +340,7 @@ namespace MWMechanics
|
||||||
float magnitude = victim.getClass()
|
float magnitude = victim.getClass()
|
||||||
.getCreatureStats(victim)
|
.getCreatureStats(victim)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::FireShield + i)
|
.getOrDefault(ESM::MagicEffect::FireShield + i)
|
||||||
.getMagnitude();
|
.getMagnitude();
|
||||||
|
|
||||||
if (!magnitude)
|
if (!magnitude)
|
||||||
|
|
|
@ -225,8 +225,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
void CreatureStats::modifyMagicEffects(const MagicEffects& effects)
|
void CreatureStats::modifyMagicEffects(const MagicEffects& effects)
|
||||||
{
|
{
|
||||||
bool recalc = effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier()
|
bool recalc = effects.getOrDefault(ESM::MagicEffect::FortifyMaximumMagicka).getModifier()
|
||||||
!= mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier();
|
!= mMagicEffects.getOrDefault(ESM::MagicEffect::FortifyMaximumMagicka).getModifier();
|
||||||
mMagicEffects.setModifiers(effects);
|
mMagicEffects.setModifiers(effects);
|
||||||
if (recalc)
|
if (recalc)
|
||||||
recalculateMagicka();
|
recalculateMagicka();
|
||||||
|
@ -246,7 +246,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool CreatureStats::isParalyzed() const
|
bool CreatureStats::isParalyzed() const
|
||||||
{
|
{
|
||||||
return mMagicEffects.get(ESM::MagicEffect::Paralyze).getMagnitude() > 0;
|
return mMagicEffects.getOrDefault(ESM::MagicEffect::Paralyze).getMagnitude() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreatureStats::isDead() const
|
bool CreatureStats::isDead() const
|
||||||
|
@ -359,7 +359,7 @@ namespace MWMechanics
|
||||||
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f)
|
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f)
|
||||||
+ (getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
+ (getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||||
evasion *= getFatigueTerm();
|
evasion *= getFatigueTerm();
|
||||||
evasion += std::min(100.f, mMagicEffects.get(ESM::MagicEffect::Sanctuary).getMagnitude());
|
evasion += std::min(100.f, mMagicEffects.getOrDefault(ESM::MagicEffect::Sanctuary).getMagnitude());
|
||||||
|
|
||||||
return evasion;
|
return evasion;
|
||||||
}
|
}
|
||||||
|
@ -436,8 +436,8 @@ namespace MWMechanics
|
||||||
else
|
else
|
||||||
base = world->getStore().get<ESM::GameSetting>().find("fNPCbaseMagickaMult")->mValue.getFloat();
|
base = world->getStore().get<ESM::GameSetting>().find("fNPCbaseMagickaMult")->mValue.getFloat();
|
||||||
|
|
||||||
double magickaFactor
|
double magickaFactor = base
|
||||||
= base + mMagicEffects.get(EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).getMagnitude() * 0.1;
|
+ mMagicEffects.getOrDefault(EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).getMagnitude() * 0.1;
|
||||||
|
|
||||||
DynamicStat<float> magicka = getMagicka();
|
DynamicStat<float> magicka = getMagicka();
|
||||||
float currentToBaseRatio = magicka.getBase() > 0 ? magicka.getCurrent() / magicka.getBase() : 0;
|
float currentToBaseRatio = magicka.getBase() > 0 ? magicka.getCurrent() / magicka.getBase() : 0;
|
||||||
|
|
|
@ -46,18 +46,18 @@ namespace MWMechanics
|
||||||
if (Spells::hasCorprusEffect(spell))
|
if (Spells::hasCorprusEffect(spell))
|
||||||
resist = 1.f
|
resist = 1.f
|
||||||
- 0.01f
|
- 0.01f
|
||||||
* (actorEffects.get(ESM::MagicEffect::ResistCorprusDisease).getMagnitude()
|
* (actorEffects.getOrDefault(ESM::MagicEffect::ResistCorprusDisease).getMagnitude()
|
||||||
- actorEffects.get(ESM::MagicEffect::WeaknessToCorprusDisease).getMagnitude());
|
- actorEffects.getOrDefault(ESM::MagicEffect::WeaknessToCorprusDisease).getMagnitude());
|
||||||
else if (spell->mData.mType == ESM::Spell::ST_Disease)
|
else if (spell->mData.mType == ESM::Spell::ST_Disease)
|
||||||
resist = 1.f
|
resist = 1.f
|
||||||
- 0.01f
|
- 0.01f
|
||||||
* (actorEffects.get(ESM::MagicEffect::ResistCommonDisease).getMagnitude()
|
* (actorEffects.getOrDefault(ESM::MagicEffect::ResistCommonDisease).getMagnitude()
|
||||||
- actorEffects.get(ESM::MagicEffect::WeaknessToCommonDisease).getMagnitude());
|
- actorEffects.getOrDefault(ESM::MagicEffect::WeaknessToCommonDisease).getMagnitude());
|
||||||
else if (spell->mData.mType == ESM::Spell::ST_Blight)
|
else if (spell->mData.mType == ESM::Spell::ST_Blight)
|
||||||
resist = 1.f
|
resist = 1.f
|
||||||
- 0.01f
|
- 0.01f
|
||||||
* (actorEffects.get(ESM::MagicEffect::ResistBlightDisease).getMagnitude()
|
* (actorEffects.getOrDefault(ESM::MagicEffect::ResistBlightDisease).getMagnitude()
|
||||||
- actorEffects.get(ESM::MagicEffect::WeaknessToBlightDisease).getMagnitude());
|
- actorEffects.getOrDefault(ESM::MagicEffect::WeaknessToBlightDisease).getMagnitude());
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
for (Collection::iterator it = mCollection.begin(); it != mCollection.end(); ++it)
|
for (Collection::iterator it = mCollection.begin(); it != mCollection.end(); ++it)
|
||||||
{
|
{
|
||||||
it->second.setModifier(effects.get(it->first).getModifier());
|
it->second.setModifier(effects.getOrDefault(it->first).getModifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Collection::const_iterator it = effects.begin(); it != effects.end(); ++it)
|
for (Collection::const_iterator it = effects.begin(); it != effects.end(); ++it)
|
||||||
|
@ -156,18 +156,23 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EffectParam MagicEffects::get(const EffectKey& key) const
|
EffectParam MagicEffects::getOrDefault(const EffectKey& key) const
|
||||||
|
{
|
||||||
|
std::optional<EffectParam> param;
|
||||||
|
get(key, param);
|
||||||
|
return param.value_or(EffectParam());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MagicEffects::get(const EffectKey& key, std::optional<EffectParam>& param) const
|
||||||
{
|
{
|
||||||
Collection::const_iterator iter = mCollection.find(key);
|
Collection::const_iterator iter = mCollection.find(key);
|
||||||
|
|
||||||
if (iter == mCollection.end())
|
if (iter != mCollection.end())
|
||||||
{
|
{
|
||||||
return EffectParam();
|
param = iter->second;
|
||||||
}
|
return true;
|
||||||
else
|
|
||||||
{
|
|
||||||
return iter->second;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MagicEffects MagicEffects::diff(const MagicEffects& prev, const MagicEffects& now)
|
MagicEffects MagicEffects::diff(const MagicEffects& prev, const MagicEffects& now)
|
||||||
|
@ -263,7 +268,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (spellLine.empty())
|
if (spellLine.empty())
|
||||||
{
|
{
|
||||||
const std::string& effectIDStr = ESM::MagicEffect::effectIdToString(effect.mIndex);
|
auto& effectIDStr = ESM::MagicEffect::indexToGmstString(effect.mIndex);
|
||||||
spellLine = windowManager->getGameSettingString(effectIDStr, {});
|
spellLine = windowManager->getGameSettingString(effectIDStr, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWMECHANICS_MAGICEFFECTS_H
|
#define GAME_MWMECHANICS_MAGICEFFECTS_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -104,7 +105,8 @@ namespace MWMechanics
|
||||||
/// Copy Modifier values from \a effects, but keep original mBase values.
|
/// Copy Modifier values from \a effects, but keep original mBase values.
|
||||||
void setModifiers(const MagicEffects& effects);
|
void setModifiers(const MagicEffects& effects);
|
||||||
|
|
||||||
EffectParam get(const EffectKey& key) const;
|
EffectParam getOrDefault(const EffectKey& key) const;
|
||||||
|
bool get(const EffectKey& key, std::optional<EffectParam>& param) const;
|
||||||
///< This function can safely be used for keys that are not present.
|
///< This function can safely be used for keys that are not present.
|
||||||
|
|
||||||
static MagicEffects diff(const MagicEffects& prev, const MagicEffects& now);
|
static MagicEffects diff(const MagicEffects& prev, const MagicEffects& now);
|
||||||
|
|
|
@ -577,7 +577,11 @@ namespace MWMechanics
|
||||||
if (playerStats.getDrawState() == MWMechanics::DrawState::Weapon)
|
if (playerStats.getDrawState() == MWMechanics::DrawState::Weapon)
|
||||||
x += fDispWeaponDrawn;
|
x += fDispWeaponDrawn;
|
||||||
|
|
||||||
x += ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Charm).getMagnitude();
|
x += ptr.getClass()
|
||||||
|
.getCreatureStats(ptr)
|
||||||
|
.getMagicEffects()
|
||||||
|
.getOrDefault(ESM::MagicEffect::Charm)
|
||||||
|
.getMagnitude();
|
||||||
|
|
||||||
if (clamp)
|
if (clamp)
|
||||||
return std::clamp<int>(x, 0, 100); //, normally clamped to [0..100] when used
|
return std::clamp<int>(x, 0, 100); //, normally clamped to [0..100] when used
|
||||||
|
@ -1558,8 +1562,8 @@ namespace MWMechanics
|
||||||
osg::Vec3f pos2(observer.getRefData().getPosition().asVec3());
|
osg::Vec3f pos2(observer.getRefData().getPosition().asVec3());
|
||||||
float distTerm = fSneakDistBase + fSneakDistMult * (pos1 - pos2).length();
|
float distTerm = fSneakDistBase + fSneakDistMult * (pos1 - pos2).length();
|
||||||
|
|
||||||
float chameleon = stats.getMagicEffects().get(ESM::MagicEffect::Chameleon).getMagnitude();
|
float chameleon = stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Chameleon).getMagnitude();
|
||||||
float invisibility = stats.getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude();
|
float invisibility = stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Invisibility).getMagnitude();
|
||||||
float x = sneakTerm * distTerm * stats.getFatigueTerm() + chameleon;
|
float x = sneakTerm * distTerm * stats.getFatigueTerm() + chameleon;
|
||||||
if (invisibility > 0.f)
|
if (invisibility > 0.f)
|
||||||
x += 100.f;
|
x += 100.f;
|
||||||
|
@ -1567,7 +1571,7 @@ namespace MWMechanics
|
||||||
CreatureStats& observerStats = observer.getClass().getCreatureStats(observer);
|
CreatureStats& observerStats = observer.getClass().getCreatureStats(observer);
|
||||||
float obsAgility = observerStats.getAttribute(ESM::Attribute::Agility).getModified();
|
float obsAgility = observerStats.getAttribute(ESM::Attribute::Agility).getModified();
|
||||||
float obsLuck = observerStats.getAttribute(ESM::Attribute::Luck).getModified();
|
float obsLuck = observerStats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||||
float obsBlind = observerStats.getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude();
|
float obsBlind = observerStats.getMagicEffects().getOrDefault(ESM::MagicEffect::Blind).getMagnitude();
|
||||||
float obsSneak = observer.getClass().getSkill(observer, ESM::Skill::Sneak);
|
float obsSneak = observer.getClass().getSkill(observer, ESM::Skill::Sneak);
|
||||||
|
|
||||||
float obsTerm = obsSneak + 0.2f * obsAgility + 0.1f * obsLuck - obsBlind;
|
float obsTerm = obsSneak + 0.2f * obsAgility + 0.1f * obsLuck - obsBlind;
|
||||||
|
@ -1755,14 +1759,14 @@ namespace MWMechanics
|
||||||
&& ptr.getClass()
|
&& ptr.getClass()
|
||||||
.getCreatureStats(ptr)
|
.getCreatureStats(ptr)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::CalmHumanoid)
|
.getOrDefault(ESM::MagicEffect::CalmHumanoid)
|
||||||
.getMagnitude()
|
.getMagnitude()
|
||||||
> 0)
|
> 0)
|
||||||
|| (!ptr.getClass().isNpc()
|
|| (!ptr.getClass().isNpc()
|
||||||
&& ptr.getClass()
|
&& ptr.getClass()
|
||||||
.getCreatureStats(ptr)
|
.getCreatureStats(ptr)
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::CalmCreature)
|
.getOrDefault(ESM::MagicEffect::CalmCreature)
|
||||||
.getMagnitude()
|
.getMagnitude()
|
||||||
> 0))
|
> 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -319,9 +319,9 @@ namespace
|
||||||
{
|
{
|
||||||
bool canReflect = !(magicEffect->mData.mFlags & ESM::MagicEffect::Unreflectable)
|
bool canReflect = !(magicEffect->mData.mFlags & ESM::MagicEffect::Unreflectable)
|
||||||
&& !(effect.mFlags & ESM::ActiveEffect::Flag_Ignore_Reflect)
|
&& !(effect.mFlags & ESM::ActiveEffect::Flag_Ignore_Reflect)
|
||||||
&& magnitudes.get(ESM::MagicEffect::Reflect).getMagnitude() > 0.f && !caster.isEmpty();
|
&& magnitudes.getOrDefault(ESM::MagicEffect::Reflect).getMagnitude() > 0.f && !caster.isEmpty();
|
||||||
bool canAbsorb = !(effect.mFlags & ESM::ActiveEffect::Flag_Ignore_SpellAbsorption)
|
bool canAbsorb = !(effect.mFlags & ESM::ActiveEffect::Flag_Ignore_SpellAbsorption)
|
||||||
&& magnitudes.get(ESM::MagicEffect::SpellAbsorption).getMagnitude() > 0.f;
|
&& magnitudes.getOrDefault(ESM::MagicEffect::SpellAbsorption).getMagnitude() > 0.f;
|
||||||
if (canReflect || canAbsorb)
|
if (canReflect || canAbsorb)
|
||||||
{
|
{
|
||||||
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
@ -561,7 +561,8 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
const auto& magnitudes = target.getClass().getCreatureStats(target).getMagicEffects();
|
const auto& magnitudes = target.getClass().getCreatureStats(target).getMagicEffects();
|
||||||
float volume = std::clamp(
|
float volume = std::clamp(
|
||||||
(magnitudes.get(effect.mEffectId).getModifier() + effect.mMagnitude) / 100.f, 0.f, 1.f);
|
(magnitudes.getOrDefault(effect.mEffectId).getModifier() + effect.mMagnitude) / 100.f, 0.f,
|
||||||
|
1.f);
|
||||||
MWBase::Environment::get().getSoundManager()->playSound3D(target,
|
MWBase::Environment::get().getSoundManager()->playSound3D(target,
|
||||||
ESM::RefId::stringRefId("magic sound"), volume, 1.f, MWSound::Type::Sfx,
|
ESM::RefId::stringRefId("magic sound"), volume, 1.f, MWSound::Type::Sfx,
|
||||||
MWSound::PlayMode::LoopNoEnv);
|
MWSound::PlayMode::LoopNoEnv);
|
||||||
|
@ -1058,7 +1059,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
case ESM::MagicEffect::CommandCreature:
|
case ESM::MagicEffect::CommandCreature:
|
||||||
case ESM::MagicEffect::CommandHumanoid:
|
case ESM::MagicEffect::CommandHumanoid:
|
||||||
if (magnitudes.get(effect.mEffectId).getMagnitude() <= 0.f)
|
if (magnitudes.getOrDefault(effect.mEffectId).getMagnitude() <= 0.f)
|
||||||
{
|
{
|
||||||
auto& seq = target.getClass().getCreatureStats(target).getAiSequence();
|
auto& seq = target.getClass().getCreatureStats(target).getAiSequence();
|
||||||
seq.erasePackageIf([&](const auto& package) {
|
seq.erasePackageIf([&](const auto& package) {
|
||||||
|
@ -1068,7 +1069,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ESM::MagicEffect::ExtraSpell:
|
case ESM::MagicEffect::ExtraSpell:
|
||||||
if (magnitudes.get(effect.mEffectId).getMagnitude() <= 0.f)
|
if (magnitudes.getOrDefault(effect.mEffectId).getMagnitude() <= 0.f)
|
||||||
target.getClass().getInventoryStore(target).autoEquip();
|
target.getClass().getInventoryStore(target).autoEquip();
|
||||||
break;
|
break;
|
||||||
case ESM::MagicEffect::TurnUndead:
|
case ESM::MagicEffect::TurnUndead:
|
||||||
|
@ -1096,7 +1097,7 @@ namespace MWMechanics
|
||||||
break;
|
break;
|
||||||
case ESM::MagicEffect::NightEye:
|
case ESM::MagicEffect::NightEye:
|
||||||
{
|
{
|
||||||
const MWMechanics::EffectParam nightEye = magnitudes.get(effect.mEffectId);
|
const MWMechanics::EffectParam nightEye = magnitudes.getOrDefault(effect.mEffectId);
|
||||||
if (nightEye.getMagnitude() < 0.f && nightEye.getBase() < 0)
|
if (nightEye.getMagnitude() < 0.f && nightEye.getBase() < 0)
|
||||||
{
|
{
|
||||||
// The PCVisionBonus functions are different from every other magic effect function in that they
|
// The PCVisionBonus functions are different from every other magic effect function in that they
|
||||||
|
@ -1115,7 +1116,7 @@ namespace MWMechanics
|
||||||
target, effect, ESM::MagicEffect::RallyCreature, AiSetting::Flee, effect.mMagnitude, invalid);
|
target, effect, ESM::MagicEffect::RallyCreature, AiSetting::Flee, effect.mMagnitude, invalid);
|
||||||
break;
|
break;
|
||||||
case ESM::MagicEffect::Sound:
|
case ESM::MagicEffect::Sound:
|
||||||
if (magnitudes.get(effect.mEffectId).getModifier() <= 0.f && target == getPlayer())
|
if (magnitudes.getOrDefault(effect.mEffectId).getModifier() <= 0.f && target == getPlayer())
|
||||||
MWBase::Environment::get().getSoundManager()->stopSound3D(
|
MWBase::Environment::get().getSoundManager()->stopSound3D(
|
||||||
target, ESM::RefId::stringRefId("magic sound"));
|
target, ESM::RefId::stringRefId("magic sound"));
|
||||||
break;
|
break;
|
||||||
|
@ -1275,7 +1276,7 @@ namespace MWMechanics
|
||||||
auto& magnitudes = target.getClass().getCreatureStats(target).getMagicEffects();
|
auto& magnitudes = target.getClass().getCreatureStats(target).getMagicEffects();
|
||||||
magnitudes.add(EffectKey(effect.mEffectId, effect.mArg), EffectParam(-effect.mMagnitude));
|
magnitudes.add(EffectKey(effect.mEffectId, effect.mArg), EffectParam(-effect.mMagnitude));
|
||||||
removeMagicEffect(target, spellParams, effect);
|
removeMagicEffect(target, spellParams, effect);
|
||||||
if (magnitudes.get(effect.mEffectId).getMagnitude() <= 0.f)
|
if (magnitudes.getOrDefault(effect.mEffectId).getMagnitude() <= 0.f)
|
||||||
{
|
{
|
||||||
auto anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
auto anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
||||||
if (anim)
|
if (anim)
|
||||||
|
|
|
@ -265,7 +265,7 @@ namespace MWMechanics
|
||||||
const CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
|
const CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
|
||||||
|
|
||||||
// Enemy can't cast spells
|
// Enemy can't cast spells
|
||||||
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude() > 0)
|
if (stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Silence).getMagnitude() > 0)
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
if (stats.isParalyzed() || stats.getKnockedDown())
|
if (stats.isParalyzed() || stats.getKnockedDown())
|
||||||
|
@ -596,7 +596,7 @@ namespace MWMechanics
|
||||||
if (effect.mEffectID <= ESM::MagicEffect::BoundLongbow)
|
if (effect.mEffectID <= ESM::MagicEffect::BoundLongbow)
|
||||||
{
|
{
|
||||||
for (int e = ESM::MagicEffect::BoundDagger; e <= ESM::MagicEffect::BoundLongbow; ++e)
|
for (int e = ESM::MagicEffect::BoundDagger; e <= ESM::MagicEffect::BoundLongbow; ++e)
|
||||||
if (actor.getClass().getCreatureStats(actor).getMagicEffects().get(e).getMagnitude() > 0.f
|
if (actor.getClass().getCreatureStats(actor).getMagicEffects().getOrDefault(e).getMagnitude() > 0.f
|
||||||
&& (e != ESM::MagicEffect::BoundLongbow || effect.mEffectID == e
|
&& (e != ESM::MagicEffect::BoundLongbow || effect.mEffectID == e
|
||||||
|| rateAmmo(actor, enemy, getWeaponType(ESM::Weapon::MarksmanBow)->mAmmoType) <= 0.f))
|
|| rateAmmo(actor, enemy, getWeaponType(ESM::Weapon::MarksmanBow)->mAmmoType) <= 0.f))
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
@ -619,7 +619,11 @@ namespace MWMechanics
|
||||||
// Prefer summoning items we know how to use
|
// Prefer summoning items we know how to use
|
||||||
rating *= (50.f + actor.getClass().getSkill(actor, skill)) / 100.f;
|
rating *= (50.f + actor.getClass().getSkill(actor, skill)) / 100.f;
|
||||||
}
|
}
|
||||||
else if (actor.getClass().getCreatureStats(actor).getMagicEffects().get(effect.mEffectID).getMagnitude()
|
else if (actor.getClass()
|
||||||
|
.getCreatureStats(actor)
|
||||||
|
.getMagicEffects()
|
||||||
|
.getOrDefault(effect.mEffectID)
|
||||||
|
.getMagnitude()
|
||||||
> 0.f)
|
> 0.f)
|
||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
@ -662,14 +666,14 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
|
CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
|
||||||
|
|
||||||
if (stats.getMagicEffects().get(effect.mEffectID).getMagnitude() > 0)
|
if (stats.getMagicEffects().getOrDefault(effect.mEffectID).getMagnitude() > 0)
|
||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
|
||||||
if (stats.getMagicEffects().get(effect.mEffectID).getMagnitude() > 0)
|
if (stats.getMagicEffects().getOrDefault(effect.mEffectID).getMagnitude() > 0)
|
||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,16 +79,16 @@ namespace MWMechanics
|
||||||
|
|
||||||
float resistance = 0;
|
float resistance = 0;
|
||||||
if (resistanceEffect != -1)
|
if (resistanceEffect != -1)
|
||||||
resistance += actorEffects->get(resistanceEffect).getMagnitude();
|
resistance += actorEffects->getOrDefault(resistanceEffect).getMagnitude();
|
||||||
if (weaknessEffect != -1)
|
if (weaknessEffect != -1)
|
||||||
resistance -= actorEffects->get(weaknessEffect).getMagnitude();
|
resistance -= actorEffects->getOrDefault(weaknessEffect).getMagnitude();
|
||||||
|
|
||||||
if (effectId == ESM::MagicEffect::FireDamage)
|
if (effectId == ESM::MagicEffect::FireDamage)
|
||||||
resistance += actorEffects->get(ESM::MagicEffect::FireShield).getMagnitude();
|
resistance += actorEffects->getOrDefault(ESM::MagicEffect::FireShield).getMagnitude();
|
||||||
if (effectId == ESM::MagicEffect::ShockDamage)
|
if (effectId == ESM::MagicEffect::ShockDamage)
|
||||||
resistance += actorEffects->get(ESM::MagicEffect::LightningShield).getMagnitude();
|
resistance += actorEffects->getOrDefault(ESM::MagicEffect::LightningShield).getMagnitude();
|
||||||
if (effectId == ESM::MagicEffect::FrostDamage)
|
if (effectId == ESM::MagicEffect::FrostDamage)
|
||||||
resistance += actorEffects->get(ESM::MagicEffect::FrostShield).getMagnitude();
|
resistance += actorEffects->getOrDefault(ESM::MagicEffect::FrostShield).getMagnitude();
|
||||||
|
|
||||||
return resistance;
|
return resistance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ namespace MWMechanics
|
||||||
friend class SpellList;
|
friend class SpellList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Collection = std::vector<const ESM::Spell*>;
|
||||||
|
|
||||||
Spells();
|
Spells();
|
||||||
|
|
||||||
Spells(const Spells&);
|
Spells(const Spells&);
|
||||||
|
@ -65,9 +67,9 @@ namespace MWMechanics
|
||||||
void purgeCorprusDisease();
|
void purgeCorprusDisease();
|
||||||
void purgeCurses();
|
void purgeCurses();
|
||||||
|
|
||||||
std::vector<const ESM::Spell*>::const_iterator begin() const;
|
Collection::const_iterator begin() const;
|
||||||
|
|
||||||
std::vector<const ESM::Spell*>::const_iterator end() const;
|
Collection::const_iterator end() const;
|
||||||
|
|
||||||
bool hasSpell(const ESM::RefId& spell) const;
|
bool hasSpell(const ESM::RefId& spell) const;
|
||||||
bool hasSpell(const ESM::Spell* spell) const;
|
bool hasSpell(const ESM::Spell* spell) const;
|
||||||
|
|
|
@ -151,7 +151,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
|
||||||
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude() && !godmode)
|
if (stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Silence).getMagnitude() && !godmode)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (spell->mData.mType == ESM::Spell::ST_Power)
|
if (spell->mData.mType == ESM::Spell::ST_Power)
|
||||||
|
@ -169,7 +169,7 @@ namespace MWMechanics
|
||||||
if (spell->mData.mFlags & ESM::Spell::F_Always)
|
if (spell->mData.mFlags & ESM::Spell::F_Always)
|
||||||
return 100;
|
return 100;
|
||||||
|
|
||||||
float castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude();
|
float castBonus = -stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Sound).getMagnitude();
|
||||||
float castChance = baseChance + castBonus;
|
float castChance = baseChance + castBonus;
|
||||||
castChance *= stats.getFatigueTerm();
|
castChance *= stats.getFatigueTerm();
|
||||||
|
|
||||||
|
|
|
@ -666,7 +666,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
// check if Actor should spawn above water
|
// check if Actor should spawn above water
|
||||||
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||||
const bool canWaterWalk = effects.get(ESM::MagicEffect::WaterWalking).getMagnitude() > 0;
|
const bool canWaterWalk = effects.getOrDefault(ESM::MagicEffect::WaterWalking).getMagnitude() > 0;
|
||||||
|
|
||||||
auto actor = std::make_shared<Actor>(ptr, shape, mTaskScheduler.get(), canWaterWalk, mActorCollisionShapeType);
|
auto actor = std::make_shared<Actor>(ptr, shape, mTaskScheduler.get(), canWaterWalk, mActorCollisionShapeType);
|
||||||
|
|
||||||
|
@ -750,7 +750,7 @@ namespace MWPhysics
|
||||||
const MWMechanics::MagicEffects& effects = stats.getMagicEffects();
|
const MWMechanics::MagicEffects& effects = stats.getMagicEffects();
|
||||||
|
|
||||||
bool waterCollision = false;
|
bool waterCollision = false;
|
||||||
if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude())
|
if (cell->getCell()->hasWater() && effects.getOrDefault(ESM::MagicEffect::WaterWalking).getMagnitude())
|
||||||
{
|
{
|
||||||
if (physicActor->getCollisionMode()
|
if (physicActor->getCollisionMode()
|
||||||
|| !world->isUnderwater(ptr.getCell(), ptr.getRefData().getPosition().asVec3()))
|
|| !world->isUnderwater(ptr.getCell(), ptr.getRefData().getPosition().asVec3()))
|
||||||
|
@ -761,10 +761,10 @@ namespace MWPhysics
|
||||||
|
|
||||||
// Slow fall reduces fall speed by a factor of (effect magnitude / 200)
|
// Slow fall reduces fall speed by a factor of (effect magnitude / 200)
|
||||||
const float slowFall
|
const float slowFall
|
||||||
= 1.f - std::clamp(effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f, 0.f, 1.f);
|
= 1.f - std::clamp(effects.getOrDefault(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f, 0.f, 1.f);
|
||||||
const bool godmode = ptr == world->getPlayerConstPtr() && world->getGodModeState();
|
const bool godmode = ptr == world->getPlayerConstPtr() && world->getGodModeState();
|
||||||
const bool inert = stats.isDead()
|
const bool inert = stats.isDead()
|
||||||
|| (!godmode && stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getModifier() > 0);
|
|| (!godmode && stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Paralyze).getModifier() > 0);
|
||||||
|
|
||||||
simulations.emplace_back(ActorSimulation{
|
simulations.emplace_back(ActorSimulation{
|
||||||
physicActor, ActorFrameData{ *physicActor, inert, waterCollision, slowFall, waterlevel } });
|
physicActor, ActorFrameData{ *physicActor, inert, waterCollision, slowFall, waterlevel } });
|
||||||
|
|
|
@ -222,7 +222,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
const MWWorld::Class& cls = ptr.getClass();
|
const MWWorld::Class& cls = ptr.getClass();
|
||||||
NpcAnimation::NpcType curType = Type_Normal;
|
NpcAnimation::NpcType curType = Type_Normal;
|
||||||
if (cls.getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude() > 0)
|
if (cls.getCreatureStats(ptr).getMagicEffects().getOrDefault(ESM::MagicEffect::Vampirism).getMagnitude() > 0)
|
||||||
curType = Type_Vampire;
|
curType = Type_Vampire;
|
||||||
if (cls.getNpcStats(ptr).isWerewolf())
|
if (cls.getNpcStats(ptr).isWerewolf())
|
||||||
curType = Type_Werewolf;
|
curType = Type_Werewolf;
|
||||||
|
|
|
@ -582,7 +582,7 @@ namespace MWScript
|
||||||
k.has_value() && *k >= 0 && *k <= 32767)
|
k.has_value() && *k >= 0 && *k <= 32767)
|
||||||
key = *k;
|
key = *k;
|
||||||
else
|
else
|
||||||
key = ESM::MagicEffect::effectStringToId({ effect });
|
key = ESM::MagicEffect::effectGmstIdToIndex(effect);
|
||||||
|
|
||||||
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
|
|
||||||
|
|
|
@ -1193,17 +1193,17 @@ namespace MWScript
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||||
float currentValue = effects.get(mPositiveEffect).getMagnitude();
|
float currentValue = effects.getOrDefault(mPositiveEffect).getMagnitude();
|
||||||
if (mNegativeEffect != -1)
|
if (mNegativeEffect != -1)
|
||||||
currentValue -= effects.get(mNegativeEffect).getMagnitude();
|
currentValue -= effects.getOrDefault(mNegativeEffect).getMagnitude();
|
||||||
|
|
||||||
// GetResist* should take in account elemental shields
|
// GetResist* should take in account elemental shields
|
||||||
if (mPositiveEffect == ESM::MagicEffect::ResistFire)
|
if (mPositiveEffect == ESM::MagicEffect::ResistFire)
|
||||||
currentValue += effects.get(ESM::MagicEffect::FireShield).getMagnitude();
|
currentValue += effects.getOrDefault(ESM::MagicEffect::FireShield).getMagnitude();
|
||||||
if (mPositiveEffect == ESM::MagicEffect::ResistShock)
|
if (mPositiveEffect == ESM::MagicEffect::ResistShock)
|
||||||
currentValue += effects.get(ESM::MagicEffect::LightningShield).getMagnitude();
|
currentValue += effects.getOrDefault(ESM::MagicEffect::LightningShield).getMagnitude();
|
||||||
if (mPositiveEffect == ESM::MagicEffect::ResistFrost)
|
if (mPositiveEffect == ESM::MagicEffect::ResistFrost)
|
||||||
currentValue += effects.get(ESM::MagicEffect::FrostShield).getMagnitude();
|
currentValue += effects.getOrDefault(ESM::MagicEffect::FrostShield).getMagnitude();
|
||||||
|
|
||||||
int ret = static_cast<int>(currentValue);
|
int ret = static_cast<int>(currentValue);
|
||||||
runtime.push(ret);
|
runtime.push(ret);
|
||||||
|
@ -1227,17 +1227,17 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||||
float currentValue = effects.get(mPositiveEffect).getMagnitude();
|
float currentValue = effects.getOrDefault(mPositiveEffect).getMagnitude();
|
||||||
if (mNegativeEffect != -1)
|
if (mNegativeEffect != -1)
|
||||||
currentValue -= effects.get(mNegativeEffect).getMagnitude();
|
currentValue -= effects.getOrDefault(mNegativeEffect).getMagnitude();
|
||||||
|
|
||||||
// SetResist* should take in account elemental shields
|
// SetResist* should take in account elemental shields
|
||||||
if (mPositiveEffect == ESM::MagicEffect::ResistFire)
|
if (mPositiveEffect == ESM::MagicEffect::ResistFire)
|
||||||
currentValue += effects.get(ESM::MagicEffect::FireShield).getMagnitude();
|
currentValue += effects.getOrDefault(ESM::MagicEffect::FireShield).getMagnitude();
|
||||||
if (mPositiveEffect == ESM::MagicEffect::ResistShock)
|
if (mPositiveEffect == ESM::MagicEffect::ResistShock)
|
||||||
currentValue += effects.get(ESM::MagicEffect::LightningShield).getMagnitude();
|
currentValue += effects.getOrDefault(ESM::MagicEffect::LightningShield).getMagnitude();
|
||||||
if (mPositiveEffect == ESM::MagicEffect::ResistFrost)
|
if (mPositiveEffect == ESM::MagicEffect::ResistFrost)
|
||||||
currentValue += effects.get(ESM::MagicEffect::FrostShield).getMagnitude();
|
currentValue += effects.getOrDefault(ESM::MagicEffect::FrostShield).getMagnitude();
|
||||||
|
|
||||||
int arg = runtime[0].mInteger;
|
int arg = runtime[0].mInteger;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
@ -1276,7 +1276,8 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
MWMechanics::EffectParam nightEye
|
MWMechanics::EffectParam nightEye
|
||||||
= player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye);
|
= player.getClass().getCreatureStats(player).getMagicEffects().getOrDefault(
|
||||||
|
ESM::MagicEffect::NightEye);
|
||||||
runtime.push(std::clamp(nightEye.getMagnitude() / 100.f, 0.f, 1.f));
|
runtime.push(std::clamp(nightEye.getMagnitude() / 100.f, 0.f, 1.f));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1290,8 +1291,8 @@ namespace MWScript
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
auto& effects = player.getClass().getCreatureStats(player).getMagicEffects();
|
auto& effects = player.getClass().getCreatureStats(player).getMagicEffects();
|
||||||
float delta
|
float delta = std::clamp(arg * 100.f, 0.f, 100.f)
|
||||||
= std::clamp(arg * 100.f, 0.f, 100.f) - effects.get(ESM::MagicEffect::NightEye).getMagnitude();
|
- effects.getOrDefault(ESM::MagicEffect::NightEye).getMagnitude();
|
||||||
effects.modifyBase(ESM::MagicEffect::NightEye, static_cast<int>(delta));
|
effects.modifyBase(ESM::MagicEffect::NightEye, static_cast<int>(delta));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1305,7 +1306,7 @@ namespace MWScript
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
auto& effects = player.getClass().getCreatureStats(player).getMagicEffects();
|
auto& effects = player.getClass().getCreatureStats(player).getMagicEffects();
|
||||||
const MWMechanics::EffectParam nightEye = effects.get(ESM::MagicEffect::NightEye);
|
const MWMechanics::EffectParam nightEye = effects.getOrDefault(ESM::MagicEffect::NightEye);
|
||||||
float newBase = std::clamp(nightEye.getMagnitude() + arg * 100.f, 0.f, 100.f);
|
float newBase = std::clamp(nightEye.getMagnitude() + arg * 100.f, 0.f, 100.f);
|
||||||
newBase -= nightEye.getModifier();
|
newBase -= nightEye.getModifier();
|
||||||
float delta = std::clamp(newBase, 0.f, 100.f) - nightEye.getMagnitude();
|
float delta = std::clamp(newBase, 0.f, 100.f) - nightEye.getMagnitude();
|
||||||
|
|
|
@ -538,7 +538,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
iter->mAttribute = -1;
|
iter->mAttribute = -1;
|
||||||
Log(Debug::Verbose)
|
Log(Debug::Verbose)
|
||||||
<< ESM::MagicEffect::effectIdToString(iter->mEffectID) << " effect of spell '" << spell.mId
|
<< ESM::MagicEffect::indexToGmstString(iter->mEffectID) << " effect of spell '" << spell.mId
|
||||||
<< "' has an attribute argument present. Dropping the argument.";
|
<< "' has an attribute argument present. Dropping the argument.";
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -549,7 +549,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
iter->mSkill = -1;
|
iter->mSkill = -1;
|
||||||
Log(Debug::Verbose)
|
Log(Debug::Verbose)
|
||||||
<< ESM::MagicEffect::effectIdToString(iter->mEffectID) << " effect of spell '" << spell.mId
|
<< ESM::MagicEffect::indexToGmstString(iter->mEffectID) << " effect of spell '" << spell.mId
|
||||||
<< "' has a skill argument present. Dropping the argument.";
|
<< "' has a skill argument present. Dropping the argument.";
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -558,7 +558,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
iter->mSkill = -1;
|
iter->mSkill = -1;
|
||||||
iter->mAttribute = -1;
|
iter->mAttribute = -1;
|
||||||
Log(Debug::Verbose) << ESM::MagicEffect::effectIdToString(iter->mEffectID) << " effect of spell '"
|
Log(Debug::Verbose) << ESM::MagicEffect::indexToGmstString(iter->mEffectID) << " effect of spell '"
|
||||||
<< spell.mId << "' has argument(s) present. Dropping the argument(s).";
|
<< spell.mId << "' has argument(s) present. Dropping the argument(s).";
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -503,10 +503,10 @@ namespace MWWorld
|
||||||
int blind = 0;
|
int blind = 0;
|
||||||
const auto& magicEffects = playerClass.getCreatureStats(player).getMagicEffects();
|
const auto& magicEffects = playerClass.getCreatureStats(player).getMagicEffects();
|
||||||
if (!world->getGodModeState())
|
if (!world->getGodModeState())
|
||||||
blind = static_cast<int>(magicEffects.get(ESM::MagicEffect::Blind).getModifier());
|
blind = static_cast<int>(magicEffects.getOrDefault(ESM::MagicEffect::Blind).getModifier());
|
||||||
windowMgr->setBlindness(std::clamp(blind, 0, 100));
|
windowMgr->setBlindness(std::clamp(blind, 0, 100));
|
||||||
|
|
||||||
int nightEye = static_cast<int>(magicEffects.get(ESM::MagicEffect::NightEye).getMagnitude());
|
int nightEye = static_cast<int>(magicEffects.getOrDefault(ESM::MagicEffect::NightEye).getMagnitude());
|
||||||
rendering->setNightEyeFactor(std::min(1.f, (nightEye / 100.f)));
|
rendering->setNightEyeFactor(std::min(1.f, (nightEye / 100.f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2137,13 +2137,15 @@ namespace MWWorld
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const bool isPlayer = ptr == getPlayerConstPtr();
|
const bool isPlayer = ptr == getPlayerConstPtr();
|
||||||
if (!(isPlayer && mGodMode) && stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getModifier() > 0)
|
if (!(isPlayer && mGodMode)
|
||||||
|
&& stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Paralyze).getModifier() > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ptr.getClass().canFly(ptr))
|
if (ptr.getClass().canFly(ptr))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (stats.getMagicEffects().get(ESM::MagicEffect::Levitate).getMagnitude() > 0 && isLevitationEnabled())
|
if (stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Levitate).getMagnitude() > 0
|
||||||
|
&& isLevitationEnabled())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const MWPhysics::Actor* actor = mPhysics->getActor(ptr);
|
const MWPhysics::Actor* actor = mPhysics->getActor(ptr);
|
||||||
|
@ -2159,7 +2161,7 @@ namespace MWWorld
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
if (stats.getMagicEffects().get(ESM::MagicEffect::SlowFall).getMagnitude() > 0)
|
if (stats.getMagicEffects().getOrDefault(ESM::MagicEffect::SlowFall).getMagnitude() > 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -3446,11 +3448,11 @@ namespace MWWorld
|
||||||
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||||
float dist = 0;
|
float dist = 0;
|
||||||
if (type == World::Detect_Creature)
|
if (type == World::Detect_Creature)
|
||||||
dist = effects.get(ESM::MagicEffect::DetectAnimal).getMagnitude();
|
dist = effects.getOrDefault(ESM::MagicEffect::DetectAnimal).getMagnitude();
|
||||||
else if (type == World::Detect_Key)
|
else if (type == World::Detect_Key)
|
||||||
dist = effects.get(ESM::MagicEffect::DetectKey).getMagnitude();
|
dist = effects.getOrDefault(ESM::MagicEffect::DetectKey).getMagnitude();
|
||||||
else if (type == World::Detect_Enchantment)
|
else if (type == World::Detect_Enchantment)
|
||||||
dist = effects.get(ESM::MagicEffect::DetectEnchantment).getMagnitude();
|
dist = effects.getOrDefault(ESM::MagicEffect::DetectEnchantment).getMagnitude();
|
||||||
|
|
||||||
if (!dist)
|
if (!dist)
|
||||||
return;
|
return;
|
||||||
|
@ -3478,7 +3480,7 @@ namespace MWWorld
|
||||||
.getClass()
|
.getClass()
|
||||||
.getCreatureStats(mPlayer->getPlayer())
|
.getCreatureStats(mPlayer->getPlayer())
|
||||||
.getMagicEffects()
|
.getMagicEffects()
|
||||||
.get(ESM::MagicEffect::Telekinesis)
|
.getOrDefault(ESM::MagicEffect::Telekinesis)
|
||||||
.getMagnitude();
|
.getMagnitude();
|
||||||
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
|
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "attr.hpp"
|
#include "attr.hpp"
|
||||||
|
#include <components/misc/strings/algorithm.hpp>
|
||||||
|
|
||||||
using namespace ESM;
|
using namespace ESM;
|
||||||
|
|
||||||
|
@ -56,3 +57,12 @@ const std::string Attribute::sAttributeIcons[Attribute::Length] = {
|
||||||
"icons\\k\\attribute_personality.dds",
|
"icons\\k\\attribute_personality.dds",
|
||||||
"icons\\k\\attribute_luck.dds",
|
"icons\\k\\attribute_luck.dds",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Attribute::AttributeID Attribute::stringToAttributeId(std::string_view attribute)
|
||||||
|
{
|
||||||
|
for (auto id : sAttributeIds)
|
||||||
|
if (Misc::StringUtils::ciEqual(sAttributeNames[id], attribute))
|
||||||
|
return id;
|
||||||
|
|
||||||
|
throw std::logic_error("No such attribute: " + std::string(attribute));
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace ESM
|
||||||
static const std::string sGmstAttributeIds[Length];
|
static const std::string sGmstAttributeIds[Length];
|
||||||
static const std::string sGmstAttributeDescIds[Length];
|
static const std::string sGmstAttributeDescIds[Length];
|
||||||
static const std::string sAttributeIcons[Length];
|
static const std::string sAttributeIcons[Length];
|
||||||
|
|
||||||
|
static AttributeID stringToAttributeId(std::string_view attribute);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,156 +24,6 @@ namespace ESM
|
||||||
0x1048, 0x1048, 0x1048, 0x1048 };
|
0x1048, 0x1048, 0x1048, 0x1048 };
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string_view MagicEffect::sIndexNames[MagicEffect::Length] = {
|
|
||||||
"WaterBreathing",
|
|
||||||
"SwiftSwim",
|
|
||||||
"WaterWalking",
|
|
||||||
"Shield",
|
|
||||||
"FireShield",
|
|
||||||
"LightningShield",
|
|
||||||
"FrostShield",
|
|
||||||
"Burden",
|
|
||||||
"Feather",
|
|
||||||
"Jump",
|
|
||||||
"Levitate",
|
|
||||||
"SlowFall",
|
|
||||||
"Lock",
|
|
||||||
"Open",
|
|
||||||
"FireDamage",
|
|
||||||
"ShockDamage",
|
|
||||||
"FrostDamage",
|
|
||||||
"DrainAttribute",
|
|
||||||
"DrainHealth",
|
|
||||||
"DrainMagicka",
|
|
||||||
"DrainFatigue",
|
|
||||||
"DrainSkill",
|
|
||||||
"DamageAttribute",
|
|
||||||
"DamageHealth",
|
|
||||||
"DamageMagicka",
|
|
||||||
"DamageFatigue",
|
|
||||||
"DamageSkill",
|
|
||||||
"Poison",
|
|
||||||
"WeaknessToFire",
|
|
||||||
"WeaknessToFrost",
|
|
||||||
"WeaknessToShock",
|
|
||||||
"WeaknessToMagicka",
|
|
||||||
"WeaknessToCommonDisease",
|
|
||||||
"WeaknessToBlightDisease",
|
|
||||||
"WeaknessToCorprusDisease",
|
|
||||||
"WeaknessToPoison",
|
|
||||||
"WeaknessToNormalWeapons",
|
|
||||||
"DisintegrateWeapon",
|
|
||||||
"DisintegrateArmor",
|
|
||||||
"Invisibility",
|
|
||||||
"Chameleon",
|
|
||||||
"Light",
|
|
||||||
"Sanctuary",
|
|
||||||
"NightEye",
|
|
||||||
"Charm",
|
|
||||||
"Paralyze",
|
|
||||||
"Silence",
|
|
||||||
"Blind",
|
|
||||||
"Sound",
|
|
||||||
"CalmHumanoid",
|
|
||||||
"CalmCreature",
|
|
||||||
"FrenzyHumanoid",
|
|
||||||
"FrenzyCreature",
|
|
||||||
"DemoralizeHumanoid",
|
|
||||||
"DemoralizeCreature",
|
|
||||||
"RallyHumanoid",
|
|
||||||
"RallyCreature",
|
|
||||||
"Dispel",
|
|
||||||
"Soultrap",
|
|
||||||
"Telekinesis",
|
|
||||||
"Mark",
|
|
||||||
"Recall",
|
|
||||||
"DivineIntervention",
|
|
||||||
"AlmsiviIntervention",
|
|
||||||
"DetectAnimal",
|
|
||||||
"DetectEnchantment",
|
|
||||||
"DetectKey",
|
|
||||||
"SpellAbsorption",
|
|
||||||
"Reflect",
|
|
||||||
"CureCommonDisease",
|
|
||||||
"CureBlightDisease",
|
|
||||||
"CureCorprusDisease",
|
|
||||||
"CurePoison",
|
|
||||||
"CureParalyzation",
|
|
||||||
"RestoreAttribute",
|
|
||||||
"RestoreHealth",
|
|
||||||
"RestoreMagicka",
|
|
||||||
"RestoreFatigue",
|
|
||||||
"RestoreSkill",
|
|
||||||
"FortifyAttribute",
|
|
||||||
"FortifyHealth",
|
|
||||||
"FortifyMagicka",
|
|
||||||
"FortifyFatigue",
|
|
||||||
"FortifySkill",
|
|
||||||
"FortifyMaximumMagicka",
|
|
||||||
"AbsorbAttribute",
|
|
||||||
"AbsorbHealth",
|
|
||||||
"AbsorbMagicka",
|
|
||||||
"AbsorbFatigue",
|
|
||||||
"AbsorbSkill",
|
|
||||||
"ResistFire",
|
|
||||||
"ResistFrost",
|
|
||||||
"ResistShock",
|
|
||||||
"ResistMagicka",
|
|
||||||
"ResistCommonDisease",
|
|
||||||
"ResistBlightDisease",
|
|
||||||
"ResistCorprusDisease",
|
|
||||||
"ResistPoison",
|
|
||||||
"ResistNormalWeapons",
|
|
||||||
"ResistParalysis",
|
|
||||||
"RemoveCurse",
|
|
||||||
"TurnUndead",
|
|
||||||
"SummonScamp",
|
|
||||||
"SummonClannfear",
|
|
||||||
"SummonDaedroth",
|
|
||||||
"SummonDremora",
|
|
||||||
"SummonAncestralGhost",
|
|
||||||
"SummonSkeletalMinion",
|
|
||||||
"SummonBonewalker",
|
|
||||||
"SummonGreaterBonewalker",
|
|
||||||
"SummonBonelord",
|
|
||||||
"SummonWingedTwilight",
|
|
||||||
"SummonHunger",
|
|
||||||
"SummonGoldenSaint",
|
|
||||||
"SummonFlameAtronach",
|
|
||||||
"SummonFrostAtronach",
|
|
||||||
"SummonStormAtronach",
|
|
||||||
"FortifyAttack",
|
|
||||||
"CommandCreature",
|
|
||||||
"CommandHumanoid",
|
|
||||||
"BoundDagger",
|
|
||||||
"BoundLongsword",
|
|
||||||
"BoundMace",
|
|
||||||
"BoundBattleAxe",
|
|
||||||
"BoundSpear",
|
|
||||||
"BoundLongbow",
|
|
||||||
"ExtraSpell",
|
|
||||||
"BoundCuirass",
|
|
||||||
"BoundHelm",
|
|
||||||
"BoundBoots",
|
|
||||||
"BoundShield",
|
|
||||||
"BoundGloves",
|
|
||||||
"Corprus",
|
|
||||||
"Vampirism",
|
|
||||||
"SummonCenturionSphere",
|
|
||||||
"SunDamage",
|
|
||||||
"StuntedMagicka",
|
|
||||||
|
|
||||||
// Tribunal only
|
|
||||||
"SummonFabricant",
|
|
||||||
|
|
||||||
// Bloodmoon only
|
|
||||||
"SummonWolf",
|
|
||||||
"SummonBear",
|
|
||||||
"SummonBonewolf",
|
|
||||||
"SummonCreature04",
|
|
||||||
"SummonCreature05",
|
|
||||||
};
|
|
||||||
|
|
||||||
void MagicEffect::load(ESMReader& esm, bool& isDeleted)
|
void MagicEffect::load(ESMReader& esm, bool& isDeleted)
|
||||||
{
|
{
|
||||||
isDeleted = false; // MagicEffect record can't be deleted now (may be changed in the future)
|
isDeleted = false; // MagicEffect record can't be deleted now (may be changed in the future)
|
||||||
|
@ -351,172 +201,325 @@ namespace ESM
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<short, std::string> genNameMap()
|
// Map effect ID to GMST name
|
||||||
{
|
const std::array<std::string, MagicEffect::Length> MagicEffect::sGmstEffectIds = {
|
||||||
// Map effect ID to GMST name
|
|
||||||
// http://www.uesp.net/morrow/hints/mweffects.shtml
|
|
||||||
std::map<short, std::string> names;
|
|
||||||
names[85] = "sEffectAbsorbAttribute";
|
|
||||||
names[88] = "sEffectAbsorbFatigue";
|
|
||||||
names[86] = "sEffectAbsorbHealth";
|
|
||||||
names[87] = "sEffectAbsorbSpellPoints";
|
|
||||||
names[89] = "sEffectAbsorbSkill";
|
|
||||||
names[63] = "sEffectAlmsiviIntervention";
|
|
||||||
names[47] = "sEffectBlind";
|
|
||||||
names[123] = "sEffectBoundBattleAxe";
|
|
||||||
names[129] = "sEffectBoundBoots";
|
|
||||||
names[127] = "sEffectBoundCuirass";
|
|
||||||
names[120] = "sEffectBoundDagger";
|
|
||||||
names[131] = "sEffectBoundGloves";
|
|
||||||
names[128] = "sEffectBoundHelm";
|
|
||||||
names[125] = "sEffectBoundLongbow";
|
|
||||||
names[126] = "sEffectExtraSpell";
|
|
||||||
names[121] = "sEffectBoundLongsword";
|
|
||||||
names[122] = "sEffectBoundMace";
|
|
||||||
names[130] = "sEffectBoundShield";
|
|
||||||
names[124] = "sEffectBoundSpear";
|
|
||||||
names[7] = "sEffectBurden";
|
|
||||||
names[50] = "sEffectCalmCreature";
|
|
||||||
names[49] = "sEffectCalmHumanoid";
|
|
||||||
names[40] = "sEffectChameleon";
|
|
||||||
names[44] = "sEffectCharm";
|
|
||||||
names[118] = "sEffectCommandCreatures";
|
|
||||||
names[119] = "sEffectCommandHumanoids";
|
|
||||||
names[132] = "sEffectCorpus"; // NB this typo. (bethesda made it)
|
|
||||||
names[70] = "sEffectCureBlightDisease";
|
|
||||||
names[69] = "sEffectCureCommonDisease";
|
|
||||||
names[71] = "sEffectCureCorprusDisease";
|
|
||||||
names[73] = "sEffectCureParalyzation";
|
|
||||||
names[72] = "sEffectCurePoison";
|
|
||||||
names[22] = "sEffectDamageAttribute";
|
|
||||||
names[25] = "sEffectDamageFatigue";
|
|
||||||
names[23] = "sEffectDamageHealth";
|
|
||||||
names[24] = "sEffectDamageMagicka";
|
|
||||||
names[26] = "sEffectDamageSkill";
|
|
||||||
names[54] = "sEffectDemoralizeCreature";
|
|
||||||
names[53] = "sEffectDemoralizeHumanoid";
|
|
||||||
names[64] = "sEffectDetectAnimal";
|
|
||||||
names[65] = "sEffectDetectEnchantment";
|
|
||||||
names[66] = "sEffectDetectKey";
|
|
||||||
names[38] = "sEffectDisintegrateArmor";
|
|
||||||
names[37] = "sEffectDisintegrateWeapon";
|
|
||||||
names[57] = "sEffectDispel";
|
|
||||||
names[62] = "sEffectDivineIntervention";
|
|
||||||
names[17] = "sEffectDrainAttribute";
|
|
||||||
names[20] = "sEffectDrainFatigue";
|
|
||||||
names[18] = "sEffectDrainHealth";
|
|
||||||
names[19] = "sEffectDrainSpellpoints";
|
|
||||||
names[21] = "sEffectDrainSkill";
|
|
||||||
names[8] = "sEffectFeather";
|
|
||||||
names[14] = "sEffectFireDamage";
|
|
||||||
names[4] = "sEffectFireShield";
|
|
||||||
names[117] = "sEffectFortifyAttackBonus";
|
|
||||||
names[79] = "sEffectFortifyAttribute";
|
|
||||||
names[82] = "sEffectFortifyFatigue";
|
|
||||||
names[80] = "sEffectFortifyHealth";
|
|
||||||
names[81] = "sEffectFortifySpellpoints";
|
|
||||||
names[84] = "sEffectFortifyMagickaMultiplier";
|
|
||||||
names[83] = "sEffectFortifySkill";
|
|
||||||
names[52] = "sEffectFrenzyCreature";
|
|
||||||
names[51] = "sEffectFrenzyHumanoid";
|
|
||||||
names[16] = "sEffectFrostDamage";
|
|
||||||
names[6] = "sEffectFrostShield";
|
|
||||||
names[39] = "sEffectInvisibility";
|
|
||||||
names[9] = "sEffectJump";
|
|
||||||
names[10] = "sEffectLevitate";
|
|
||||||
names[41] = "sEffectLight";
|
|
||||||
names[5] = "sEffectLightningShield";
|
|
||||||
names[12] = "sEffectLock";
|
|
||||||
names[60] = "sEffectMark";
|
|
||||||
names[43] = "sEffectNightEye";
|
|
||||||
names[13] = "sEffectOpen";
|
|
||||||
names[45] = "sEffectParalyze";
|
|
||||||
names[27] = "sEffectPoison";
|
|
||||||
names[56] = "sEffectRallyCreature";
|
|
||||||
names[55] = "sEffectRallyHumanoid";
|
|
||||||
names[61] = "sEffectRecall";
|
|
||||||
names[68] = "sEffectReflect";
|
|
||||||
names[100] = "sEffectRemoveCurse";
|
|
||||||
names[95] = "sEffectResistBlightDisease";
|
|
||||||
names[94] = "sEffectResistCommonDisease";
|
|
||||||
names[96] = "sEffectResistCorprusDisease";
|
|
||||||
names[90] = "sEffectResistFire";
|
|
||||||
names[91] = "sEffectResistFrost";
|
|
||||||
names[93] = "sEffectResistMagicka";
|
|
||||||
names[98] = "sEffectResistNormalWeapons";
|
|
||||||
names[99] = "sEffectResistParalysis";
|
|
||||||
names[97] = "sEffectResistPoison";
|
|
||||||
names[92] = "sEffectResistShock";
|
|
||||||
names[74] = "sEffectRestoreAttribute";
|
|
||||||
names[77] = "sEffectRestoreFatigue";
|
|
||||||
names[75] = "sEffectRestoreHealth";
|
|
||||||
names[76] = "sEffectRestoreSpellPoints";
|
|
||||||
names[78] = "sEffectRestoreSkill";
|
|
||||||
names[42] = "sEffectSanctuary";
|
|
||||||
names[3] = "sEffectShield";
|
|
||||||
names[15] = "sEffectShockDamage";
|
|
||||||
names[46] = "sEffectSilence";
|
|
||||||
names[11] = "sEffectSlowFall";
|
|
||||||
names[58] = "sEffectSoultrap";
|
|
||||||
names[48] = "sEffectSound";
|
|
||||||
names[67] = "sEffectSpellAbsorption";
|
|
||||||
names[136] = "sEffectStuntedMagicka";
|
|
||||||
names[106] = "sEffectSummonAncestralGhost";
|
|
||||||
names[110] = "sEffectSummonBonelord";
|
|
||||||
names[108] = "sEffectSummonLeastBonewalker";
|
|
||||||
names[134] = "sEffectSummonCenturionSphere";
|
|
||||||
names[103] = "sEffectSummonClannfear";
|
|
||||||
names[104] = "sEffectSummonDaedroth";
|
|
||||||
names[105] = "sEffectSummonDremora";
|
|
||||||
names[114] = "sEffectSummonFlameAtronach";
|
|
||||||
names[115] = "sEffectSummonFrostAtronach";
|
|
||||||
names[113] = "sEffectSummonGoldenSaint";
|
|
||||||
names[109] = "sEffectSummonGreaterBonewalker";
|
|
||||||
names[112] = "sEffectSummonHunger";
|
|
||||||
names[102] = "sEffectSummonScamp";
|
|
||||||
names[107] = "sEffectSummonSkeletalMinion";
|
|
||||||
names[116] = "sEffectSummonStormAtronach";
|
|
||||||
names[111] = "sEffectSummonWingedTwilight";
|
|
||||||
names[135] = "sEffectSunDamage";
|
|
||||||
names[1] = "sEffectSwiftSwim";
|
|
||||||
names[59] = "sEffectTelekinesis";
|
|
||||||
names[101] = "sEffectTurnUndead";
|
|
||||||
names[133] = "sEffectVampirism";
|
|
||||||
names[0] = "sEffectWaterBreathing";
|
|
||||||
names[2] = "sEffectWaterWalking";
|
|
||||||
names[33] = "sEffectWeaknesstoBlightDisease";
|
|
||||||
names[32] = "sEffectWeaknesstoCommonDisease";
|
|
||||||
names[34] = "sEffectWeaknesstoCorprusDisease";
|
|
||||||
names[28] = "sEffectWeaknesstoFire";
|
|
||||||
names[29] = "sEffectWeaknesstoFrost";
|
|
||||||
names[31] = "sEffectWeaknesstoMagicka";
|
|
||||||
names[36] = "sEffectWeaknesstoNormalWeapons";
|
|
||||||
names[35] = "sEffectWeaknesstoPoison";
|
|
||||||
names[30] = "sEffectWeaknesstoShock";
|
|
||||||
|
|
||||||
// bloodmoon
|
"sEffectWaterBreathing",
|
||||||
names[138] = "sEffectSummonCreature01";
|
"sEffectSwiftSwim",
|
||||||
names[139] = "sEffectSummonCreature02";
|
"sEffectWaterWalking",
|
||||||
names[140] = "sEffectSummonCreature03";
|
"sEffectShield",
|
||||||
names[141] = "sEffectSummonCreature04";
|
"sEffectFireShield",
|
||||||
names[142] = "sEffectSummonCreature05";
|
"sEffectLightningShield",
|
||||||
|
"sEffectFrostShield",
|
||||||
|
"sEffectBurden",
|
||||||
|
"sEffectFeather",
|
||||||
|
"sEffectJump",
|
||||||
|
"sEffectLevitate",
|
||||||
|
"sEffectSlowFall",
|
||||||
|
"sEffectLock",
|
||||||
|
"sEffectOpen",
|
||||||
|
"sEffectFireDamage",
|
||||||
|
"sEffectShockDamage",
|
||||||
|
"sEffectFrostDamage",
|
||||||
|
"sEffectDrainAttribute",
|
||||||
|
"sEffectDrainHealth",
|
||||||
|
"sEffectDrainSpellpoints",
|
||||||
|
"sEffectDrainFatigue",
|
||||||
|
"sEffectDrainSkill",
|
||||||
|
"sEffectDamageAttribute",
|
||||||
|
"sEffectDamageHealth",
|
||||||
|
"sEffectDamageMagicka",
|
||||||
|
"sEffectDamageFatigue",
|
||||||
|
"sEffectDamageSkill",
|
||||||
|
"sEffectPoison",
|
||||||
|
"sEffectWeaknesstoFire",
|
||||||
|
"sEffectWeaknesstoFrost",
|
||||||
|
"sEffectWeaknesstoShock",
|
||||||
|
"sEffectWeaknesstoMagicka",
|
||||||
|
"sEffectWeaknesstoCommonDisease",
|
||||||
|
"sEffectWeaknesstoBlightDisease",
|
||||||
|
"sEffectWeaknesstoCorprusDisease",
|
||||||
|
"sEffectWeaknesstoPoison",
|
||||||
|
"sEffectWeaknesstoNormalWeapons",
|
||||||
|
"sEffectDisintegrateWeapon",
|
||||||
|
"sEffectDisintegrateArmor",
|
||||||
|
"sEffectInvisibility",
|
||||||
|
"sEffectChameleon",
|
||||||
|
"sEffectLight",
|
||||||
|
"sEffectSanctuary",
|
||||||
|
"sEffectNightEye",
|
||||||
|
"sEffectCharm",
|
||||||
|
"sEffectParalyze",
|
||||||
|
"sEffectSilence",
|
||||||
|
"sEffectBlind",
|
||||||
|
"sEffectSound",
|
||||||
|
"sEffectCalmHumanoid",
|
||||||
|
"sEffectCalmCreature",
|
||||||
|
"sEffectFrenzyHumanoid",
|
||||||
|
"sEffectFrenzyCreature",
|
||||||
|
"sEffectDemoralizeHumanoid",
|
||||||
|
"sEffectDemoralizeCreature",
|
||||||
|
"sEffectRallyHumanoid",
|
||||||
|
"sEffectRallyCreature",
|
||||||
|
"sEffectDispel",
|
||||||
|
"sEffectSoultrap",
|
||||||
|
"sEffectTelekinesis",
|
||||||
|
"sEffectMark",
|
||||||
|
"sEffectRecall",
|
||||||
|
"sEffectDivineIntervention",
|
||||||
|
"sEffectAlmsiviIntervention",
|
||||||
|
"sEffectDetectAnimal",
|
||||||
|
"sEffectDetectEnchantment",
|
||||||
|
"sEffectDetectKey",
|
||||||
|
"sEffectSpellAbsorption",
|
||||||
|
"sEffectReflect",
|
||||||
|
"sEffectCureCommonDisease",
|
||||||
|
"sEffectCureBlightDisease",
|
||||||
|
"sEffectCureCorprusDisease",
|
||||||
|
"sEffectCurePoison",
|
||||||
|
"sEffectCureParalyzation",
|
||||||
|
"sEffectRestoreAttribute",
|
||||||
|
"sEffectRestoreHealth",
|
||||||
|
"sEffectRestoreSpellPoints",
|
||||||
|
"sEffectRestoreFatigue",
|
||||||
|
"sEffectRestoreSkill",
|
||||||
|
"sEffectFortifyAttribute",
|
||||||
|
"sEffectFortifyHealth",
|
||||||
|
"sEffectFortifySpellpoints",
|
||||||
|
"sEffectFortifyFatigue",
|
||||||
|
"sEffectFortifySkill",
|
||||||
|
"sEffectFortifyMagickaMultiplier",
|
||||||
|
"sEffectAbsorbAttribute",
|
||||||
|
"sEffectAbsorbHealth",
|
||||||
|
"sEffectAbsorbSpellPoints",
|
||||||
|
"sEffectAbsorbFatigue",
|
||||||
|
"sEffectAbsorbSkill",
|
||||||
|
"sEffectResistFire",
|
||||||
|
"sEffectResistFrost",
|
||||||
|
"sEffectResistShock",
|
||||||
|
"sEffectResistMagicka",
|
||||||
|
"sEffectResistCommonDisease",
|
||||||
|
"sEffectResistBlightDisease",
|
||||||
|
"sEffectResistCorprusDisease",
|
||||||
|
"sEffectResistPoison",
|
||||||
|
"sEffectResistNormalWeapons",
|
||||||
|
"sEffectResistParalysis",
|
||||||
|
"sEffectRemoveCurse",
|
||||||
|
"sEffectTurnUndead",
|
||||||
|
"sEffectSummonScamp",
|
||||||
|
"sEffectSummonClannfear",
|
||||||
|
"sEffectSummonDaedroth",
|
||||||
|
"sEffectSummonDremora",
|
||||||
|
"sEffectSummonAncestralGhost",
|
||||||
|
"sEffectSummonSkeletalMinion",
|
||||||
|
"sEffectSummonLeastBonewalker",
|
||||||
|
"sEffectSummonGreaterBonewalker",
|
||||||
|
"sEffectSummonBonelord",
|
||||||
|
"sEffectSummonWingedTwilight",
|
||||||
|
"sEffectSummonHunger",
|
||||||
|
"sEffectSummonGoldenSaint",
|
||||||
|
"sEffectSummonFlameAtronach",
|
||||||
|
"sEffectSummonFrostAtronach",
|
||||||
|
"sEffectSummonStormAtronach",
|
||||||
|
"sEffectFortifyAttackBonus",
|
||||||
|
"sEffectCommandCreatures",
|
||||||
|
"sEffectCommandHumanoids",
|
||||||
|
"sEffectBoundDagger",
|
||||||
|
"sEffectBoundLongsword",
|
||||||
|
"sEffectBoundMace",
|
||||||
|
"sEffectBoundBattleAxe",
|
||||||
|
"sEffectBoundSpear",
|
||||||
|
"sEffectBoundLongbow",
|
||||||
|
"sEffectExtraSpell",
|
||||||
|
"sEffectBoundCuirass",
|
||||||
|
"sEffectBoundHelm",
|
||||||
|
"sEffectBoundBoots",
|
||||||
|
"sEffectBoundShield",
|
||||||
|
"sEffectBoundGloves",
|
||||||
|
"sEffectCorpus", // NB this typo. (bethesda made it)
|
||||||
|
"sEffectVampirism",
|
||||||
|
"sEffectSummonCenturionSphere",
|
||||||
|
"sEffectSunDamage",
|
||||||
|
"sEffectStuntedMagicka",
|
||||||
|
|
||||||
// tribunal
|
// tribunal
|
||||||
names[137] = "sEffectSummonFabricant";
|
"sEffectSummonFabricant",
|
||||||
|
|
||||||
return names;
|
// bloodmoon
|
||||||
}
|
"sEffectSummonCreature01",
|
||||||
const std::map<short, std::string> MagicEffect::sNames = genNameMap();
|
"sEffectSummonCreature02",
|
||||||
|
"sEffectSummonCreature03",
|
||||||
|
"sEffectSummonCreature04",
|
||||||
|
"sEffectSummonCreature05",
|
||||||
|
};
|
||||||
|
|
||||||
const std::string& MagicEffect::effectIdToString(short effectID)
|
// Map effect ID to identifying name
|
||||||
|
const std::array<std::string_view, MagicEffect::Length> MagicEffect::sIndexNames = {
|
||||||
|
"WaterBreathing",
|
||||||
|
"SwiftSwim",
|
||||||
|
"WaterWalking",
|
||||||
|
"Shield",
|
||||||
|
"FireShield",
|
||||||
|
"LightningShield",
|
||||||
|
"FrostShield",
|
||||||
|
"Burden",
|
||||||
|
"Feather",
|
||||||
|
"Jump",
|
||||||
|
"Levitate",
|
||||||
|
"SlowFall",
|
||||||
|
"Lock",
|
||||||
|
"Open",
|
||||||
|
"FireDamage",
|
||||||
|
"ShockDamage",
|
||||||
|
"FrostDamage",
|
||||||
|
"DrainAttribute",
|
||||||
|
"DrainHealth",
|
||||||
|
"DrainMagicka",
|
||||||
|
"DrainFatigue",
|
||||||
|
"DrainSkill",
|
||||||
|
"DamageAttribute",
|
||||||
|
"DamageHealth",
|
||||||
|
"DamageMagicka",
|
||||||
|
"DamageFatigue",
|
||||||
|
"DamageSkill",
|
||||||
|
"Poison",
|
||||||
|
"WeaknessToFire",
|
||||||
|
"WeaknessToFrost",
|
||||||
|
"WeaknessToShock",
|
||||||
|
"WeaknessToMagicka",
|
||||||
|
"WeaknessToCommonDisease",
|
||||||
|
"WeaknessToBlightDisease",
|
||||||
|
"WeaknessToCorprusDisease",
|
||||||
|
"WeaknessToPoison",
|
||||||
|
"WeaknessToNormalWeapons",
|
||||||
|
"DisintegrateWeapon",
|
||||||
|
"DisintegrateArmor",
|
||||||
|
"Invisibility",
|
||||||
|
"Chameleon",
|
||||||
|
"Light",
|
||||||
|
"Sanctuary",
|
||||||
|
"NightEye",
|
||||||
|
"Charm",
|
||||||
|
"Paralyze",
|
||||||
|
"Silence",
|
||||||
|
"Blind",
|
||||||
|
"Sound",
|
||||||
|
"CalmHumanoid",
|
||||||
|
"CalmCreature",
|
||||||
|
"FrenzyHumanoid",
|
||||||
|
"FrenzyCreature",
|
||||||
|
"DemoralizeHumanoid",
|
||||||
|
"DemoralizeCreature",
|
||||||
|
"RallyHumanoid",
|
||||||
|
"RallyCreature",
|
||||||
|
"Dispel",
|
||||||
|
"Soultrap",
|
||||||
|
"Telekinesis",
|
||||||
|
"Mark",
|
||||||
|
"Recall",
|
||||||
|
"DivineIntervention",
|
||||||
|
"AlmsiviIntervention",
|
||||||
|
"DetectAnimal",
|
||||||
|
"DetectEnchantment",
|
||||||
|
"DetectKey",
|
||||||
|
"SpellAbsorption",
|
||||||
|
"Reflect",
|
||||||
|
"CureCommonDisease",
|
||||||
|
"CureBlightDisease",
|
||||||
|
"CureCorprusDisease",
|
||||||
|
"CurePoison",
|
||||||
|
"CureParalyzation",
|
||||||
|
"RestoreAttribute",
|
||||||
|
"RestoreHealth",
|
||||||
|
"RestoreMagicka",
|
||||||
|
"RestoreFatigue",
|
||||||
|
"RestoreSkill",
|
||||||
|
"FortifyAttribute",
|
||||||
|
"FortifyHealth",
|
||||||
|
"FortifyMagicka",
|
||||||
|
"FortifyFatigue",
|
||||||
|
"FortifySkill",
|
||||||
|
"FortifyMaximumMagicka",
|
||||||
|
"AbsorbAttribute",
|
||||||
|
"AbsorbHealth",
|
||||||
|
"AbsorbMagicka",
|
||||||
|
"AbsorbFatigue",
|
||||||
|
"AbsorbSkill",
|
||||||
|
"ResistFire",
|
||||||
|
"ResistFrost",
|
||||||
|
"ResistShock",
|
||||||
|
"ResistMagicka",
|
||||||
|
"ResistCommonDisease",
|
||||||
|
"ResistBlightDisease",
|
||||||
|
"ResistCorprusDisease",
|
||||||
|
"ResistPoison",
|
||||||
|
"ResistNormalWeapons",
|
||||||
|
"ResistParalysis",
|
||||||
|
"RemoveCurse",
|
||||||
|
"TurnUndead",
|
||||||
|
"SummonScamp",
|
||||||
|
"SummonClannfear",
|
||||||
|
"SummonDaedroth",
|
||||||
|
"SummonDremora",
|
||||||
|
"SummonAncestralGhost",
|
||||||
|
"SummonSkeletalMinion",
|
||||||
|
"SummonBonewalker",
|
||||||
|
"SummonGreaterBonewalker",
|
||||||
|
"SummonBonelord",
|
||||||
|
"SummonWingedTwilight",
|
||||||
|
"SummonHunger",
|
||||||
|
"SummonGoldenSaint",
|
||||||
|
"SummonFlameAtronach",
|
||||||
|
"SummonFrostAtronach",
|
||||||
|
"SummonStormAtronach",
|
||||||
|
"FortifyAttack",
|
||||||
|
"CommandCreature",
|
||||||
|
"CommandHumanoid",
|
||||||
|
"BoundDagger",
|
||||||
|
"BoundLongsword",
|
||||||
|
"BoundMace",
|
||||||
|
"BoundBattleAxe",
|
||||||
|
"BoundSpear",
|
||||||
|
"BoundLongbow",
|
||||||
|
"ExtraSpell",
|
||||||
|
"BoundCuirass",
|
||||||
|
"BoundHelm",
|
||||||
|
"BoundBoots",
|
||||||
|
"BoundShield",
|
||||||
|
"BoundGloves",
|
||||||
|
"Corprus",
|
||||||
|
"Vampirism",
|
||||||
|
"SummonCenturionSphere",
|
||||||
|
"SunDamage",
|
||||||
|
"StuntedMagicka",
|
||||||
|
|
||||||
|
// tribunal
|
||||||
|
"SummonFabricant",
|
||||||
|
|
||||||
|
// bloodmoon
|
||||||
|
"SummonWolf",
|
||||||
|
"SummonBear",
|
||||||
|
"SummonBonewolf",
|
||||||
|
"SummonCreature04",
|
||||||
|
"SummonCreature05",
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Collection>
|
||||||
|
static std::map<std::string_view, int, Misc::StringUtils::CiComp> initStringToIntMap(const Collection& strings)
|
||||||
{
|
{
|
||||||
std::map<short, std::string>::const_iterator name = sNames.find(effectID);
|
std::map<std::string_view, int, Misc::StringUtils::CiComp> map;
|
||||||
if (name == sNames.end())
|
for (size_t i = 0; i < strings.size(); i++)
|
||||||
throw std::runtime_error(std::string("Unimplemented effect ID ") + std::to_string(effectID));
|
map[strings[i]] = i;
|
||||||
|
|
||||||
return name->second;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::map<std::string_view, int, Misc::StringUtils::CiComp> MagicEffect::sGmstEffectIdToIndexMap
|
||||||
|
= initStringToIntMap(MagicEffect::sGmstEffectIds);
|
||||||
|
|
||||||
|
const std::map<std::string_view, int, Misc::StringUtils::CiComp> MagicEffect::sIndexNameToIndexMap
|
||||||
|
= initStringToIntMap(MagicEffect::sIndexNames);
|
||||||
|
|
||||||
class FindSecond
|
class FindSecond
|
||||||
{
|
{
|
||||||
std::string_view mName;
|
std::string_view mName;
|
||||||
|
@ -535,17 +538,6 @@ namespace ESM
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
short MagicEffect::effectStringToId(std::string_view effect)
|
|
||||||
{
|
|
||||||
std::map<short, std::string>::const_iterator name;
|
|
||||||
|
|
||||||
name = std::find_if(sNames.begin(), sNames.end(), FindSecond(effect));
|
|
||||||
if (name == sNames.end())
|
|
||||||
throw std::runtime_error("Unimplemented effect " + std::string(effect));
|
|
||||||
|
|
||||||
return name->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
MagicEffect::MagnitudeDisplayType MagicEffect::getMagnitudeDisplayType() const
|
MagicEffect::MagnitudeDisplayType MagicEffect::getMagnitudeDisplayType() const
|
||||||
{
|
{
|
||||||
if (mData.mFlags & NoMagnitude)
|
if (mData.mFlags & NoMagnitude)
|
||||||
|
@ -587,6 +579,40 @@ namespace ESM
|
||||||
mDescription.clear();
|
mDescription.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& MagicEffect::indexToGmstString(int effectID)
|
||||||
|
{
|
||||||
|
if (effectID < 0 || static_cast<std::size_t>(effectID) >= sGmstEffectIds.size())
|
||||||
|
throw std::runtime_error(std::string("Unimplemented effect ID ") + std::to_string(effectID));
|
||||||
|
|
||||||
|
return sGmstEffectIds[effectID];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view MagicEffect::indexToName(int effectID)
|
||||||
|
{
|
||||||
|
if (effectID < 0 || static_cast<std::size_t>(effectID) >= sIndexNames.size())
|
||||||
|
throw std::runtime_error(std::string("Unimplemented effect ID ") + std::to_string(effectID));
|
||||||
|
|
||||||
|
return sIndexNames[effectID];
|
||||||
|
}
|
||||||
|
|
||||||
|
int MagicEffect::indexNameToIndex(std::string_view effect)
|
||||||
|
{
|
||||||
|
auto name = sIndexNameToIndexMap.find(effect);
|
||||||
|
if (name == sIndexNameToIndexMap.end())
|
||||||
|
throw std::runtime_error("Unimplemented effect " + std::string(effect));
|
||||||
|
|
||||||
|
return name->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MagicEffect::effectGmstIdToIndex(std::string_view gmstId)
|
||||||
|
{
|
||||||
|
auto name = sGmstEffectIdToIndexMap.find(gmstId);
|
||||||
|
if (name == sGmstEffectIdToIndexMap.end())
|
||||||
|
throw std::runtime_error("Unimplemented effect " + std::string(gmstId));
|
||||||
|
|
||||||
|
return name->second;
|
||||||
|
}
|
||||||
|
|
||||||
RefId MagicEffect::indexToRefId(int index)
|
RefId MagicEffect::indexToRefId(int index)
|
||||||
{
|
{
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
#ifndef OPENMW_ESM_MGEF_H
|
#ifndef OPENMW_ESM_MGEF_H
|
||||||
#define OPENMW_ESM_MGEF_H
|
#define OPENMW_ESM_MGEF_H
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "components/esm/defs.hpp"
|
#include "components/esm/defs.hpp"
|
||||||
#include "components/esm/refid.hpp"
|
#include "components/esm/refid.hpp"
|
||||||
|
#include "components/misc/strings/algorithm.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -79,11 +81,6 @@ namespace ESM
|
||||||
float mUnknown2; // Called "Size Cap" in CS
|
float mUnknown2; // Called "Size Cap" in CS
|
||||||
}; // 36 bytes
|
}; // 36 bytes
|
||||||
|
|
||||||
static const std::map<short, std::string> sNames;
|
|
||||||
|
|
||||||
static const std::string& effectIdToString(short effectID);
|
|
||||||
static short effectStringToId(std::string_view effect);
|
|
||||||
|
|
||||||
/// Returns the effect that provides resistance against \a effect (or -1 if there's none)
|
/// Returns the effect that provides resistance against \a effect (or -1 if there's none)
|
||||||
static short getResistanceEffect(short effect);
|
static short getResistanceEffect(short effect);
|
||||||
/// Returns the effect that induces weakness against \a effect (or -1 if there's none)
|
/// Returns the effect that induces weakness against \a effect (or -1 if there's none)
|
||||||
|
@ -269,7 +266,15 @@ namespace ESM
|
||||||
Length
|
Length
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::string_view sIndexNames[MagicEffect::Length];
|
static const std::array<std::string, Length> sGmstEffectIds;
|
||||||
|
static const std::array<std::string_view, Length> sIndexNames;
|
||||||
|
static const std::map<std::string_view, int, Misc::StringUtils::CiComp> sGmstEffectIdToIndexMap;
|
||||||
|
static const std::map<std::string_view, int, Misc::StringUtils::CiComp> sIndexNameToIndexMap;
|
||||||
|
|
||||||
|
static const std::string& indexToGmstString(int effectID);
|
||||||
|
static std::string_view indexToName(int effectID);
|
||||||
|
static int indexNameToIndex(std::string_view effect);
|
||||||
|
static int effectGmstIdToIndex(std::string_view gmstId);
|
||||||
|
|
||||||
static RefId indexToRefId(int index);
|
static RefId indexToRefId(int index);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
|
#include <components/misc/strings/algorithm.hpp>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
const std::string Skill::sSkillNames[Length] = {
|
const std::string Skill::sSkillNames[Length] = {
|
||||||
|
@ -97,6 +99,15 @@ namespace ESM
|
||||||
Destruction, Alteration, Illusion, Conjuration, Mysticism, Restoration, Alchemy, Unarmored, Security, Sneak,
|
Destruction, Alteration, Illusion, Conjuration, Mysticism, Restoration, Alchemy, Unarmored, Security, Sneak,
|
||||||
Acrobatics, LightArmor, ShortBlade, Marksman, Mercantile, Speechcraft, HandToHand } };
|
Acrobatics, LightArmor, ShortBlade, Marksman, Mercantile, Speechcraft, HandToHand } };
|
||||||
|
|
||||||
|
Skill::SkillEnum Skill::stringToSkillId(std::string_view skill)
|
||||||
|
{
|
||||||
|
for (auto id : sSkillIds)
|
||||||
|
if (Misc::StringUtils::ciEqual(sSkillNames[id], skill))
|
||||||
|
return id;
|
||||||
|
|
||||||
|
throw std::logic_error("No such skill: " + std::string(skill));
|
||||||
|
}
|
||||||
|
|
||||||
void Skill::load(ESMReader& esm, bool& isDeleted)
|
void Skill::load(ESMReader& esm, bool& isDeleted)
|
||||||
{
|
{
|
||||||
isDeleted = false; // Skill record can't be deleted now (may be changed in the future)
|
isDeleted = false; // Skill record can't be deleted now (may be changed in the future)
|
||||||
|
|
|
@ -81,6 +81,8 @@ namespace ESM
|
||||||
static const std::string sIconNames[Length];
|
static const std::string sIconNames[Length];
|
||||||
static const std::array<SkillEnum, Length> sSkillIds;
|
static const std::array<SkillEnum, Length> sSkillIds;
|
||||||
|
|
||||||
|
static SkillEnum stringToSkillId(std::string_view skill);
|
||||||
|
|
||||||
void load(ESMReader& esm, bool& isDeleted);
|
void load(ESMReader& esm, bool& isDeleted);
|
||||||
void save(ESMWriter& esm, bool isDeleted = false) const;
|
void save(ESMWriter& esm, bool isDeleted = false) const;
|
||||||
|
|
||||||
|
|
|
@ -383,6 +383,156 @@
|
||||||
-- @field #number Restoration Restoration
|
-- @field #number Restoration Restoration
|
||||||
|
|
||||||
|
|
||||||
|
--- Possible @{#MagicEffectId} values
|
||||||
|
-- @field [parent=#Magic] #MagicEffectId EFFECT_TYPE
|
||||||
|
|
||||||
|
--- `core.magic.EFFECT_TYPE`
|
||||||
|
-- @type MagicEffectId
|
||||||
|
-- @field #number WaterBreathing "waterbreathing"
|
||||||
|
-- @field #number SwiftSwim "swiftswim"
|
||||||
|
-- @field #number WaterWalking "waterwalking"
|
||||||
|
-- @field #number Shield "shield"
|
||||||
|
-- @field #number FireShield "fireshield"
|
||||||
|
-- @field #number LightningShield "lightningshield"
|
||||||
|
-- @field #number FrostShield "frostshield"
|
||||||
|
-- @field #number Burden "burden"
|
||||||
|
-- @field #number Feather "feather"
|
||||||
|
-- @field #number Jump "jump"
|
||||||
|
-- @field #number Levitate "levitate"
|
||||||
|
-- @field #number SlowFall "slowfall"
|
||||||
|
-- @field #number Lock "lock"
|
||||||
|
-- @field #number Open "open"
|
||||||
|
-- @field #number FireDamage "firedamage"
|
||||||
|
-- @field #number ShockDamage "shockdamage"
|
||||||
|
-- @field #number FrostDamage "frostdamage"
|
||||||
|
-- @field #number DrainAttribute "drainattribute"
|
||||||
|
-- @field #number DrainHealth "drainhealth"
|
||||||
|
-- @field #number DrainMagicka "drainmagicka"
|
||||||
|
-- @field #number DrainFatigue "drainfatigue"
|
||||||
|
-- @field #number DrainSkill "drainskill"
|
||||||
|
-- @field #number DamageAttribute "damageattribute"
|
||||||
|
-- @field #number DamageHealth "damagehealth"
|
||||||
|
-- @field #number DamageMagicka "damagemagicka"
|
||||||
|
-- @field #number DamageFatigue "damagefatigue"
|
||||||
|
-- @field #number DamageSkill "damageskill"
|
||||||
|
-- @field #number Poison "poison"
|
||||||
|
-- @field #number WeaknessToFire "weaknesstofire"
|
||||||
|
-- @field #number WeaknessToFrost "weaknesstofrost"
|
||||||
|
-- @field #number WeaknessToShock "weaknesstoshock"
|
||||||
|
-- @field #number WeaknessToMagicka "weaknesstomagicka"
|
||||||
|
-- @field #number WeaknessToCommonDisease "weaknesstocommondisease"
|
||||||
|
-- @field #number WeaknessToBlightDisease "weaknesstoblightdisease"
|
||||||
|
-- @field #number WeaknessToCorprusDisease "weaknesstocorprusdisease"
|
||||||
|
-- @field #number WeaknessToPoison "weaknesstopoison"
|
||||||
|
-- @field #number WeaknessToNormalWeapons "weaknesstonormalweapons"
|
||||||
|
-- @field #number DisintegrateWeapon "disintegrateweapon"
|
||||||
|
-- @field #number DisintegrateArmor "disintegratearmor"
|
||||||
|
-- @field #number Invisibility "invisibility"
|
||||||
|
-- @field #number Chameleon "chameleon"
|
||||||
|
-- @field #number Light "light"
|
||||||
|
-- @field #number Sanctuary "sanctuary"
|
||||||
|
-- @field #number NightEye "nighteye"
|
||||||
|
-- @field #number Charm "charm"
|
||||||
|
-- @field #number Paralyze "paralyze"
|
||||||
|
-- @field #number Silence "silence"
|
||||||
|
-- @field #number Blind "blind"
|
||||||
|
-- @field #number Sound "sound"
|
||||||
|
-- @field #number CalmHumanoid "calmhumanoid"
|
||||||
|
-- @field #number CalmCreature "calmcreature"
|
||||||
|
-- @field #number FrenzyHumanoid "frenzyhumanoid"
|
||||||
|
-- @field #number FrenzyCreature "frenzycreature"
|
||||||
|
-- @field #number DemoralizeHumanoid "demoralizehumanoid"
|
||||||
|
-- @field #number DemoralizeCreature "demoralizecreature"
|
||||||
|
-- @field #number RallyHumanoid "rallyhumanoid"
|
||||||
|
-- @field #number RallyCreature "rallycreature"
|
||||||
|
-- @field #number Dispel "dispel"
|
||||||
|
-- @field #number Soultrap "soultrap"
|
||||||
|
-- @field #number Telekinesis "telekinesis"
|
||||||
|
-- @field #number Mark "mark"
|
||||||
|
-- @field #number Recall "recall"
|
||||||
|
-- @field #number DivineIntervention "divineintervention"
|
||||||
|
-- @field #number AlmsiviIntervention "almsiviintervention"
|
||||||
|
-- @field #number DetectAnimal "detectanimal"
|
||||||
|
-- @field #number DetectEnchantment "detectenchantment"
|
||||||
|
-- @field #number DetectKey "detectkey"
|
||||||
|
-- @field #number SpellAbsorption "spellabsorption"
|
||||||
|
-- @field #number Reflect "reflect"
|
||||||
|
-- @field #number CureCommonDisease "curecommondisease"
|
||||||
|
-- @field #number CureBlightDisease "cureblightdisease"
|
||||||
|
-- @field #number CureCorprusDisease "curecorprusdisease"
|
||||||
|
-- @field #number CurePoison "curepoison"
|
||||||
|
-- @field #number CureParalyzation "cureparalyzation"
|
||||||
|
-- @field #number RestoreAttribute "restoreattribute"
|
||||||
|
-- @field #number RestoreHealth "restorehealth"
|
||||||
|
-- @field #number RestoreMagicka "restoremagicka"
|
||||||
|
-- @field #number RestoreFatigue "restorefatigue"
|
||||||
|
-- @field #number RestoreSkill "restoreskill"
|
||||||
|
-- @field #number FortifyAttribute "fortifyattribute"
|
||||||
|
-- @field #number FortifyHealth "fortifyhealth"
|
||||||
|
-- @field #number FortifyMagicka "fortifymagicka"
|
||||||
|
-- @field #number FortifyFatigue "fortifyfatigue"
|
||||||
|
-- @field #number FortifySkill "fortifyskill"
|
||||||
|
-- @field #number FortifyMaximumMagicka "fortifymaximummagicka"
|
||||||
|
-- @field #number AbsorbAttribute "absorbattribute"
|
||||||
|
-- @field #number AbsorbHealth "absorbhealth"
|
||||||
|
-- @field #number AbsorbMagicka "absorbmagicka"
|
||||||
|
-- @field #number AbsorbFatigue "absorbfatigue"
|
||||||
|
-- @field #number AbsorbSkill "absorbskill"
|
||||||
|
-- @field #number ResistFire "resistfire"
|
||||||
|
-- @field #number ResistFrost "resistfrost"
|
||||||
|
-- @field #number ResistShock "resistshock"
|
||||||
|
-- @field #number ResistMagicka "resistmagicka"
|
||||||
|
-- @field #number ResistCommonDisease "resistcommondisease"
|
||||||
|
-- @field #number ResistBlightDisease "resistblightdisease"
|
||||||
|
-- @field #number ResistCorprusDisease "resistcorprusdisease"
|
||||||
|
-- @field #number ResistPoison "resistpoison"
|
||||||
|
-- @field #number ResistNormalWeapons "resistnormalweapons"
|
||||||
|
-- @field #number ResistParalysis "resistparalysis"
|
||||||
|
-- @field #number RemoveCurse "removecurse"
|
||||||
|
-- @field #number TurnUndead "turnundead"
|
||||||
|
-- @field #number SummonScamp "summonscamp"
|
||||||
|
-- @field #number SummonClannfear "summonclannfear"
|
||||||
|
-- @field #number SummonDaedroth "summondaedroth"
|
||||||
|
-- @field #number SummonDremora "summondremora"
|
||||||
|
-- @field #number SummonAncestralGhost "summonancestralghost"
|
||||||
|
-- @field #number SummonSkeletalMinion "summonskeletalminion"
|
||||||
|
-- @field #number SummonBonewalker "summonbonewalker"
|
||||||
|
-- @field #number SummonGreaterBonewalker "summongreaterbonewalker"
|
||||||
|
-- @field #number SummonBonelord "summonbonelord"
|
||||||
|
-- @field #number SummonWingedTwilight "summonwingedtwilight"
|
||||||
|
-- @field #number SummonHunger "summonhunger"
|
||||||
|
-- @field #number SummonGoldenSaint "summongoldensaint"
|
||||||
|
-- @field #number SummonFlameAtronach "summonflameatronach"
|
||||||
|
-- @field #number SummonFrostAtronach "summonfrostatronach"
|
||||||
|
-- @field #number SummonStormAtronach "summonstormatronach"
|
||||||
|
-- @field #number FortifyAttack "fortifyattack"
|
||||||
|
-- @field #number CommandCreature "commandcreature"
|
||||||
|
-- @field #number CommandHumanoid "commandhumanoid"
|
||||||
|
-- @field #number BoundDagger "bounddagger"
|
||||||
|
-- @field #number BoundLongsword "boundlongsword"
|
||||||
|
-- @field #number BoundMace "boundmace"
|
||||||
|
-- @field #number BoundBattleAxe "boundbattleaxe"
|
||||||
|
-- @field #number BoundSpear "boundspear"
|
||||||
|
-- @field #number BoundLongbow "boundlongbow"
|
||||||
|
-- @field #number ExtraSpell "extraspell"
|
||||||
|
-- @field #number BoundCuirass "boundcuirass"
|
||||||
|
-- @field #number BoundHelm "boundhelm"
|
||||||
|
-- @field #number BoundBoots "boundboots"
|
||||||
|
-- @field #number BoundShield "boundshield"
|
||||||
|
-- @field #number BoundGloves "boundgloves"
|
||||||
|
-- @field #number Corprus "corprus"
|
||||||
|
-- @field #number Vampirism "vampirism"
|
||||||
|
-- @field #number SummonCenturionSphere "summoncenturionsphere"
|
||||||
|
-- @field #number SunDamage "sundamage"
|
||||||
|
-- @field #number StuntedMagicka "stuntedmagicka"
|
||||||
|
-- @field #number SummonFabricant "summonfabricant"
|
||||||
|
-- @field #number SummonWolf "summonwolf"
|
||||||
|
-- @field #number SummonBear "summonbear"
|
||||||
|
-- @field #number SummonBonewolf "summonbonewolf"
|
||||||
|
-- @field #number SummonCreature04 "summoncreature04"
|
||||||
|
-- @field #number SummonCreature05 "summoncreature05"
|
||||||
|
|
||||||
|
|
||||||
--- Possible @{#SpellType} values
|
--- Possible @{#SpellType} values
|
||||||
-- @field [parent=#Magic] #SpellType SPELL_TYPE
|
-- @field [parent=#Magic] #SpellType SPELL_TYPE
|
||||||
|
|
||||||
|
@ -407,7 +557,7 @@
|
||||||
-- end
|
-- end
|
||||||
-- end
|
-- end
|
||||||
|
|
||||||
--- Map from effectId to @{#SpellEffect}
|
--- Map from @{#MagicEffectId} to @{#MagicEffect}
|
||||||
-- @field [parent=#Magic] #map<#number, #MagicEffect> effects
|
-- @field [parent=#Magic] #map<#number, #MagicEffect> effects
|
||||||
-- @usage -- Print all harmful effects
|
-- @usage -- Print all harmful effects
|
||||||
-- for _, effect in pairs(core.magic.effects) do
|
-- for _, effect in pairs(core.magic.effects) do
|
||||||
|
@ -426,8 +576,8 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @type MagicEffect
|
-- @type MagicEffect
|
||||||
-- @field #number id
|
-- @field #string Effect id string
|
||||||
-- @field #string name
|
-- @field #string name Localized name of the effect
|
||||||
-- @field #number school @{#MagicSchool}
|
-- @field #number school @{#MagicSchool}
|
||||||
-- @field #number baseCost
|
-- @field #number baseCost
|
||||||
-- @field openmw.util#Color color
|
-- @field openmw.util#Color color
|
||||||
|
@ -443,5 +593,15 @@
|
||||||
-- @field #number magnitudeMin
|
-- @field #number magnitudeMin
|
||||||
-- @field #number magnitudeMax
|
-- @field #number magnitudeMax
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @type ActiveEffect
|
||||||
|
-- @field #ActiveEffect effect @{#ActiveEffect}
|
||||||
|
-- @field #any affectedSkill @{#SKILL} or nil
|
||||||
|
-- @field #any affectedAttribute @{#ATTRIBUTE} or nil
|
||||||
|
-- @field #string id Effect id string
|
||||||
|
-- @field #string name Localized name of the effect
|
||||||
|
-- @field #number magnitude
|
||||||
|
-- @field #number magnitudeBase
|
||||||
|
-- @field #number magnitudeModifier
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -162,7 +162,68 @@
|
||||||
-- @param openmw.core#Spell spell Spell (can be nil)
|
-- @param openmw.core#Spell spell Spell (can be nil)
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Return the spells (@{ActorSpells}) of the given actor.
|
-- Return the active magic effects (@{#ActorActiveEffects}) currently affecting the given actor.
|
||||||
|
-- @function [parent=#Actor] activeEffects
|
||||||
|
-- @param openmw.core#GameObject actor
|
||||||
|
-- @return #ActorActiveEffects
|
||||||
|
|
||||||
|
--- Read-only list of effects currently affecting the actor.
|
||||||
|
-- @type ActorActiveEffects
|
||||||
|
-- @usage -- print active effects
|
||||||
|
-- for _, effect in pairs(Actor.activeEffects(self)) do
|
||||||
|
-- print('Active Effect: '..effect.id..', attribute='..tostring(effect.affectedAttribute)..', skill='..tostring(effect.affectedSkill)..', magnitude='..tostring(effect.magnitude))
|
||||||
|
-- end
|
||||||
|
-- @usage -- Check for a specific effect
|
||||||
|
-- local effect = Actor.activeEffects(self):getEffect(core.magic.EFFECT_TYPE.Telekinesis)
|
||||||
|
-- if effect then
|
||||||
|
-- print(effect.id..', attribute='..tostring(effect.affectedAttribute)..', skill='..tostring(effect.affectedSkill)..', magnitude='..tostring(effect.magnitude))
|
||||||
|
-- else
|
||||||
|
-- print('No Telekinesis effect')
|
||||||
|
-- end
|
||||||
|
-- @usage -- Check for a specific effect targeting a specific attribute.
|
||||||
|
-- local effect = Actor.activeEffects(self):getEffect(core.magic.EFFECT_TYPE.FortifyAttribute, core.ATTRIBUTE.Luck)
|
||||||
|
-- if effect then
|
||||||
|
-- print(effect.id..', attribute='..tostring(effect.affectedAttribute)..', skill='..tostring(effect.affectedSkill)..', magnitude='..tostring(effect.magnitude))
|
||||||
|
-- else
|
||||||
|
-- print('No Fortify Luck effect')
|
||||||
|
-- end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Get a specific active effect on the actor.
|
||||||
|
-- @function [parent=#ActorActiveEffects] getEffect
|
||||||
|
-- @param self
|
||||||
|
-- @param string effect ID
|
||||||
|
-- @param string Optional skill or attribute ID
|
||||||
|
-- @return #ActiveEffect if such an effect is active, nil otherwise
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Return the active spells (@{#ActorActiveSpells}) currently affecting the given actor.
|
||||||
|
-- @function [parent=#Actor] activeSpells
|
||||||
|
-- @param openmw.core#GameObject actor
|
||||||
|
-- @return #ActorActiveSpells
|
||||||
|
|
||||||
|
--- Read-only list of spells currently affecting the actor.
|
||||||
|
-- @type ActorActiveSpells
|
||||||
|
-- @usage -- print active spells
|
||||||
|
-- for _, spell in pairs(Actor.activeSpells(self)) do
|
||||||
|
-- print('Active Spell: '..tostring(spell))
|
||||||
|
-- end
|
||||||
|
-- @usage -- Check for a specific spell
|
||||||
|
-- if Actor.activeSpells(self):isSpellActive('bound longbow') then
|
||||||
|
-- print('Player has bound longbow')
|
||||||
|
-- else
|
||||||
|
-- print('Player does not have bound longbow')
|
||||||
|
-- end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Get whether a specific spell is active on the actor.
|
||||||
|
-- @function [parent=#ActorActiveSpells] isSpellActive
|
||||||
|
-- @param self
|
||||||
|
-- @param #any spellOrId @{openmw.core#Spell} or string spell id
|
||||||
|
-- @return true if spell is active, false otherwise
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Return the spells (@{#ActorSpells}) of the given actor.
|
||||||
-- @function [parent=#Actor] spells
|
-- @function [parent=#Actor] spells
|
||||||
-- @param openmw.core#GameObject actor
|
-- @param openmw.core#GameObject actor
|
||||||
-- @return #ActorSpells
|
-- @return #ActorSpells
|
||||||
|
|
Loading…
Reference in a new issue