1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-19 18:09:50 +00:00

Merge branch 'ingredients'

This commit is contained in:
Marc Zinnschlag 2012-09-13 13:31:46 +02:00
commit 835c530e06
14 changed files with 487 additions and 262 deletions

View file

@ -51,7 +51,7 @@ add_openmw_dir (mwworld
refdata worldimp physicssystem scene globals class action nullaction actionteleport
containerstore actiontalk actiontake manualref player cellfunctors
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply
actionequip timestamp actionalchemy cellstore actionapply actioneat
)
add_openmw_dir (mwclass

View file

@ -11,6 +11,7 @@
#include "../mwworld/actiontake.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/actioneat.hpp"
#include "../mwgui/tooltips.hpp"
@ -19,6 +20,14 @@
namespace MWClass
{
std::string Ingredient::getId (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Ingredient> *ref =
ptr.get<ESM::Ingredient>();
return ref->base->mId;
}
void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
const std::string model = getModel(ptr);
@ -84,6 +93,16 @@ namespace MWClass
return ref->base->data.value;
}
boost::shared_ptr<MWWorld::Action> Ingredient::use (const MWWorld::Ptr& ptr) const
{
boost::shared_ptr<MWWorld::Action> action (new MWWorld::ActionEat (ptr));
action->setSound ("Swallow");
return action;
}
void Ingredient::registerSelf()
{
boost::shared_ptr<Class> instance (new Ingredient);

View file

@ -12,6 +12,9 @@ namespace MWClass
public:
virtual std::string getId (const MWWorld::Ptr& ptr) const;
///< Return ID of \a ptr
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
@ -37,6 +40,10 @@ namespace MWClass
virtual int getValue (const MWWorld::Ptr& ptr) const;
///< Return trade value of the object. Throws an exception, if the object can't be traded.
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const;

View file

@ -365,7 +365,7 @@ namespace MWClass
/// \todo consider instant effects
return stats.getActiveSpells().addSpell (id);
return stats.getActiveSpells().addSpell (id, actor);
}
void Npc::skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType) const

View file

@ -5,12 +5,20 @@
#include <components/esm/loadalch.hpp>
#include <components/esm/loadspel.hpp>
#include <components/esm/loadingr.hpp>
#include <components/esm/loadmgef.hpp>
#include <components/esm/loadskil.hpp>
#include <components/esm_store/store.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp"
#include "creaturestats.hpp"
#include "npcstats.hpp"
namespace MWMechanics
{
void ActiveSpells::update() const
@ -41,47 +49,102 @@ namespace MWMechanics
}
if (rebuild)
rebuildEffects();
}
void ActiveSpells::rebuildEffects() const
{
MWWorld::TimeStamp now = MWBase::Environment::get().getWorld()->getTimeStamp();
mEffects = MagicEffects();
for (TIterator iter (begin()); iter!=end(); ++iter)
{
mEffects = MagicEffects();
std::pair<ESM::EffectList, bool> effects = getEffectList (iter->first);
for (TIterator iter (begin()); iter!=end(); ++iter)
const MWWorld::TimeStamp& start = iter->second.first;
float magnitude = iter->second.second;
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.first.list.begin());
iter!=effects.first.list.end(); ++iter)
{
const ESM::EffectList& effects = getEffectList (iter->first);
const MWWorld::TimeStamp& start = iter->second.first;
float magnitude = iter->second.second;
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.list.begin());
iter!=effects.list.end(); ++iter)
if (iter->duration)
{
if (iter->duration)
{
MWWorld::TimeStamp end = start;
end += static_cast<double> (iter->duration)*
MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60);
int duration = iter->duration;
if (effects.second)
duration *= magnitude;
MWWorld::TimeStamp end = start;
end += static_cast<double> (duration)*
MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60);
if (end>now)
if (end>now)
{
EffectParam param;
if (effects.second)
{
EffectParam param;
param.mMagnitude = static_cast<int> (
(iter->magnMax-iter->magnMin+1)*magnitude + iter->magnMin);
mEffects.add (*iter, param);
const ESM::MagicEffect *magicEffect =
MWBase::Environment::get().getWorld()->getStore().magicEffects.find (
iter->effectID);
if (iter->duration==0)
{
param.mMagnitude =
static_cast<int> (magnitude / (0.1 * magicEffect->data.baseCost));
}
else
{
param.mMagnitude =
static_cast<int> (0.05*magnitude / (0.1 * magicEffect->data.baseCost));
}
}
else
param.mMagnitude = static_cast<int> (
(iter->magnMax-iter->magnMin)*magnitude + iter->magnMin);
mEffects.add (*iter, param);
}
}
}
}
}
}
const ESM::EffectList& ActiveSpells::getEffectList (const std::string& id) const
std::pair<ESM::EffectList, bool> ActiveSpells::getEffectList (const std::string& id) const
{
if (const ESM::Spell *spell =
MWBase::Environment::get().getWorld()->getStore().spells.search (id))
return spell->effects;
return std::make_pair (spell->effects, false);
if (const ESM::Potion *potion =
MWBase::Environment::get().getWorld()->getStore().potions.search (id))
return potion->effects;
return std::make_pair (potion->effects, false);
if (const ESM::Ingredient *ingredient =
MWBase::Environment::get().getWorld()->getStore().ingreds.search (id))
{
const ESM::MagicEffect *magicEffect =
MWBase::Environment::get().getWorld()->getStore().magicEffects.find (
ingredient->data.effectID[0]);
ESM::ENAMstruct effect;
effect.effectID = ingredient->data.effectID[0];
effect.skill = ingredient->data.skills[0];
effect.attribute = ingredient->data.attributes[0];
effect.range = 0;
effect.area = 0;
effect.duration = magicEffect->data.flags & ESM::MagicEffect::NoDuration ? 0 : 1;
effect.magnMin = 1;
effect.magnMax = 1;
std::pair<ESM::EffectList, bool> result;
result.first.list.push_back (effect);
result.second = true;
return result;
}
throw std::runtime_error ("ID " + id + " can not produce lasting effects");
}
@ -90,14 +153,14 @@ namespace MWMechanics
: mSpellsChanged (false), mLastUpdate (MWBase::Environment::get().getWorld()->getTimeStamp())
{}
bool ActiveSpells::addSpell (const std::string& id)
bool ActiveSpells::addSpell (const std::string& id, const MWWorld::Ptr& actor)
{
const ESM::EffectList& effects = getEffectList (id);
std::pair<ESM::EffectList, bool> effects = getEffectList (id);
bool found = false;
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.list.begin());
iter!=effects.list.end(); ++iter)
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.first.list.begin());
iter!=effects.first.list.end(); ++iter)
{
if (iter->duration)
{
@ -113,6 +176,22 @@ namespace MWMechanics
float random = static_cast<float> (std::rand()) / RAND_MAX;
if (effects.second)
{
// ingredient -> special treatment required.
const CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor);
const NpcStats& npcStats = MWWorld::Class::get (actor).getNpcStats (actor);
float x =
(npcStats.getSkill (ESM::Skill::Alchemy).getModified() +
0.2 * creatureStats.getAttribute (1).getModified()
+ 0.1 * creatureStats.getAttribute (7).getModified())
* creatureStats.getFatigueTerm();
random *= 100;
random = random / std::min (x, 100.0f);
random *= 0.25 * x;
}
if (iter==mSpells.end())
mSpells.insert (std::make_pair (id,
std::make_pair (MWBase::Environment::get().getWorld()->getTimeStamp(), random)));
@ -155,17 +234,20 @@ namespace MWMechanics
double ActiveSpells::timeToExpire (const TIterator& iterator) const
{
const ESM::EffectList& effects = getEffectList (iterator->first);
std::pair<ESM::EffectList, bool> effects = getEffectList (iterator->first);
int duration = 0;
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.list.begin());
iter!=effects.list.end(); ++iter)
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.first.list.begin());
iter!=effects.first.list.end(); ++iter)
{
if (iter->duration>duration)
duration = iter->duration;
}
if (effects.second)
duration *= iterator->second.second;
double scaledDuration = duration *
MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60);

View file

@ -15,6 +15,11 @@ namespace ESM
struct EffectList;
}
namespace MWWorld
{
class Ptr;
}
namespace MWMechanics
{
/// \brief Lasting spell effects
@ -36,14 +41,16 @@ namespace MWMechanics
mutable MWWorld::TimeStamp mLastUpdate;
void update() const;
void rebuildEffects() const;
const ESM::EffectList& getEffectList (const std::string& id) const;
std::pair<ESM::EffectList, bool> getEffectList (const std::string& id) const;
public:
ActiveSpells();
bool addSpell (const std::string& id);
bool addSpell (const std::string& id, const MWWorld::Ptr& actor);
///< Overwrites an existing spell with the same ID. If the spell does not have any
/// non-instant effects, it is ignored.
///

View file

@ -1,51 +1,14 @@
#include "creaturestats.hpp"
#include <algorithm>
#include <components/esm_store/store.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace MWMechanics
{
CreatureStats::CreatureStats()
{}
// Can't use all benefits of members initialization because of
// lack of copy constructors
CreatureStats::CreatureStats(const CreatureStats &orig)
: mLevel(orig.mLevel), mHello(orig.mHello), mFight(orig.mFight),
mFlee(orig.mFlee), mAlarm(orig.mAlarm)
{
for (int i = 0; i < 8; ++i) {
mAttributes[i] = orig.mAttributes[i];
}
for (int i = 0; i < 3; ++i) {
mDynamic[i] = orig.mDynamic[i];
}
mSpells = orig.mSpells;
mActiveSpells = orig.mActiveSpells;
mMagicEffects = orig.mMagicEffects;
}
CreatureStats::~CreatureStats()
{}
const CreatureStats &
CreatureStats::operator=(const CreatureStats &orig)
{
for (int i = 0; i < 8; ++i) {
mAttributes[i] = orig.mAttributes[i];
}
for (int i = 0; i < 3; ++i) {
mDynamic[i] = orig.mDynamic[i];
}
mLevel = orig.mLevel;
mSpells = orig.mSpells;
mActiveSpells = orig.mActiveSpells;
mMagicEffects = orig.mMagicEffects;
mHello = orig.mHello;
mFight = orig.mFight;
mFlee = orig.mFlee;
mAlarm = orig.mAlarm;
return *this;
}
{
const AiSequence& CreatureStats::getAiSequence() const
{
return mAiSequence;
@ -55,4 +18,189 @@ namespace MWMechanics
{
return mAiSequence;
}
float CreatureStats::getFatigueTerm() const
{
int max = getFatigue().getModified();
int current = getFatigue().getCurrent();
float normalised = max==0 ? 1 : std::max (0.0f, static_cast<float> (current)/max);
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
return store.gameSettings.find ("fFatigueBase")->getFloat()
- store.gameSettings.find ("fFatigueMult")->getFloat() * (1-normalised);
}
const Stat<int> &CreatureStats::getAttribute(int index) const
{
if (index < 0 || index > 7) {
throw std::runtime_error("attribute index is out of range");
}
return mAttributes[index];
}
const DynamicStat<int> &CreatureStats::getHealth() const
{
return mDynamic[0];
}
const DynamicStat<int> &CreatureStats::getMagicka() const
{
return mDynamic[1];
}
const DynamicStat<int> &CreatureStats::getFatigue() const
{
return mDynamic[2];
}
const Spells &CreatureStats::getSpells() const
{
return mSpells;
}
const ActiveSpells &CreatureStats::getActiveSpells() const
{
return mActiveSpells;
}
const MagicEffects &CreatureStats::getMagicEffects() const
{
return mMagicEffects;
}
int CreatureStats::getLevel() const
{
return mLevel;
}
int CreatureStats::getHello() const
{
return mHello;
}
int CreatureStats::getFight() const
{
return mFight;
}
int CreatureStats::getFlee() const
{
return mFlee;
}
int CreatureStats::getAlarm() const
{
return mAlarm;
}
Stat<int> &CreatureStats::getAttribute(int index)
{
if (index < 0 || index > 7) {
throw std::runtime_error("attribute index is out of range");
}
return mAttributes[index];
}
DynamicStat<int> &CreatureStats::getHealth()
{
return mDynamic[0];
}
DynamicStat<int> &CreatureStats::getMagicka()
{
return mDynamic[1];
}
DynamicStat<int> &CreatureStats::getFatigue()
{
return mDynamic[2];
}
DynamicStat<int> &CreatureStats::getDynamic(int index)
{
if (index < 0 || index > 2) {
throw std::runtime_error("dynamic stat index is out of range");
}
return mDynamic[index];
}
Spells &CreatureStats::getSpells()
{
return mSpells;
}
void CreatureStats::setSpells(const Spells &spells)
{
mSpells = spells;
}
ActiveSpells &CreatureStats::getActiveSpells()
{
return mActiveSpells;
}
MagicEffects &CreatureStats::getMagicEffects()
{
return mMagicEffects;
}
void CreatureStats::setAttribute(int index, const Stat<int> &value)
{
if (index < 0 || index > 7) {
throw std::runtime_error("attribute index is out of range");
}
mAttributes[index] = value;
}
void CreatureStats::setHealth(const DynamicStat<int> &value)
{
mDynamic[0] = value;
}
void CreatureStats::setMagicka(const DynamicStat<int> &value)
{
mDynamic[1] = value;
}
void CreatureStats::setFatigue(const DynamicStat<int> &value)
{
mDynamic[2] = value;
}
void CreatureStats::setLevel(int level)
{
mLevel = level;
}
void CreatureStats::setActiveSpells(const ActiveSpells &active)
{
mActiveSpells = active;
}
void CreatureStats::setMagicEffects(const MagicEffects &effects)
{
mMagicEffects = effects;
}
void CreatureStats::setHello(int value)
{
mHello = value;
}
void CreatureStats::setFight(int value)
{
mFight = value;
}
void CreatureStats::setFlee(int value)
{
mFlee = value;
}
void CreatureStats::setAlarm(int value)
{
mAlarm = value;
}
}

View file

@ -31,11 +31,6 @@ namespace MWMechanics
AiSequence mAiSequence;
public:
CreatureStats();
CreatureStats(const CreatureStats &);
virtual ~CreatureStats();
const CreatureStats & operator=(const CreatureStats &);
const Stat<int> & getAttribute(int index) const;
@ -106,185 +101,10 @@ namespace MWMechanics
const AiSequence& getAiSequence() const;
AiSequence& getAiSequence();
};
// Inline const getters
inline const Stat<int> &
CreatureStats::getAttribute(int index) const {
if (index < 0 || index > 7) {
throw std::runtime_error("attribute index is out of range");
}
return mAttributes[index];
}
inline const DynamicStat<int> &
CreatureStats::getHealth() const {
return mDynamic[0];
}
inline const DynamicStat<int> &
CreatureStats::getMagicka() const {
return mDynamic[1];
}
inline const DynamicStat<int> &
CreatureStats::getFatigue() const {
return mDynamic[2];
}
inline const Spells &
CreatureStats::getSpells() const {
return mSpells;
}
inline const ActiveSpells &
CreatureStats::getActiveSpells() const {
return mActiveSpells;
}
inline const MagicEffects &
CreatureStats::getMagicEffects() const {
return mMagicEffects;
}
inline int
CreatureStats::getLevel() const {
return mLevel;
}
inline int
CreatureStats::getHello() const {
return mHello;
}
inline int
CreatureStats::getFight() const {
return mFight;
}
inline int
CreatureStats::getFlee() const {
return mFlee;
}
inline int
CreatureStats::getAlarm() const {
return mAlarm;
}
// Inline non-const getters
inline Stat<int> &
CreatureStats::getAttribute(int index) {
if (index < 0 || index > 7) {
throw std::runtime_error("attribute index is out of range");
}
return mAttributes[index];
}
inline DynamicStat<int> &
CreatureStats::getHealth() {
return mDynamic[0];
}
inline DynamicStat<int> &
CreatureStats::getMagicka() {
return mDynamic[1];
}
inline DynamicStat<int> &
CreatureStats::getFatigue() {
return mDynamic[2];
}
inline DynamicStat<int> &
CreatureStats::getDynamic(int index) {
if (index < 0 || index > 2) {
throw std::runtime_error("dynamic stat index is out of range");
}
return mDynamic[index];
}
inline Spells &
CreatureStats::getSpells() {
return mSpells;
}
inline void
CreatureStats::setSpells(const Spells &spells) {
mSpells = spells;
}
inline ActiveSpells &
CreatureStats::getActiveSpells() {
return mActiveSpells;
}
inline MagicEffects &
CreatureStats::getMagicEffects() {
return mMagicEffects;
}
// Inline setters
inline void
CreatureStats::setAttribute(int index, const Stat<int> &value) {
if (index < 0 || index > 7) {
throw std::runtime_error("attribute index is out of range");
}
mAttributes[index] = value;
}
inline void
CreatureStats::setHealth(const DynamicStat<int> &value) {
mDynamic[0] = value;
}
inline void
CreatureStats::setMagicka(const DynamicStat<int> &value) {
mDynamic[1] = value;
}
inline void
CreatureStats::setFatigue(const DynamicStat<int> &value) {
mDynamic[2] = value;
}
inline void
CreatureStats::setLevel(int level) {
mLevel = level;
}
inline void
CreatureStats::setActiveSpells(const ActiveSpells &active) {
mActiveSpells = active;
}
inline void
CreatureStats::setMagicEffects(const MagicEffects &effects) {
mMagicEffects = effects;
}
inline void
CreatureStats::setHello(int value) {
mHello = value;
}
inline void
CreatureStats::setFight(int value) {
mFight = value;
}
inline void
CreatureStats::setFlee(int value) {
mFlee = value;
}
inline void
CreatureStats::setAlarm(int value) {
mAlarm = value;
}
float getFatigueTerm() const;
///< Return effective fatigue
};
}
#endif

View file

@ -0,0 +1,49 @@
#include "actioneat.hpp"
#include <cstdlib>
#include <components/esm/loadskil.hpp>
#include <components/esm_store/store.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "class.hpp"
namespace MWWorld
{
void ActionEat::executeImp (const Ptr& actor)
{
// remove used item
getTarget().getRefData().setCount (getTarget().getRefData().getCount()-1);
// check for success
const MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor);
MWMechanics::NpcStats& npcStats = MWWorld::Class::get (actor).getNpcStats (actor);
float x =
(npcStats.getSkill (ESM::Skill::Alchemy).getModified() +
0.2 * creatureStats.getAttribute (1).getModified()
+ 0.1 * creatureStats.getAttribute (7).getModified())
* creatureStats.getFatigueTerm();
if (x>=100*static_cast<float> (std::rand()) / RAND_MAX)
{
// apply to actor
std::string id = Class::get (getTarget()).getId (getTarget());
Class::get (actor).apply (actor, id, actor);
// we ignore the result here. Skill increases no matter if the ingredient did something or not.
// increase skill
Class::get (actor).skillUsageSucceeded (actor, ESM::Skill::Alchemy, 1);
}
}
ActionEat::ActionEat (const MWWorld::Ptr& object) : Action (false, object) {}
}

View file

@ -0,0 +1,19 @@
#ifndef GAME_MWWORLD_ACTIONEAT_H
#define GAME_MWWORLD_ACTIONEAT_H
#include "action.hpp"
#include "ptr.hpp"
namespace MWWorld
{
class ActionEat : public Action
{
virtual void executeImp (const Ptr& actor);
public:
ActionEat (const MWWorld::Ptr& object);
};
}
#endif

View file

@ -1,8 +1,15 @@
#include "loadgmst.hpp"
#include <stdexcept>
#include "defs.hpp"
namespace ESM
{
/// \todo Review GMST "fixing". Probably remove completely or at least make it optional. Its definitely not
/// working properly in its current state and I doubt it can be fixed without breaking other stuff.
// Some handy macros
#define cI(s,x) { if(id == (s)) return (i == (x)); }
#define cF(s,x) { if(id == (s)) return (f == (x)); }
@ -169,4 +176,32 @@ void GameSetting::load(ESMReader &esm)
dirty = true;
}
int GameSetting::getInt() const
{
switch (type)
{
case VT_Float: return static_cast<int> (f);
case VT_Int: return i;
default: throw std::runtime_error ("GMST " + id + " is not of a numeric type");
}
}
int GameSetting::getFloat() const
{
switch (type)
{
case VT_Float: return f;
case VT_Int: return i;
default: throw std::runtime_error ("GMST " + id + " is not of a numeric type");
}
}
std::string GameSetting::getString() const
{
if (type==VT_String)
return str;
throw std::runtime_error ("GMST " + id + " is not a string");
}
}

View file

@ -83,6 +83,15 @@ struct GameSetting
bool isDirtyBloodmoon();
void load(ESMReader &esm);
int getInt() const;
///< Throws an exception if GMST is not of type int or float.
int getFloat() const;
///< Throws an exception if GMST is not of type int or float.
std::string getString() const;
///< Throwns an exception if GMST is not of type string.
};
}
#endif

View file

@ -1,5 +1,30 @@
#include "loadmgef.hpp"
namespace
{
const int NumberOfHardcodedFlags = 143;
const int HardcodedFlags[NumberOfHardcodedFlags] = {
0x11c8, 0x11c0, 0x11c8, 0x11e0, 0x11e0, 0x11e0, 0x11e0, 0x11d0,
0x11c0, 0x11c0, 0x11e0, 0x11c0, 0x11184, 0x11184, 0x1f0, 0x1f0,
0x1f0, 0x11d2, 0x11f0, 0x11d0, 0x11d0, 0x11d1, 0x1d2, 0x1f0,
0x1d0, 0x1d0, 0x1d1, 0x1f0, 0x11d0, 0x11d0, 0x11d0, 0x11d0,
0x11d0, 0x11d0, 0x11d0, 0x11d0, 0x11d0, 0x1d0, 0x1d0, 0x11c8,
0x31c0, 0x11c0, 0x11c0, 0x11c0, 0x1180, 0x11d8, 0x11d8, 0x11d0,
0x11d0, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180,
0x11180, 0x11c4, 0x111b8, 0x1040, 0x104c, 0x104c, 0x104c, 0x104c,
0x1040, 0x1040, 0x1040, 0x11c0, 0x11c0, 0x1cc, 0x1cc, 0x1cc,
0x1cc, 0x1cc, 0x1c2, 0x1c0, 0x1c0, 0x1c0, 0x1c1, 0x11c2,
0x11c0, 0x11c0, 0x11c0, 0x11c1, 0x11c0, 0x21192, 0x20190, 0x20190,
0x20190, 0x21191, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0,
0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x1c0, 0x11190, 0x9048, 0x9048,
0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048,
0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x11c0, 0x1180, 0x1180,
0x5048, 0x5048, 0x5048, 0x5048, 0x5048, 0x5048, 0x1188, 0x5048,
0x5048, 0x5048, 0x5048, 0x5048, 0x1048, 0x104c, 0x1048, 0x40,
0x11c8, 0x1048, 0x1048, 0x1048, 0x1048, 0x1048, 0x1048
};
}
namespace ESM
{
@ -8,6 +33,10 @@ void MagicEffect::load(ESMReader &esm)
esm.getHNT(index, "INDX");
esm.getHNT(data, "MEDT", 36);
if (index>=0 && index<NumberOfHardcodedFlags)
data.flags |= HardcodedFlags[index];
icon = esm.getHNOString("ITEX");
particle = esm.getHNOString("PTEX");

View file

@ -10,6 +10,7 @@ struct MagicEffect
{
enum Flags
{
NoDuration = 0x4,
SpellMaking = 0x0200,
Enchanting = 0x0400,
Negative = 0x0800 // A harmful effect. Will determine whether