forked from mirror/openmw-tes3mp
Merge branch 'effects'
This commit is contained in:
commit
420cd53be0
18 changed files with 548 additions and 51 deletions
|
@ -48,6 +48,7 @@ add_openmw_dir (mwworld
|
|||
refdata world physicssystem scene globals class action nullaction actionteleport
|
||||
containerstore actiontalk actiontake manualref player cellfunctors
|
||||
cells localscripts customdata weather inventorystore ptr actionread
|
||||
timestamp
|
||||
)
|
||||
|
||||
add_openmw_dir (mwclass
|
||||
|
@ -57,6 +58,7 @@ add_openmw_dir (mwclass
|
|||
|
||||
add_openmw_dir (mwmechanics
|
||||
mechanicsmanager stat creaturestats magiceffects movement actors drawstate spells
|
||||
activespells
|
||||
)
|
||||
|
||||
add_openmw_dir (mwbase
|
||||
|
|
162
apps/openmw/mwmechanics/activespells.cpp
Normal file
162
apps/openmw/mwmechanics/activespells.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
|
||||
#include "activespells.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
void ActiveSpells::update() const
|
||||
{
|
||||
bool rebuild = false;
|
||||
|
||||
MWWorld::TimeStamp now = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||
|
||||
if (mLastUpdate!=now)
|
||||
{
|
||||
TContainer::iterator iter (mSpells.begin());
|
||||
while (iter!=mSpells.end())
|
||||
if (!timeToExpire (iter))
|
||||
{
|
||||
mSpells.erase (iter++);
|
||||
rebuild = true;
|
||||
}
|
||||
else
|
||||
++iter;
|
||||
|
||||
mLastUpdate = now;
|
||||
}
|
||||
|
||||
if (mSpellsChanged)
|
||||
{
|
||||
mSpellsChanged = false;
|
||||
rebuild = true;
|
||||
}
|
||||
|
||||
if (rebuild)
|
||||
{
|
||||
mEffects = MagicEffects();
|
||||
|
||||
for (TIterator iter (begin()); iter!=end(); ++iter)
|
||||
{
|
||||
const ESM::Spell& spell =
|
||||
*MWBase::Environment::get().getWorld()->getStore().spells.find (iter->first);
|
||||
|
||||
const MWWorld::TimeStamp& start = iter->second.first;
|
||||
float magnitude = iter->second.second;
|
||||
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter (spell.effects.list.begin());
|
||||
iter!=spell.effects.list.end(); ++iter)
|
||||
{
|
||||
if (iter->duration)
|
||||
{
|
||||
MWWorld::TimeStamp end = start;
|
||||
end += static_cast<double> (iter->duration)*
|
||||
MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60);
|
||||
|
||||
if (end>now)
|
||||
{
|
||||
EffectParam param;
|
||||
param.mMagnitude = static_cast<int> (
|
||||
(iter->magnMax-iter->magnMin+1)*magnitude + iter->magnMin);
|
||||
mEffects.add (*iter, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ActiveSpells::ActiveSpells()
|
||||
: mSpellsChanged (false), mLastUpdate (MWBase::Environment::get().getWorld()->getTimeStamp())
|
||||
{}
|
||||
|
||||
void ActiveSpells::addSpell (const std::string& id)
|
||||
{
|
||||
const ESM::Spell& spell = *MWBase::Environment::get().getWorld()->getStore().spells.find (id);
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter (spell.effects.list.begin());
|
||||
iter!=spell.effects.list.end(); ++iter)
|
||||
{
|
||||
if (iter->duration)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
TContainer::iterator iter = mSpells.find (id);
|
||||
|
||||
float random = static_cast<float> (std::rand()) / RAND_MAX;
|
||||
|
||||
if (iter==mSpells.end())
|
||||
mSpells.insert (std::make_pair (id,
|
||||
std::make_pair (MWBase::Environment::get().getWorld()->getTimeStamp(), random)));
|
||||
else
|
||||
iter->second = std::make_pair (MWBase::Environment::get().getWorld()->getTimeStamp(), random);
|
||||
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::removeSpell (const std::string& id)
|
||||
{
|
||||
TContainer::iterator iter = mSpells.find (id);
|
||||
|
||||
if (iter!=mSpells.end())
|
||||
{
|
||||
mSpells.erase (iter);
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
const MagicEffects& ActiveSpells::getMagicEffects() const
|
||||
{
|
||||
update();
|
||||
return mEffects;
|
||||
}
|
||||
|
||||
ActiveSpells::TIterator ActiveSpells::begin() const
|
||||
{
|
||||
update();
|
||||
return mSpells.begin();
|
||||
}
|
||||
|
||||
ActiveSpells::TIterator ActiveSpells::end() const
|
||||
{
|
||||
update();
|
||||
return mSpells.end();
|
||||
}
|
||||
|
||||
double ActiveSpells::timeToExpire (const TIterator& iterator) const
|
||||
{
|
||||
const ESM::Spell& spell =
|
||||
*MWBase::Environment::get().getWorld()->getStore().spells.find (iterator->first);
|
||||
|
||||
int duration = 0;
|
||||
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter (spell.effects.list.begin());
|
||||
iter!=spell.effects.list.end(); ++iter)
|
||||
{
|
||||
if (iter->duration>duration)
|
||||
duration = iter->duration;
|
||||
}
|
||||
|
||||
double scaledDuration = duration *
|
||||
MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60);
|
||||
|
||||
double usedUp = MWBase::Environment::get().getWorld()->getTimeStamp()-iterator->second.first;
|
||||
|
||||
if (usedUp>=scaledDuration)
|
||||
return 0;
|
||||
|
||||
return scaledDuration-usedUp;
|
||||
}
|
||||
}
|
58
apps/openmw/mwmechanics/activespells.hpp
Normal file
58
apps/openmw/mwmechanics/activespells.hpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
#ifndef GAME_MWMECHANICS_ACTIVESPELLS_H
|
||||
#define GAME_MWMECHANICS_ACTIVESPELLS_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "../mwworld/timestamp.hpp"
|
||||
|
||||
#include "magiceffects.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Spell;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
/// \brief Lasting spell effects
|
||||
class ActiveSpells
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::map<std::string, std::pair<MWWorld::TimeStamp, float> > TContainer;
|
||||
typedef TContainer::const_iterator TIterator;
|
||||
|
||||
private:
|
||||
|
||||
mutable TContainer mSpells; // spellId, (time of casting, relative magnitude)
|
||||
mutable MagicEffects mEffects;
|
||||
mutable bool mSpellsChanged;
|
||||
mutable MWWorld::TimeStamp mLastUpdate;
|
||||
|
||||
void update() const;
|
||||
|
||||
public:
|
||||
|
||||
ActiveSpells();
|
||||
|
||||
void addSpell (const std::string& id);
|
||||
///< Overwrites an existing spell with the same ID. If the spell does not have any
|
||||
/// non-instant effects, it is ignored.
|
||||
|
||||
void removeSpell (const std::string& id);
|
||||
|
||||
const MagicEffects& getMagicEffects() const;
|
||||
|
||||
TIterator begin() const;
|
||||
|
||||
TIterator end() const;
|
||||
|
||||
double timeToExpire (const TIterator& iterator) const;
|
||||
///< Returns time (in in-game hours) until the spell pointed to by \a iterator
|
||||
/// expires.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -8,11 +8,30 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
||||
#include "creaturestats.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
void Actors::updateActor (const MWWorld::Ptr& ptr, float duration)
|
||||
{
|
||||
// magic effects
|
||||
adjustMagicEffects (ptr);
|
||||
|
||||
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
|
||||
|
||||
// calculate dynamic stats
|
||||
int strength = creatureStats.mAttributes[0].getBase();
|
||||
int intelligence = creatureStats.mAttributes[1].getBase();
|
||||
int willpower = creatureStats.mAttributes[2].getBase();
|
||||
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)));
|
||||
creatureStats.mDynamic[1].setBase (static_cast<int> (intelligence +
|
||||
magickaFactor * intelligence));
|
||||
creatureStats.mDynamic[2].setBase (strength+willpower+agility+endurance);
|
||||
}
|
||||
|
||||
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)
|
||||
|
@ -22,6 +41,27 @@ namespace MWMechanics
|
|||
MWWorld::Class::get (ptr).getNpcStats (ptr));
|
||||
}
|
||||
|
||||
void Actors::adjustMagicEffects (const MWWorld::Ptr& creature)
|
||||
{
|
||||
CreatureStats& creatureStats = MWWorld::Class::get (creature).getCreatureStats (creature);
|
||||
|
||||
MagicEffects now = creatureStats.mSpells.getMagicEffects();
|
||||
|
||||
if (creature.getTypeName()==typeid (ESM::NPC).name())
|
||||
{
|
||||
MWWorld::InventoryStore& store = MWWorld::Class::get (creature).getInventoryStore (creature);
|
||||
now += store.getMagicEffects();
|
||||
}
|
||||
|
||||
now += creatureStats.mActiveSpells.getMagicEffects();
|
||||
|
||||
MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now);
|
||||
|
||||
creatureStats.mMagicEffects = now;
|
||||
|
||||
// TODO apply diff to other stats
|
||||
}
|
||||
|
||||
Actors::Actors() : mDuration (0) {}
|
||||
|
||||
void Actors::addActor (const MWWorld::Ptr& ptr)
|
||||
|
|
|
@ -19,10 +19,10 @@ namespace MWMechanics
|
|||
std::set<MWWorld::Ptr> mActors;
|
||||
float mDuration;
|
||||
|
||||
void updateActor (const MWWorld::Ptr& ptr, float duration);
|
||||
|
||||
void updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused);
|
||||
|
||||
void adjustMagicEffects (const MWWorld::Ptr& creature);
|
||||
|
||||
public:
|
||||
|
||||
Actors();
|
||||
|
@ -39,6 +39,11 @@ namespace MWMechanics
|
|||
void update (std::vector<std::pair<std::string, Ogre::Vector3> >& movement,
|
||||
float duration, bool paused);
|
||||
///< Update actor stats and store desired velocity vectors in \a movement
|
||||
|
||||
void updateActor (const MWWorld::Ptr& ptr, float duration);
|
||||
///< This function is normally called automatically during the update process, but it can
|
||||
/// also be called explicitly at any time to force an update.
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "stat.hpp"
|
||||
#include "magiceffects.hpp"
|
||||
#include "spells.hpp"
|
||||
#include "activespells.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
@ -16,6 +17,7 @@ namespace MWMechanics
|
|||
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue
|
||||
int mLevel;
|
||||
Spells mSpells;
|
||||
ActiveSpells mActiveSpells;
|
||||
MagicEffects mMagicEffects;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
#include "magiceffects.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
|
@ -66,6 +68,46 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
void MagicEffects::add (const ESM::EffectList& list)
|
||||
{
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter (list.list.begin()); iter!=list.list.end();
|
||||
++iter)
|
||||
{
|
||||
EffectParam param;
|
||||
|
||||
if (iter->magnMin>=iter->magnMax)
|
||||
param.mMagnitude = iter->magnMin;
|
||||
else
|
||||
param.mMagnitude = static_cast<int> (
|
||||
(iter->magnMax-iter->magnMin+1)*
|
||||
(static_cast<float> (std::rand()) / RAND_MAX) + iter->magnMin);
|
||||
|
||||
add (*iter, param);
|
||||
}
|
||||
}
|
||||
|
||||
MagicEffects& MagicEffects::operator+= (const MagicEffects& effects)
|
||||
{
|
||||
if (this==&effects)
|
||||
{
|
||||
MagicEffects temp (effects);
|
||||
*this += temp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
for (Collection::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter)
|
||||
{
|
||||
Collection::iterator result = mCollection.find (iter->first);
|
||||
|
||||
if (result!=mCollection.end())
|
||||
result->second += iter->second;
|
||||
else
|
||||
mCollection.insert (*iter);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
EffectParam MagicEffects::get (const EffectKey& key) const
|
||||
{
|
||||
Collection::const_iterator iter = mCollection.find (key);
|
||||
|
@ -85,11 +127,11 @@ namespace MWMechanics
|
|||
MagicEffects result;
|
||||
|
||||
// adding/changing
|
||||
for (Collection::const_iterator iter (now.Begin()); iter!=now.End(); ++iter)
|
||||
for (Collection::const_iterator iter (now.begin()); iter!=now.end(); ++iter)
|
||||
{
|
||||
Collection::const_iterator other = prev.mCollection.find (iter->first);
|
||||
|
||||
if (other==prev.End())
|
||||
if (other==prev.end())
|
||||
{
|
||||
// adding
|
||||
result.add (iter->first, iter->second);
|
||||
|
@ -102,17 +144,16 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
// removing
|
||||
for (Collection::const_iterator iter (prev.Begin()); iter!=prev.End(); ++iter)
|
||||
for (Collection::const_iterator iter (prev.begin()); iter!=prev.end(); ++iter)
|
||||
{
|
||||
Collection::const_iterator other = now.mCollection.find (iter->first);
|
||||
|
||||
if (other==prev.End())
|
||||
if (other==prev.end())
|
||||
{
|
||||
result.add (iter->first, EffectParam() - iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
namespace ESM
|
||||
{
|
||||
struct ENAMstruct;
|
||||
struct EffectList;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
|
@ -60,12 +61,16 @@ namespace MWMechanics
|
|||
|
||||
public:
|
||||
|
||||
Collection::const_iterator Begin() const { return mCollection.begin(); }
|
||||
Collection::const_iterator begin() const { return mCollection.begin(); }
|
||||
|
||||
Collection::const_iterator End() const { return mCollection.end(); }
|
||||
Collection::const_iterator end() const { return mCollection.end(); }
|
||||
|
||||
void add (const EffectKey& key, const EffectParam& param);
|
||||
|
||||
void add (const ESM::EffectList& list);
|
||||
|
||||
MagicEffects& operator+= (const MagicEffects& effects);
|
||||
|
||||
EffectParam get (const EffectKey& key) const;
|
||||
///< This function can safely be used for keys that are not present.
|
||||
|
||||
|
|
|
@ -139,42 +139,13 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
// magic effects
|
||||
adjustMagicEffects (ptr);
|
||||
|
||||
// calculate dynamic stats
|
||||
int strength = creatureStats.mAttributes[0].getBase();
|
||||
int intelligence = creatureStats.mAttributes[1].getBase();
|
||||
int willpower = creatureStats.mAttributes[2].getBase();
|
||||
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)));
|
||||
creatureStats.mDynamic[1].setBase (static_cast<int> (intelligence +
|
||||
magickaFactor * intelligence));
|
||||
creatureStats.mDynamic[2].setBase (strength+willpower+agility+endurance);
|
||||
// forced update and current value adjustments
|
||||
mActors.updateActor (ptr, 0);
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified());
|
||||
}
|
||||
|
||||
void MechanicsManager::adjustMagicEffects (MWWorld::Ptr& creature)
|
||||
{
|
||||
MWMechanics::CreatureStats& creatureStats =
|
||||
MWWorld::Class::get (creature).getCreatureStats (creature);
|
||||
|
||||
MagicEffects now = creatureStats.mSpells.getMagicEffects();
|
||||
|
||||
/// \todo add effects from active spells and equipment
|
||||
|
||||
MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now);
|
||||
|
||||
creatureStats.mMagicEffects = now;
|
||||
|
||||
// TODO apply diff to other stats
|
||||
}
|
||||
|
||||
MechanicsManager::MechanicsManager()
|
||||
: mUpdatePlayer (true), mClassSelected (false),
|
||||
|
|
|
@ -31,8 +31,6 @@ namespace MWMechanics
|
|||
///< 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 adjustMagicEffects (MWWorld::Ptr& creature);
|
||||
|
||||
public:
|
||||
|
||||
MechanicsManager ();
|
||||
|
|
|
@ -13,13 +13,7 @@ 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);
|
||||
}
|
||||
effects.add (spell->effects);
|
||||
}
|
||||
|
||||
Spells::TIterator Spells::begin() const
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace MWWorld
|
|||
void clear();
|
||||
///< Empty container.
|
||||
|
||||
void flagAsModified();
|
||||
virtual void flagAsModified();
|
||||
///< \attention This function is internal to the world model and should not be called from
|
||||
/// outside.
|
||||
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include <components/esm/loadench.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
||||
#include "class.hpp"
|
||||
|
@ -32,7 +38,7 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots)
|
|||
slots.push_back (end());
|
||||
}
|
||||
|
||||
MWWorld::InventoryStore::InventoryStore()
|
||||
MWWorld::InventoryStore::InventoryStore() : mMagicEffectsUpToDate (false)
|
||||
{
|
||||
initSlots (mSlots);
|
||||
}
|
||||
|
@ -40,11 +46,15 @@ MWWorld::InventoryStore::InventoryStore()
|
|||
MWWorld::InventoryStore::InventoryStore (const InventoryStore& store)
|
||||
: ContainerStore (store)
|
||||
{
|
||||
mMagicEffects = store.mMagicEffects;
|
||||
mMagicEffectsUpToDate = store.mMagicEffectsUpToDate;
|
||||
copySlots (store);
|
||||
}
|
||||
|
||||
MWWorld::InventoryStore& MWWorld::InventoryStore::operator= (const InventoryStore& store)
|
||||
{
|
||||
mMagicEffects = store.mMagicEffects;
|
||||
mMagicEffectsUpToDate = store.mMagicEffectsUpToDate;
|
||||
ContainerStore::operator= (store);
|
||||
mSlots.clear();
|
||||
copySlots (store);
|
||||
|
@ -201,6 +211,39 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats)
|
|||
}
|
||||
}
|
||||
|
||||
const MWMechanics::MagicEffects& MWWorld::InventoryStore::getMagicEffects()
|
||||
{
|
||||
if (!mMagicEffectsUpToDate)
|
||||
{
|
||||
mMagicEffects = MWMechanics::MagicEffects();
|
||||
|
||||
for (TSlots::const_iterator iter (mSlots.begin()); iter!=mSlots.end(); ++iter)
|
||||
if (*iter!=end())
|
||||
{
|
||||
std::string enchantmentId = MWWorld::Class::get (**iter).getEnchantment (**iter);
|
||||
|
||||
if (!enchantmentId.empty())
|
||||
{
|
||||
const ESM::Enchantment& enchantment =
|
||||
*MWBase::Environment::get().getWorld()->getStore().enchants.find (enchantmentId);
|
||||
|
||||
if (enchantment.data.type==ESM::Enchantment::ConstantEffect)
|
||||
mMagicEffects.add (enchantment.effects);
|
||||
}
|
||||
}
|
||||
|
||||
mMagicEffectsUpToDate = true;
|
||||
}
|
||||
|
||||
return mMagicEffects;
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::flagAsModified()
|
||||
{
|
||||
ContainerStore::flagAsModified();
|
||||
mMagicEffectsUpToDate = false;
|
||||
}
|
||||
|
||||
bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2)
|
||||
{
|
||||
bool canStack = MWWorld::ContainerStore::stacks(ptr1, ptr2);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "containerstore.hpp"
|
||||
|
||||
#include "../mwmechanics/magiceffects.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
struct NpcStats;
|
||||
|
@ -41,6 +43,9 @@ namespace MWWorld
|
|||
|
||||
private:
|
||||
|
||||
mutable MWMechanics::MagicEffects mMagicEffects;
|
||||
mutable bool mMagicEffectsUpToDate;
|
||||
|
||||
typedef std::vector<ContainerStoreIterator> TSlots;
|
||||
|
||||
mutable TSlots mSlots;
|
||||
|
@ -65,6 +70,15 @@ namespace MWWorld
|
|||
void autoEquip (const MWMechanics::NpcStats& stats);
|
||||
///< Auto equip items according to stats and item value.
|
||||
|
||||
const MWMechanics::MagicEffects& getMagicEffects();
|
||||
///< Return magic effects from worn items.
|
||||
///
|
||||
/// \todo make this const again, after the constness of Ptrs and iterators has been addressed.
|
||||
|
||||
virtual void flagAsModified();
|
||||
///< \attention This function is internal to the world model and should not be called from
|
||||
/// outside.
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2);
|
||||
|
|
108
apps/openmw/mwworld/timestamp.cpp
Normal file
108
apps/openmw/mwworld/timestamp.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
|
||||
#include "timestamp.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
TimeStamp::TimeStamp (float hour, int day)
|
||||
: mHour (hour), mDay (day)
|
||||
{
|
||||
if (hour<0 || hour>=24 || day<0)
|
||||
throw std::runtime_error ("invalid time stamp");
|
||||
}
|
||||
|
||||
float TimeStamp::getHour() const
|
||||
{
|
||||
return mHour;
|
||||
}
|
||||
|
||||
int TimeStamp::getDay() const
|
||||
{
|
||||
return mDay;
|
||||
}
|
||||
|
||||
TimeStamp& TimeStamp::operator+= (double hours)
|
||||
{
|
||||
if (hours<0)
|
||||
throw std::runtime_error ("can't move time stamp backwards in time");
|
||||
|
||||
hours += mHour;
|
||||
|
||||
mHour = static_cast<float> (std::fmod (hours, 24));
|
||||
|
||||
mDay += hours / 24;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator== (const TimeStamp& left, const TimeStamp& right)
|
||||
{
|
||||
return left.getHour()==right.getHour() && left.getDay()==right.getDay();
|
||||
}
|
||||
|
||||
bool operator!= (const TimeStamp& left, const TimeStamp& right)
|
||||
{
|
||||
return !(left==right);
|
||||
}
|
||||
|
||||
bool operator< (const TimeStamp& left, const TimeStamp& right)
|
||||
{
|
||||
if (left.getDay()<right.getDay())
|
||||
return true;
|
||||
|
||||
if (left.getDay()>right.getDay())
|
||||
return false;
|
||||
|
||||
return left.getHour()<right.getHour();
|
||||
}
|
||||
|
||||
bool operator<= (const TimeStamp& left, const TimeStamp& right)
|
||||
{
|
||||
return left<right || left==right;
|
||||
}
|
||||
|
||||
bool operator> (const TimeStamp& left, const TimeStamp& right)
|
||||
{
|
||||
return !(left<=right);
|
||||
}
|
||||
|
||||
bool operator>= (const TimeStamp& left, const TimeStamp& right)
|
||||
{
|
||||
return !(left<right);
|
||||
}
|
||||
|
||||
TimeStamp operator+ (const TimeStamp& stamp, double hours)
|
||||
{
|
||||
return TimeStamp (stamp) + hours;
|
||||
}
|
||||
|
||||
TimeStamp operator+ (double hours, const TimeStamp& stamp)
|
||||
{
|
||||
return TimeStamp (stamp) + hours;
|
||||
}
|
||||
|
||||
double operator- (const TimeStamp& left, const TimeStamp& right)
|
||||
{
|
||||
if (left<right)
|
||||
return -(right-left);
|
||||
|
||||
int days = left.getDay() - right.getDay();
|
||||
|
||||
double hours = 0;
|
||||
|
||||
if (left.getHour()<right.getHour())
|
||||
{
|
||||
hours = 24-right.getHour()+left.getHour();
|
||||
++days;
|
||||
}
|
||||
else
|
||||
{
|
||||
hours = left.getHour()-right.getHour();
|
||||
}
|
||||
|
||||
return hours + 24*days;
|
||||
}
|
||||
}
|
44
apps/openmw/mwworld/timestamp.hpp
Normal file
44
apps/openmw/mwworld/timestamp.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef GAME_MWWORLD_TIMESTAMP_H
|
||||
#define GAME_MWWORLD_TIMESTAMP_H
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
/// \brief In-game time stamp
|
||||
///
|
||||
/// This class is based on the global variables GameHour and DaysPassed.
|
||||
class TimeStamp
|
||||
{
|
||||
float mHour;
|
||||
int mDay;
|
||||
|
||||
public:
|
||||
|
||||
explicit TimeStamp (float hour = 0, int day = 0);
|
||||
///< \oaram hour [0, 23)
|
||||
/// \param day >=0
|
||||
|
||||
float getHour() const;
|
||||
|
||||
int getDay() const;
|
||||
|
||||
TimeStamp& operator+= (double hours);
|
||||
///< \param hours >=0
|
||||
};
|
||||
|
||||
bool operator== (const TimeStamp& left, const TimeStamp& right);
|
||||
bool operator!= (const TimeStamp& left, const TimeStamp& right);
|
||||
|
||||
bool operator< (const TimeStamp& left, const TimeStamp& right);
|
||||
bool operator<= (const TimeStamp& left, const TimeStamp& right);
|
||||
|
||||
bool operator> (const TimeStamp& left, const TimeStamp& right);
|
||||
bool operator>= (const TimeStamp& left, const TimeStamp& right);
|
||||
|
||||
TimeStamp operator+ (const TimeStamp& stamp, double hours);
|
||||
TimeStamp operator+ (double hours, const TimeStamp& stamp);
|
||||
|
||||
double operator- (const TimeStamp& left, const TimeStamp& right);
|
||||
///< Returns the difference between \a left and \a right in in-game hours.
|
||||
}
|
||||
|
||||
#endif
|
|
@ -471,6 +471,12 @@ namespace MWWorld
|
|||
mRendering->skySetDate (mGlobalVariables->getInt ("day"), month);
|
||||
}
|
||||
|
||||
TimeStamp World::getTimeStamp() const
|
||||
{
|
||||
return TimeStamp (mGlobalVariables->getFloat ("gamehour"),
|
||||
mGlobalVariables->getInt ("dayspassed"));
|
||||
}
|
||||
|
||||
bool World::toggleSky()
|
||||
{
|
||||
if (mSky)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "physicssystem.hpp"
|
||||
#include "cells.hpp"
|
||||
#include "localscripts.hpp"
|
||||
#include "timestamp.hpp"
|
||||
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
#include <openengine/ogre/fader.hpp>
|
||||
|
@ -185,6 +186,9 @@ namespace MWWorld
|
|||
void setDay (int day);
|
||||
///< Set in-game time day.
|
||||
|
||||
TimeStamp getTimeStamp() const;
|
||||
///< Return current in-game time stamp.
|
||||
|
||||
bool toggleSky();
|
||||
///< \return Resulting mode
|
||||
|
||||
|
|
Loading…
Reference in a new issue