mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-05-03 07:17:59 +03:00
Merge remote branch 'zini/master' into gui-windows
This commit is contained in:
commit
38b434771a
40 changed files with 2919 additions and 121 deletions
3
apps/doc.hpp
Normal file
3
apps/doc.hpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
// Note: This is not a regular source file.
|
||||
|
||||
/// \defgroup apps Applications
|
|
@ -184,11 +184,14 @@ set(GAMECLASS_HEADER
|
|||
source_group(apps\\openmw\\mwclass FILES ${GAMECLASS} ${GAMECLASS_HEADER})
|
||||
|
||||
set(GAMEMECHANICS
|
||||
mwmechanics/mechanicsmanager.cpp)
|
||||
mwmechanics/mechanicsmanager.cpp
|
||||
mwmechanics/magiceffects.cpp
|
||||
)
|
||||
set(GAMEMECHANICS_HEADER
|
||||
mwmechanics/mechanicsmanager.hpp
|
||||
mwmechanics/stat.hpp
|
||||
mwmechanics/creaturestats.hpp
|
||||
mwmechanics/magiceffects.hpp
|
||||
)
|
||||
source_group(apps\\openmw\\mwmechanics FILES ${GAMEMECHANICS} ${GAMEMECHANICS_HEADER})
|
||||
|
||||
|
|
44
apps/openmw/doc.hpp
Normal file
44
apps/openmw/doc.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Note: This is not a regular source file.
|
||||
|
||||
/// \ingroup apps
|
||||
/// \defgroup openmw OpenMW
|
||||
|
||||
/// \namespace OMW
|
||||
/// \ingroup openmw
|
||||
/// \brief Integration of OpenMW-subsystems
|
||||
|
||||
/// \namespace MWDialogue
|
||||
/// \ingroup openmw
|
||||
/// \brief NPC dialogues
|
||||
|
||||
/// \namespace MWMechanics
|
||||
/// \ingroup openmw
|
||||
/// \brief Game mechanics and NPC-AI
|
||||
|
||||
/// \namespace MWSound
|
||||
/// \ingroup openmw
|
||||
/// \brief Sound & music
|
||||
|
||||
/// \namespace MWGUI
|
||||
/// \ingroup openmw
|
||||
/// \brief HUD and windows
|
||||
|
||||
/// \namespace MWRender
|
||||
/// \ingroup openmw
|
||||
/// \brief Rendering via Ogre
|
||||
|
||||
/// \namespace MWWorld
|
||||
/// \ingroup openmw
|
||||
/// \brief World data
|
||||
|
||||
/// \namespace MWClass
|
||||
/// \ingroup openmw
|
||||
/// \brief Workaround for non-OOP design of the record system
|
||||
|
||||
/// \namespace MWInput
|
||||
/// \ingroup openmw
|
||||
/// \brief User input and character controls
|
||||
|
||||
/// \namespace MWScript
|
||||
/// \ingroup openmw
|
||||
/// \brief MW-specific script extentions and integration of the script system into OpenMW
|
|
@ -117,6 +117,7 @@ OMW::Engine::Engine()
|
|||
, mVerboseScripts (false)
|
||||
, mNewGame (false)
|
||||
, mUseSound (true)
|
||||
, mCompileAll (false)
|
||||
, mScriptManager (0)
|
||||
, mScriptContext (0)
|
||||
, mGuiManager (0)
|
||||
|
@ -278,9 +279,20 @@ void OMW::Engine::go()
|
|||
|
||||
// load cell
|
||||
ESM::Position pos;
|
||||
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
|
||||
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
||||
mEnvironment.mWorld->changeCell (mCellName, pos);
|
||||
pos.pos[2] = 0;
|
||||
|
||||
if (const ESM::Cell *exterior = mEnvironment.mWorld->getExterior (mCellName))
|
||||
{
|
||||
mEnvironment.mWorld->indexToPosition (exterior->data.gridX, exterior->data.gridY,
|
||||
pos.pos[0], pos.pos[1], true);
|
||||
mEnvironment.mWorld->changeToExteriorCell (pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.pos[0] = pos.pos[1] = 0;
|
||||
mEnvironment.mWorld->changeCell (mCellName, pos);
|
||||
}
|
||||
|
||||
// Sets up the input system
|
||||
MWInput::MWInputManager input(mOgre, mEnvironment.mWorld->getPlayerPos(),
|
||||
|
@ -305,6 +317,29 @@ void OMW::Engine::go()
|
|||
std::cout << " Music Error: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
// scripts
|
||||
if (mCompileAll)
|
||||
{
|
||||
typedef ESMS::ScriptListT<ESM::Script>::MapType Container;
|
||||
|
||||
Container scripts = mEnvironment.mWorld->getStore().scripts.list;
|
||||
|
||||
int count = 0;
|
||||
int success = 0;
|
||||
|
||||
for (Container::const_iterator iter (scripts.begin()); iter!=scripts.end(); ++iter, ++count)
|
||||
if (mScriptManager->compile (iter->first))
|
||||
++success;
|
||||
|
||||
if (count)
|
||||
std::cout
|
||||
<< "compiled " << success << " of " << count << " scripts ("
|
||||
<< 100*static_cast<double> (success)/count
|
||||
<< "%)"
|
||||
<< std::endl;
|
||||
|
||||
}
|
||||
|
||||
// Start the main rendering loop
|
||||
mOgre.start();
|
||||
|
||||
|
@ -345,3 +380,8 @@ void OMW::Engine::activate()
|
|||
interpreterContext.executeActivation();
|
||||
}
|
||||
}
|
||||
|
||||
void OMW::Engine::setCompileAll (bool all)
|
||||
{
|
||||
mCompileAll = all;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace OMW
|
|||
bool mVerboseScripts;
|
||||
bool mNewGame;
|
||||
bool mUseSound;
|
||||
bool mCompileAll;
|
||||
|
||||
MWWorld::Environment mEnvironment;
|
||||
MWScript::ScriptManager *mScriptManager;
|
||||
|
@ -127,6 +128,9 @@ namespace OMW
|
|||
|
||||
/// Activate the focussed object.
|
||||
void activate();
|
||||
|
||||
/// Compile all scripts (excludign dialogue scripts) at startup?
|
||||
void setCompileAll (bool all);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ using namespace std;
|
|||
bool parseOptions (int argc, char**argv, OMW::Engine& engine)
|
||||
{
|
||||
// Create a local alias for brevity
|
||||
namespace bpo = boost::program_options;
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
bpo::options_description desc (
|
||||
"Syntax: openmw <options>\nAllowed options");
|
||||
|
@ -43,23 +43,24 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
|
|||
("data", bpo::value<std::string>()->default_value ("data"),
|
||||
"set data directory")
|
||||
("start", bpo::value<std::string>()->default_value ("Beshara"),
|
||||
"set initial cell (only interior cells supported at the moment")
|
||||
"set initial cell")
|
||||
("master", bpo::value<std::string>()->default_value ("Morrowind"),
|
||||
"master file")
|
||||
( "debug", "debug mode" )
|
||||
( "nosound", "disable all sound" )
|
||||
( "script-verbose", "verbose script output" )
|
||||
( "new-game", "activate char gen/new game mechanics" )
|
||||
( "script-all", "compile all scripts (excluding dialogue scripts) at startup")
|
||||
;
|
||||
|
||||
|
||||
bpo::variables_map variables;
|
||||
|
||||
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||
std::string configFilePath(macBundlePath() + "/Contents/MacOS/openmw.cfg");
|
||||
std::ifstream configFile (configFilePath.c_str());
|
||||
#else
|
||||
std::ifstream configFile ("openmw.cfg");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||
|
||||
|
@ -78,19 +79,22 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
|
|||
engine.setDataDir (variables["data"].as<std::string>());
|
||||
engine.setCell (variables["start"].as<std::string>());
|
||||
engine.addMaster (variables["master"].as<std::string>());
|
||||
|
||||
|
||||
if (variables.count ("debug"))
|
||||
engine.enableDebugMode();
|
||||
|
||||
if (variables.count ("nosound"))
|
||||
engine.disableSound();
|
||||
|
||||
|
||||
if (variables.count ("script-verbose"))
|
||||
engine.enableVerboseScripts();
|
||||
|
||||
if (variables.count ("new-game"))
|
||||
engine.setNewGame();
|
||||
|
||||
if (variables.count ("script-all"))
|
||||
engine.setCompileAll (true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -100,7 +104,7 @@ int main(int argc, char**argv)
|
|||
try
|
||||
{
|
||||
OMW::Engine engine;
|
||||
|
||||
|
||||
if (parseOptions (argc, argv, engine))
|
||||
{
|
||||
engine.go();
|
||||
|
@ -111,7 +115,7 @@ int main(int argc, char**argv)
|
|||
cout << "\nERROR: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -560,13 +560,19 @@ void WindowManager::onClassChoice(MyGUI::WidgetPtr, int _index)
|
|||
}
|
||||
}
|
||||
|
||||
void WindowManager::showClassQuestionDialog()
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
struct Step
|
||||
{
|
||||
const char* text;
|
||||
const char* buttons[3];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void WindowManager::showClassQuestionDialog()
|
||||
{
|
||||
static boost::array<Step, 2> steps = { {
|
||||
{"On a clear day you chance upon a strange animal, its legs trapped in a hunter's clawsnare. Judging from the bleeding, it will not survive long.",
|
||||
{"Use herbs from your pack to put it to sleep?",
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#ifndef GAME_MWMECHANICS_CREATURESTATS_H
|
||||
#define GAME_MWMECHANICS_CREATURESTATS_H
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "stat.hpp"
|
||||
#include "magiceffects.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
@ -10,6 +14,8 @@ namespace MWMechanics
|
|||
Stat<int> mAttributes[8];
|
||||
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue
|
||||
int mLevel;
|
||||
std::set<std::string> mAbilities;
|
||||
MagicEffects mMagicEffects;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
118
apps/openmw/mwmechanics/magiceffects.cpp
Normal file
118
apps/openmw/mwmechanics/magiceffects.cpp
Normal file
|
@ -0,0 +1,118 @@
|
|||
|
||||
#include "magiceffects.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
EffectKey::EffectKey() : mId (0), mArg (-1) {}
|
||||
|
||||
EffectKey::EffectKey (const ESM::ENAMstruct& effect)
|
||||
{
|
||||
mId = effect.effectID;
|
||||
mArg = -1;
|
||||
|
||||
if (effect.skill!=-1)
|
||||
mArg = effect.skill;
|
||||
|
||||
if (effect.attribute!=-1)
|
||||
{
|
||||
if (mArg!=-1)
|
||||
throw std::runtime_error (
|
||||
"magic effect can't have both a skill and an attribute argument");
|
||||
|
||||
mArg = effect.attribute;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator< (const EffectKey& left, const EffectKey& right)
|
||||
{
|
||||
if (left.mId<right.mId)
|
||||
return true;
|
||||
|
||||
if (left.mId>right.mId)
|
||||
return false;
|
||||
|
||||
return left.mArg<right.mArg;
|
||||
}
|
||||
|
||||
EffectParam::EffectParam() : mMagnitude (0) {}
|
||||
|
||||
EffectParam& EffectParam::operator+= (const EffectParam& param)
|
||||
{
|
||||
mMagnitude += param.mMagnitude;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EffectParam& EffectParam::operator-= (const EffectParam& param)
|
||||
{
|
||||
mMagnitude -= param.mMagnitude;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MagicEffects::add (const EffectKey& key, const EffectParam& param)
|
||||
{
|
||||
Collection::iterator iter = mCollection.find (key);
|
||||
|
||||
if (iter==mCollection.end())
|
||||
{
|
||||
mCollection.insert (std::make_pair (key, param));
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->second += param;
|
||||
}
|
||||
}
|
||||
|
||||
EffectParam MagicEffects::get (const EffectKey& key) const
|
||||
{
|
||||
Collection::const_iterator iter = mCollection.find (key);
|
||||
|
||||
if (iter==mCollection.end())
|
||||
{
|
||||
return EffectParam();
|
||||
}
|
||||
else
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
MagicEffects MagicEffects::diff (const MagicEffects& prev, const MagicEffects& now)
|
||||
{
|
||||
MagicEffects result;
|
||||
|
||||
// adding/changing
|
||||
for (Collection::const_iterator iter (now.Begin()); iter!=now.End(); ++iter)
|
||||
{
|
||||
Collection::const_iterator other = prev.mCollection.find (iter->first);
|
||||
|
||||
if (other==prev.End())
|
||||
{
|
||||
// adding
|
||||
result.add (iter->first, iter->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// changing
|
||||
result.add (iter->first, iter->second - other->second);
|
||||
}
|
||||
}
|
||||
|
||||
// removing
|
||||
for (Collection::const_iterator iter (prev.Begin()); iter!=prev.End(); ++iter)
|
||||
{
|
||||
Collection::const_iterator other = now.mCollection.find (iter->first);
|
||||
|
||||
if (other==prev.End())
|
||||
{
|
||||
result.add (iter->first, EffectParam() - iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
77
apps/openmw/mwmechanics/magiceffects.hpp
Normal file
77
apps/openmw/mwmechanics/magiceffects.hpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef GAME_MWMECHANICS_MAGICEFFECTS_H
|
||||
#define GAME_MWMECHANICS_MAGICEFFECTS_H
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ENAMstruct;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
struct EffectKey
|
||||
{
|
||||
int mId;
|
||||
int mArg; // skill or ability
|
||||
|
||||
EffectKey();
|
||||
|
||||
EffectKey (int id, int arg = -1) : mId (id), mArg (arg) {}
|
||||
|
||||
EffectKey (const ESM::ENAMstruct& effect);
|
||||
};
|
||||
|
||||
bool operator< (const EffectKey& left, const EffectKey& right);
|
||||
|
||||
struct EffectParam
|
||||
{
|
||||
int mMagnitude;
|
||||
|
||||
EffectParam();
|
||||
|
||||
EffectParam& operator+= (const EffectParam& param);
|
||||
|
||||
EffectParam& operator-= (const EffectParam& param);
|
||||
};
|
||||
|
||||
inline EffectParam operator+ (const EffectParam& left, const EffectParam& right)
|
||||
{
|
||||
EffectParam param (left);
|
||||
return param += right;
|
||||
}
|
||||
|
||||
inline EffectParam operator- (const EffectParam& left, const EffectParam& right)
|
||||
{
|
||||
EffectParam param (left);
|
||||
return param -= right;
|
||||
}
|
||||
|
||||
/// \brief Effects currently affecting a NPC or creature
|
||||
class MagicEffects
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::map<EffectKey, EffectParam> Collection;
|
||||
|
||||
private:
|
||||
|
||||
Collection mCollection;
|
||||
|
||||
public:
|
||||
|
||||
Collection::const_iterator Begin() const { return mCollection.begin(); }
|
||||
|
||||
Collection::const_iterator End() const { return mCollection.end(); }
|
||||
|
||||
void add (const EffectKey& key, const EffectParam& param);
|
||||
|
||||
EffectParam get (const EffectKey& key) const;
|
||||
///< This function can safely be used for keys that are not present.
|
||||
|
||||
static MagicEffects diff (const MagicEffects& prev, const MagicEffects& now);
|
||||
///< Return changes from \a prev to \a now.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -22,63 +22,123 @@ namespace MWMechanics
|
|||
|
||||
// reset
|
||||
creatureStats.mLevel = player->npdt52.level;
|
||||
creatureStats.mAbilities.clear();
|
||||
creatureStats.mMagicEffects = MagicEffects();
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
npcStats.mSkill[i].setBase (player->npdt52.skills[i]);
|
||||
|
||||
// race
|
||||
const ESM::Race *race =
|
||||
mEnvironment.mWorld->getStore().races.find (mEnvironment.mWorld->getPlayerPos().getRace());
|
||||
|
||||
bool male = mEnvironment.mWorld->getPlayerPos().isMale();
|
||||
|
||||
for (int i=0; i<8; ++i)
|
||||
if (mRaceSelected)
|
||||
{
|
||||
const ESM::Race::MaleFemale *attribute = 0;
|
||||
switch (i)
|
||||
const ESM::Race *race =
|
||||
mEnvironment.mWorld->getStore().races.find (
|
||||
mEnvironment.mWorld->getPlayerPos().getRace());
|
||||
|
||||
bool male = mEnvironment.mWorld->getPlayerPos().isMale();
|
||||
|
||||
for (int i=0; i<8; ++i)
|
||||
{
|
||||
case 0: attribute = &race->data.strength; break;
|
||||
case 1: attribute = &race->data.intelligence; break;
|
||||
case 2: attribute = &race->data.willpower; break;
|
||||
case 3: attribute = &race->data.agility; break;
|
||||
case 4: attribute = &race->data.speed; break;
|
||||
case 5: attribute = &race->data.endurance; break;
|
||||
case 6: attribute = &race->data.personality; break;
|
||||
case 7: attribute = &race->data.luck; break;
|
||||
const ESM::Race::MaleFemale *attribute = 0;
|
||||
switch (i)
|
||||
{
|
||||
case 0: attribute = &race->data.strength; break;
|
||||
case 1: attribute = &race->data.intelligence; break;
|
||||
case 2: attribute = &race->data.willpower; break;
|
||||
case 3: attribute = &race->data.agility; break;
|
||||
case 4: attribute = &race->data.speed; break;
|
||||
case 5: attribute = &race->data.endurance; break;
|
||||
case 6: attribute = &race->data.personality; break;
|
||||
case 7: attribute = &race->data.luck; break;
|
||||
}
|
||||
|
||||
creatureStats.mAttributes[i].setBase (
|
||||
static_cast<int> (male ? attribute->male : attribute->female));
|
||||
}
|
||||
|
||||
creatureStats.mAttributes[i].setBase (
|
||||
static_cast<int> (male ? attribute->male : attribute->female));
|
||||
}
|
||||
|
||||
for (int i=0; i<7; ++i)
|
||||
{
|
||||
int index = race->data.bonus[i].skill;
|
||||
|
||||
if (index>=0 && index<27)
|
||||
for (int i=0; i<7; ++i)
|
||||
{
|
||||
npcStats.mSkill[i].setBase (
|
||||
npcStats.mSkill[i].getBase() + race->data.bonus[i].bonus);
|
||||
int index = race->data.bonus[i].skill;
|
||||
|
||||
if (index>=0 && index<27)
|
||||
{
|
||||
npcStats.mSkill[index].setBase (
|
||||
npcStats.mSkill[index].getBase() + race->data.bonus[i].bonus);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::const_iterator iter (race->powers.list.begin());
|
||||
iter!=race->powers.list.end(); ++iter)
|
||||
{
|
||||
insertSpell (*iter, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// birthsign
|
||||
|
||||
// class
|
||||
const ESM::Class& class_ = mEnvironment.mWorld->getPlayerPos().getClass();
|
||||
|
||||
for (int i=0; i<2; ++i)
|
||||
if (!mEnvironment.mWorld->getPlayerPos().getBirthsign().empty())
|
||||
{
|
||||
int attribute = class_.data.attribute[i];
|
||||
if (attribute>=0 && attribute<8)
|
||||
const ESM::BirthSign *sign =
|
||||
mEnvironment.mWorld->getStore().birthSigns.find (
|
||||
mEnvironment.mWorld->getPlayerPos().getBirthsign());
|
||||
|
||||
for (std::vector<std::string>::const_iterator iter (sign->powers.list.begin());
|
||||
iter!=sign->powers.list.end(); ++iter)
|
||||
{
|
||||
creatureStats.mAttributes[attribute].setBase (
|
||||
creatureStats.mAttributes[attribute].getBase() + 10);
|
||||
insertSpell (*iter, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// class
|
||||
if (mClassSelected)
|
||||
{
|
||||
const ESM::Class& class_ = mEnvironment.mWorld->getPlayerPos().getClass();
|
||||
|
||||
for (int i=0; i<2; ++i)
|
||||
{
|
||||
int attribute = class_.data.attribute[i];
|
||||
if (attribute>=0 && attribute<8)
|
||||
{
|
||||
creatureStats.mAttributes[attribute].setBase (
|
||||
creatureStats.mAttributes[attribute].getBase() + 10);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<2; ++i)
|
||||
{
|
||||
int bonus = i==0 ? 10 : 25;
|
||||
|
||||
for (int i2=0; i2<5; ++i2)
|
||||
{
|
||||
int index = class_.data.skills[i2][i];
|
||||
|
||||
if (index>=0 && index<27)
|
||||
{
|
||||
npcStats.mSkill[index].setBase (
|
||||
npcStats.mSkill[index].getBase() + bonus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef ESMS::IndexListT<ESM::Skill>::MapType ContainerType;
|
||||
const ContainerType& skills = mEnvironment.mWorld->getStore().skills.list;
|
||||
|
||||
for (ContainerType::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter)
|
||||
{
|
||||
if (iter->second.data.specialization==class_.data.specialization)
|
||||
{
|
||||
int index = iter->first;
|
||||
|
||||
if (index>=0 && index<27)
|
||||
{
|
||||
npcStats.mSkill[index].setBase (
|
||||
npcStats.mSkill[index].getBase() + 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// magic effects
|
||||
adjustMagicEffects (ptr);
|
||||
|
||||
// calculate dynamic stats
|
||||
int strength = creatureStats.mAttributes[0].getBase();
|
||||
|
@ -87,17 +147,81 @@ namespace MWMechanics
|
|||
int agility = creatureStats.mAttributes[3].getBase();
|
||||
int endurance = creatureStats.mAttributes[5].getBase();
|
||||
|
||||
double magickaFactor = creatureStats.mMagicEffects.get (EffectKey (84)).mMagnitude*0.1 + 0.5;
|
||||
|
||||
creatureStats.mDynamic[0].setBase (static_cast<int> (0.5 * (strength + endurance)));
|
||||
// TODO: calculate factor
|
||||
creatureStats.mDynamic[1].setBase (static_cast<int> (intelligence + 1 * intelligence));
|
||||
creatureStats.mDynamic[1].setBase (static_cast<int> (intelligence +
|
||||
magickaFactor * intelligence));
|
||||
creatureStats.mDynamic[2].setBase (strength+willpower+agility+endurance);
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
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)
|
||||
{
|
||||
MWMechanics::CreatureStats& creatureStats =
|
||||
MWWorld::Class::get (creature).getCreatureStats (creature);
|
||||
|
||||
MagicEffects now;
|
||||
|
||||
for (std::set<std::string>::const_iterator iter (creatureStats.mAbilities.begin());
|
||||
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);
|
||||
|
||||
creatureStats.mMagicEffects = now;
|
||||
|
||||
// TODO apply diff to other stats
|
||||
}
|
||||
|
||||
MechanicsManager::MechanicsManager (MWWorld::Environment& environment)
|
||||
: mEnvironment (environment), mUpdatePlayer (true)
|
||||
: mEnvironment (environment), mUpdatePlayer (true), mClassSelected (false),
|
||||
mRaceSelected (false)
|
||||
{
|
||||
buildPlayer();
|
||||
}
|
||||
|
@ -237,6 +361,7 @@ namespace MWMechanics
|
|||
{
|
||||
mEnvironment.mWorld->getPlayerPos().setGender (male);
|
||||
mEnvironment.mWorld->getPlayerPos().setRace (race);
|
||||
mRaceSelected = true;
|
||||
buildPlayer();
|
||||
mUpdatePlayer = true;
|
||||
}
|
||||
|
@ -250,6 +375,7 @@ namespace MWMechanics
|
|||
void MechanicsManager::setPlayerClass (const std::string& id)
|
||||
{
|
||||
mEnvironment.mWorld->getPlayerPos().setClass (*mEnvironment.mWorld->getStore().classes.find (id));
|
||||
mClassSelected = true;
|
||||
buildPlayer();
|
||||
mUpdatePlayer = true;
|
||||
}
|
||||
|
@ -257,6 +383,7 @@ namespace MWMechanics
|
|||
void MechanicsManager::setPlayerClass (const ESM::Class& class_)
|
||||
{
|
||||
mEnvironment.mWorld->getPlayerPos().setClass (class_);
|
||||
mClassSelected = true;
|
||||
buildPlayer();
|
||||
mUpdatePlayer = true;
|
||||
}
|
||||
|
|
|
@ -23,11 +23,17 @@ namespace MWMechanics
|
|||
CreatureStats mWatchedCreature;
|
||||
NpcStats mWatchedNpc;
|
||||
bool mUpdatePlayer;
|
||||
bool mClassSelected;
|
||||
bool mRaceSelected;
|
||||
|
||||
void buildPlayer();
|
||||
///< 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.
|
||||
|
||||
void insertSpell (const std::string& id, MWWorld::Ptr& creature);
|
||||
|
||||
void adjustMagicEffects (MWWorld::Ptr& creature);
|
||||
|
||||
public:
|
||||
|
||||
MechanicsManager (MWWorld::Environment& environment);
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Interpreter
|
|||
|
||||
namespace MWScript
|
||||
{
|
||||
/// \brief stats-related script functionality (creatures and NPCs)
|
||||
/// \brief Container-related script functionality (chests, NPCs, creatures)
|
||||
namespace Container
|
||||
{
|
||||
void registerExtensions (Compiler::Extensions& extensions);
|
||||
|
|
|
@ -95,4 +95,10 @@ op 0x2000085-0x200008b: Disable Controls
|
|||
op 0x200008c: Unlock
|
||||
op 0x200008d: Unlock, explicit reference
|
||||
op 0x200008e: COE
|
||||
opcodes 0x200008f-0x3ffffff unused
|
||||
op 0x200008e-0x20000a8: GetSkill
|
||||
op 0x20000a9-0x20000c3: GetSkill, explicit reference
|
||||
op 0x20000c4-0x20000de: SetSkill
|
||||
op 0x20000df-0x20000f9: SetSkill, explicit reference
|
||||
op 0x20000fa-0x2000114: ModSkill
|
||||
op 0x2000115-0x200012f: ModSKill, explicit reference
|
||||
opcodes 0x2000130-0x3ffffff unused
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Interpreter
|
|||
}
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
{
|
||||
class ScriptManager
|
||||
{
|
||||
Compiler::StreamErrorHandler mErrorHandler;
|
||||
|
@ -35,19 +35,21 @@ namespace MWScript
|
|||
bool mVerbose;
|
||||
Compiler::Context& mCompilerContext;
|
||||
Compiler::FileParser mParser;
|
||||
|
||||
|
||||
std::map<std::string, std::vector<Interpreter::Type_Code> > mScripts;
|
||||
|
||||
bool compile (const std::string& name);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
ScriptManager (const ESMS::ESMStore& store, bool verbose,
|
||||
Compiler::Context& compilerContext);
|
||||
|
||||
|
||||
void run (const std::string& name, Interpreter::Context& interpreterContext);
|
||||
///< Run the script with the given name (compile first, if not compiled yet)
|
||||
|
||||
bool compile (const std::string& name);
|
||||
///< Compile script with the given namen
|
||||
/// \return Success?
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -468,6 +468,160 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
class OpGetSkill : public Interpreter::Opcode0
|
||||
{
|
||||
int mIndex;
|
||||
|
||||
public:
|
||||
|
||||
OpGetSkill (int index) : mIndex (index) {}
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
|
||||
Interpreter::Type_Integer value =
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex].
|
||||
getModified();
|
||||
|
||||
runtime.push (value);
|
||||
}
|
||||
};
|
||||
|
||||
class OpGetSkillExplicit : public Interpreter::Opcode0
|
||||
{
|
||||
int mIndex;
|
||||
|
||||
public:
|
||||
|
||||
OpGetSkillExplicit (int index) : mIndex (index) {}
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getWorld().getPtr (id, false);
|
||||
|
||||
Interpreter::Type_Integer value =
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex].
|
||||
getModified();
|
||||
|
||||
runtime.push (value);
|
||||
}
|
||||
};
|
||||
|
||||
class OpSetSkill : public Interpreter::Opcode0
|
||||
{
|
||||
int mIndex;
|
||||
|
||||
public:
|
||||
|
||||
OpSetSkill (int index) : mIndex (index) {}
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex].
|
||||
setModified (value, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class OpSetSkillExplicit : public Interpreter::Opcode0
|
||||
{
|
||||
int mIndex;
|
||||
|
||||
public:
|
||||
|
||||
OpSetSkillExplicit (int index) : mIndex (index) {}
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getWorld().getPtr (id, false);
|
||||
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex].
|
||||
setModified (value, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class OpModSkill : public Interpreter::Opcode0
|
||||
{
|
||||
int mIndex;
|
||||
|
||||
public:
|
||||
|
||||
OpModSkill (int index) : mIndex (index) {}
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
|
||||
value += MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex].
|
||||
getModified();
|
||||
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex].
|
||||
setModified (value, 0, 100);
|
||||
}
|
||||
};
|
||||
|
||||
class OpModSkillExplicit : public Interpreter::Opcode0
|
||||
{
|
||||
int mIndex;
|
||||
|
||||
public:
|
||||
|
||||
OpModSkillExplicit (int index) : mIndex (index) {}
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getWorld().getPtr (id, false);
|
||||
|
||||
value +=
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex].
|
||||
getModified();
|
||||
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex].
|
||||
setModified (value, 0, 100);
|
||||
}
|
||||
};
|
||||
|
||||
const int numberOfAttributes = 8;
|
||||
|
||||
const int opcodeGetAttribute = 0x2000027;
|
||||
|
@ -490,6 +644,15 @@ namespace MWScript
|
|||
const int opcodeGetDynamicGetRatio = 0x200006f;
|
||||
const int opcodeGetDynamicGetRatioExplicit = 0x2000072;
|
||||
|
||||
const int numberOfSkills = 27;
|
||||
|
||||
const int opcodeGetSkill = 0x200008e;
|
||||
const int opcodeGetSkillExplicit = 0x20000a9;
|
||||
const int opcodeSetSkill = 0x20000c4;
|
||||
const int opcodeSetSkillExplicit = 0x20000df;
|
||||
const int opcodeModSkill = 0x20000fa;
|
||||
const int opcodeModSkillExplicit = 0x2000115;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
static const char *attributes[numberOfAttributes] =
|
||||
|
@ -503,6 +666,16 @@ namespace MWScript
|
|||
"health", "magicka", "fatigue"
|
||||
};
|
||||
|
||||
static const char *skills[numberOfSkills] =
|
||||
{
|
||||
"block", "armorer", "mediumarmor", "heavyarmor", "bluntweapon",
|
||||
"longblade", "axe", "spear", "athletics", "enchant", "destruction",
|
||||
"alteration", "illusion", "conjuration", "mysticism",
|
||||
"restoration", "alchemy", "unarmored", "security", "sneak",
|
||||
"acrobatics", "lightarmor", "shortblade", "marksman",
|
||||
"merchantile", "speechcraft", "handtohand"
|
||||
};
|
||||
|
||||
std::string get ("get");
|
||||
std::string set ("set");
|
||||
std::string mod ("mod");
|
||||
|
@ -537,7 +710,18 @@ namespace MWScript
|
|||
|
||||
extensions.registerFunction (get + dynamics[i] + getRatio, 'f', "",
|
||||
opcodeGetDynamicGetRatio+i, opcodeGetDynamicGetRatioExplicit+i);
|
||||
}
|
||||
|
||||
for (int i=0; i<numberOfSkills; ++i)
|
||||
{
|
||||
extensions.registerFunction (get + skills[i], 'l', "",
|
||||
opcodeGetSkill+i, opcodeGetSkillExplicit+i);
|
||||
|
||||
extensions.registerInstruction (set + skills[i], "l",
|
||||
opcodeSetSkill+i, opcodeSetSkillExplicit+i);
|
||||
|
||||
extensions.registerInstruction (mod + skills[i], "l",
|
||||
opcodeModSkill+i, opcodeModSkillExplicit+i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -581,6 +765,18 @@ namespace MWScript
|
|||
interpreter.installSegment5 (opcodeGetDynamicGetRatioExplicit+i,
|
||||
new OpGetDynamicGetRatioExplicit (i));
|
||||
}
|
||||
|
||||
for (int i=0; i<numberOfSkills; ++i)
|
||||
{
|
||||
interpreter.installSegment5 (opcodeGetSkill+i, new OpGetSkill (i));
|
||||
interpreter.installSegment5 (opcodeGetSkillExplicit+i, new OpGetSkillExplicit (i));
|
||||
|
||||
interpreter.installSegment5 (opcodeSetSkill+i, new OpSetSkill (i));
|
||||
interpreter.installSegment5 (opcodeSetSkillExplicit+i, new OpSetSkillExplicit (i));
|
||||
|
||||
interpreter.installSegment5 (opcodeModSkill+i, new OpModSkill (i));
|
||||
interpreter.installSegment5 (opcodeModSkillExplicit+i, new OpModSkillExplicit (i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue