forked from mirror/openmw-tes3mp
Merge branch 'spells'
Conflicts: apps/openmw/CMakeLists.txt apps/openmw/mwmechanics/npcstats.hpp
This commit is contained in:
commit
37f478b69a
10 changed files with 216 additions and 55 deletions
|
@ -55,7 +55,7 @@ add_openmw_dir (mwclass
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwmechanics
|
add_openmw_dir (mwmechanics
|
||||||
mechanicsmanager stat creaturestats magiceffects movement actors drawstate
|
mechanicsmanager stat creaturestats magiceffects movement actors drawstate spells
|
||||||
)
|
)
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
|
|
|
@ -61,6 +61,10 @@ namespace MWClass
|
||||||
for (int i=0; i<27; ++i)
|
for (int i=0; i<27; ++i)
|
||||||
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
|
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter (ref->base->spells.list.begin());
|
||||||
|
iter!=ref->base->spells.list.end(); ++iter)
|
||||||
|
data->mCreatureStats.mSpells.add (*iter);
|
||||||
|
|
||||||
// creature stats
|
// creature stats
|
||||||
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
|
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
|
||||||
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
|
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "stat.hpp"
|
#include "stat.hpp"
|
||||||
#include "magiceffects.hpp"
|
#include "magiceffects.hpp"
|
||||||
|
#include "spells.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
@ -14,7 +15,7 @@ namespace MWMechanics
|
||||||
Stat<int> mAttributes[8];
|
Stat<int> mAttributes[8];
|
||||||
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue
|
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue
|
||||||
int mLevel;
|
int mLevel;
|
||||||
std::set<std::string> mAbilities;
|
Spells mSpells;
|
||||||
MagicEffects mMagicEffects;
|
MagicEffects mMagicEffects;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
// reset
|
// reset
|
||||||
creatureStats.mLevel = player->npdt52.level;
|
creatureStats.mLevel = player->npdt52.level;
|
||||||
creatureStats.mAbilities.clear();
|
creatureStats.mSpells.clear();
|
||||||
creatureStats.mMagicEffects = MagicEffects();
|
creatureStats.mMagicEffects = MagicEffects();
|
||||||
|
|
||||||
for (int i=0; i<27; ++i)
|
for (int i=0; i<27; ++i)
|
||||||
|
@ -71,7 +71,7 @@ namespace MWMechanics
|
||||||
for (std::vector<std::string>::const_iterator iter (race->powers.list.begin());
|
for (std::vector<std::string>::const_iterator iter (race->powers.list.begin());
|
||||||
iter!=race->powers.list.end(); ++iter)
|
iter!=race->powers.list.end(); ++iter)
|
||||||
{
|
{
|
||||||
insertSpell (*iter, ptr);
|
creatureStats.mSpells.add (*iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ namespace MWMechanics
|
||||||
for (std::vector<std::string>::const_iterator iter (sign->powers.list.begin());
|
for (std::vector<std::string>::const_iterator iter (sign->powers.list.begin());
|
||||||
iter!=sign->powers.list.end(); ++iter)
|
iter!=sign->powers.list.end(); ++iter)
|
||||||
{
|
{
|
||||||
insertSpell (*iter, ptr);
|
creatureStats.mSpells.add (*iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,59 +159,14 @@ namespace MWMechanics
|
||||||
creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified());
|
creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MechanicsManager::insertSpell (const std::string& id, MWWorld::Ptr& creature)
|
|
||||||
{
|
|
||||||
MWMechanics::CreatureStats& creatureStats =
|
|
||||||
MWWorld::Class::get (creature).getCreatureStats (creature);
|
|
||||||
|
|
||||||
const ESM::Spell *spell = mEnvironment.mWorld->getStore().spells.find (id);
|
|
||||||
|
|
||||||
switch (spell->data.type)
|
|
||||||
{
|
|
||||||
case ESM::Spell::ST_Ability:
|
|
||||||
|
|
||||||
if (creatureStats.mAbilities.find (id)==creatureStats.mAbilities.end())
|
|
||||||
{
|
|
||||||
creatureStats.mAbilities.insert (id);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// TODO ST_SPELL, ST_Blight, ST_Disease, ST_Curse, ST_Power
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
std::cout
|
|
||||||
<< "adding unsupported spell type (" << spell->data.type
|
|
||||||
<< ") to creature: " << id << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MechanicsManager::adjustMagicEffects (MWWorld::Ptr& creature)
|
void MechanicsManager::adjustMagicEffects (MWWorld::Ptr& creature)
|
||||||
{
|
{
|
||||||
MWMechanics::CreatureStats& creatureStats =
|
MWMechanics::CreatureStats& creatureStats =
|
||||||
MWWorld::Class::get (creature).getCreatureStats (creature);
|
MWWorld::Class::get (creature).getCreatureStats (creature);
|
||||||
|
|
||||||
MagicEffects now;
|
MagicEffects now = creatureStats.mSpells.getMagicEffects (mEnvironment);
|
||||||
|
|
||||||
for (std::set<std::string>::const_iterator iter (creatureStats.mAbilities.begin());
|
/// \todo add effects from active spells and equipment
|
||||||
iter!=creatureStats.mAbilities.end(); ++iter)
|
|
||||||
{
|
|
||||||
const ESM::Spell *spell = mEnvironment.mWorld->getStore().spells.find (*iter);
|
|
||||||
|
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->effects.list.begin();
|
|
||||||
iter!=spell->effects.list.end(); ++iter)
|
|
||||||
{
|
|
||||||
if (iter->range==0) // self
|
|
||||||
{
|
|
||||||
EffectParam param;
|
|
||||||
param.mMagnitude = iter->magnMax; // TODO calculate magnitude
|
|
||||||
now.add (EffectKey (*iter), param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO add effects from other spell types, active spells and equipment
|
|
||||||
|
|
||||||
MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now);
|
MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now);
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,6 @@ namespace MWMechanics
|
||||||
///< build player according to stored class/race/birthsign information. Will
|
///< build player according to stored class/race/birthsign information. Will
|
||||||
/// default to the values of the ESM::NPC object, if no explicit information is given.
|
/// default to the values of the ESM::NPC object, if no explicit information is given.
|
||||||
|
|
||||||
void insertSpell (const std::string& id, MWWorld::Ptr& creature);
|
|
||||||
|
|
||||||
void adjustMagicEffects (MWWorld::Ptr& creature);
|
void adjustMagicEffects (MWWorld::Ptr& creature);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWMECHANICS_NPCSTATS_H
|
#define GAME_MWMECHANICS_NPCSTATS_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "stat.hpp"
|
#include "stat.hpp"
|
||||||
#include "drawstate.hpp"
|
#include "drawstate.hpp"
|
||||||
|
@ -11,6 +12,10 @@ namespace MWMechanics
|
||||||
/// \brief Additional stats for NPCs
|
/// \brief Additional stats for NPCs
|
||||||
///
|
///
|
||||||
/// For non-NPC-specific stats, see the CreatureStats struct.
|
/// For non-NPC-specific stats, see the CreatureStats struct.
|
||||||
|
///
|
||||||
|
/// \note For technical reasons the spell list and the currently selected spell is also handled by
|
||||||
|
/// CreatureStats, even though they are actually NPC stats.
|
||||||
|
|
||||||
struct NpcStats
|
struct NpcStats
|
||||||
{
|
{
|
||||||
// NPCs other than the player can only have one faction. But for the sake of consistency
|
// NPCs other than the player can only have one faction. But for the sake of consistency
|
||||||
|
|
81
apps/openmw/mwmechanics/spells.cpp
Normal file
81
apps/openmw/mwmechanics/spells.cpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
|
||||||
|
#include "spells.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/loadspel.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
|
#include "magiceffects.hpp"
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
void Spells::addSpell (const ESM::Spell *spell, MagicEffects& effects) const
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->effects.list.begin();
|
||||||
|
iter!=spell->effects.list.end(); ++iter)
|
||||||
|
{
|
||||||
|
EffectParam param;
|
||||||
|
param.mMagnitude = iter->magnMax; /// \todo calculate magnitude
|
||||||
|
effects.add (EffectKey (*iter), param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spells::TIterator Spells::begin() const
|
||||||
|
{
|
||||||
|
return mSpells.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Spells::TIterator Spells::end() const
|
||||||
|
{
|
||||||
|
return mSpells.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::add (const std::string& spellId)
|
||||||
|
{
|
||||||
|
if (std::find (mSpells.begin(), mSpells.end(), spellId)!=mSpells.end())
|
||||||
|
mSpells.push_back (spellId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::remove (const std::string& spellId)
|
||||||
|
{
|
||||||
|
TContainer::iterator iter = std::find (mSpells.begin(), mSpells.end(), spellId);
|
||||||
|
|
||||||
|
if (iter!=mSpells.end())
|
||||||
|
mSpells.erase (iter);
|
||||||
|
|
||||||
|
if (spellId==mSelectedSpell)
|
||||||
|
mSelectedSpell.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
MagicEffects Spells::getMagicEffects (const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
MagicEffects effects;
|
||||||
|
|
||||||
|
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
||||||
|
{
|
||||||
|
const ESM::Spell *spell = environment.mWorld->getStore().spells.find (*iter);
|
||||||
|
|
||||||
|
if (spell->data.type==ESM::Spell::ST_Ability || spell->data.type==ESM::Spell::ST_Blight ||
|
||||||
|
spell->data.type==ESM::Spell::ST_Disease || spell->data.type==ESM::Spell::ST_Curse)
|
||||||
|
addSpell (spell, effects);
|
||||||
|
}
|
||||||
|
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::clear()
|
||||||
|
{
|
||||||
|
mSpells.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::setSelectedSpell (const std::string& spellId)
|
||||||
|
{
|
||||||
|
mSelectedSpell = spellId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string Spells::getSelectedSpell() const
|
||||||
|
{
|
||||||
|
return mSelectedSpell;
|
||||||
|
}
|
||||||
|
}
|
66
apps/openmw/mwmechanics/spells.hpp
Normal file
66
apps/openmw/mwmechanics/spells.hpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef GAME_MWMECHANICS_SPELLS_H
|
||||||
|
#define GAME_MWMECHANICS_SPELLS_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct Spell;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
struct Environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
class MagicEffects;
|
||||||
|
|
||||||
|
/// \brief Spell list
|
||||||
|
///
|
||||||
|
/// This class manages known spells as well as abilities, powers and permanent negative effects like
|
||||||
|
/// diseaes.
|
||||||
|
class Spells
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::vector<std::string> TContainer;
|
||||||
|
typedef TContainer::const_iterator TIterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector<std::string> mSpells;
|
||||||
|
std::string mSelectedSpell;
|
||||||
|
|
||||||
|
void addSpell (const ESM::Spell *, MagicEffects& effects) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TIterator begin() const;
|
||||||
|
|
||||||
|
TIterator end() const;
|
||||||
|
|
||||||
|
void add (const std::string& spell);
|
||||||
|
///< Adding a spell that is already listed in *this is a no-op.
|
||||||
|
|
||||||
|
void remove (const std::string& spell);
|
||||||
|
///< If the spell to be removed is the selected spell, the selected spell will be changed to
|
||||||
|
/// no spell (empty string).
|
||||||
|
|
||||||
|
MagicEffects getMagicEffects (const MWWorld::Environment& environment) const;
|
||||||
|
///< Return sum of magic effects resulting from abilities, blights, deseases and curses.
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
///< Remove all spells of al types.
|
||||||
|
|
||||||
|
void setSelectedSpell (const std::string& spellId);
|
||||||
|
///< This function does not verify, if the spell is available.
|
||||||
|
|
||||||
|
const std::string getSelectedSpell() const;
|
||||||
|
///< May return an empty string.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -129,4 +129,8 @@ op 0x2000143: ModWaterLevel
|
||||||
op 0x2000144: ToggleWater, twa
|
op 0x2000144: ToggleWater, twa
|
||||||
op 0x2000145: ToggleFogOfWar (tfow)
|
op 0x2000145: ToggleFogOfWar (tfow)
|
||||||
op 0x2000146: TogglePathgrid
|
op 0x2000146: TogglePathgrid
|
||||||
opcodes 0x2000147-0x3ffffff unused
|
op 0x2000147: AddSpell
|
||||||
|
op 0x2000148: AddSpell, explicit reference
|
||||||
|
op 0x2000149: RemoveSpell
|
||||||
|
op 0x200014a: RemoveSpell, explicit reference
|
||||||
|
opcodes 0x200014b-0x3ffffff unused
|
||||||
|
|
|
@ -280,6 +280,38 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpAddSpell : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.add (id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpRemoveSpell : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.remove (id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const int numberOfAttributes = 8;
|
const int numberOfAttributes = 8;
|
||||||
|
|
||||||
const int opcodeGetAttribute = 0x2000027;
|
const int opcodeGetAttribute = 0x2000027;
|
||||||
|
@ -311,6 +343,11 @@ namespace MWScript
|
||||||
const int opcodeModSkill = 0x20000fa;
|
const int opcodeModSkill = 0x20000fa;
|
||||||
const int opcodeModSkillExplicit = 0x2000115;
|
const int opcodeModSkillExplicit = 0x2000115;
|
||||||
|
|
||||||
|
const int opcodeAddSpell = 0x2000147;
|
||||||
|
const int opcodeAddSpellExplicit = 0x2000148;
|
||||||
|
const int opcodeRemoveSpell = 0x2000149;
|
||||||
|
const int opcodeRemoveSpellExplicit = 0x200014a;
|
||||||
|
|
||||||
void registerExtensions (Compiler::Extensions& extensions)
|
void registerExtensions (Compiler::Extensions& extensions)
|
||||||
{
|
{
|
||||||
static const char *attributes[numberOfAttributes] =
|
static const char *attributes[numberOfAttributes] =
|
||||||
|
@ -381,6 +418,10 @@ namespace MWScript
|
||||||
extensions.registerInstruction (mod + skills[i], "l",
|
extensions.registerInstruction (mod + skills[i], "l",
|
||||||
opcodeModSkill+i, opcodeModSkillExplicit+i);
|
opcodeModSkill+i, opcodeModSkillExplicit+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extensions.registerInstruction ("addspell", "c", opcodeAddSpell, opcodeAddSpellExplicit);
|
||||||
|
extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell,
|
||||||
|
opcodeRemoveSpellExplicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
|
@ -436,6 +477,12 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (opcodeModSkill+i, new OpModSkill<ImplicitRef> (i));
|
interpreter.installSegment5 (opcodeModSkill+i, new OpModSkill<ImplicitRef> (i));
|
||||||
interpreter.installSegment5 (opcodeModSkillExplicit+i, new OpModSkill<ExplicitRef> (i));
|
interpreter.installSegment5 (opcodeModSkillExplicit+i, new OpModSkill<ExplicitRef> (i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interpreter.installSegment5 (opcodeAddSpell, new OpAddSpell<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeAddSpellExplicit, new OpAddSpell<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeRemoveSpell, new OpRemoveSpell<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeRemoveSpellExplicit,
|
||||||
|
new OpRemoveSpell<ExplicitRef>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue