From f6a876bc3d201baa52de4bc2dc76fe12e63b4fcf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 15:27:49 +0200 Subject: [PATCH 01/63] added actor ID --- apps/openmw/mwbase/world.hpp | 3 +++ apps/openmw/mwmechanics/creaturestats.cpp | 18 +++++++++++++- apps/openmw/mwmechanics/creaturestats.hpp | 9 +++++++ apps/openmw/mwworld/cellstore.cpp | 29 +++++++++++++++++++++++ apps/openmw/mwworld/cellstore.hpp | 3 +++ apps/openmw/mwworld/scene.cpp | 10 ++++++++ apps/openmw/mwworld/scene.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 7 +++++- apps/openmw/mwworld/worldimp.hpp | 3 +++ 9 files changed, 82 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 44c8c96be..c397b190f 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -200,6 +200,9 @@ namespace MWBase virtual MWWorld::Ptr searchPtrViaHandle (const std::string& handle) = 0; ///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found + virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0; + ///< Search is limited to the active cells. + /// \todo enable reference in the OGRE scene virtual void enable (const MWWorld::Ptr& ptr) = 0; diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 40ac92251..8490226cb 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -11,6 +11,8 @@ namespace MWMechanics { + int CreatureStats::sActorId = 0; + CreatureStats::CreatureStats() : mLevel (0), mDead (false), mDied (false), mFriendlyHits (0), mTalkedTo (false), mAlarmed (false), @@ -18,7 +20,8 @@ namespace MWMechanics mAttackingOrSpell(false), mIsWerewolf(false), mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), - mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f) + mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), + mActorId (-1) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -516,4 +519,17 @@ namespace MWMechanics { return mGoldPool; } + + int CreatureStats::getActorId() + { + if (mActorId==-1) + mActorId = sActorId++; + + return mActorId; + } + + bool CreatureStats::matchesActorId (int id) const + { + return mActorId!=-1 && id==mActorId; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 633dc285c..23d9303c0 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -24,6 +24,7 @@ namespace MWMechanics /// class CreatureStats { + static int sActorId; DrawState_ mDrawState; AttributeValue mAttributes[8]; DynamicStat mDynamic[3]; // health, magicka, fatigue @@ -60,6 +61,7 @@ namespace MWMechanics MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay int mGoldPool; // the pool of merchant gold not in inventory + int mActorId; protected: bool mIsWerewolf; @@ -239,6 +241,13 @@ namespace MWMechanics void setGoldPool(int pool); int getGoldPool() const; + + int getActorId(); + ///< Will generate an actor ID, if the actor does not have one yet. + + bool matchesActorId (int id) const; + ///< Check if \a id matches the actor ID of *this (if the actor does not have an ID + /// assigned this function will return false). }; } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index e5f0c4b88..7a85623cf 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -15,6 +15,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "ptr.hpp" #include "esmstore.hpp" #include "class.hpp" @@ -40,6 +42,22 @@ namespace return MWWorld::Ptr(); } + template + MWWorld::Ptr searchViaActorId (MWWorld::CellRefList& actorList, int actorId, + MWWorld::CellStore *cell) + { + for (typename MWWorld::CellRefList::List::iterator iter (actorList.mList.begin()); + iter!=actorList.mList.end(); ++iter) + { + MWWorld::Ptr actor (&*iter, cell); + + if (MWWorld::Class::get (actor).getCreatureStats (actor).matchesActorId (actorId)) + return actor; + } + + return MWWorld::Ptr(); + } + template void writeReferenceCollection (ESM::ESMWriter& writer, const MWWorld::CellRefList& collection) @@ -319,6 +337,17 @@ namespace MWWorld return Ptr(); } + Ptr CellStore::searchViaActorId (int id) + { + if (Ptr ptr = ::searchViaActorId (mNpcs, id, this)) + return ptr; + + if (Ptr ptr = ::searchViaActorId (mCreatures, id, this)) + return ptr; + + return Ptr(); + } + float CellStore::getWaterLevel() const { return mWaterLevel; diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 88b49ed1c..69d1a53a3 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -80,6 +80,9 @@ namespace MWWorld Ptr searchViaHandle (const std::string& handle); ///< Will return an empty Ptr if cell is not loaded. + Ptr searchViaActorId (int id); + ///< Will return an empty Ptr if cell is not loaded. + float getWaterLevel() const; void setWaterLevel (float level); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 3d4413a35..9d456e236 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -496,4 +496,14 @@ namespace MWWorld } return false; } + + Ptr Scene::searchPtrViaActorId (int actorId) + { + for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + if (Ptr ptr = (*iter)->searchViaActorId (actorId)) + return ptr; + + return Ptr(); + } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 16d4877a9..b85a3d7ce 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -102,6 +102,8 @@ namespace MWWorld ///< Remove an object from the scene, but not from the world model. bool isCellActive(const CellStore &cell); + + Ptr searchPtrViaActorId (int actorId); }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index de9c8f04a..79c8b38f3 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -549,6 +549,11 @@ namespace MWWorld return MWWorld::Ptr(); } + Ptr World::searchPtrViaActorId (int actorId) + { + return mWorldScene->searchPtrViaActorId (actorId); + } + void World::addContainerScripts(const Ptr& reference, CellStore * cell) { if( reference.getTypeName()==typeid (ESM::Container).name() || @@ -1909,7 +1914,7 @@ namespace MWWorld out.push_back(searchPtrViaHandle(*it)); } } - + bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) { if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled()) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 645330683..2328e67a8 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -287,6 +287,9 @@ namespace MWWorld virtual Ptr searchPtrViaHandle (const std::string& handle); ///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found + virtual Ptr searchPtrViaActorId (int actorId); + ///< Search is limited to the active cells. + virtual void adjustPosition (const Ptr& ptr); ///< Adjust position after load to be on ground. Must be called after model load. From 9a1b5dc1c64d54f64694eba5f9c21cf0e7dfcd25 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 15:32:00 +0200 Subject: [PATCH 02/63] a bit of cleanup --- apps/openmw/mwworld/scene.cpp | 10 ++++++++++ apps/openmw/mwworld/scene.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 11 +---------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 9d456e236..b277b2494 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -497,6 +497,16 @@ namespace MWWorld return false; } + Ptr Scene::searchPtrViaHandle (const std::string& handle) + { + for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + if (Ptr ptr = (*iter)->searchViaHandle (handle)) + return ptr; + + return Ptr(); + } + Ptr Scene::searchPtrViaActorId (int actorId) { for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index b85a3d7ce..a26ad99de 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -103,6 +103,8 @@ namespace MWWorld bool isCellActive(const CellStore &cell); + Ptr searchPtrViaHandle (const std::string& handle); + Ptr searchPtrViaActorId (int actorId); }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 79c8b38f3..6fa182894 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -536,17 +536,8 @@ namespace MWWorld { if (mPlayer->getPlayer().getRefData().getHandle()==handle) return mPlayer->getPlayer(); - for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); - iter!=mWorldScene->getActiveCells().end(); ++iter) - { - CellStore* cellstore = *iter; - Ptr ptr = cellstore->searchViaHandle (handle); - if (!ptr.isEmpty()) - return ptr; - } - - return MWWorld::Ptr(); + return mWorldScene->searchPtrViaHandle (handle); } Ptr World::searchPtrViaActorId (int actorId) From 8f90dd43ecb62676323fb507ba7d014faa6d22f7 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 29 Apr 2014 12:52:08 -0400 Subject: [PATCH 03/63] Changed things to use typedef ScriptARgs/ScriptReturn, which makes finding out what those weird strings meant much much easier --- components/compiler/extensions.cpp | 10 ++++---- components/compiler/extensions.hpp | 38 +++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/components/compiler/extensions.cpp b/components/compiler/extensions.cpp index c09abcbaf..c2b11c615 100644 --- a/components/compiler/extensions.cpp +++ b/components/compiler/extensions.cpp @@ -21,7 +21,7 @@ namespace Compiler return iter->second; } - bool Extensions::isFunction (int keyword, char& returnType, std::string& argumentType, + bool Extensions::isFunction (int keyword, ScriptReturn& returnType, ScriptArgs& argumentType, bool& explicitReference) const { std::map::const_iterator iter = mFunctions.find (keyword); @@ -37,7 +37,7 @@ namespace Compiler return true; } - bool Extensions::isInstruction (int keyword, std::string& argumentType, + bool Extensions::isInstruction (int keyword, ScriptArgs& argumentType, bool& explicitReference) const { std::map::const_iterator iter = mInstructions.find (keyword); @@ -52,8 +52,8 @@ namespace Compiler return true; } - void Extensions::registerFunction (const std::string& keyword, char returnType, - const std::string& argumentType, int code, int codeExplicit) + void Extensions::registerFunction (const std::string& keyword, ScriptReturn returnType, + const ScriptArgs& argumentType, int code, int codeExplicit) { Function function; @@ -83,7 +83,7 @@ namespace Compiler } void Extensions::registerInstruction (const std::string& keyword, - const std::string& argumentType, int code, int codeExplicit) + const ScriptArgs& argumentType, int code, int codeExplicit) { Instruction instruction; diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index 18bb24ed0..5be81ac08 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -11,14 +11,36 @@ namespace Compiler { class Literals; - /// \brief Collection of compiler extensions + /// Typedef for script arguments string + /** Every character reperesents an argument to the command. All arguments are required until a /, after which + every argument is optional.
+ Eg: fff/f represents 3 required floats followed by one optional float
+ f - Float
+ c - String
+ l - Integer
+ s - Short
+ S - Also string (Seemed to be mostly used for Cell Names)
+ x - none? + **/ + typedef std::string ScriptArgs; + + /// Typedef for script return char + /** The character represents the type of data being returned.
+ f - float
+ S - String (Cell names)
+ l - Integer + **/ + typedef char ScriptReturn; + + /// \brief Collection of compiler extensions class Extensions { + struct Function { char mReturn; - std::string mArguments; + ScriptArgs mArguments; int mCode; int mCodeExplicit; int mSegment; @@ -26,7 +48,7 @@ namespace Compiler struct Instruction { - std::string mArguments; + ScriptArgs mArguments; int mCode; int mCodeExplicit; int mSegment; @@ -46,21 +68,21 @@ namespace Compiler /// - if no match is found 0 is returned. /// - keyword must be all lower case. - bool isFunction (int keyword, char& returnType, std::string& argumentType, + bool isFunction (int keyword, ScriptReturn& returnType, ScriptArgs& argumentType, bool& explicitReference) const; ///< Is this keyword registered with a function? If yes, return return and argument /// types. /// \param explicitReference In: has explicit reference; Out: set to false, if /// explicit reference is not available for this instruction. - bool isInstruction (int keyword, std::string& argumentType, + bool isInstruction (int keyword, ScriptArgs& argumentType, bool& explicitReference) const; ///< Is this keyword registered with a function? If yes, return argument types. /// \param explicitReference In: has explicit reference; Out: set to false, if /// explicit reference is not available for this instruction. - void registerFunction (const std::string& keyword, char returnType, - const std::string& argumentType, int code, int codeExplicit = -1); + void registerFunction (const std::string& keyword, ScriptReturn returnType, + const ScriptArgs& argumentType, int code, int codeExplicit = -1); ///< Register a custom function /// - keyword must be all lower case. /// - keyword must be unique @@ -68,7 +90,7 @@ namespace Compiler /// \note Currently only segment 3 and segment 5 opcodes are supported. void registerInstruction (const std::string& keyword, - const std::string& argumentType, int code, int codeExplicit = -1); + const ScriptArgs& argumentType, int code, int codeExplicit = -1); ///< Register a custom instruction /// - keyword must be all lower case. /// - keyword must be unique From 0c2843b0f7e081bfe64c9362f4101462f1223a2d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 19:56:33 +0200 Subject: [PATCH 04/63] some missing cleanup --- apps/openmw/mwmechanics/creaturestats.cpp | 5 +++++ apps/openmw/mwmechanics/creaturestats.hpp | 2 ++ apps/openmw/mwstate/statemanagerimp.cpp | 3 +++ 3 files changed, 10 insertions(+) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 8490226cb..910760685 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -532,4 +532,9 @@ namespace MWMechanics { return mActorId!=-1 && id==mActorId; } + + void CreatureStats::cleanup() + { + sActorId = 0; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 23d9303c0..aee11a358 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -248,6 +248,8 @@ namespace MWMechanics bool matchesActorId (int id) const; ///< Check if \a id matches the actor ID of *this (if the actor does not have an ID /// assigned this function will return false). + + static void cleanup(); }; } diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 33f2dce7c..6dcfd9076 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -28,6 +28,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwmechanics/npcstats.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "../mwscript/globalscripts.hpp" @@ -46,6 +47,8 @@ void MWState::StateManager::cleanup (bool force) mState = State_NoGame; mCharacterManager.clearCurrentCharacter(); mTimePlayed = 0; + + MWMechanics::CreatureStats::cleanup(); } } From 10a5bb946461ec6d48e184a36b76fbb7e8ef9652 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 29 Apr 2014 23:40:59 -0400 Subject: [PATCH 05/63] Made code a bit more standardized and added a good bit of documentation. --- apps/openmw/mwinput/inputmanagerimp.hpp | 6 +- apps/openmw/mwmechanics/aiactivate.hpp | 9 +-- apps/openmw/mwmechanics/aicombat.hpp | 5 +- apps/openmw/mwmechanics/aiescort.hpp | 10 ++- apps/openmw/mwmechanics/aifollow.hpp | 16 ++++- apps/openmw/mwmechanics/aipackage.hpp | 23 ++++--- apps/openmw/mwmechanics/aipersue.hpp | 6 +- apps/openmw/mwmechanics/aisequence.hpp | 62 ++++++++++------- apps/openmw/mwmechanics/aitravel.hpp | 7 +- apps/openmw/mwmechanics/aiwander.hpp | 23 ++++--- apps/openmw/mwmechanics/alchemy.hpp | 92 ++++++++++++------------- 11 files changed, 152 insertions(+), 107 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 3787a9c07..ace4cc6d0 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -46,10 +46,7 @@ namespace MyGUI namespace MWInput { - - /** - * @brief Class that handles all input and key bindings for OpenMW. - */ + /// \brief Class that handles all input and key bindings for OpenMW. class InputManager : public MWBase::InputManager, public SFO::KeyListener, @@ -68,6 +65,7 @@ namespace MWInput /// Clear all savegame-specific data virtual void clear(); + virtual void update(float dt, bool disableControls=false, bool disableEvents=false); void setPlayer (MWWorld::Player* player) { mPlayer = player; } diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index fd54869f6..b6ce9f85d 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -7,15 +7,16 @@ #include "pathfinding.hpp" namespace MWMechanics -{ - +{ + /// \brief Causes actor to walk to activatable object and activate it class AiActivate : public AiPackage { - public: + public: + /// Constructor + /** \param objectId Reference to object to activate **/ AiActivate(const std::string &objectId); virtual AiActivate *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; private: diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 30b72acd9..833b0063c 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -14,20 +14,23 @@ namespace MWMechanics { + /// \brief Causes the actor to fight another actor class AiCombat : public AiPackage { public: + ///Constructor + /** \param actor Actor to fight **/ AiCombat(const MWWorld::Ptr& actor); virtual AiCombat *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; virtual unsigned int getPriority() const; + ///Returns target ID const std::string &getTargetId() const; private: diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index 53b57c058..3771417fa 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -8,18 +8,22 @@ namespace MWMechanics { + /// \brief AI Package to have an NPC lead the player to a specific point class AiEscort : public AiPackage { public: + /// Implementation of AiEscort + /** The Actor will escort the specified actor to the world position x, y, z until they reach their position, or they run out of time + \implement AiEscort **/ AiEscort(const std::string &actorId,int duration, float x, float y, float z); - ///< \implement AiEscort + /// Implementation of AiEscortCell + /** The Actor will escort the specified actor to the cell position x, y, z until they reach their position, or they run out of time + \implement AiEscortCell **/ AiEscort(const std::string &actorId,const std::string &cellId,int duration, float x, float y, float z); - ///< \implement AiEscortCell virtual AiEscort *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 48a8eb4c2..4eb3e3757 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -8,22 +8,32 @@ namespace MWMechanics { - + /// \brief AiPackage for an actor to follow another actor/the PC + /** The AI will follow the target until a condition (time, or position) are set. Both can be disabled to cause the actor to follow the other indefinitely + **/ class AiFollow : public AiPackage { public: + /// Follow Actor for duration or until you arrive at a world position AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z); + /// Follow Actor for duration or until you arrive at a position in a cell AiFollow(const std::string &ActorId,const std::string &CellId,float duration, float X, float Y, float Z); + /// Follow Actor indefinitively AiFollow(const std::string &ActorId); + virtual AiFollow *clone() const; + virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? + virtual int getTypeId() const; + /// Returns the actor being followed std::string getFollowedActor(); private: - bool mAlwaysFollow; //this will make the actor always follow, thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). + /// This will make the actor always follow. + /** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/ + bool mAlwaysFollow; float mDuration; float mX; float mY; diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 8e015da15..30eab7f8b 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -12,6 +12,7 @@ namespace MWMechanics class AiPackage { public: + ///Enumerates the various AITypes availible. enum TypeId { TypeIdNone = -1, TypeIdWander = 0, @@ -23,18 +24,22 @@ namespace MWMechanics TypeIdPersue = 6 }; + ///Default Deconstructor virtual ~AiPackage(); - - virtual AiPackage *clone() const = 0; - - virtual bool execute (const MWWorld::Ptr& actor,float duration) = 0; - ///< \return Package completed? - - virtual int getTypeId() const = 0; - ///< @see enum TypeId + ///Clones the package + virtual AiPackage *clone() const = 0; + + /// Updates and runs the package (Should run every frame) + /// \return Package completed? + virtual bool execute (const MWWorld::Ptr& actor,float duration) = 0; + + /// Returns the TypeID of the AiPackage + /// \see enum TypeId + virtual int getTypeId() const = 0; + + /// Higher number is higher priority (0 beeing the lowest) virtual unsigned int getPriority() const {return 0;} - ///< higher number is higher priority (0 beeing the lowest) }; } diff --git a/apps/openmw/mwmechanics/aipersue.hpp b/apps/openmw/mwmechanics/aipersue.hpp index 3fd708ab3..bf5410676 100644 --- a/apps/openmw/mwmechanics/aipersue.hpp +++ b/apps/openmw/mwmechanics/aipersue.hpp @@ -8,14 +8,16 @@ namespace MWMechanics { - + /// \brief Makes the actor very closely follow the actor + /** Used for getting closer to fight, or to arrest (I think?) **/ class AiPersue : public AiPackage { public: + ///Constructor + /** \param objectId Actor to pursue **/ AiPersue(const std::string &objectId); virtual AiPersue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; private: diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index cb1b0de02..a751e0397 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -13,65 +13,79 @@ namespace MWWorld namespace MWMechanics { class AiPackage; - + /// \brief Sequence of AI-packages for a single actor + /** Each package will be run in succession for an actor until completed **/ class AiSequence { + ///AiPackages to run though std::list mPackages; + ///Finished with all AiPackages bool mDone; + ///Copy AiSequence void copy (const AiSequence& sequence); - // The type of AI package that ran last + /// The type of AI package that ran last int mLastAiPackage; public: - + ///Default constructor AiSequence(); - + + /// Copy Constructor AiSequence (const AiSequence& sequence); - + + /// Assignment operator AiSequence& operator= (const AiSequence& sequence); - + + /// Destructor virtual ~AiSequence(); + /// Returns currently executing AiPackage type + /** \see enum AiPackage::TypeId **/ int getTypeId() const; - ///< @see enum AiPackage::TypeId + /// Get the typeid of the Ai package that ran last + /** NOT the currently "active" Ai package that will be run in the next frame. + This difference is important when an Ai package has just finished and been removed. + \see enum AiPackage::TypeId **/ int getLastRunTypeId() const { return mLastAiPackage; } - ///< Get the typeid of the Ai package that ran last, NOT the currently "active" Ai package that will be run in the next frame. - /// This difference is important when an Ai package has just finished and been removed. + /// Return true and assign target if combat package is currently active, return false otherwise bool getCombatTarget (std::string &targetActorId) const; - ///< Return true and assign target if combat package is currently - /// active, return false otherwise + /// Removes all combat packages until first non-combat or stack empty. void stopCombat(); - ///< Removes all combat packages until first non-combat or stack empty. + /// Removes all persue packages until first non-persue or stack empty. void stopPersue(); - ///< Removes all persue packages until first non-persue or stack empty. - + + /// Has a package been completed during the last update? bool isPackageDone() const; - ///< Has a package been completed during the last update? - + + /// Execute current package, switching if needed. void execute (const MWWorld::Ptr& actor,float duration); - ///< Execute package. - + + /// Remove all packages. void clear(); - ///< Remove all packages. + ///< Add \a package to the front of the sequence + /** Suspends current package **/ void stack (const AiPackage& package, const MWWorld::Ptr& actor); - ///< Add \a package to the front of the sequence (suspends current package) - + + /// Add \a package to the end of the sequence + /** Executed after all other packages have been completed **/ void queue (const AiPackage& package); - ///< Add \a package to the end of the sequence (executed after all other packages have been - /// completed) + /// Return the current active package. + /** If there is no active package, it will throw an exception **/ AiPackage* getActivePackage(); - ///< return the current active package. If there is no active package, throw an exeption + /// Fills the AiSequence with packages + /** Typically used for loading from the ESM + \see ESM::AIPackageList **/ void fill (const ESM::AIPackageList& list); }; } diff --git a/apps/openmw/mwmechanics/aitravel.hpp b/apps/openmw/mwmechanics/aitravel.hpp index 72f3e0298..ea7f1dc32 100644 --- a/apps/openmw/mwmechanics/aitravel.hpp +++ b/apps/openmw/mwmechanics/aitravel.hpp @@ -6,15 +6,16 @@ #include "pathfinding.hpp" namespace MWMechanics -{ +{ + /// \brief Causes the AI to travel to the specified point class AiTravel : public AiPackage { - public: + public: + /// Default constructor AiTravel(float x, float y, float z); virtual AiTravel *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 2975c8315..6481b2a01 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -14,20 +14,27 @@ namespace MWMechanics { + /// \brief Causes the Actor to wander within a specified range class AiWander : public AiPackage { public: - + /// Constructor + /** \param distance Max distance the ACtor will wander + \param duration Time, in hours, that this package will be preformed + \param timeOfDay Start time of the package, if it has a duration. Currently unimplemented + \param idle Chances of each idle to play (9 in total) + \param repeat Repeat wander or not **/ AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat); - virtual AiPackage *clone() const; - virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? - virtual int getTypeId() const; - ///< 0: Wander + virtual AiPackage *clone() const; + + virtual bool execute (const MWWorld::Ptr& actor,float duration); + + virtual int getTypeId() const; + + /// Set the position to return to for a stationary (non-wandering) actor + /** In case another AI package moved the actor elsewhere **/ void setReturnPosition (const Ogre::Vector3& position); - ///< Set the position to return to for a stationary (non-wandering) actor, in case - /// another AI package moved the actor elsewhere private: void stopWalking(const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwmechanics/alchemy.hpp b/apps/openmw/mwmechanics/alchemy.hpp index 31cafa4dc..b2b0fe1ee 100644 --- a/apps/openmw/mwmechanics/alchemy.hpp +++ b/apps/openmw/mwmechanics/alchemy.hpp @@ -31,6 +31,8 @@ namespace MWMechanics typedef std::vector TEffectsContainer; typedef TEffectsContainer::const_iterator TEffectsIterator; + /// Result of potion creation + /** Only Result_Success results in success **/ enum Result { Result_Success, @@ -42,6 +44,46 @@ namespace MWMechanics Result_RandomFailure }; + /// Set alchemist and configure alchemy setup accordingly. + /** \a npc may be empty to indicate that there is no alchemist (alchemy session has ended). **/ + void setAlchemist (const MWWorld::Ptr& npc); + + /// \attention Iterates over tool slots, not over tools. Some of the slots may be empty. + TToolsIterator beginTools() const; + + TToolsIterator endTools() const; + + /// \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty. + TIngredientsIterator beginIngredients() const; + + TIngredientsIterator endIngredients() const; + + /// Remove alchemist, tools and ingredients. + void clear(); + + /// Add ingredient into the next free slot. + /// + /// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being + /// listed already. + int addIngredient (const MWWorld::Ptr& ingredient); + + /// Remove ingredient from slot (calling this function on an empty slot is a no-op). + void removeIngredient (int index); + + TEffectsIterator beginEffects() const; + + TEffectsIterator endEffects() const; + + /// Return the name of the potion that would be created when calling create (if a record for such + /// a potion already exists) or return an empty string. + std::string getPotionName() const; + + /// Try to create a potion from the ingredients, place it in the inventory of the alchemist and + /// adjust the skills of the alchemist accordingly. + /// \param name must not be an empty string, unless there is already a potion record ( + /// getPotionName() does not return an empty string). + Result create (const std::string& name); + private: MWWorld::Ptr mAlchemist; @@ -50,19 +92,19 @@ namespace MWMechanics TEffectsContainer mEffects; int mValue; + /// List all effects shared by at least two ingredients. std::set listEffects() const; - ///< List all effects shared by at least two ingredients. void applyTools (int flags, float& value) const; void updateEffects(); + /// Return existing recrod for created potion (may return 0) const ESM::Potion *getRecord() const; - ///< Return existing recrod for created potion (may return 0) - void removeIngredients(); - ///< Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and + /// Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and /// update effect list accordingly. + void removeIngredients(); void addPotion (const std::string& name); ///< Add a potion to the alchemist's inventory. @@ -74,48 +116,6 @@ namespace MWMechanics ///< Return chance of success. int countIngredients() const; - - public: - - void setAlchemist (const MWWorld::Ptr& npc); - ///< Set alchemist and configure alchemy setup accordingly. \a npc may be empty to indicate that - /// there is no alchemist (alchemy session has ended). - - TToolsIterator beginTools() const; - ///< \attention Iterates over tool slots, not over tools. Some of the slots may be empty. - - TToolsIterator endTools() const; - - TIngredientsIterator beginIngredients() const; - ///< \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty. - - TIngredientsIterator endIngredients() const; - - void clear(); - ///< Remove alchemist, tools and ingredients. - - int addIngredient (const MWWorld::Ptr& ingredient); - ///< Add ingredient into the next free slot. - /// - /// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being - /// listed already. - - void removeIngredient (int index); - ///< Remove ingredient from slot (calling this function on an empty slot is a no-op). - - TEffectsIterator beginEffects() const; - - TEffectsIterator endEffects() const; - - std::string getPotionName() const; - ///< Return the name of the potion that would be created when calling create (if a record for such - /// a potion already exists) or return an empty string. - - Result create (const std::string& name); - ///< Try to create a potion from the ingredients, place it in the inventory of the alchemist and - /// adjust the skills of the alchemist accordingly. - /// \param name must not be an empty string, unless there is already a potion record ( - /// getPotionName() does not return an empty string). }; } From 46eb20b98ce990756ad1f9af5054f0a571dca43c Mon Sep 17 00:00:00 2001 From: slothlife Date: Fri, 9 May 2014 08:32:52 -0500 Subject: [PATCH 06/63] Fixes for warnings when building with MSVC Most warnings are innocuous (wrong type-specifier for forward declarations, conversion of literals into unsigned integers, warnings about methods optimized out), but I believe actual bugs were revealed in vartypedelegate.cpp and combat.cpp. --- CMakeLists.txt | 1 + apps/esmtool/esmtool.cpp | 2 - apps/mwiniimporter/main.cpp | 2 +- apps/opencs/model/doc/document.cpp | 516 +++++++++--------- apps/opencs/model/doc/document.hpp | 2 +- apps/opencs/model/doc/documentmanager.hpp | 4 +- apps/opencs/model/world/commands.hpp | 4 +- apps/opencs/model/world/idtable.hpp | 2 +- apps/opencs/model/world/infocollection.hpp | 4 +- apps/opencs/model/world/ref.hpp | 2 +- apps/opencs/model/world/refcollection.hpp | 2 +- apps/opencs/model/world/refidadapter.hpp | 4 +- apps/opencs/view/render/lightingday.cpp | 4 +- apps/opencs/view/render/lightingnight.cpp | 6 +- apps/opencs/view/render/scenewidget.cpp | 4 +- apps/opencs/view/world/vartypedelegate.cpp | 2 +- apps/openmw/mwgui/bookpage.cpp | 4 +- apps/openmw/mwgui/companionwindow.cpp | 2 +- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/spellicons.hpp | 2 + apps/openmw/mwmechanics/combat.cpp | 4 +- apps/openmw/mwmechanics/levelledlist.hpp | 2 +- apps/openmw/mwrender/localmap.cpp | 2 +- apps/openmw/mwrender/occlusionquery.cpp | 2 +- apps/openmw/mwrender/weaponanimation.hpp | 1 + .../mwscript/transformationextensions.cpp | 4 +- apps/openmw/mwsound/ffmpeg_decoder.cpp | 2 +- apps/openmw/mwsound/openal_output.cpp | 12 +- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +- .../contentselector/model/contentmodel.cpp | 1 - components/esm/esmreader.hpp | 2 +- components/esm/inventorystate.hpp | 2 + components/esm/loadcell.hpp | 2 +- components/ogreinit/ogreplugin.cpp | 6 +- components/terrain/material.cpp | 4 +- 37 files changed, 314 insertions(+), 311 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd437ed61..89bf75c6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -610,6 +610,7 @@ if (WIN32) 4305 # Truncating value (double to float, for example) 4309 # Variable overflow, trying to store 128 in a signed char for example 4355 # Using 'this' in member initialization list + 4505 # Unreferenced local function has been removed 4701 # Potentially uninitialized local variable used 4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt ) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index eef96c8c9..6b67cf7d5 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -218,8 +218,6 @@ int main(int argc, char**argv) std::cout << "Invalid or no mode specified, dying horribly. Have a nice day." << std::endl; return 1; } - - return 0; } void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 364a6b1a4..c2cb8117a 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) { std::cerr << "cfg file does not exist" << std::endl; MwIniImporter importer; - importer.setVerbose(vm.count("verbose")); + importer.setVerbose(vm.count("verbose") != 0); // Font encoding settings std::string encoding(vm["encoding"].as()); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 3ef14ee7e..72d7f5cd8 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -292,264 +292,264 @@ void CSMDoc::Document::addGmsts() static const float gmstFloatsValues[] = { - 0.3, // fAIFleeFleeMult - 7.0, // fAIFleeHealthMult - 3.0, // fAIMagicSpellMult - 1.0, // fAIMeleeArmorMult - 1.0, // fAIMeleeSummWeaponMult - 2.0, // fAIMeleeWeaponMult - 5.0, // fAIRangeMagicSpellMult - 5.0, // fAIRangeMeleeWeaponMult - 2000.0, // fAlarmRadius - 1.0, // fAthleticsRunBonus - 40.0, // fAudioDefaultMaxDistance - 5.0, // fAudioDefaultMinDistance - 50.0, // fAudioMaxDistanceMult - 20.0, // fAudioMinDistanceMult - 60.0, // fAudioVoiceDefaultMaxDistance - 10.0, // fAudioVoiceDefaultMinDistance - 50.0, // fAutoPCSpellChance - 80.0, // fAutoSpellChance - 50.0, // fBargainOfferBase - -4.0, // fBargainOfferMulti - 24.0, // fBarterGoldResetDelay - 1.75, // fBaseRunMultiplier - 1.25, // fBlockStillBonus - 150.0, // fBribe1000Mod - 75.0, // fBribe100Mod - 35.0, // fBribe10Mod - 60.0, // fCombatAngleXY - 60.0, // fCombatAngleZ - 0.25, // fCombatArmorMinMult - -90.0, // fCombatBlockLeftAngle - 30.0, // fCombatBlockRightAngle - 4.0, // fCombatCriticalStrikeMult - 0.1, // fCombatDelayCreature - 0.1, // fCombatDelayNPC - 128.0, // fCombatDistance - 0.3, // fCombatDistanceWerewolfMod - 30.0, // fCombatForceSideAngle - 0.2, // fCombatInvisoMult - 1.5, // fCombatKODamageMult - 45.0, // fCombatTorsoSideAngle - 0.3, // fCombatTorsoStartPercent - 0.8, // fCombatTorsoStopPercent - 15.0, // fConstantEffectMult - 72.0, // fCorpseClearDelay - 72.0, // fCorpseRespawnDelay - 0.5, // fCrimeGoldDiscountMult - 0.9, // fCrimeGoldTurnInMult - 1.0, // fCrimeStealing - 0.5, // fDamageStrengthBase - 0.1, // fDamageStrengthMult - 5.0, // fDifficultyMult - 2.5, // fDiseaseXferChance - -10.0, // fDispAttacking - -1.0, // fDispBargainFailMod - 1.0, // fDispBargainSuccessMod - 0.0, // fDispCrimeMod - -10.0, // fDispDiseaseMod - 3.0, // fDispFactionMod - 1.0, // fDispFactionRankBase - 0.5, // fDispFactionRankMult - 1.0, // fDispositionMod - 50.0, // fDispPersonalityBase - 0.5, // fDispPersonalityMult - -25.0, // fDispPickPocketMod - 5.0, // fDispRaceMod - -0.5, // fDispStealing - -5.0, // fDispWeaponDrawn - 0.5, // fEffectCostMult - 0.1, // fElementalShieldMult - 3.0, // fEnchantmentChanceMult - 0.5, // fEnchantmentConstantChanceMult - 100.0, // fEnchantmentConstantDurationMult - 0.1, // fEnchantmentMult - 1000.0, // fEnchantmentValueMult - 0.3, // fEncumberedMoveEffect - 5.0, // fEncumbranceStrMult - 0.04, // fEndFatigueMult - 0.25, // fFallAcroBase - 0.01, // fFallAcroMult - 400.0, // fFallDamageDistanceMin - 0.0, // fFallDistanceBase - 0.07, // fFallDistanceMult - 2.0, // fFatigueAttackBase - 0.0, // fFatigueAttackMult - 1.25, // fFatigueBase - 4.0, // fFatigueBlockBase - 0.0, // fFatigueBlockMult - 5.0, // fFatigueJumpBase - 0.0, // fFatigueJumpMult - 0.5, // fFatigueMult - 2.5, // fFatigueReturnBase - 0.02, // fFatigueReturnMult - 5.0, // fFatigueRunBase - 2.0, // fFatigueRunMult - 1.5, // fFatigueSneakBase - 1.5, // fFatigueSneakMult - 0.0, // fFatigueSpellBase - 0.0, // fFatigueSpellCostMult - 0.0, // fFatigueSpellMult - 7.0, // fFatigueSwimRunBase - 0.0, // fFatigueSwimRunMult - 2.5, // fFatigueSwimWalkBase - 0.0, // fFatigueSwimWalkMult - 0.2, // fFightDispMult - 0.005, // fFightDistanceMultiplier - 50.0, // fFightStealing - 3000.0, // fFleeDistance - 512.0, // fGreetDistanceReset - 0.1, // fHandtoHandHealthPer - 1.0, // fHandToHandReach - 0.5, // fHoldBreathEndMult - 20.0, // fHoldBreathTime - 0.75, // fIdleChanceMultiplier - 1.0, // fIngredientMult - 0.5, // fInteriorHeadTrackMult - 128.0, // fJumpAcrobaticsBase - 4.0, // fJumpAcroMultiplier - 0.5, // fJumpEncumbranceBase - 1.0, // fJumpEncumbranceMultiplier - 0.5, // fJumpMoveBase - 0.5, // fJumpMoveMult - 1.0, // fJumpRunMultiplier - 0.5, // fKnockDownMult - 5.0, // fLevelMod - 0.1, // fLevelUpHealthEndMult - 0.6, // fLightMaxMod - 10.0, // fLuckMod - 10.0, // fMagesGuildTravel - 1.5, // fMagicCreatureCastDelay - 0.0167, // fMagicDetectRefreshRate - 1.0, // fMagicItemConstantMult - 1.0, // fMagicItemCostMult - 1.0, // fMagicItemOnceMult - 1.0, // fMagicItemPriceMult - 0.05, // fMagicItemRechargePerSecond - 1.0, // fMagicItemStrikeMult - 1.0, // fMagicItemUsedMult - 3.0, // fMagicStartIconBlink - 0.5, // fMagicSunBlockedMult - 0.75, // fMajorSkillBonus - 300.0, // fMaxFlySpeed - 0.5, // fMaxHandToHandMult - 400.0, // fMaxHeadTrackDistance - 200.0, // fMaxWalkSpeed - 300.0, // fMaxWalkSpeedCreature - 0.9, // fMedMaxMod - 0.1, // fMessageTimePerChar - 5.0, // fMinFlySpeed - 0.1, // fMinHandToHandMult - 1.0, // fMinorSkillBonus - 100.0, // fMinWalkSpeed - 5.0, // fMinWalkSpeedCreature - 1.25, // fMiscSkillBonus - 2.0, // fNPCbaseMagickaMult - 0.5, // fNPCHealthBarFade - 3.0, // fNPCHealthBarTime - 1.0, // fPCbaseMagickaMult - 0.3, // fPerDieRollMult - 5.0, // fPersonalityMod - 1.0, // fPerTempMult - -1.0, // fPickLockMult - 0.3, // fPickPocketMod - 20.0, // fPotionMinUsefulDuration - 0.5, // fPotionStrengthMult - 0.5, // fPotionT1DurMult - 1.5, // fPotionT1MagMult - 20.0, // fPotionT4BaseStrengthMult - 12.0, // fPotionT4EquipStrengthMult - 3000.0, // fProjectileMaxSpeed - 400.0, // fProjectileMinSpeed - 25.0, // fProjectileThrownStoreChance - 3.0, // fRepairAmountMult - 1.0, // fRepairMult - 1.0, // fReputationMod - 0.15, // fRestMagicMult - 0.0, // fSeriousWoundMult - 0.25, // fSleepRandMod - 0.3, // fSleepRestMod - -1.0, // fSneakBootMult - 0.5, // fSneakDistanceBase - 0.002, // fSneakDistanceMultiplier - 0.5, // fSneakNoViewMult - 1.0, // fSneakSkillMult - 0.75, // fSneakSpeedMultiplier - 1.0, // fSneakUseDelay - 500.0, // fSneakUseDist - 1.5, // fSneakViewMult - 3.0, // fSoulGemMult - 0.8, // fSpecialSkillBonus - 7.0, // fSpellMakingValueMult - 2.0, // fSpellPriceMult - 10.0, // fSpellValueMult - 0.25, // fStromWalkMult - 0.7, // fStromWindSpeed - 3.0, // fSuffocationDamage - 0.9, // fSwimHeightScale - 0.1, // fSwimRunAthleticsMult - 0.5, // fSwimRunBase - 0.02, // fSwimWalkAthleticsMult - 0.5, // fSwimWalkBase - 1.0, // fSwingBlockBase - 1.0, // fSwingBlockMult - 1000.0, // fTargetSpellMaxSpeed - 1000.0, // fThrownWeaponMaxSpeed - 300.0, // fThrownWeaponMinSpeed - 0.0, // fTrapCostMult - 4000.0, // fTravelMult - 16000.0,// fTravelTimeMult - 0.1, // fUnarmoredBase1 - 0.065, // fUnarmoredBase2 - 30.0, // fVanityDelay - 10.0, // fVoiceIdleOdds - 0.0, // fWaterReflectUpdateAlways - 10.0, // fWaterReflectUpdateSeldom - 0.1, // fWeaponDamageMult - 1.0, // fWeaponFatigueBlockMult - 0.25, // fWeaponFatigueMult - 150.0, // fWereWolfAcrobatics - 150.0, // fWereWolfAgility - 1.0, // fWereWolfAlchemy - 1.0, // fWereWolfAlteration - 1.0, // fWereWolfArmorer - 150.0, // fWereWolfAthletics - 1.0, // fWereWolfAxe - 1.0, // fWereWolfBlock - 1.0, // fWereWolfBluntWeapon - 1.0, // fWereWolfConjuration - 1.0, // fWereWolfDestruction - 1.0, // fWereWolfEnchant - 150.0, // fWereWolfEndurance - 400.0, // fWereWolfFatigue - 100.0, // fWereWolfHandtoHand - 2.0, // fWereWolfHealth - 1.0, // fWereWolfHeavyArmor - 1.0, // fWereWolfIllusion - 1.0, // fWereWolfIntellegence - 1.0, // fWereWolfLightArmor - 1.0, // fWereWolfLongBlade - 1.0, // fWereWolfLuck - 100.0, // fWereWolfMagicka - 1.0, // fWereWolfMarksman - 1.0, // fWereWolfMediumArmor - 1.0, // fWereWolfMerchantile - 1.0, // fWereWolfMysticism - 1.0, // fWereWolfPersonality - 1.0, // fWereWolfRestoration - 1.5, // fWereWolfRunMult - 1.0, // fWereWolfSecurity - 1.0, // fWereWolfShortBlade - 1.5, // fWereWolfSilverWeaponDamageMult - 1.0, // fWereWolfSneak - 1.0, // fWereWolfSpear - 1.0, // fWereWolfSpeechcraft - 150.0, // fWereWolfSpeed - 150.0, // fWereWolfStrength - 100.0, // fWereWolfUnarmored - 1.0, // fWereWolfWillPower - 15.0, // fWortChanceValue + 0.3f, // fAIFleeFleeMult + 7.0f, // fAIFleeHealthMult + 3.0f, // fAIMagicSpellMult + 1.0f, // fAIMeleeArmorMult + 1.0f, // fAIMeleeSummWeaponMult + 2.0f, // fAIMeleeWeaponMult + 5.0f, // fAIRangeMagicSpellMult + 5.0f, // fAIRangeMeleeWeaponMult + 2000.0f, // fAlarmRadius + 1.0f, // fAthleticsRunBonus + 40.0f, // fAudioDefaultMaxDistance + 5.0f, // fAudioDefaultMinDistance + 50.0f, // fAudioMaxDistanceMult + 20.0f, // fAudioMinDistanceMult + 60.0f, // fAudioVoiceDefaultMaxDistance + 10.0f, // fAudioVoiceDefaultMinDistance + 50.0f, // fAutoPCSpellChance + 80.0f, // fAutoSpellChance + 50.0f, // fBargainOfferBase + -4.0f, // fBargainOfferMulti + 24.0f, // fBarterGoldResetDelay + 1.75f, // fBaseRunMultiplier + 1.25f, // fBlockStillBonus + 150.0f, // fBribe1000Mod + 75.0f, // fBribe100Mod + 35.0f, // fBribe10Mod + 60.0f, // fCombatAngleXY + 60.0f, // fCombatAngleZ + 0.25f, // fCombatArmorMinMult + -90.0f, // fCombatBlockLeftAngle + 30.0f, // fCombatBlockRightAngle + 4.0f, // fCombatCriticalStrikeMult + 0.1f, // fCombatDelayCreature + 0.1f, // fCombatDelayNPC + 128.0f, // fCombatDistance + 0.3f, // fCombatDistanceWerewolfMod + 30.0f, // fCombatForceSideAngle + 0.2f, // fCombatInvisoMult + 1.5f, // fCombatKODamageMult + 45.0f, // fCombatTorsoSideAngle + 0.3f, // fCombatTorsoStartPercent + 0.8f, // fCombatTorsoStopPercent + 15.0f, // fConstantEffectMult + 72.0f, // fCorpseClearDelay + 72.0f, // fCorpseRespawnDelay + 0.5f, // fCrimeGoldDiscountMult + 0.9f, // fCrimeGoldTurnInMult + 1.0f, // fCrimeStealing + 0.5f, // fDamageStrengthBase + 0.1f, // fDamageStrengthMult + 5.0f, // fDifficultyMult + 2.5f, // fDiseaseXferChance + -10.0f, // fDispAttacking + -1.0f, // fDispBargainFailMod + 1.0f, // fDispBargainSuccessMod + 0.0f, // fDispCrimeMod + -10.0f, // fDispDiseaseMod + 3.0f, // fDispFactionMod + 1.0f, // fDispFactionRankBase + 0.5f, // fDispFactionRankMult + 1.0f, // fDispositionMod + 50.0f, // fDispPersonalityBase + 0.5f, // fDispPersonalityMult + -25.0f, // fDispPickPocketMod + 5.0f, // fDispRaceMod + -0.5f, // fDispStealing + -5.0f, // fDispWeaponDrawn + 0.5f, // fEffectCostMult + 0.1f, // fElementalShieldMult + 3.0f, // fEnchantmentChanceMult + 0.5f, // fEnchantmentConstantChanceMult + 100.0f, // fEnchantmentConstantDurationMult + 0.1f, // fEnchantmentMult + 1000.0f, // fEnchantmentValueMult + 0.3f, // fEncumberedMoveEffect + 5.0f, // fEncumbranceStrMult + 0.04f, // fEndFatigueMult + 0.25f, // fFallAcroBase + 0.01f, // fFallAcroMult + 400.0f, // fFallDamageDistanceMin + 0.0f, // fFallDistanceBase + 0.07f, // fFallDistanceMult + 2.0f, // fFatigueAttackBase + 0.0f, // fFatigueAttackMult + 1.25f, // fFatigueBase + 4.0f, // fFatigueBlockBase + 0.0f, // fFatigueBlockMult + 5.0f, // fFatigueJumpBase + 0.0f, // fFatigueJumpMult + 0.5f, // fFatigueMult + 2.5f, // fFatigueReturnBase + 0.02f, // fFatigueReturnMult + 5.0f, // fFatigueRunBase + 2.0f, // fFatigueRunMult + 1.5f, // fFatigueSneakBase + 1.5f, // fFatigueSneakMult + 0.0f, // fFatigueSpellBase + 0.0f, // fFatigueSpellCostMult + 0.0f, // fFatigueSpellMult + 7.0f, // fFatigueSwimRunBase + 0.0f, // fFatigueSwimRunMult + 2.5f, // fFatigueSwimWalkBase + 0.0f, // fFatigueSwimWalkMult + 0.2f, // fFightDispMult + 0.005f, // fFightDistanceMultiplier + 50.0f, // fFightStealing + 3000.0f, // fFleeDistance + 512.0f, // fGreetDistanceReset + 0.1f, // fHandtoHandHealthPer + 1.0f, // fHandToHandReach + 0.5f, // fHoldBreathEndMult + 20.0f, // fHoldBreathTime + 0.75f, // fIdleChanceMultiplier + 1.0f, // fIngredientMult + 0.5f, // fInteriorHeadTrackMult + 128.0f, // fJumpAcrobaticsBase + 4.0f, // fJumpAcroMultiplier + 0.5f, // fJumpEncumbranceBase + 1.0f, // fJumpEncumbranceMultiplier + 0.5f, // fJumpMoveBase + 0.5f, // fJumpMoveMult + 1.0f, // fJumpRunMultiplier + 0.5f, // fKnockDownMult + 5.0f, // fLevelMod + 0.1f, // fLevelUpHealthEndMult + 0.6f, // fLightMaxMod + 10.0f, // fLuckMod + 10.0f, // fMagesGuildTravel + 1.5f, // fMagicCreatureCastDelay + 0.0167f, // fMagicDetectRefreshRate + 1.0f, // fMagicItemConstantMult + 1.0f, // fMagicItemCostMult + 1.0f, // fMagicItemOnceMult + 1.0f, // fMagicItemPriceMult + 0.05f, // fMagicItemRechargePerSecond + 1.0f, // fMagicItemStrikeMult + 1.0f, // fMagicItemUsedMult + 3.0f, // fMagicStartIconBlink + 0.5f, // fMagicSunBlockedMult + 0.75f, // fMajorSkillBonus + 300.0f, // fMaxFlySpeed + 0.5f, // fMaxHandToHandMult + 400.0f, // fMaxHeadTrackDistance + 200.0f, // fMaxWalkSpeed + 300.0f, // fMaxWalkSpeedCreature + 0.9f, // fMedMaxMod + 0.1f, // fMessageTimePerChar + 5.0f, // fMinFlySpeed + 0.1f, // fMinHandToHandMult + 1.0f, // fMinorSkillBonus + 100.0f, // fMinWalkSpeed + 5.0f, // fMinWalkSpeedCreature + 1.25f, // fMiscSkillBonus + 2.0f, // fNPCbaseMagickaMult + 0.5f, // fNPCHealthBarFade + 3.0f, // fNPCHealthBarTime + 1.0f, // fPCbaseMagickaMult + 0.3f, // fPerDieRollMult + 5.0f, // fPersonalityMod + 1.0f, // fPerTempMult + -1.0f, // fPickLockMult + 0.3f, // fPickPocketMod + 20.0f, // fPotionMinUsefulDuration + 0.5f, // fPotionStrengthMult + 0.5f, // fPotionT1DurMult + 1.5f, // fPotionT1MagMult + 20.0f, // fPotionT4BaseStrengthMult + 12.0f, // fPotionT4EquipStrengthMult + 3000.0f, // fProjectileMaxSpeed + 400.0f, // fProjectileMinSpeed + 25.0f, // fProjectileThrownStoreChance + 3.0f, // fRepairAmountMult + 1.0f, // fRepairMult + 1.0f, // fReputationMod + 0.15f, // fRestMagicMult + 0.0f, // fSeriousWoundMult + 0.25f, // fSleepRandMod + 0.3f, // fSleepRestMod + -1.0f, // fSneakBootMult + 0.5f, // fSneakDistanceBase + 0.002f, // fSneakDistanceMultiplier + 0.5f, // fSneakNoViewMult + 1.0f, // fSneakSkillMult + 0.75f, // fSneakSpeedMultiplier + 1.0f, // fSneakUseDelay + 500.0f, // fSneakUseDist + 1.5f, // fSneakViewMult + 3.0f, // fSoulGemMult + 0.8f, // fSpecialSkillBonus + 7.0f, // fSpellMakingValueMult + 2.0f, // fSpellPriceMult + 10.0f, // fSpellValueMult + 0.25f, // fStromWalkMult + 0.7f, // fStromWindSpeed + 3.0f, // fSuffocationDamage + 0.9f, // fSwimHeightScale + 0.1f, // fSwimRunAthleticsMult + 0.5f, // fSwimRunBase + 0.02f, // fSwimWalkAthleticsMult + 0.5f, // fSwimWalkBase + 1.0f, // fSwingBlockBase + 1.0f, // fSwingBlockMult + 1000.0f, // fTargetSpellMaxSpeed + 1000.0f, // fThrownWeaponMaxSpeed + 300.0f, // fThrownWeaponMinSpeed + 0.0f, // fTrapCostMult + 4000.0f, // fTravelMult + 16000.0f,// fTravelTimeMult + 0.1f, // fUnarmoredBase1 + 0.065f, // fUnarmoredBase2 + 30.0f, // fVanityDelay + 10.0f, // fVoiceIdleOdds + 0.0f, // fWaterReflectUpdateAlways + 10.0f, // fWaterReflectUpdateSeldom + 0.1f, // fWeaponDamageMult + 1.0f, // fWeaponFatigueBlockMult + 0.25f, // fWeaponFatigueMult + 150.0f, // fWereWolfAcrobatics + 150.0f, // fWereWolfAgility + 1.0f, // fWereWolfAlchemy + 1.0f, // fWereWolfAlteration + 1.0f, // fWereWolfArmorer + 150.0f, // fWereWolfAthletics + 1.0f, // fWereWolfAxe + 1.0f, // fWereWolfBlock + 1.0f, // fWereWolfBluntWeapon + 1.0f, // fWereWolfConjuration + 1.0f, // fWereWolfDestruction + 1.0f, // fWereWolfEnchant + 150.0f, // fWereWolfEndurance + 400.0f, // fWereWolfFatigue + 100.0f, // fWereWolfHandtoHand + 2.0f, // fWereWolfHealth + 1.0f, // fWereWolfHeavyArmor + 1.0f, // fWereWolfIllusion + 1.0f, // fWereWolfIntellegence + 1.0f, // fWereWolfLightArmor + 1.0f, // fWereWolfLongBlade + 1.0f, // fWereWolfLuck + 100.0f, // fWereWolfMagicka + 1.0f, // fWereWolfMarksman + 1.0f, // fWereWolfMediumArmor + 1.0f, // fWereWolfMerchantile + 1.0f, // fWereWolfMysticism + 1.0f, // fWereWolfPersonality + 1.0f, // fWereWolfRestoration + 1.5f, // fWereWolfRunMult + 1.0f, // fWereWolfSecurity + 1.0f, // fWereWolfShortBlade + 1.5f, // fWereWolfSilverWeaponDamageMult + 1.0f, // fWereWolfSneak + 1.0f, // fWereWolfSpear + 1.0f, // fWereWolfSpeechcraft + 150.0f, // fWereWolfSpeed + 150.0f, // fWereWolfStrength + 100.0f, // fWereWolfUnarmored + 1.0f, // fWereWolfWillPower + 15.0f, // fWortChanceValue }; static const char *gmstIntegers[] = diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 201fb4342..9f0617eb9 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -26,7 +26,7 @@ namespace ESM namespace Files { - class ConfigurationManager; + struct ConfigurationManager; } namespace CSMDoc diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index b969862e9..6c66f2c0e 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -8,7 +8,7 @@ namespace Files { - class ConfigurationManager; + struct ConfigurationManager; } namespace CSMDoc @@ -46,4 +46,4 @@ namespace CSMDoc }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index ec6350658..bc477e26a 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -20,7 +20,7 @@ namespace CSMWorld { class IdTable; class IdTable; - class RecordBase; + struct RecordBase; class ModifyCommand : public QUndoCommand { @@ -137,4 +137,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 8b5462825..c5c84eeda 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -11,7 +11,7 @@ namespace CSMWorld { class CollectionBase; - class RecordBase; + struct RecordBase; class IdTable : public QAbstractItemModel { diff --git a/apps/opencs/model/world/infocollection.hpp b/apps/opencs/model/world/infocollection.hpp index ae61f5d39..08024d45d 100644 --- a/apps/opencs/model/world/infocollection.hpp +++ b/apps/opencs/model/world/infocollection.hpp @@ -6,7 +6,7 @@ namespace ESM { - class Dialogue; + struct Dialogue; } namespace CSMWorld @@ -47,4 +47,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index fcf016ee2..4c7699185 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -10,7 +10,7 @@ namespace ESM namespace CSMWorld { - class Cell; + struct Cell; /// \brief Wrapper for CellRef sub record struct CellRef : public ESM::CellRef diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 173efba05..be2f5e579 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -8,7 +8,7 @@ namespace CSMWorld { struct Cell; - struct UniversalId; + class UniversalId; /// \brief References in cells class RefCollection : public Collection diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 0870a2d3e..74c5dfe58 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -9,7 +9,7 @@ namespace CSMWorld { class RefIdColumn; class RefIdData; - class RecordBase; + struct RecordBase; class RefIdAdapter { @@ -35,4 +35,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/render/lightingday.cpp b/apps/opencs/view/render/lightingday.cpp index ab0257c0c..fa2656f89 100644 --- a/apps/opencs/view/render/lightingday.cpp +++ b/apps/opencs/view/render/lightingday.cpp @@ -13,7 +13,7 @@ void CSVRender::LightingDay::activate (Ogre::SceneManager *sceneManager, if (defaultAmbient) mSceneManager->setAmbientLight (*defaultAmbient); else - mSceneManager->setAmbientLight (Ogre::ColourValue (0.7, 0.7, 0.7, 1)); + mSceneManager->setAmbientLight (Ogre::ColourValue (0.7f, 0.7f, 0.7f, 1.0f)); mLight = mSceneManager->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); @@ -33,4 +33,4 @@ void CSVRender::LightingDay::deactivate() void CSVRender::LightingDay::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/lightingnight.cpp b/apps/opencs/view/render/lightingnight.cpp index 516bb3f40..f49171775 100644 --- a/apps/opencs/view/render/lightingnight.cpp +++ b/apps/opencs/view/render/lightingnight.cpp @@ -13,12 +13,12 @@ void CSVRender::LightingNight::activate (Ogre::SceneManager *sceneManager, if (defaultAmbient) mSceneManager->setAmbientLight (*defaultAmbient); else - mSceneManager->setAmbientLight (Ogre::ColourValue (0.2, 0.2, 0.2, 1)); + mSceneManager->setAmbientLight (Ogre::ColourValue (0.2f, 0.2f, 0.2f, 1.0f)); mLight = mSceneManager->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); mLight->setDirection (Ogre::Vector3 (0, 0, -1)); - mLight->setDiffuseColour (Ogre::ColourValue (0.2, 0.2, 0.2)); + mLight->setDiffuseColour (Ogre::ColourValue (0.2f, 0.2f, 0.2f)); } void CSVRender::LightingNight::deactivate() @@ -33,4 +33,4 @@ void CSVRender::LightingNight::deactivate() void CSVRender::LightingNight::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 8a58b7d32..f56ba82ec 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -42,7 +42,7 @@ namespace CSVRender mCamera->setPosition (300, 0, 0); mCamera->lookAt (0, 0, 0); - mCamera->setNearClipDistance (0.1); + mCamera->setNearClipDistance (0.1f); mCamera->setFarClipDistance (30000); mCamera->roll (Ogre::Degree (90)); @@ -104,7 +104,7 @@ namespace CSVRender #endif mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, ¶ms); - mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3,0.3,0.3,1)); + mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3f,0.3f,0.3f,1.0f)); Ogre::Real aspectRatio = Ogre::Real(width()) / Ogre::Real(height()); mCamera->setAspectRatio(aspectRatio); diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index 15ce2dbaf..fc00f4491 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -79,7 +79,7 @@ void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) std::vector enums = CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType); - if (type<0 && type>=enums.size()) + if (static_cast(type) >= enums.size()) throw std::logic_error ("Unsupported variable type"); mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str()))); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 52682342f..b797a7742 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -767,7 +767,7 @@ public: PageDisplay () { - mPage = -1; + mPage = static_cast(-1); mViewTop = 0; mViewBottom = 0; mFocusItem = NULL; @@ -917,7 +917,7 @@ public: else { mBook.reset (); - mPage = -1; + mPage = static_cast(-1); mViewTop = 0; mViewBottom = 0; } diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index a0a34108e..0044583db 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -23,7 +23,7 @@ CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* ma : WindowBase("openmw_companion_window.layout") , mDragAndDrop(dragAndDrop) , mMessageBoxManager(manager) - , mSelectedItem(-1) + , mSelectedItem(static_cast(-1)) , mModel(NULL) , mSortModel(NULL) { diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 585647338..8b287a10d 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -111,7 +111,7 @@ namespace MWGui ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop) : WindowBase("openmw_container_window.layout") , mDragAndDrop(dragAndDrop) - , mSelectedItem(-1) + , mSelectedItem(static_cast(-1)) , mModel(NULL) , mSortModel(NULL) , mPickpocketDetected(false) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 6c43f47b4..3c6f99e68 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -510,7 +510,7 @@ namespace MWGui void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos) { - mHistory->setPosition(0,-pos); + mHistory->setPosition(0, (~pos) + 1); } void DialogueWindow::addResponse(const std::string &text, const std::string &title) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 2bea088e3..af631a2fe 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -38,7 +38,7 @@ namespace MWGui , mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())) , mPreviewDirty(true) , mDragAndDrop(dragAndDrop) - , mSelectedItem(-1) + , mSelectedItem(static_cast(-1)) , mGuiMode(GM_Inventory) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 1bb80f3d4..82d8b1f2d 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -42,6 +42,8 @@ namespace MWGui std::map > mEffectSources; + virtual ~EffectSourceVisitor() {} + virtual void visit (MWMechanics::EffectKey key, const std::string& sourceName, const std::string& casterHandle, float magnitude, float remainingTime = -1); diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index cdc12e210..5ffa7a547 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -146,8 +146,8 @@ namespace MWMechanics || weapon.get()->mBase->mData.mFlags & ESM::Weapon::Magical)) damage *= multiplier; - if (weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver - & actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) + if ((weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver) + && actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) damage *= MWBase::Environment::get().getWorld()->getStore().get().find("fWereWolfSilverWeaponDamageMult")->getFloat(); if (damage == 0 && attacker.getRefData().getHandle() == "player") diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 120616f9f..6888d88a6 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -70,7 +70,7 @@ namespace MWMechanics return getLevelledItem(ref.getPtr().get()->mBase, failChance); } } - catch (std::logic_error& e) + catch (std::logic_error&) { // Vanilla doesn't fail on nonexistent items in levelled lists std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 0f6d782a6..4486559ba 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -267,7 +267,7 @@ void LocalMap::render(const float x, const float y, // initialize to (0, 0, 0, 1) for (int p=0; pgetBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 67bc75e02..92a49acc0 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -35,7 +35,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0); } - catch (Ogre::Exception& e) + catch (Ogre::Exception&) { mSupported = false; } diff --git a/apps/openmw/mwrender/weaponanimation.hpp b/apps/openmw/mwrender/weaponanimation.hpp index c09aa65d9..cbe910c71 100644 --- a/apps/openmw/mwrender/weaponanimation.hpp +++ b/apps/openmw/mwrender/weaponanimation.hpp @@ -33,6 +33,7 @@ namespace MWRender { public: WeaponAnimation() : mPitchFactor(0) {} + virtual ~WeaponAnimation() {} virtual void attachArrow(MWWorld::Ptr actor); virtual void releaseArrow(MWWorld::Ptr actor); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 1efc79643..705193798 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -295,7 +295,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception &e) + catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) @@ -395,7 +395,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception &e) + catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index c595de5ae..75f7ccae4 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -204,7 +204,7 @@ void FFmpeg_Decoder::open(const std::string &fname) mFrame = avcodec_alloc_frame(); } - catch(std::exception &e) + catch(std::exception&) { if (mFormatCtx->pb->buffer != NULL) { diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 9a3dd7342..b245b9241 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -288,7 +288,7 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode mOutput.mActiveSounds.push_back(this); } - catch(std::exception &e) + catch(std::exception&) { alDeleteBuffers(sNumBuffers, mBuffers); alGetError(); @@ -471,7 +471,7 @@ bool OpenAL_SoundStream::process() mIsFinished = finished; } - catch(std::exception &e) { + catch(std::exception&) { std::cout<< "Error updating stream \""<getName()<<"\"" <open(fname); } - catch(Ogre::FileNotFoundException &e) + catch(Ogre::FileNotFoundException&) { std::string::size_type pos = fname.rfind('.'); if(pos == std::string::npos) @@ -859,7 +859,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float vol, f buf = getBuffer(fname); sound.reset(new OpenAL_Sound(*this, src, buf, Ogre::Vector3(0.0f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -898,7 +898,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre buf = getBuffer(fname); sound.reset(new OpenAL_Sound3D(*this, src, buf, pos, vol, basevol, pitch, min, max, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -940,7 +940,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float volume, fl { sound.reset(new OpenAL_SoundStream(*this, src, decoder, volume, pitch, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); throw; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 8ce87a25e..6854358f5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -321,7 +321,7 @@ namespace MWSound sound = mOutput->playSound(file, volume, basevol, pitch, mode|type, offset); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); } - catch(std::exception &e) + catch(std::exception&) { //std::cout <<"Sound Error: "< &getGameFiles() const { return mHeader.mMaster; } diff --git a/components/esm/inventorystate.hpp b/components/esm/inventorystate.hpp index 3cfffbccc..21776f683 100644 --- a/components/esm/inventorystate.hpp +++ b/components/esm/inventorystate.hpp @@ -14,6 +14,8 @@ namespace ESM /// \brief State for inventories and containers struct InventoryState { + virtual ~InventoryState() {} + // anything but lights (type, slot) std::vector > > mItems; diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index f01c88c65..b5eede9f5 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -129,7 +129,7 @@ struct Cell bool hasWater() const { - return (mData.mFlags&HasWater); + return (mData.mFlags & HasWater) != 0; } // Restore the given reader to the stored position. Will try to open diff --git a/components/ogreinit/ogreplugin.cpp b/components/ogreinit/ogreplugin.cpp index 6070c43a8..91f3fce95 100644 --- a/components/ogreinit/ogreplugin.cpp +++ b/components/ogreinit/ogreplugin.cpp @@ -30,8 +30,7 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: return false; #endif //OGRE_PLATFORM == OGRE_PLATFORM_WIN32 } -#endif //defined(DEBUG) - +#else //!defined(DEBUG) pluginPath = pluginDir + "/" + pluginName + pluginExt; if (boost::filesystem::exists(pluginPath)) { ogreRoot.loadPlugin(pluginPath); @@ -40,6 +39,7 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: else { return false; } +#endif } -} \ No newline at end of file +} diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index faa73a986..a65b6b3b1 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -181,7 +181,7 @@ namespace Terrain // shadow. TODO: repeated, put in function if (mShadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) + for (Ogre::uint i = 0; i < (mSplitShadows ? 3u : 1u); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); @@ -334,7 +334,7 @@ namespace Terrain // shadow if (shadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) + for (Ogre::uint i = 0; i < (mSplitShadows ? 3u : 1u); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); From ac8abd339827b2aedb792ed35569fb03cef4bffa Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 14:34:55 +0200 Subject: [PATCH 07/63] assert -> exception to gracefully handle corrupted savegames --- apps/openmw/mwrender/localmap.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 56b2326ec..78d7527f7 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -296,7 +296,8 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, ESM::FogState* fog = cell->getFog(); // We are using the same bounds and angle as we were using when the textures were originally made. Segments should come out the same. - assert (i < int(fog->mFogTextures.size())); + if (i >= int(fog->mFogTextures.size())) + throw std::runtime_error("fog texture count mismatch"); ESM::FogTexture& esm = fog->mFogTextures[i]; loadFogOfWar(texturePrefix, esm); @@ -351,7 +352,8 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& Ogre::Image image; image.load(stream, "tga"); - assert (image.getWidth() == sFogOfWarResolution && image.getHeight() == sFogOfWarResolution); + if (image.getWidth() != sFogOfWarResolution || image.getHeight() != sFogOfWarResolution) + throw std::runtime_error("fog texture size mismatch"); std::string texName = texturePrefix + "_fog"; From 961c4d4dc4ef07b6bf994529e492c6fefd0158f1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 15:17:25 +0200 Subject: [PATCH 08/63] Fixes #772: Give scripts a chance to run before updating map, so that disabled objects are not visible --- apps/openmw/mwgui/mapwindow.cpp | 13 ++++++++++++- apps/openmw/mwgui/mapwindow.hpp | 11 +++++++++-- apps/openmw/mwworld/scene.cpp | 17 +++++++++++++---- apps/openmw/mwworld/scene.hpp | 2 ++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index dc22dcb22..2bd5e44cb 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -465,7 +465,18 @@ namespace MWGui void MapWindow::cellExplored(int x, int y) { - mGlobalMapRender->exploreCell(x,y); + mQueuedToExplore.push_back(std::make_pair(x,y)); + } + + void MapWindow::onFrame(float dt) + { + for (std::vector::iterator it = mQueuedToExplore.begin(); it != mQueuedToExplore.end(); ++it) + { + mGlobalMapRender->exploreCell(it->first, it->second); + } + mQueuedToExplore.clear(); + + NoDrop::onFrame(dt); } void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index a28c71ac9..5251fac23 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -97,14 +97,17 @@ namespace MWGui void renderGlobalMap(Loading::Listener* loadingListener); - void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map + // adds the marker to the global map + void addVisitedLocation(const std::string& name, int x, int y); + + // reveals this cell's map on the global map void cellExplored(int x, int y); void setGlobalMapPlayerPosition (float worldX, float worldY); virtual void open(); - void onFrame(float dt) { NoDrop::onFrame(dt); } + void onFrame(float dt); /// Clear all savegame-specific data void clear(); @@ -132,6 +135,10 @@ namespace MWGui typedef std::pair CellId; std::vector mMarkers; + // Cells that should be explored in the next frame (i.e. their map revealed on the global map) + // We can't do this immediately, because the map update is not immediate either (see mNeedMapUpdate in scene.cpp) + std::vector mQueuedToExplore; + MyGUI::Button* mEventBoxGlobal; MyGUI::Button* mEventBoxLocal; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 3d4413a35..49fd8cb89 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -85,7 +85,15 @@ namespace namespace MWWorld { - void Scene::update (float duration, bool paused){ + void Scene::update (float duration, bool paused) + { + if (mNeedMapUpdate) + { + for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) + mRendering.requestMap(*active); + mNeedMapUpdate = false; + } + mRendering.update (duration, paused); } @@ -197,8 +205,9 @@ namespace MWWorld mRendering.updateTerrain(); - for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) - mRendering.requestMap(*active); + // Delay the map update until scripts have been given a chance to run. + // If we don't do this, objects that should be disabled will still appear on the map. + mNeedMapUpdate = true; MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); } @@ -342,7 +351,7 @@ namespace MWWorld //We need the ogre renderer and a scene node. Scene::Scene (MWRender::RenderingManager& rendering, PhysicsSystem *physics) - : mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering) + : mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering), mNeedMapUpdate(false) { } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 16d4877a9..8d8765378 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -58,6 +58,8 @@ namespace MWWorld PhysicsSystem *mPhysics; MWRender::RenderingManager& mRendering; + bool mNeedMapUpdate; + void playerCellChange (CellStore *cell, const ESM::Position& position, bool adjustPlayerPos = true); From 7428511ea06145261522f7e16864555b98394ca4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 15:22:46 +0200 Subject: [PATCH 09/63] Bug #772: Do not show door markers for disabled doors --- apps/openmw/mwworld/worldimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ba36d4a86..d5da19dfa 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1491,6 +1491,9 @@ namespace MWWorld { MWWorld::LiveCellRef& ref = *it; + if (!ref.mData.isEnabled()) + continue; + if (ref.mRef.mTeleport) { World::DoorMarker newMarker; From 54a893994a9c708192c7d0055dbcd3ac5ffec314 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 15:23:44 +0200 Subject: [PATCH 10/63] Also update local map when paused, to make it update properly when teleporting via GUI/console --- apps/openmw/mwrender/renderingmanager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 948f85b5e..a3c53dc44 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -380,6 +380,10 @@ void RenderingManager::update (float duration, bool paused) mCamera->update(duration, paused); + Ogre::SceneNode *node = data.getBaseNode(); + Ogre::Quaternion orient = node->_getDerivedOrientation(); + mLocalMap->updatePlayer(playerPos, orient); + if(paused) return; @@ -393,10 +397,6 @@ void RenderingManager::update (float duration, bool paused) mSkyManager->setGlare(mOcclusionQuery->getSunVisibility()); - Ogre::SceneNode *node = data.getBaseNode(); - Ogre::Quaternion orient = node->_getDerivedOrientation(); - - mLocalMap->updatePlayer(playerPos, orient); mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam)); From 2bc2684a667ee0123b806d66eeb8538ff5a23c0c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 15:36:31 +0200 Subject: [PATCH 11/63] Fixes #275: force updating exterior cell maps even if already in cache --- apps/openmw/mwrender/localmap.cpp | 12 ++++++++++-- apps/openmw/mwrender/localmap.hpp | 3 ++- apps/openmw/mwworld/scene.cpp | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 78d7527f7..4168127df 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -168,7 +168,10 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, float zMin, float zMax) mCameraPosNode->setPosition(Vector3(0,0,0)); - render((x+0.5)*sSize, (y+0.5)*sSize, zMin, zMax, sSize, sSize, name); + // Note: using force=true for exterior cell maps. + // They must be updated even if they were visited before, because the set of surrounding active cells might be different + // (and objects in a different cell can "bleed" into another cell's map if they cross the border) + render((x+0.5)*sSize, (y+0.5)*sSize, zMin, zMax, sSize, sSize, name, true); if (mBuffers.find(name) == mBuffers.end()) { @@ -371,7 +374,7 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& void LocalMap::render(const float x, const float y, const float zlow, const float zhigh, - const float xw, const float yw, const std::string& texture) + const float xw, const float yw, const std::string& texture, bool force) { mCellCamera->setFarClipDistance( (zhigh-zlow) + 2000 ); mCellCamera->setNearClipDistance(50); @@ -410,6 +413,11 @@ void LocalMap::render(const float x, const float y, PF_R8G8B8); tex->getBuffer()->blit(mRenderTexture->getBuffer()); } + else if (force) + { + mRenderTarget->update(); + tex->getBuffer()->blit(mRenderTexture->getBuffer()); + } mRenderingManager->enableLights(true); mLight->setVisible(false); diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 941171527..babf7224e 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -106,10 +106,11 @@ namespace MWRender float mAngle; const Ogre::Vector2 rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle); + /// @param force Always render, even if we already have a cached map void render(const float x, const float y, const float zlow, const float zhigh, const float xw, const float yw, - const std::string& texture); + const std::string& texture, bool force=false); // Creates a fog of war texture and initializes it to full black void createFogOfWar(const std::string& texturePrefix); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 49fd8cb89..7af926dca 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -89,6 +89,8 @@ namespace MWWorld { if (mNeedMapUpdate) { + // Note: exterior cell maps must be updated, even if they were visited before, because the set of surrounding cells might be different + // (and objects in a different cell can "bleed" into another cells map if they cross the border) for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) mRendering.requestMap(*active); mNeedMapUpdate = false; From b0fbea9d57e55c3708d487b6ddf8c95c596b903b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 21:03:27 +0200 Subject: [PATCH 12/63] Removed a wrong assertion. Max drowning time is defined by GMST. --- apps/openmw/mwmechanics/npcstats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 819c2701c..b1d2c75b1 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -432,9 +432,9 @@ float MWMechanics::NpcStats::getTimeToStartDrowning() const { return mTimeToStartDrowning; } + void MWMechanics::NpcStats::setTimeToStartDrowning(float time) { - assert(time>=0 && time<=20); mTimeToStartDrowning=time; } From 117b812fb1890c559deb3d872f3e3affa48edd60 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 12 May 2014 02:20:56 +0200 Subject: [PATCH 13/63] Fix invisibility not breaking on certain actions --- apps/openmw/mwgui/hud.cpp | 3 +++ apps/openmw/mwgui/inventorywindow.cpp | 4 +++- apps/openmw/mwworld/actionapply.cpp | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index be4a9a14e..ccd4489ba 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -233,6 +233,9 @@ namespace MWGui MWBase::World* world = MWBase::Environment::get().getWorld(); + MWBase::Environment::get().getWorld()->breakInvisibility( + MWBase::Environment::get().getWorld()->getPlayerPtr()); + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition(); float mouseX = cursorPosition.left / float(viewSize.width); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 2bea088e3..d6da3b30e 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -541,9 +541,11 @@ namespace MWGui int count = object.getRefData().getCount(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + MWBase::Environment::get().getWorld()->breakInvisibility(player); + // add to player inventory // can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr newObject = *player.getClass().getContainerStore (player).add (object, object.getRefData().getCount(), player); // remove from world MWBase::Environment::get().getWorld()->deleteObject (object); diff --git a/apps/openmw/mwworld/actionapply.cpp b/apps/openmw/mwworld/actionapply.cpp index f78b8f798..bd3e87548 100644 --- a/apps/openmw/mwworld/actionapply.cpp +++ b/apps/openmw/mwworld/actionapply.cpp @@ -3,6 +3,9 @@ #include "class.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + namespace MWWorld { ActionApply::ActionApply (const Ptr& target, const std::string& id) @@ -11,6 +14,8 @@ namespace MWWorld void ActionApply::executeImp (const Ptr& actor) { + MWBase::Environment::get().getWorld()->breakInvisibility(actor); + MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor); } @@ -22,6 +27,8 @@ namespace MWWorld void ActionApplyWithSkill::executeImp (const Ptr& actor) { + MWBase::Environment::get().getWorld()->breakInvisibility(actor); + if (MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor) && mUsageType!=-1) MWWorld::Class::get (getTarget()).skillUsageSucceeded (actor, mSkillIndex, mUsageType); } From 6cc691115bcbc4fc04e0f80a2373cb3e8736851c Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 12 May 2014 21:04:02 +0200 Subject: [PATCH 14/63] Savegame: store most of CreatureStats --- apps/openmw/mwclass/npc.cpp | 3 - apps/openmw/mwgui/windowmanagerimp.cpp | 19 ++- apps/openmw/mwmechanics/creaturestats.cpp | 79 ++++++++--- apps/openmw/mwmechanics/creaturestats.hpp | 7 +- apps/openmw/mwmechanics/drawstate.hpp | 6 +- .../mwmechanics/mechanicsmanagerimp.cpp | 4 +- apps/openmw/mwmechanics/npcstats.cpp | 21 ++- apps/openmw/mwmechanics/npcstats.hpp | 5 +- apps/openmw/mwmechanics/spells.cpp | 77 +++++++++- apps/openmw/mwmechanics/spells.hpp | 19 ++- apps/openmw/mwrender/localmap.cpp | 3 +- apps/openmw/mwstate/statemanagerimp.cpp | 2 + apps/openmw/mwworld/esmstore.cpp | 2 +- apps/openmw/mwworld/inventorystore.hpp | 1 + apps/openmw/mwworld/timestamp.cpp | 18 ++- apps/openmw/mwworld/timestamp.hpp | 10 +- apps/openmw/mwworld/worldimp.cpp | 4 +- components/CMakeLists.txt | 2 +- components/esm/creaturestats.cpp | 132 +++++++++++++++++- components/esm/creaturestats.hpp | 34 ++++- components/esm/defs.hpp | 7 + components/esm/esmwriter.cpp | 3 + components/esm/esmwriter.hpp | 1 + components/esm/npcstats.cpp | 29 +++- components/esm/npcstats.hpp | 6 +- components/esm/quickkeys.cpp | 17 ++- components/esm/spellstate.cpp | 66 +++++++++ components/esm/spellstate.hpp | 29 ++++ 28 files changed, 526 insertions(+), 80 deletions(-) create mode 100644 components/esm/spellstate.cpp create mode 100644 components/esm/spellstate.hpp diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index b548e0844..4c9b683a4 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -357,9 +357,6 @@ namespace MWClass data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "", MWBase::Environment::get().getWorld()->getStore()); - // Relates to NPC gold reset delay - data->mNpcStats.setTradeTime(MWWorld::TimeStamp(0.0, 0)); - data->mNpcStats.setGoldPool(gold); // store diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e3baf84fb..ed6910221 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1326,9 +1326,6 @@ namespace MWGui void WindowManager::updatePlayer() { - unsetSelectedSpell(); - unsetSelectedWeapon(); - mInventoryWindow->updatePlayer(); } @@ -1425,6 +1422,14 @@ namespace MWGui mQuickKeysMenu->write(writer); progress.increaseProgress(); + + if (!mSelectedSpell.empty()) + { + writer.startRecord(ESM::REC_ASPL); + writer.writeHNString("ID__", mSelectedSpell); + writer.endRecord(ESM::REC_ASPL); + progress.increaseProgress(); + } } void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type) @@ -1433,12 +1438,18 @@ namespace MWGui mMap->readRecord(reader, type); else if (type == ESM::REC_KEYS) mQuickKeysMenu->readRecord(reader, type); + else if (type == ESM::REC_ASPL) + { + reader.getSubNameIs("ID__"); + mSelectedSpell = reader.getHString(); + } } int WindowManager::countSavedGameRecords() const { return 1 // Global map - + 1; // QuickKeysMenu + + 1 // QuickKeysMenu + + (!mSelectedSpell.empty() ? 1 : 0); } bool WindowManager::isSavingAllowed() const diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 40ac92251..1482ee24e 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -17,8 +17,10 @@ namespace MWMechanics mAttacked (false), mHostile (false), mAttackingOrSpell(false), mIsWerewolf(false), - mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), - mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f) + mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), + mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), + mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), + mTradeTime(0,0), mGoldPool(0) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -348,20 +350,6 @@ namespace MWMechanics return mLastHitObject; } - bool CreatureStats::canUsePower(const std::string &power) const - { - std::map::const_iterator it = mUsedPowers.find(power); - if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp()) - return true; - else - return false; - } - - void CreatureStats::usePower(const std::string &power) - { - mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp(); - } - void CreatureStats::addToFallHeight(float height) { mFallHeight += height; @@ -481,20 +469,75 @@ namespace MWMechanics void CreatureStats::writeState (ESM::CreatureStats& state) const { - for (int i=0; i<8; ++i) + for (int i=0; i mUsedPowers; - MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay int mGoldPool; // the pool of merchant gold not in inventory protected: + // These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods. bool mIsWerewolf; AttributeValue mWerewolfAttributes[8]; + int mLevel; public: @@ -84,9 +84,6 @@ namespace MWMechanics /// @return total fall height float land(); - bool canUsePower (const std::string& power) const; - void usePower (const std::string& power); - const AttributeValue & getAttribute(int index) const; const DynamicStat & getHealth() const; diff --git a/apps/openmw/mwmechanics/drawstate.hpp b/apps/openmw/mwmechanics/drawstate.hpp index 5be00505c..7f59d8d78 100644 --- a/apps/openmw/mwmechanics/drawstate.hpp +++ b/apps/openmw/mwmechanics/drawstate.hpp @@ -6,9 +6,9 @@ namespace MWMechanics /// \note The _ suffix is required to avoid a collision with a Windoze macro. Die, Microsoft! Die! enum DrawState_ { - DrawState_Weapon = 0, - DrawState_Spell = 1, - DrawState_Nothing = 2 + DrawState_Nothing = 0, + DrawState_Weapon = 1, + DrawState_Spell = 2 }; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index eb51ddfc5..2b1f82b92 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -342,7 +342,9 @@ namespace MWMechanics MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); if (enchantItem != inv.end()) winMgr->setSelectedEnchantItem(*enchantItem); - else if (winMgr->getSelectedSpell() == "") + else if (!winMgr->getSelectedSpell().empty()) + winMgr->setSelectedSpell(winMgr->getSelectedSpell(), int(MWMechanics::getSpellSuccessChance(winMgr->getSelectedSpell(), mWatched))); + else winMgr->unsetSelectedSpell(); } diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index b1d2c75b1..24e758e32 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -446,11 +446,16 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const state.mDisposition = mDisposition; - for (int i=0; i<27; ++i) + for (int i=0; i::const_iterator iter (state.mUsedIds.begin()); diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index 0ae596a54..185a58b94 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -31,8 +31,8 @@ namespace MWMechanics std::map mFactionRank; int mDisposition; - SkillValue mSkill[27]; - SkillValue mWerewolfSkill[27]; + SkillValue mSkill[ESM::Skill::Length]; + SkillValue mWerewolfSkill[ESM::Skill::Length]; int mBounty; std::set mExpelled; std::map mFactionReputation; @@ -40,7 +40,6 @@ namespace MWMechanics int mCrimeId; int mWerewolfKills; int mProfit; - float mAttackStrength; int mLevelProgress; // 0-10 diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index c2bf794f1..a326b7a6d 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -30,10 +31,19 @@ namespace MWMechanics { const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find(spellId); - std::vector random; - random.resize(spell->mEffects.mList.size()); - for (unsigned int i=0; i (std::rand()) / RAND_MAX; + std::map random; + + // Determine the random magnitudes (unless this is a castable spell, in which case + // they will be determined when the spell is cast) + if (spell->mData.mType != ESM::Spell::ST_Power && spell->mData.mType != ESM::Spell::ST_Spell) + { + for (unsigned int i=0; imEffects.mList.size();++i) + { + if (spell->mEffects.mList[i].mMagnMin != spell->mEffects.mList[i].mMagnMax) + random[i] = static_cast (std::rand()) / RAND_MAX; + } + } + mSpells.insert (std::make_pair (Misc::StringUtils::lowerCase(spellId), random)); } } @@ -67,7 +77,11 @@ namespace MWMechanics int i=0; for (std::vector::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it) { - effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * iter->second[i]); + float random = 1.f; + if (iter->second.find(i) != iter->second.end()) + random = iter->second.at(i); + + effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random); ++i; } } @@ -192,9 +206,60 @@ namespace MWMechanics for (std::vector::const_iterator effectIt = list.mList.begin(); effectIt != list.mList.end(); ++effectIt, ++i) { - float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * it->second[i]; + float random = 1.f; + if (it->second.find(i) != it->second.end()) + random = it->second.at(i); + + float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, "", magnitude); } } } + + bool Spells::canUsePower(const std::string &power) const + { + std::map::const_iterator it = mUsedPowers.find(power); + if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp()) + return true; + else + return false; + } + + void Spells::usePower(const std::string &power) + { + mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp(); + } + + void Spells::readState(const ESM::SpellState &state) + { + mSpells = state.mSpells; + mSelectedSpell = state.mSelectedSpell; + + // Discard spells that are no longer available due to changed content files + for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().search(iter->first); + if (!spell) + { + if (iter->first == mSelectedSpell) + mSelectedSpell = ""; + mSpells.erase(iter++); + } + else + ++iter; + } + + // No need to discard spells here (doesn't really matter if non existent ids are kept) + for (std::map::const_iterator it = state.mUsedPowers.begin(); it != state.mUsedPowers.end(); ++it) + mUsedPowers[it->first] = MWWorld::TimeStamp(it->second); + } + + void Spells::writeState(ESM::SpellState &state) const + { + state.mSpells = mSpells; + state.mSelectedSpell = mSelectedSpell; + + for (std::map::const_iterator it = mUsedPowers.begin(); it != mUsedPowers.end(); ++it) + state.mUsedPowers[it->first] = it->second.toEsm(); + } } diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index 354b1fd0b..6997a9d7a 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -7,12 +7,16 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/timestamp.hpp" #include "magiceffects.hpp" + namespace ESM { struct Spell; + + struct SpellState; } namespace MWMechanics @@ -22,21 +26,29 @@ namespace MWMechanics /// \brief Spell list /// /// This class manages known spells as well as abilities, powers and permanent negative effects like - /// diseases. + /// diseases. It also keeps track of used powers (which can only be used every 24h). class Spells { public: - typedef std::map > TContainer; // ID, normalised magnitudes + + typedef std::map > TContainer; // ID, typedef TContainer::const_iterator TIterator; private: TContainer mSpells; + + // Note: this is the spell that's about to be cast, *not* the spell selected in the GUI (which may be different) std::string mSelectedSpell; + std::map mUsedPowers; + public: + bool canUsePower (const std::string& power) const; + void usePower (const std::string& power); + void purgeCommonDisease(); void purgeBlightDisease(); void purgeCorprusDisease(); @@ -72,6 +84,9 @@ namespace MWMechanics bool hasBlightDisease() const; void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor) const; + + void readState (const ESM::SpellState& state); + void writeState (ESM::SpellState& state) const; }; } diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 4168127df..0d32dd0ef 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -342,8 +342,6 @@ Ogre::TexturePtr LocalMap::createFogOfWarTexture(const std::string &texName) PF_A8R8G8B8, TU_DYNAMIC_WRITE_ONLY); } - else - tex->unload(); return tex; } @@ -362,6 +360,7 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& Ogre::TexturePtr tex = createFogOfWarTexture(texName); + tex->unload(); tex->loadImage(image); // create a buffer to use for dynamic operations diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index c89041710..153da1f30 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -326,6 +326,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl case ESM::REC_GMAP: case ESM::REC_KEYS: + case ESM::REC_ASPL: + MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val); break; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index a769e7f67..ed140434b 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -199,7 +199,7 @@ void ESMStore::setUp() if (!mRaces.find (player->mRace) || !mClasses.find (player->mClass)) - throw std::runtime_error ("Invalid player record (race or class unavilable"); + throw std::runtime_error ("Invalid player record (race or class unavailable"); } return true; diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index b4b275b6a..95b956907 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -87,6 +87,7 @@ namespace MWWorld float mMultiplier; }; + // TODO: store in savegame typedef std::map > TEffectMagnitudes; TEffectMagnitudes mPermanentMagicEffectMagnitudes; diff --git a/apps/openmw/mwworld/timestamp.cpp b/apps/openmw/mwworld/timestamp.cpp index 126d5490c..a73ed7ca5 100644 --- a/apps/openmw/mwworld/timestamp.cpp +++ b/apps/openmw/mwworld/timestamp.cpp @@ -1,10 +1,10 @@ - #include "timestamp.hpp" #include - #include +#include + namespace MWWorld { TimeStamp::TimeStamp (float hour, int day) @@ -105,4 +105,18 @@ namespace MWWorld return hours + 24*days; } + + ESM::TimeStamp TimeStamp::toEsm() const + { + ESM::TimeStamp ret; + ret.mDay = mDay; + ret.mHour = mHour; + return ret; + } + + TimeStamp::TimeStamp(const ESM::TimeStamp &esm) + { + mDay = esm.mDay; + mHour = esm.mHour; + } } diff --git a/apps/openmw/mwworld/timestamp.hpp b/apps/openmw/mwworld/timestamp.hpp index e2d8b242a..54cd40baf 100644 --- a/apps/openmw/mwworld/timestamp.hpp +++ b/apps/openmw/mwworld/timestamp.hpp @@ -1,6 +1,11 @@ #ifndef GAME_MWWORLD_TIMESTAMP_H #define GAME_MWWORLD_TIMESTAMP_H +namespace ESM +{ + class TimeStamp; +} + namespace MWWorld { /// \brief In-game time stamp @@ -14,9 +19,12 @@ namespace MWWorld public: explicit TimeStamp (float hour = 0, int day = 0); - ///< \oaram hour [0, 23) + ///< \param hour [0, 23) /// \param day >=0 + explicit TimeStamp (const ESM::TimeStamp& esm); + ESM::TimeStamp toEsm () const; + float getHour() const; int getDay() const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d5da19dfa..b9a8f8dda 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2164,8 +2164,8 @@ namespace MWWorld // If this is a power, check if it was already used in the last 24h if (!fail && spell->mData.mType == ESM::Spell::ST_Power) { - if (stats.canUsePower(spell->mId)) - stats.usePower(spell->mId); + if (stats.getSpells().canUsePower(spell->mId)) + stats.getSpells().usePower(spell->mId); else { message = "#{sPowerAlreadyUsed}"; diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 3dd5df295..533288048 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate + npcstats creaturestats weatherstate quickkeys fogstate spellstate ) add_component_dir (misc diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index fe250089a..5bb6de662 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -8,13 +8,143 @@ void ESM::CreatureStats::load (ESMReader &esm) for (int i=0; i<3; ++i) mDynamic[i].load (esm); + + mGoldPool = 0; + esm.getHNOT (mGoldPool, "GOLD"); + + mTradeTime.mDay = 0; + mTradeTime.mHour = 0; + esm.getHNOT (mTradeTime, "TIME"); + + mDead = false; + esm.getHNOT (mDead, "DEAD"); + + mDied = false; + esm.getHNOT (mDied, "DIED"); + + mFriendlyHits = 0; + esm.getHNOT (mFriendlyHits, "FRHT"); + + mTalkedTo = false; + esm.getHNOT (mTalkedTo, "TALK"); + + mAlarmed = false; + esm.getHNOT (mAlarmed, "ALRM"); + + mHostile = false; + esm.getHNOT (mHostile, "HOST"); + + mAttackingOrSpell = false; + esm.getHNOT (mAttackingOrSpell, "ATCK"); + + mKnockdown = false; + esm.getHNOT (mKnockdown, "KNCK"); + + mKnockdownOneFrame = false; + esm.getHNOT (mKnockdownOneFrame, "KNC1"); + + mKnockdownOverOneFrame = false; + esm.getHNOT (mKnockdownOverOneFrame, "KNCO"); + + mHitRecovery = false; + esm.getHNOT (mHitRecovery, "HITR"); + + mBlock = false; + esm.getHNOT (mBlock, "BLCK"); + + mMovementFlags = 0; + esm.getHNOT (mMovementFlags, "MOVE"); + + mAttackStrength = 0; + esm.getHNOT (mAttackStrength, "ASTR"); + + mFallHeight = 0; + esm.getHNOT (mFallHeight, "FALL"); + + mLastHitObject = esm.getHNOString ("LHIT"); + + mRecalcDynamicStats = false; + esm.getHNOT (mRecalcDynamicStats, "CALC"); + + mDrawState = 0; + esm.getHNOT (mDrawState, "DRAW"); + + mLevel = 1; + esm.getHNOT (mLevel, "LEVL"); + + mSpells.load(esm); } void ESM::CreatureStats::save (ESMWriter &esm) const { + for (int i=0; i<8; ++i) mAttributes[i].save (esm); for (int i=0; i<3; ++i) mDynamic[i].save (esm); -} \ No newline at end of file + + if (mGoldPool) + esm.writeHNT ("GOLD", mGoldPool); + + esm.writeHNT ("TIME", mTradeTime); + + if (mDead) + esm.writeHNT ("DEAD", mDead); + + if (mDied) + esm.writeHNT ("DIED", mDied); + + if (mFriendlyHits) + esm.writeHNT ("FRHT", mFriendlyHits); + + if (mTalkedTo) + esm.writeHNT ("TALK", mTalkedTo); + + if (mAlarmed) + esm.writeHNT ("ALRM", mAlarmed); + + if (mHostile) + esm.writeHNT ("HOST", mHostile); + + if (mAttackingOrSpell) + esm.writeHNT ("ATCK", mAttackingOrSpell); + + if (mKnockdown) + esm.writeHNT ("KNCK", mKnockdown); + + if (mKnockdownOneFrame) + esm.writeHNT ("KNC1", mKnockdownOneFrame); + + if (mKnockdownOverOneFrame) + esm.writeHNT ("KNCO", mKnockdownOverOneFrame); + + if (mHitRecovery) + esm.writeHNT ("HITR", mHitRecovery); + + if (mBlock) + esm.writeHNT ("BLCK", mBlock); + + if (mMovementFlags) + esm.writeHNT ("MOVE", mMovementFlags); + + if (mAttackStrength) + esm.writeHNT ("ASTR", mAttackStrength); + + if (mFallHeight) + esm.writeHNT ("FALL", mFallHeight); + + if (!mLastHitObject.empty()) + esm.writeHNString ("LHIT", mLastHitObject); + + if (mRecalcDynamicStats) + esm.writeHNT ("CALC", mRecalcDynamicStats); + + if (mDrawState) + esm.writeHNT ("DRAW", mDrawState); + + if (mLevel != 1) + esm.writeHNT ("LEVL", mLevel); + + mSpells.save(esm); +} diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 540044f38..2cf2c5b4f 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -7,21 +7,51 @@ #include "statstate.hpp" +#include "defs.hpp" + +#include "spellstate.hpp" + namespace ESM { class ESMReader; class ESMWriter; // format 0, saved games only - struct CreatureStats { StatState mAttributes[8]; StatState mDynamic[3]; + ESM::TimeStamp mTradeTime; + int mGoldPool; + + bool mDead; + bool mDied; + int mFriendlyHits; + bool mTalkedTo; + bool mAlarmed; + bool mAttacked; + bool mHostile; + bool mAttackingOrSpell; + bool mKnockdown; + bool mKnockdownOneFrame; + bool mKnockdownOverOneFrame; + bool mHitRecovery; + bool mBlock; + unsigned int mMovementFlags; + float mAttackStrength; + float mFallHeight; + std::string mLastHitObject; + bool mRecalcDynamicStats; + int mDrawState; + + int mLevel; + + SpellState mSpells; + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; } -#endif \ No newline at end of file +#endif diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 5a99d0c2e..9ef4dabd2 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -6,6 +6,12 @@ namespace ESM { +struct TimeStamp +{ + float mHour; + int mDay; +}; + // Pixel color value. Standard four-byte rr,gg,bb,aa format. typedef int32_t Color; @@ -101,6 +107,7 @@ enum RecNameInts REC_WTHR = 0x52485457, REC_KEYS = FourCC<'K','E','Y','S'>::value, REC_DYNA = FourCC<'D','Y','N','A'>::value, + REC_ASPL = FourCC<'A','S','P','L'>::value, // format 1 REC_FILT = 0x544C4946 diff --git a/components/esm/esmwriter.cpp b/components/esm/esmwriter.cpp index 91f123eb7..9d8d943d9 100644 --- a/components/esm/esmwriter.cpp +++ b/components/esm/esmwriter.cpp @@ -100,6 +100,9 @@ namespace ESM void ESMWriter::startSubRecord(const std::string& name) { + // Sub-record hierarchies are not properly supported in ESMReader. This should be fixed later. + assert (mRecords.size() <= 1); + writeName(name); RecordData rec; rec.name = name; diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index b385ac067..57faefdf4 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -96,6 +96,7 @@ class ESMWriter void startRecord(const std::string& name, uint32_t flags = 0); void startRecord(uint32_t name, uint32_t flags = 0); + /// @note Sub-record hierarchies are not properly supported in ESMReader. This should be fixed later. void startSubRecord(const std::string& name); void endRecord(const std::string& name); void endRecord(uint32_t name); diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index 80238ad68..21f573bc7 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -36,6 +36,18 @@ void ESM::NpcStats::load (ESMReader &esm) mSkills[i].mWerewolf.load (esm); } + bool hasWerewolfAttributes = false; + esm.getHNOT (hasWerewolfAttributes, "HWAT"); + + if (hasWerewolfAttributes) + { + for (int i=0; i<8; ++i) + mWerewolfAttributes[i].load (esm); + } + + mIsWerewolf = false; + esm.getHNOT (mIsWerewolf, "WOLF"); + mBounty = 0; esm.getHNOT (mBounty, "BOUN"); @@ -48,8 +60,9 @@ void ESM::NpcStats::load (ESMReader &esm) mProfit = 0; esm.getHNOT (mProfit, "PROF"); - mAttackStrength = 0; - esm.getHNOT (mAttackStrength, "ASTR"); + // No longer used. Now part of CreatureStats. + float attackStrength = 0; + esm.getHNOT (attackStrength, "ASTR"); mLevelProgress = 0; esm.getHNOT (mLevelProgress, "LPRO"); @@ -101,6 +114,13 @@ void ESM::NpcStats::save (ESMWriter &esm) const mSkills[i].mWerewolf.save (esm); } + esm.writeHNT ("HWAT", true); + for (int i=0; i<8; ++i) + mWerewolfAttributes[i].save (esm); + + if (mIsWerewolf) + esm.writeHNT ("WOLF", mIsWerewolf); + if (mBounty) esm.writeHNT ("BOUN", mBounty); @@ -113,9 +133,6 @@ void ESM::NpcStats::save (ESMWriter &esm) const if (mProfit) esm.writeHNT ("PROF", mProfit); - if (mAttackStrength) - esm.writeHNT ("ASTR", mAttackStrength); - if (mLevelProgress) esm.writeHNT ("LPRO", mLevelProgress); @@ -136,4 +153,4 @@ void ESM::NpcStats::save (ESMWriter &esm) const if (mCrimeId != -1) esm.writeHNT ("CRID", mCrimeId); -} \ No newline at end of file +} diff --git a/components/esm/npcstats.hpp b/components/esm/npcstats.hpp index 504cd0163..ce7c75d2a 100644 --- a/components/esm/npcstats.hpp +++ b/components/esm/npcstats.hpp @@ -31,6 +31,9 @@ namespace ESM Faction(); }; + StatState mWerewolfAttributes[8]; + bool mIsWerewolf; + std::map mFactions; int mDisposition; Skill mSkills[27]; @@ -38,7 +41,6 @@ namespace ESM int mReputation; int mWerewolfKills; int mProfit; - float mAttackStrength; int mLevelProgress; int mSkillIncrease[8]; std::vector mUsedIds; @@ -52,4 +54,4 @@ namespace ESM }; } -#endif \ No newline at end of file +#endif diff --git a/components/esm/quickkeys.cpp b/components/esm/quickkeys.cpp index ad2b671aa..42cd91c5b 100644 --- a/components/esm/quickkeys.cpp +++ b/components/esm/quickkeys.cpp @@ -8,11 +8,13 @@ namespace ESM void QuickKeys::load(ESMReader &esm) { - while (esm.isNextSub("KEY_")) + if (esm.isNextSub("KEY_")) + esm.getSubHeader(); // no longer used, because sub-record hierachies do not work properly in esmreader + + while (esm.isNextSub("TYPE")) { - esm.getSubHeader(); int keyType; - esm.getHNT(keyType, "TYPE"); + esm.getHT(keyType); std::string id; id = esm.getHNString("ID__"); @@ -21,21 +23,18 @@ namespace ESM key.mId = id; mKeys.push_back(key); + + if (esm.isNextSub("KEY_")) + esm.getSubHeader(); // no longer used, because sub-record hierachies do not work properly in esmreader } } void QuickKeys::save(ESMWriter &esm) const { - const std::string recKey = "KEY_"; - for (std::vector::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it) { - esm.startSubRecord(recKey); - esm.writeHNT("TYPE", it->mType); esm.writeHNString("ID__", it->mId); - - esm.endRecord(recKey); } } diff --git a/components/esm/spellstate.cpp b/components/esm/spellstate.cpp new file mode 100644 index 000000000..2dca2dcec --- /dev/null +++ b/components/esm/spellstate.cpp @@ -0,0 +1,66 @@ +#include "spellstate.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void SpellState::load(ESMReader &esm) + { + while (esm.isNextSub("SPEL")) + { + std::string id = esm.getHString(); + + std::map random; + while (esm.isNextSub("INDX")) + { + int index; + esm.getHT(index); + + float magnitude; + esm.getHNT(magnitude, "RAND"); + + random[index] = magnitude; + } + + mSpells[id] = random; + } + + while (esm.isNextSub("USED")) + { + std::string id = esm.getHString(); + TimeStamp time; + esm.getHNT(time, "TIME"); + + mUsedPowers[id] = time; + } + + mSelectedSpell = esm.getHNOString("SLCT"); + } + + void SpellState::save(ESMWriter &esm) const + { + for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it) + { + esm.writeHNString("SPEL", it->first); + + const std::map& random = it->second; + for (std::map::const_iterator rIt = random.begin(); rIt != random.end(); ++rIt) + { + esm.writeHNT("INDX", rIt->first); + esm.writeHNT("RAND", rIt->second); + } + } + + for (std::map::const_iterator it = mUsedPowers.begin(); it != mUsedPowers.end(); ++it) + { + esm.writeHNString("USED", it->first); + esm.writeHNT("TIME", it->second); + } + + if (!mSelectedSpell.empty()) + esm.writeHNString("SLCT", mSelectedSpell); + } + +} diff --git a/components/esm/spellstate.hpp b/components/esm/spellstate.hpp new file mode 100644 index 000000000..cb5c0ff0d --- /dev/null +++ b/components/esm/spellstate.hpp @@ -0,0 +1,29 @@ +#ifndef OPENMW_ESM_SPELLSTATE_H +#define OPENMW_ESM_SPELLSTATE_H + +#include +#include + +#include "defs.hpp" + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + struct SpellState + { + typedef std::map > TContainer; + TContainer mSpells; + + std::map mUsedPowers; + + std::string mSelectedSpell; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; + +} + +#endif From f11079f1e4a42d28dcb1a04f172d87ef397d60a9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 12 May 2014 23:01:21 +0200 Subject: [PATCH 15/63] Fix findGround (off by 2 units) --- libs/openengine/bullet/trace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index afda52448..6eab43a60 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -116,7 +116,7 @@ void ActorTracer::findGround(btCollisionObject *actor, const Ogre::Vector3 &star mFraction = newTraceCallback.m_closestHitFraction; mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); mEndPos = (end-start)*mFraction + start; - mEndPos[2] -= 1.0f; + mEndPos[2] += 1.0f; } else { From 386604bc9dd859f4b11c3f2117b8cfd2888457e6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 01:43:52 +0200 Subject: [PATCH 16/63] Fixes #869: Added methods to control external and internal collision modes separately When an actor dies, we should only disable external collisions, i.e. prevent other actors from colliding with the dead body. The dead actor, however, should still have gravity and collision applied. Also moved disableCollision to when the death animation finishes, not as soon as the actor's health is 0. --- apps/openmw/mwmechanics/actors.cpp | 5 ++--- apps/openmw/mwworld/physicssystem.cpp | 4 ++-- apps/openmw/mwworld/worldimp.cpp | 2 +- libs/openengine/bullet/physic.cpp | 9 ++++++--- libs/openengine/bullet/physic.hpp | 10 +++++++++- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6375bdd1b..b935284d3 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -920,9 +920,6 @@ namespace MWMechanics spells.purge(iter->first.getRefData().getHandle()); } - // FIXME: see http://bugs.openmw.org/issues/869 - MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); - if (iter->second->kill()) { ++mDeathCount[cls.getId(iter->first)]; @@ -939,6 +936,8 @@ namespace MWMechanics stats.setMagicEffects(MWMechanics::MagicEffects()); calculateCreatureStatModifiers(iter->first, 0); + MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); + if (cls.isEssential(iter->first)) MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index e30a2bbc1..cf2ff87c6 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -626,12 +626,12 @@ namespace MWWorld bool cmode = act->getCollisionMode(); if(cmode) { - act->enableCollisions(false); + act->enableCollisionMode(false); return false; } else { - act->enableCollisions(true); + act->enableCollisionMode(true); return true; } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b9a8f8dda..538cd17df 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1957,7 +1957,7 @@ namespace MWWorld { OEngine::Physic::PhysicActor *physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle()); - physicActor->enableCollisions(enable); + physicActor->enableCollisionBody(enable); } bool World::findInteriorPosition(const std::string &name, ESM::Position &pos) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 4484d9862..c10892e52 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -41,15 +41,18 @@ namespace Physic } } - void PhysicActor::enableCollisions(bool collision) + void PhysicActor::enableCollisionMode(bool collision) + { + mCollisionMode = collision; + } + + void PhysicActor::enableCollisionBody(bool collision) { assert(mBody); if(collision && !mCollisionMode) enableCollisionBody(); if(!collision && mCollisionMode) disableCollisionBody(); - mCollisionMode = collision; } - void PhysicActor::setPosition(const Ogre::Vector3 &pos) { assert(mBody); diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 4ef611dc8..4e035446e 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -99,7 +99,15 @@ namespace Physic */ void setRotation(const Ogre::Quaternion &quat); - void enableCollisions(bool collision); + /** + * Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry. + */ + void enableCollisionMode(bool collision); + + /** + * Enables or disables the *external* collision body. If disabled, other actors will not collide with this actor. + */ + void enableCollisionBody(bool collision); bool getCollisionMode() const { From 2c74ea381e1bf290ac67fe062f085dc77f0c7d75 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 12 May 2014 21:05:32 -0400 Subject: [PATCH 17/63] Moved pathfinding code to aiPackage, implemented it's use with aiFollow and aiPursue --- apps/openmw/mwmechanics/aifollow.cpp | 81 ++++------------------ apps/openmw/mwmechanics/aifollow.hpp | 8 --- apps/openmw/mwmechanics/aipackage.cpp | 91 +++++++++++++++++++++++++ apps/openmw/mwmechanics/aipackage.hpp | 18 ++++- apps/openmw/mwmechanics/aipursue.cpp | 75 ++++---------------- apps/openmw/mwmechanics/aipursue.hpp | 12 +--- apps/openmw/mwmechanics/pathfinding.cpp | 48 ++++++------- apps/openmw/mwmechanics/pathfinding.hpp | 2 + components/esm/loadpgrd.cpp | 14 ++++ components/esm/loadpgrd.hpp | 3 + 10 files changed, 181 insertions(+), 171 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 161c9700f..98ac5ee14 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -12,17 +12,23 @@ #include "steering.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), mTimer(0), mStuckTimer(0) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId("") { + mTimer = 0; + mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), mTimer(0), mStuckTimer(0) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId) { + mTimer = 0; + mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId) -: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId(""), mTimer(0), mStuckTimer(0) +: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId("") { + mTimer = 0; + mStuckTimer = 0; } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) @@ -31,10 +37,6 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) if(target == MWWorld::Ptr()) return true; //Target doesn't exist - mTimer = mTimer + duration; //Update timer - mStuckTimer = mStuckTimer + duration; //Update stuck timer - mTotalTime = mTotalTime + duration; //Update total time following - ESM::Position pos = actor.getRefData().getPosition(); //position of the actor if(!mAlwaysFollow) //Update if you only follow for a bit @@ -60,74 +62,19 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) } //Set the target desition from the actor - ESM::Pathgrid::Point dest; - dest.mX = target.getRefData().getPosition().pos[0]; - dest.mY = target.getRefData().getPosition().pos[1]; - dest.mZ = target.getRefData().getPosition().pos[2]; + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - //Current position, for pathfilding stuff - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; + pathTo(actor, dest, duration); //Go to the destination - //Build the path to get to the destination - if(mPathFinder.getPath().empty()) - mPathFinder.buildPath(start, dest, actor.getCell(), true); - - //*********************** - // Checks if you can't get to the end position at all - //*********************** - if(mTimer > 0.25) - { - if(!mPathFinder.getPath().empty()) //Path has points in it - { - ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); //Get the end of the proposed path - - if((dest.mX - lastPos.mX)*(dest.mX - lastPos.mX) - +(dest.mY - lastPos.mY)*(dest.mY - lastPos.mY) - +(dest.mZ - lastPos.mZ)*(dest.mZ - lastPos.mZ) - > 100*100) //End of the path is far from the destination - mPathFinder.addPointToPath(dest); //Adds the final destination to the path, to try to get to where you want to go - } - - mTimer = 0; - } - - //************************ - // Checks if you aren't moving; you're stuck - //************************ - if(mStuckTimer>0.5) //Checks every half of a second - { - if((mStuckPos.pos[0] - pos.pos[0])*(mStuckPos.pos[0] - pos.pos[0]) - +(mStuckPos.pos[1] - pos.pos[1])*(mStuckPos.pos[1] - pos.pos[1]) - +(mStuckPos.pos[2] - pos.pos[2])*(mStuckPos.pos[2] - pos.pos[2]) < 100) //NPC is stuck - mPathFinder.buildPath(start, dest, actor.getCell(), true); - - mStuckTimer = 0; - mStuckPos = pos; - } - - //Checks if the path isn't over, turn tomards the direction that you're going - if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) - { - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); - } - - if((dest.mX - pos.pos[0])*(dest.mX - pos.pos[0])+(dest.mY - pos.pos[1])*(dest.mY - pos.pos[1])+(dest.mZ - pos.pos[2])*(dest.mZ - pos.pos[2]) - < 100*100) + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; else actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Check if you're far away - if((dest.mX - start.mX)*(dest.mX - start.mX) - +(dest.mY - start.mY)*(dest.mY - start.mY) - +(dest.mZ - start.mZ)*(dest.mZ - start.mZ) > 1000*1000) + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) > 1000) actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run - else if((dest.mX - start.mX)*(dest.mX - start.mX) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold - +(dest.mY - start.mY)*(dest.mY - start.mY) - +(dest.mZ - start.mZ)*(dest.mZ - start.mZ) < 800*800) + else if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 800) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, false); //make NPC walk return false; diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 4eb3e3757..531082357 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -40,14 +40,6 @@ namespace MWMechanics float mZ; std::string mActorId; std::string mCellId; - - float mTimer; - float mStuckTimer; - float mTotalTime; - - ESM::Position mStuckPos; - - PathFinder mPathFinder; }; } #endif diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 8193a670b..afe99e2c0 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -1,4 +1,95 @@ #include "aipackage.hpp" +#include +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/cellstore.hpp" +#include "creaturestats.hpp" +#include "movement.hpp" + +#include + +#include "steering.hpp" + MWMechanics::AiPackage::~AiPackage() {} + + +bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration) +{ + //Update various Timers + mTimer = mTimer + duration; //Update timer + mStuckTimer = mStuckTimer + duration; //Update stuck timer + mTotalTime = mTotalTime + duration; //Update total time following + + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + + /// Stops the actor when it gets too close to a unloaded cell + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + const ESM::Cell *cell = actor.getCell()->getCell(); + Movement &movement = actor.getClass().getMovementSettings(actor); + + //Ensure pursuer doesn't leave loaded cells + if(cell->mData.mX != player.getCell()->getCell()->mData.mX) + { + int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); + //check if actor is near the border of an inactive cell. If so, stop walking. + if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) + { + movement.mPosition[1] = 0; + return false; + } + } + if(cell->mData.mY != player.getCell()->getCell()->mData.mY) + { + int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); + //check if actor is near the border of an inactive cell. If so, stop walking. + if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) + { + movement.mPosition[1] = 0; + return false; + } + } + } + + //Start position + ESM::Pathgrid::Point start = pos.pos; + + //*********************** + /// Checks if you can't get to the end position at all, adds end position to end of path + /// Rebuilds path every quarter of a second, in case the target has moved + //*********************** + if(mTimer > 0.25) + { + mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + if(!mPathFinder.getPath().empty()) //Path has points in it + { + ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); //Get the end of the proposed path + + if(distance(dest, lastPos) > 100) //End of the path is far from the destination + mPathFinder.addPointToPath(dest); //Adds the final destination to the path, to try to get to where you want to go + } + + mTimer = 0; + } + + //************************ + /// Checks if you aren't moving; attempts to unstick you + //************************ + if(mStuckTimer>0.5) //Checks every half of a second + { + if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) //NPC hasn't moved much is half a second, he's stuck + mPathFinder.buildPath(start, dest, actor.getCell(), true); + + mStuckTimer = 0; + mStuckPos = pos; + } + + //Checks if the path isn't over, turn tomards the direction that you're going + if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) + { + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); + } +} diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index b3a7facee..e36b51f69 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -1,6 +1,9 @@ #ifndef GAME_MWMECHANICS_AIPACKAGE_H #define GAME_MWMECHANICS_AIPACKAGE_H +#include "pathfinding.hpp" +#include "../../../components/esm/defs.hpp" + namespace MWWorld { class Ptr; @@ -38,8 +41,21 @@ namespace MWMechanics /// \see enum TypeId virtual int getTypeId() const = 0; - /// Higher number is higher priority (0 beeing the lowest) + /// Higher number is higher priority (0 being the lowest) virtual unsigned int getPriority() const {return 0;} + + protected: + /// Causes the actor to attempt to walk to the specified location + /** \return If the actor has arrived at his destination **/ + bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); + + PathFinder mPathFinder; + + float mTimer; + float mStuckTimer; + float mTotalTime; + + ESM::Position mStuckPos; }; } diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 0c10bd81d..4e0bc7104 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -21,75 +21,28 @@ MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const } bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) { - MWBase::World *world = MWBase::Environment::get().getWorld(); - ESM::Position pos = actor.getRefData().getPosition(); - Movement &movement = actor.getClass().getMovementSettings(actor); - const ESM::Cell *cell = actor.getCell()->getCell(); - actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow - MWWorld::Ptr player = world->getPlayerPtr(); - if(cell->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > - sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - if(cell->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > - sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } + if(target == MWWorld::Ptr()) + return true; //Target doesn't exist - // Big TODO: Sync this with current AiFollow. Move common code to a shared base class or helpers (applies to all AI packages, way too much duplicated code) + //Set the target desition from the actor + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - ESM::Position targetPos = target.getRefData().getPosition(); + pathTo(actor, dest, duration); //Go to the destination - bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; - if(!mPathFinder.isPathConstructed() || cellChange || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) - { - mCellX = cell->mData.mX; - mCellY = cell->mData.mY; - - ESM::Pathgrid::Point dest; - dest.mX = targetPos.pos[0]; - dest.mY = targetPos.pos[1]; - dest.mZ = targetPos.pos[2]; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - mPathFinder.buildPath(start, dest, actor.getCell(), true); - } - - if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+ - (pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+ - (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 100*100) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); + MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player return true; } + else + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - zTurn(actor, Ogre::Degree(zAngle)); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - movement.mPosition[1] = 1; + actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run return false; } diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 8a471228e..7d1ea5bb9 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -9,18 +9,12 @@ namespace MWMechanics { /// \brief Makes the actor very closely follow the actor - /** Used for getting closer to fight, or to arrest (I think?) **/ - class AiPersue : public AiPackage + /** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them. **/ + class AiPursue : public AiPackage { public: ///Constructor /** \param objectId Actor to pursue **/ - AiPersue(const std::string &objectId); - virtual AiPersue *clone() const; - - class AiPursue : public AiPackage - { - public: AiPursue(const std::string &objectId); virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); @@ -28,8 +22,6 @@ namespace MWMechanics private: std::string mObjectId; - - PathFinder mPathFinder; int mCellX; int mCellY; }; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index cd03939bd..d77a35ea4 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -11,30 +11,6 @@ namespace { - float distanceZCorrected(ESM::Pathgrid::Point point, float x, float y, float z) - { - x -= point.mX; - y -= point.mY; - z -= point.mZ; - return sqrt(x * x + y * y + 0.1 * z * z); - } - - float distance(ESM::Pathgrid::Point point, float x, float y, float z) - { - x -= point.mX; - y -= point.mY; - z -= point.mZ; - return sqrt(x * x + y * y + z * z); - } - - float distance(ESM::Pathgrid::Point a, ESM::Pathgrid::Point b) - { - float x = a.mX - b.mX; - float y = a.mY - b.mY; - float z = a.mZ - b.mZ; - return sqrt(x * x + y * y + z * z); - } - // Slightly cheaper version for comparisons. // Caller needs to be careful for very short distances (i.e. less than 1) // or when accumuating the results i.e. (a + b)^2 != a^2 + b^2 @@ -114,6 +90,30 @@ namespace namespace MWMechanics { + float distanceZCorrected(ESM::Pathgrid::Point point, float x, float y, float z) + { + x -= point.mX; + y -= point.mY; + z -= point.mZ; + return sqrt(x * x + y * y + 0.1 * z * z); + } + + float distance(ESM::Pathgrid::Point point, float x, float y, float z) + { + x -= point.mX; + y -= point.mY; + z -= point.mZ; + return sqrt(x * x + y * y + z * z); + } + + float distance(ESM::Pathgrid::Point a, ESM::Pathgrid::Point b) + { + float x = a.mX - b.mX; + float y = a.mY - b.mY; + float z = a.mZ - b.mZ; + return sqrt(x * x + y * y + z * z); + } + PathFinder::PathFinder() : mIsPathConstructed(false), mPathgrid(NULL), diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 29577542e..603a04f8c 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -13,6 +13,8 @@ namespace MWWorld namespace MWMechanics { + float distance(ESM::Pathgrid::Point point, float x, float y, float); + float distance(ESM::Pathgrid::Point a, ESM::Pathgrid::Point b); class PathFinder { public: diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index 3b5330e9f..5b8ce3eb2 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -8,6 +8,20 @@ namespace ESM { unsigned int Pathgrid::sRecordId = REC_PGRD; + Pathgrid::Point& Pathgrid::Point::operator=(const float rhs[]) { + mX = rhs[0]; + mY = rhs[1]; + mZ = rhs[2]; + return *this; + } + Pathgrid::Point::Point(const float rhs[]) { + mX = rhs[0]; + mY = rhs[1]; + mZ = rhs[2]; + } + Pathgrid::Point::Point():mX(0),mY(0),mZ(0) { + } + void Pathgrid::load(ESMReader &esm) { esm.getHNT(mData, "DATA", 12); diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index 9ee49552d..b940c27e6 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -31,6 +31,9 @@ struct Pathgrid unsigned char mAutogenerated; // autogenerated vs. user coloring flag? unsigned char mConnectionNum; // number of connections for this point short mUnknown; + Point& operator=(const float[]); + Point(const float[]); + Point(); }; // 16 bytes struct Edge // path grid edge From cbfa282f8d04932eaf01f20fa108c9094da1b1c3 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 03:58:32 -0400 Subject: [PATCH 18/63] Changed implementations of aifollow/pursue/activate slightly, added ability for NPCs to go through unlocked doors (They even try locked ones), and step back from opening doors (Although it still needs some work) Notes - When the door hits them while it's about to finish closing they will try to walk through the door. - Considerably more works is needed in making the NPC work out troublesome areas where they get stuck --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/world.hpp | 8 ++- apps/openmw/mwmechanics/aiactivate.cpp | 98 ++++++-------------------- apps/openmw/mwmechanics/aiactivate.hpp | 5 +- apps/openmw/mwmechanics/aifollow.cpp | 12 +--- apps/openmw/mwmechanics/aifollow.hpp | 4 +- apps/openmw/mwmechanics/aipackage.cpp | 61 ++++++++++++---- apps/openmw/mwmechanics/aipackage.hpp | 14 +++- apps/openmw/mwmechanics/aipursue.cpp | 7 +- apps/openmw/mwmechanics/aipursue.hpp | 4 +- apps/openmw/mwmechanics/obstacle.cpp | 22 ++++-- apps/openmw/mwmechanics/obstacle.hpp | 14 +++- apps/openmw/mwworld/worldimp.cpp | 19 ++++- apps/openmw/mwworld/worldimp.hpp | 7 +- 14 files changed, 149 insertions(+), 128 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 7a5283125..aee5cbeac 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -67,7 +67,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects - drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow + drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting disease pickpocket levelledlist combat steering obstacle ) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 44c8c96be..2dfa34ba3 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -390,10 +390,14 @@ namespace MWBase virtual void setupPlayer() = 0; virtual void renderPlayer() = 0; + /// if activated, should this door be opened or closed? virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door) = 0; - ///< if activated, should this door be opened or closed? + + /// activate (open or close) an non-teleport door virtual void activateDoor(const MWWorld::Ptr& door) = 0; - ///< activate (open or close) an non-teleport door + + /// Is door currently opening/closing? + virtual bool getIsMovingDoor(const MWWorld::Ptr& door) = 0; virtual bool getPlayerStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index eeedc0d7a..1463dff7e 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -19,83 +19,27 @@ MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const return new AiActivate(*this); } bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) -{ - MWBase::World *world = MWBase::Environment::get().getWorld(); - ESM::Position pos = actor.getRefData().getPosition(); - Movement &movement = actor.getClass().getMovementSettings(actor); - const ESM::Cell *cell = actor.getCell()->getCell(); - - MWWorld::Ptr player = world->getPlayerPtr(); - if(cell->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > - sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - if(cell->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > - sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - - MWWorld::Ptr target = world->searchPtr(mObjectId,false); - if(target == MWWorld::Ptr()) return true; - - ESM::Position targetPos = target.getRefData().getPosition(); - - bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; - if(!mPathFinder.isPathConstructed() || cellChange) - { - mCellX = cell->mData.mX; - mCellY = cell->mData.mY; - - ESM::Pathgrid::Point dest; - dest.mX = targetPos.pos[0]; - dest.mY = targetPos.pos[1]; - dest.mZ = targetPos.pos[2]; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - mPathFinder.buildPath(start, dest, actor.getCell(), true); - } - - if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+ - (pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+ - (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 200*200) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); - return true; - } - - if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); - return true; - } - - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - zTurn(actor, Ogre::Degree(zAngle)); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - movement.mPosition[1] = 1; - +{ + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow + + if(target == MWWorld::Ptr()) + return true; //Target doesn't exist + + //Set the target desition from the actor + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; + + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 200 || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { //Stop when you get close + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); + MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player + return true; + } + else { + pathTo(actor, dest, duration); //Go to the destination + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + } + return false; } diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index b6ce9f85d..f68438872 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -8,7 +8,8 @@ namespace MWMechanics { - /// \brief Causes actor to walk to activatable object and activate it + /// \brief Causes actor to walk to activatable object and activate it + /** Will actiavte when close to object or path grid complete **/ class AiActivate : public AiPackage { public: @@ -21,8 +22,6 @@ namespace MWMechanics private: std::string mObjectId; - - PathFinder mPathFinder; int mCellX; int mCellY; }; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 98ac5ee14..8d9e01939 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -12,23 +12,17 @@ #include "steering.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId("") +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId) -: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId("") +: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId(""), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 531082357..43681c163 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MWMECHANICS_AIFALLOW_H -#define GAME_MWMECHANICS_AIFALLOW_H +#ifndef GAME_MWMECHANICS_AIFOLLOW_H +#define GAME_MWMECHANICS_AIFOLLOW_H #include "aipackage.hpp" #include diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index afe99e2c0..90f0505a4 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -8,6 +8,7 @@ #include "../mwworld/cellstore.hpp" #include "creaturestats.hpp" #include "movement.hpp" +#include "../mwworld/action.hpp" #include @@ -15,13 +16,18 @@ MWMechanics::AiPackage::~AiPackage() {} +MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(NULL), mTimer(0), mStuckTimer(0) { + +} + bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration) { //Update various Timers - mTimer = mTimer + duration; //Update timer - mStuckTimer = mStuckTimer + duration; //Update stuck timer - mTotalTime = mTotalTime + duration; //Update total time following + mTimer += duration; //Update timer + mStuckTimer += duration; //Update stuck timer + mTotalTime += duration; //Update total time following + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor @@ -78,18 +84,45 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //************************ /// Checks if you aren't moving; attempts to unstick you //************************ - if(mStuckTimer>0.5) //Checks every half of a second + if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) //Path finished? + return true; + else if(mStuckTimer>0.5) //Every half second see if we need to take action to avoid something { - if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) //NPC hasn't moved much is half a second, he's stuck - mPathFinder.buildPath(start, dest, actor.getCell(), true); - - mStuckTimer = 0; - mStuckPos = pos; +/// TODO (tluppi#1#): Use ObstacleCheck here. Not working for some reason + //if(mObstacleCheck.check(actor, duration)) { + if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //Actually stuck + // first check if we're walking into a door + MWWorld::LiveCellRef* door = getNearbyDoor(actor); + if(door != NULL) // NOTE: checks interior cells only + { + if(door->mRef.mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped + door->mClass->activate(MWBase::Environment::get().getWorld()->getPtr(door->mRef.mRefID,false), actor).get()->execute(actor); + mLastDoorChecked = door; + } + } + else // probably walking into another NPC + { + // TODO: diagonal should have same animation as walk forward + // but doesn't seem to do that? + actor.getClass().getMovementSettings(actor).mPosition[0] = 1; + actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f; + // change the angle a bit, too + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); + } + /*else if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //NPC hasn't moved much is half a second, he's stuck + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + actor.getClass().getMovementSettings(actor).mPosition[0] = 1; + }*/ + } + else { + mStuckTimer = 0; + mStuckPos = pos; + mLastDoorChecked = NULL; //Resets it, in case he gets stuck behind the door again + } + } + else { + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; } - //Checks if the path isn't over, turn tomards the direction that you're going - if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) - { - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); - } + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); } diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index e36b51f69..37de32d8d 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -4,6 +4,8 @@ #include "pathfinding.hpp" #include "../../../components/esm/defs.hpp" +#include "obstacle.hpp" + namespace MWWorld { class Ptr; @@ -24,9 +26,13 @@ namespace MWMechanics TypeIdFollow = 3, TypeIdActivate = 4, TypeIdCombat = 5, - TypeIdPursue = 6 + TypeIdPursue = 6, + TypeIdAvoidDoor = 7 }; + ///Default constructor + AiPackage(); + ///Default Deconstructor virtual ~AiPackage(); @@ -50,10 +56,14 @@ namespace MWMechanics bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); PathFinder mPathFinder; + ObstacleCheck mObstacleCheck; + float mDoorCheckDuration; float mTimer; float mStuckTimer; - float mTotalTime; + float mTotalTime; + + MWWorld::LiveCellRef* mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door ESM::Position mStuckPos; }; diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 4e0bc7104..6e91ccb71 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -31,16 +31,15 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) //Set the target desition from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - pathTo(actor, dest, duration); //Go to the destination - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player return true; } - else - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + else { + pathTo(actor, dest, duration); //Go to the destination + } actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 7d1ea5bb9..2eb533d62 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -9,7 +9,9 @@ namespace MWMechanics { /// \brief Makes the actor very closely follow the actor - /** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them. **/ + /** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them. + Note that while very similar to AiActivate, it will ONLY activate when evry close to target (Not also when the + path is completed). **/ class AiPursue : public AiPackage { public: diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 181560935..7cd85685b 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -19,11 +19,19 @@ namespace MWMechanics // Limitation: there can be false detections, and does not test whether the // actor is facing the door. bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) + { + if(getNearbyDoor(actor, minSqr, closed)!=NULL) + return true; + else + return false; + } + + MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) { MWWorld::CellStore *cell = actor.getCell(); if(cell->getCell()->isExterior()) - return false; // check interior cells only + return NULL; // check interior cells only // Check all the doors in this cell MWWorld::CellRefList& doors = cell->get(); @@ -31,14 +39,14 @@ namespace MWMechanics MWWorld::CellRefList::List::iterator it = refList.begin(); Ogre::Vector3 pos(actor.getRefData().getPosition().pos); - // TODO: How to check whether the actor is facing a door? Below code is for - // the player, perhaps it can be adapted. + /// TODO: How to check whether the actor is facing a door? Below code is for + /// the player, perhaps it can be adapted. //MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getFacedObject(); //if(!ptr.isEmpty()) //std::cout << "faced door " << ptr.getClass().getName(ptr) << std::endl; - // TODO: The in-game observation of rot[2] value seems to be the - // opposite of the code in World::activateDoor() ::confused:: + /// TODO: The in-game observation of rot[2] value seems to be the + /// opposite of the code in World::activateDoor() ::confused:: for (; it != refList.end(); ++it) { MWWorld::LiveCellRef& ref = *it; @@ -46,10 +54,10 @@ namespace MWMechanics if((closed && ref.mData.getLocalRotation().rot[2] == 0) || (!closed && ref.mData.getLocalRotation().rot[2] >= 1)) { - return true; // found, stop searching + return &ref; // found, stop searching } } - return false; // none found + return NULL; // none found } ObstacleCheck::ObstacleCheck(): diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp index 12030b2be..e737ef9cf 100644 --- a/apps/openmw/mwmechanics/obstacle.hpp +++ b/apps/openmw/mwmechanics/obstacle.hpp @@ -1,6 +1,10 @@ #ifndef OPENMW_MECHANICS_OBSTACLE_H #define OPENMW_MECHANICS_OBSTACLE_H +//#include "../mwbase/world.hpp" +//#include "../mwworld/class.hpp" +#include "../mwworld/cellstore.hpp" + namespace MWWorld { class Ptr; @@ -8,14 +12,20 @@ namespace MWWorld namespace MWMechanics { - // NOTE: determined empirically based on in-game behaviour + /// NOTE: determined empirically based on in-game behaviour static const float MIN_DIST_TO_DOOR_SQUARED = 128*128; - // tests actor's proximity to a closed door by default + /// tests actor's proximity to a closed door by default bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr = MIN_DIST_TO_DOOR_SQUARED, bool closed = true); + /// Returns door pointer within range. No guarentee is given as too which one + /** \return Pointer to the door, or NULL if none exists **/ + MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, + float minSqr = MIN_DIST_TO_DOOR_SQUARED, + bool closed = true); + class ObstacleCheck { public: diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ba36d4a86..5d1657a34 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -30,6 +30,7 @@ #include "../mwmechanics/spellcasting.hpp" #include "../mwmechanics/levelledlist.hpp" #include "../mwmechanics/combat.hpp" +#include "../mwmechanics/aiavoiddoor.hpp" //Used to tell actors to avoid doors #include "../mwrender/sky.hpp" #include "../mwrender/animation.hpp" @@ -1210,7 +1211,11 @@ namespace MWWorld MWWorld::Ptr ptr = getPtrViaHandle(*cit); if (MWWorld::Class::get(ptr).isActor()) { - // we collided with an actor, we need to undo the rotation + // Collided with actor, ask actor to try to avoid door + MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); + if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once + seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); break; } @@ -1853,6 +1858,16 @@ namespace MWWorld return door.getRefData().getLocalRotation().rot[2] == 0; } + bool World::getIsMovingDoor(const Ptr& door) + { + //This more expensive comparison is needed for some reason + // TODO (tluppi#1#): Figure out why comparing Ptr isn't working + for(std::map::iterator it = mDoorStates.begin(); it != mDoorStates.end(); it++) + if(it->first.getCellRef().mRefID == door.getCellRef().mRefID) + return true; + return false; + } + bool World::getPlayerStandingOn (const MWWorld::Ptr& object) { MWWorld::Ptr player = mPlayer->getPlayer(); @@ -1919,7 +1934,7 @@ namespace MWWorld out.push_back(searchPtrViaHandle(*it)); } } - + bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) { if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled()) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 645330683..d111d0008 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -493,10 +493,13 @@ namespace MWWorld virtual void setupPlayer(); virtual void renderPlayer(); + /// if activated, should this door be opened or closed? virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door); - ///< if activated, should this door be opened or closed? + + /// activate (open or close) an non-teleport door virtual void activateDoor(const MWWorld::Ptr& door); - ///< activate (open or close) an non-teleport door + + virtual bool getIsMovingDoor(const MWWorld::Ptr& door); virtual bool getPlayerStandingOn (const MWWorld::Ptr& object); ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object From 2db3c89a9e78f2dc66a7ee5ab07d9e5c672cde49 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 04:09:21 -0400 Subject: [PATCH 19/63] Ensures destination is far enough to care about getting stuck --- apps/openmw/mwmechanics/aipackage.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 90f0505a4..872eecb62 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -90,7 +90,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po { /// TODO (tluppi#1#): Use ObstacleCheck here. Not working for some reason //if(mObstacleCheck.check(actor, duration)) { - if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //Actually stuck + if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10 && distance(dest, start) > 20) { //Actually stuck, and far enough away from destination to care // first check if we're walking into a door MWWorld::LiveCellRef* door = getNearbyDoor(actor); if(door != NULL) // NOTE: checks interior cells only @@ -125,4 +125,6 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po } zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); + + return false; } From e591d23880cc81c5f086c50a152ef81b5073da44 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 19:01:02 +0200 Subject: [PATCH 20/63] Fixes #894: Make sure the player's CharacterController is updated when the player is rebuilt. Necessary if the race is changed while we are still in a GUI (e.g. in the review dialog), and an update normally wouldn't occur. --- apps/openmw/mwmechanics/actors.cpp | 4 +++- apps/openmw/mwmechanics/actors.hpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index b935284d3..91ef48c09 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -781,7 +781,7 @@ namespace MWMechanics } } - void Actors::addActor (const MWWorld::Ptr& ptr) + void Actors::addActor (const MWWorld::Ptr& ptr, bool updateImmediately) { // erase previous death events since we are currently only tracking them while in an active cell MWWorld::Class::get(ptr).getCreatureStats(ptr).clearHasDied(); @@ -790,6 +790,8 @@ namespace MWMechanics MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); mActors.insert(std::make_pair(ptr, new CharacterController(ptr, anim))); + if (updateImmediately) + mActors[ptr]->update(0); } void Actors::removeActor (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index f7dff1058..e42672bad 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -58,7 +58,7 @@ namespace MWMechanics /// paused we may want to do it manually (after equipping permanent enchantment) void updateMagicEffects (const MWWorld::Ptr& ptr) { adjustMagicEffects(ptr); } - void addActor (const MWWorld::Ptr& ptr); + void addActor (const MWWorld::Ptr& ptr, bool updateImmediately=false); ///< Register an actor for stats management /// /// \note Dead actors are ignored. diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 2b1f82b92..5c2ee30e1 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -385,7 +385,7 @@ namespace MWMechanics // have been made for them. Make sure they're properly updated. MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); mActors.removeActor(ptr); - mActors.addActor(ptr); + mActors.addActor(ptr, true); } mActors.update(duration, paused); From 598221a8e77a937ad7ff3ea144709046f5955eaf Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:07:27 -0400 Subject: [PATCH 21/63] Forgot some files --- apps/openmw/mwmechanics/aiavoiddoor.cpp | 64 +++++++++++++++++++++++++ apps/openmw/mwmechanics/aiavoiddoor.hpp | 36 ++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 apps/openmw/mwmechanics/aiavoiddoor.cpp create mode 100644 apps/openmw/mwmechanics/aiavoiddoor.hpp diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp new file mode 100644 index 000000000..375e8fae7 --- /dev/null +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -0,0 +1,64 @@ +#include "aiavoiddoor.hpp" +#include +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/cellstore.hpp" +#include "creaturestats.hpp" +#include "movement.hpp" + +#include + +#include "steering.hpp" + +MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::Ptr& doorPtr) +: AiPackage(), mDoorPtr(doorPtr), mDuration(1) +{ +} + +bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration) +{ + mDuration -= duration; //Update timer + + if(mDuration < 0) + return true; // We have tried backing up for more than one second, we've probably cleared it + + if(!MWBase::Environment::get().getWorld()->getIsMovingDoor(mDoorPtr)) + return true; //Door is no longer opening + + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + ESM::Position tPos = mDoorPtr.getRefData().getPosition(); //Position of the door + float x = pos.pos[0] - tPos.pos[0]; + float y = pos.pos[1] - tPos.pos[1]; + float z = pos.pos[2] - tPos.pos[2]; + int distance = sqrt(x * x + y * y + z * z); + + if(distance > 300) //Stop backing up when you're far enough away + return true; +/// TODO: Calculate this from door size, not have it built in + + float dirToDoor = std::atan2(x,y) + pos.rot[2]; //Calculates the direction to the door, relative to the direction of the NPC + // For example, if the NPC is directly facing the door this will be pi/2 + + // Make actor move away from the door + actor.getClass().getMovementSettings(actor).mPosition[1] = -1 * std::sin(dirToDoor); //I knew I'd use trig someday + actor.getClass().getMovementSettings(actor).mPosition[0] = -1 * std::cos(dirToDoor); + + return false; +} + +std::string MWMechanics::AiAvoidDoor::getAvoidedDoor() +{ + return mDoorPtr.getCellRef().mRefID; +} + +MWMechanics::AiAvoidDoor *MWMechanics::AiAvoidDoor::clone() const +{ + return new AiAvoidDoor(*this); +} + + int MWMechanics::AiAvoidDoor::getTypeId() const +{ + return TypeIdAvoidDoor; +} + diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp new file mode 100644 index 000000000..6c90e36d6 --- /dev/null +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -0,0 +1,36 @@ +#ifndef GAME_MWMECHANICS_AIAVOIDDOOR_H +#define GAME_MWMECHANICS_AIAVOIDDOOR_H + +#include "aipackage.hpp" +#include +#include "pathfinding.hpp" +#include "../../../components/esm/defs.hpp" +#include "../mwworld/class.hpp" + +namespace MWMechanics +{ + /// \brief AiPackage to have an actor avoid an opening door + /** The AI will retreat from the door until it has finished opening, walked far away from it, or one second has passed, in an attempt to avoid it + **/ + class AiAvoidDoor : public AiPackage + { + public: + /// Avoid door until the door is fully open + AiAvoidDoor(const MWWorld::Ptr& doorPtr); + + virtual AiAvoidDoor *clone() const; + + virtual bool execute (const MWWorld::Ptr& actor,float duration); + + virtual int getTypeId() const; + + /// Returns the door being avoided + std::string getAvoidedDoor(); + + private: + float mDuration; + MWWorld::Ptr mDoorPtr; + }; +} +#endif + From 77d365e1963257ca08fe306e5f910c9d988b0272 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:25:22 -0400 Subject: [PATCH 22/63] Forced some function arguments to take in a specific array size --- components/esm/loadpgrd.cpp | 4 ++-- components/esm/loadpgrd.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index 5b8ce3eb2..efdbdd86b 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -8,13 +8,13 @@ namespace ESM { unsigned int Pathgrid::sRecordId = REC_PGRD; - Pathgrid::Point& Pathgrid::Point::operator=(const float rhs[]) { + Pathgrid::Point& Pathgrid::Point::operator=(const float rhs[3]) { mX = rhs[0]; mY = rhs[1]; mZ = rhs[2]; return *this; } - Pathgrid::Point::Point(const float rhs[]) { + Pathgrid::Point::Point(const float rhs[3]) { mX = rhs[0]; mY = rhs[1]; mZ = rhs[2]; diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index b940c27e6..926233444 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -31,8 +31,8 @@ struct Pathgrid unsigned char mAutogenerated; // autogenerated vs. user coloring flag? unsigned char mConnectionNum; // number of connections for this point short mUnknown; - Point& operator=(const float[]); - Point(const float[]); + Point& operator=(const float[3]); + Point(const float[3]); Point(); }; // 16 bytes From f01c3e0eacfa0d42bd367892723c2be4df1441cc Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 19:38:28 +0200 Subject: [PATCH 23/63] Fixes #1037: Change default footstep volume to match vanilla --- files/settings-default.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 2b44d0f4e..9eed2c7d9 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -150,7 +150,7 @@ device = master volume = 1.0 sfx volume = 1.0 music volume = 0.4 -footsteps volume = 0.6 +footsteps volume = 0.15 voice volume = 1.0 From ee36ace00b7f351e3525c156df80b456daaf3c5f Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:43:50 -0400 Subject: [PATCH 24/63] Undid some code clean up changes, and changed how some includes work --- apps/openmw/mwinput/inputmanagerimp.hpp | 6 +- apps/openmw/mwmechanics/aiavoiddoor.hpp | 2 +- apps/openmw/mwmechanics/aifollow.hpp | 2 +- apps/openmw/mwmechanics/aipackage.hpp | 2 +- apps/openmw/mwmechanics/alchemy.hpp | 92 ++++---- apps/openmw/mwmechanics/character.hpp | 293 ++++++++++++------------ 6 files changed, 197 insertions(+), 200 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index ace4cc6d0..3787a9c07 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -46,7 +46,10 @@ namespace MyGUI namespace MWInput { - /// \brief Class that handles all input and key bindings for OpenMW. + + /** + * @brief Class that handles all input and key bindings for OpenMW. + */ class InputManager : public MWBase::InputManager, public SFO::KeyListener, @@ -65,7 +68,6 @@ namespace MWInput /// Clear all savegame-specific data virtual void clear(); - virtual void update(float dt, bool disableControls=false, bool disableEvents=false); void setPlayer (MWWorld::Player* player) { mPlayer = player; } diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 6c90e36d6..6e9a1bdf5 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -4,7 +4,7 @@ #include "aipackage.hpp" #include #include "pathfinding.hpp" -#include "../../../components/esm/defs.hpp" +#include #include "../mwworld/class.hpp" namespace MWMechanics diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 43681c163..10a381410 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -4,7 +4,7 @@ #include "aipackage.hpp" #include #include "pathfinding.hpp" -#include "../../../components/esm/defs.hpp" +#include namespace MWMechanics { diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 37de32d8d..c9c8504aa 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -2,7 +2,7 @@ #define GAME_MWMECHANICS_AIPACKAGE_H #include "pathfinding.hpp" -#include "../../../components/esm/defs.hpp" +#include #include "obstacle.hpp" diff --git a/apps/openmw/mwmechanics/alchemy.hpp b/apps/openmw/mwmechanics/alchemy.hpp index b2b0fe1ee..31cafa4dc 100644 --- a/apps/openmw/mwmechanics/alchemy.hpp +++ b/apps/openmw/mwmechanics/alchemy.hpp @@ -31,8 +31,6 @@ namespace MWMechanics typedef std::vector TEffectsContainer; typedef TEffectsContainer::const_iterator TEffectsIterator; - /// Result of potion creation - /** Only Result_Success results in success **/ enum Result { Result_Success, @@ -44,46 +42,6 @@ namespace MWMechanics Result_RandomFailure }; - /// Set alchemist and configure alchemy setup accordingly. - /** \a npc may be empty to indicate that there is no alchemist (alchemy session has ended). **/ - void setAlchemist (const MWWorld::Ptr& npc); - - /// \attention Iterates over tool slots, not over tools. Some of the slots may be empty. - TToolsIterator beginTools() const; - - TToolsIterator endTools() const; - - /// \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty. - TIngredientsIterator beginIngredients() const; - - TIngredientsIterator endIngredients() const; - - /// Remove alchemist, tools and ingredients. - void clear(); - - /// Add ingredient into the next free slot. - /// - /// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being - /// listed already. - int addIngredient (const MWWorld::Ptr& ingredient); - - /// Remove ingredient from slot (calling this function on an empty slot is a no-op). - void removeIngredient (int index); - - TEffectsIterator beginEffects() const; - - TEffectsIterator endEffects() const; - - /// Return the name of the potion that would be created when calling create (if a record for such - /// a potion already exists) or return an empty string. - std::string getPotionName() const; - - /// Try to create a potion from the ingredients, place it in the inventory of the alchemist and - /// adjust the skills of the alchemist accordingly. - /// \param name must not be an empty string, unless there is already a potion record ( - /// getPotionName() does not return an empty string). - Result create (const std::string& name); - private: MWWorld::Ptr mAlchemist; @@ -92,19 +50,19 @@ namespace MWMechanics TEffectsContainer mEffects; int mValue; - /// List all effects shared by at least two ingredients. std::set listEffects() const; + ///< List all effects shared by at least two ingredients. void applyTools (int flags, float& value) const; void updateEffects(); - /// Return existing recrod for created potion (may return 0) const ESM::Potion *getRecord() const; + ///< Return existing recrod for created potion (may return 0) - /// Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and - /// update effect list accordingly. void removeIngredients(); + ///< Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and + /// update effect list accordingly. void addPotion (const std::string& name); ///< Add a potion to the alchemist's inventory. @@ -116,6 +74,48 @@ namespace MWMechanics ///< Return chance of success. int countIngredients() const; + + public: + + void setAlchemist (const MWWorld::Ptr& npc); + ///< Set alchemist and configure alchemy setup accordingly. \a npc may be empty to indicate that + /// there is no alchemist (alchemy session has ended). + + TToolsIterator beginTools() const; + ///< \attention Iterates over tool slots, not over tools. Some of the slots may be empty. + + TToolsIterator endTools() const; + + TIngredientsIterator beginIngredients() const; + ///< \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty. + + TIngredientsIterator endIngredients() const; + + void clear(); + ///< Remove alchemist, tools and ingredients. + + int addIngredient (const MWWorld::Ptr& ingredient); + ///< Add ingredient into the next free slot. + /// + /// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being + /// listed already. + + void removeIngredient (int index); + ///< Remove ingredient from slot (calling this function on an empty slot is a no-op). + + TEffectsIterator beginEffects() const; + + TEffectsIterator endEffects() const; + + std::string getPotionName() const; + ///< Return the name of the potion that would be created when calling create (if a record for such + /// a potion already exists) or return an empty string. + + Result create (const std::string& name); + ///< Try to create a potion from the ingredients, place it in the inventory of the alchemist and + /// adjust the skills of the alchemist accordingly. + /// \param name must not be an empty string, unless there is already a potion record ( + /// getPotionName() does not return an empty string). }; } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 09c995428..5aea0210f 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -21,199 +21,194 @@ namespace MWRender namespace MWMechanics { - class Movement; - class CreatureStats; +class Movement; +class CreatureStats; - ///Priority of actions - enum Priority { - Priority_Default, - Priority_Jump, - Priority_Movement, - Priority_Hit, - Priority_Weapon, - Priority_Knockdown, - Priority_Torch, +enum Priority { + Priority_Default, + Priority_Jump, + Priority_Movement, + Priority_Hit, + Priority_Weapon, + Priority_Knockdown, + Priority_Torch, - Priority_Death, + Priority_Death, - Num_Priorities - }; + Num_Priorities +}; - /// Current action of the character - enum CharacterState { - CharState_None, +enum CharacterState { + CharState_None, - CharState_SpecialIdle, - CharState_Idle, - CharState_Idle2, - CharState_Idle3, - CharState_Idle4, - CharState_Idle5, - CharState_Idle6, - CharState_Idle7, - CharState_Idle8, - CharState_Idle9, - CharState_IdleSwim, - CharState_IdleSneak, + CharState_SpecialIdle, + CharState_Idle, + CharState_Idle2, + CharState_Idle3, + CharState_Idle4, + CharState_Idle5, + CharState_Idle6, + CharState_Idle7, + CharState_Idle8, + CharState_Idle9, + CharState_IdleSwim, + CharState_IdleSneak, - CharState_WalkForward, - CharState_WalkBack, - CharState_WalkLeft, - CharState_WalkRight, + CharState_WalkForward, + CharState_WalkBack, + CharState_WalkLeft, + CharState_WalkRight, - CharState_SwimWalkForward, - CharState_SwimWalkBack, - CharState_SwimWalkLeft, - CharState_SwimWalkRight, + CharState_SwimWalkForward, + CharState_SwimWalkBack, + CharState_SwimWalkLeft, + CharState_SwimWalkRight, - CharState_RunForward, - CharState_RunBack, - CharState_RunLeft, - CharState_RunRight, + CharState_RunForward, + CharState_RunBack, + CharState_RunLeft, + CharState_RunRight, - CharState_SwimRunForward, - CharState_SwimRunBack, - CharState_SwimRunLeft, - CharState_SwimRunRight, + CharState_SwimRunForward, + CharState_SwimRunBack, + CharState_SwimRunLeft, + CharState_SwimRunRight, - CharState_SneakForward, - CharState_SneakBack, - CharState_SneakLeft, - CharState_SneakRight, + CharState_SneakForward, + CharState_SneakBack, + CharState_SneakLeft, + CharState_SneakRight, - CharState_TurnLeft, - CharState_TurnRight, + CharState_TurnLeft, + CharState_TurnRight, - CharState_Jump, + CharState_Jump, - CharState_Death1, - CharState_Death2, - CharState_Death3, - CharState_Death4, - CharState_Death5, - CharState_SwimDeath, - CharState_DeathKnockDown, - CharState_DeathKnockOut, + CharState_Death1, + CharState_Death2, + CharState_Death3, + CharState_Death4, + CharState_Death5, + CharState_SwimDeath, + CharState_DeathKnockDown, + CharState_DeathKnockOut, - CharState_Hit, - CharState_KnockDown, - CharState_KnockOut, - CharState_Block - }; + CharState_Hit, + CharState_KnockDown, + CharState_KnockOut, + CharState_Block +}; - ///Weapon type - enum WeaponType { - WeapType_None, +enum WeaponType { + WeapType_None, - WeapType_HandToHand, - WeapType_OneHand, - WeapType_TwoHand, - WeapType_TwoWide, - WeapType_BowAndArrow, - WeapType_Crossbow, - WeapType_Thrown, - WeapType_PickProbe, + WeapType_HandToHand, + WeapType_OneHand, + WeapType_TwoHand, + WeapType_TwoWide, + WeapType_BowAndArrow, + WeapType_Crossbow, + WeapType_Thrown, + WeapType_PickProbe, - WeapType_Spell - }; + WeapType_Spell +}; - ///Specific, weapon based state of the character - enum UpperBodyCharacterState { - UpperCharState_Nothing, - UpperCharState_EquipingWeap, - UpperCharState_UnEquipingWeap, - UpperCharState_WeapEquiped, - UpperCharState_StartToMinAttack, - UpperCharState_MinAttackToMaxAttack, - UpperCharState_MaxAttackToMinHit, - UpperCharState_MinHitToHit, - UpperCharState_FollowStartToFollowStop, - UpperCharState_CastingSpell - }; +enum UpperBodyCharacterState { + UpperCharState_Nothing, + UpperCharState_EquipingWeap, + UpperCharState_UnEquipingWeap, + UpperCharState_WeapEquiped, + UpperCharState_StartToMinAttack, + UpperCharState_MinAttackToMaxAttack, + UpperCharState_MaxAttackToMinHit, + UpperCharState_MinHitToHit, + UpperCharState_FollowStartToFollowStop, + UpperCharState_CastingSpell +}; - ///Current jumping state - enum JumpingState { - JumpState_None, - JumpState_Falling, - JumpState_Landing - }; +enum JumpingState { + JumpState_None, + JumpState_Falling, + JumpState_Landing +}; - class CharacterController - { - MWWorld::Ptr mPtr; - MWRender::Animation *mAnimation; +class CharacterController +{ + MWWorld::Ptr mPtr; + MWRender::Animation *mAnimation; - typedef std::deque > AnimationQueue; - AnimationQueue mAnimQueue; + typedef std::deque > AnimationQueue; + AnimationQueue mAnimQueue; - CharacterState mIdleState; - std::string mCurrentIdle; + CharacterState mIdleState; + std::string mCurrentIdle; - CharacterState mMovementState; - std::string mCurrentMovement; - float mMovementSpeed; - float mMovementAnimVelocity; + CharacterState mMovementState; + std::string mCurrentMovement; + float mMovementSpeed; + float mMovementAnimVelocity; - CharacterState mDeathState; - std::string mCurrentDeath; + CharacterState mDeathState; + std::string mCurrentDeath; - CharacterState mHitState; - std::string mCurrentHit; + CharacterState mHitState; + std::string mCurrentHit; - UpperBodyCharacterState mUpperBodyState; + UpperBodyCharacterState mUpperBodyState; - JumpingState mJumpState; - std::string mCurrentJump; + JumpingState mJumpState; + std::string mCurrentJump; - WeaponType mWeaponType; - std::string mCurrentWeapon; + WeaponType mWeaponType; + std::string mCurrentWeapon; - bool mSkipAnim; + bool mSkipAnim; - // counted for skill increase - float mSecondsOfSwimming; - float mSecondsOfRunning; + // counted for skill increase + float mSecondsOfSwimming; + float mSecondsOfRunning; - std::string mAttackType; // slash, chop or thrust - void determineAttackType(); + std::string mAttackType; // slash, chop or thrust + void determineAttackType(); - void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false); + void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false); - void clearAnimQueue(); + void clearAnimQueue(); - bool updateWeaponState(); - bool updateCreatureState(); + bool updateWeaponState(); + bool updateCreatureState(); - void updateVisibility(); + void updateVisibility(); - void playRandomDeath(float startpoint = 0.0f); + void playRandomDeath(float startpoint = 0.0f); - /// choose a random animation group with \a prefix and numeric suffix - /// @param num if non-NULL, the chosen animation number will be written here - std::string chooseRandomGroup (const std::string& prefix, int* num = NULL); + /// choose a random animation group with \a prefix and numeric suffix + /// @param num if non-NULL, the chosen animation number will be written here + std::string chooseRandomGroup (const std::string& prefix, int* num = NULL); - public: - CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); - virtual ~CharacterController(); +public: + CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); + virtual ~CharacterController(); - // Be careful when to call this, see comment in Actors - void updateContinuousVfx(); + // Be careful when to call this, see comment in Actors + void updateContinuousVfx(); - void updatePtr(const MWWorld::Ptr &ptr); + void updatePtr(const MWWorld::Ptr &ptr); - void update(float duration); + void update(float duration); - void playGroup(const std::string &groupname, int mode, int count); - void skipAnim(); - bool isAnimPlaying(const std::string &groupName); + void playGroup(const std::string &groupname, int mode, int count); + void skipAnim(); + bool isAnimPlaying(const std::string &groupName); - bool kill(); - void resurrect(); - bool isDead() const - { return mDeathState != CharState_None; } + bool kill(); + void resurrect(); + bool isDead() const + { return mDeathState != CharState_None; } - void forceStateUpdate(); - }; + void forceStateUpdate(); +}; void getWeaponGroup(WeaponType weaptype, std::string &group); MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::InventoryStore &inv, WeaponType *weaptype); From a61d804de694613874e4b8ad415cdca6c2b97b58 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:53:06 -0400 Subject: [PATCH 25/63] now that I've found the documentation, fixed some stuff for extensions --- components/compiler/extensions.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index 5be81ac08..908165ee6 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -16,12 +16,12 @@ namespace Compiler every argument is optional.
Eg: fff/f represents 3 required floats followed by one optional float
f - Float
- c - String
+ c - String, case smashed
l - Integer
s - Short
- S - Also string (Seemed to be mostly used for Cell Names)
- x - none? - + S - String, case preserved
+ x - Optional, ignored argument + \see Compiler::ExprParser::parseArguments **/ typedef std::string ScriptArgs; From d6d4d9f75d42b60a303193f074464268b99afdc4 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 14:08:08 -0400 Subject: [PATCH 26/63] Removed destructor documentation --- apps/openmw/mwmechanics/aisequence.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 5a4cb743a..8196262f5 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -40,7 +40,6 @@ namespace MWMechanics /// Assignment operator AiSequence& operator= (const AiSequence& sequence); - /// Destructor virtual ~AiSequence(); /// Returns currently executing AiPackage type From 085fb2c5a2033aa1d21e8ecbe61e537e4383fc1e Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 14:13:05 -0400 Subject: [PATCH 27/63] Simplified documentation a bit --- components/compiler/exprparser.hpp | 6 ++---- components/compiler/extensions.hpp | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 6a4e1be2f..93e0d1c36 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -98,10 +98,8 @@ namespace Compiler int parseArguments (const std::string& arguments, Scanner& scanner, std::vector& code, bool invert = false); ///< Parse sequence of arguments specified by \a arguments. - /// \param arguments Each character represents one arguments ('l': integer, - /// 'f': float, 'S': string, 'c': string (case smashed), '/': following arguments are - /// optional) - /// 'x': optional string that will be ignored (die in a fire, MW script compiler!) + /// \param arguments Uses ScriptArgs typedef + /// \see Compiler::ScriptArgs /// \param invert Store arguments in reverted order. /// \return number of optional arguments }; diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index 908165ee6..3f91ca357 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -21,7 +21,6 @@ namespace Compiler s - Short
S - String, case preserved
x - Optional, ignored argument - \see Compiler::ExprParser::parseArguments **/ typedef std::string ScriptArgs; From 680890c84689cb8b647b6ba55bec7b427b433266 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 14:21:59 -0400 Subject: [PATCH 28/63] Clarification on some documentation points --- apps/openmw/mwmechanics/aisequence.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 8196262f5..3d524a686 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -15,13 +15,13 @@ namespace MWMechanics class AiPackage; /// \brief Sequence of AI-packages for a single actor - /** Each package will be run in succession for an actor until completed **/ + /** The top-most AI package is run each frame. When completed, it is removed from the stack. **/ class AiSequence { ///AiPackages to run though std::list mPackages; - ///Finished with all AiPackages + ///Finished with top AIPackage, set for one frame bool mDone; ///Copy AiSequence From 6d540c4e073250fccbe09e06c9a2dcf93c7c29f6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 14:24:48 -0400 Subject: [PATCH 29/63] Removed merging error --- apps/openmw/mwmechanics/aisequence.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 3d524a686..7ac68dd67 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -58,9 +58,6 @@ namespace MWMechanics /// Removes all combat packages until first non-combat or stack empty. void stopCombat(); - /// Removes all persue packages until first non-persue or stack empty. - void stopPersue(); - /// Has a package been completed during the last update? bool isPackageDone() const; From 365ca6c7e1b6208fc323f1fc29db8c4747bb6ee4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 21:42:27 +0200 Subject: [PATCH 30/63] Fixes #1331: Manually disable movement state for dead actors. For dead actors, refreshCurrentAnims is no longer called, so we need to disable the movement state manually. --- apps/openmw/mwmechanics/character.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 280639f71..2b8b6eccb 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -431,6 +431,11 @@ void CharacterController::playRandomDeath(float startpoint) mDeathState = static_cast(CharState_Death1 + (selected-1)); } + // For dead actors, refreshCurrentAnims is no longer called, so we need to disable the movement state manually. + mMovementState = CharState_None; + mAnimation->disable(mCurrentMovement); + mCurrentMovement = ""; + mAnimation->play(mCurrentDeath, Priority_Death, MWRender::Animation::Group_All, false, 1.0f, "start", "stop", startpoint, 0); } From 203ef580cf3cfae01c3dcedb34842a1b71d99c14 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 20:32:29 -0400 Subject: [PATCH 31/63] Fixed moving activatable object being incorrectly activated. --- apps/openmw/mwmechanics/aiactivate.hpp | 2 +- apps/openmw/mwmechanics/aipackage.cpp | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index f68438872..0e660e967 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -9,7 +9,7 @@ namespace MWMechanics { /// \brief Causes actor to walk to activatable object and activate it - /** Will actiavte when close to object or path grid complete **/ + /** Will activate when close to object **/ class AiActivate : public AiPackage { public: diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 872eecb62..1bc350383 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -109,19 +109,15 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po // change the angle a bit, too zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); } - /*else if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //NPC hasn't moved much is half a second, he's stuck - actor.getClass().getMovementSettings(actor).mPosition[1] = 0; - actor.getClass().getMovementSettings(actor).mPosition[0] = 1; - }*/ } - else { + else { //Not stuck, so reset things mStuckTimer = 0; mStuckPos = pos; mLastDoorChecked = NULL; //Resets it, in case he gets stuck behind the door again } } else { - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward the rest of the time } zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); From 58bf7624becac34486eb6018c301de9d9f27ef04 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 21:52:05 -0400 Subject: [PATCH 32/63] Made code a bit more efficient --- apps/openmw/mwmechanics/aiactivate.cpp | 2 +- apps/openmw/mwmechanics/aiavoiddoor.hpp | 2 +- apps/openmw/mwmechanics/aipackage.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 8 ++------ 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index 1463dff7e..56c155ded 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -29,7 +29,7 @@ bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) //Set the target desition from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 200 || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { //Stop when you get close + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 200) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 6e9a1bdf5..8d225655a 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -29,7 +29,7 @@ namespace MWMechanics private: float mDuration; - MWWorld::Ptr mDoorPtr; + const MWWorld::Ptr& mDoorPtr; }; } #endif diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 1bc350383..5ccd2c8d8 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -96,7 +96,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po if(door != NULL) // NOTE: checks interior cells only { if(door->mRef.mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped - door->mClass->activate(MWBase::Environment::get().getWorld()->getPtr(door->mRef.mRefID,false), actor).get()->execute(actor); + door->mClass->activate(MWWorld::Ptr(door, actor.getCell()), actor).get()->execute(actor); mLastDoorChecked = door; } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 82489adac..96dd91f82 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1863,12 +1863,8 @@ namespace MWWorld bool World::getIsMovingDoor(const Ptr& door) { - //This more expensive comparison is needed for some reason - // TODO (tluppi#1#): Figure out why comparing Ptr isn't working - for(std::map::iterator it = mDoorStates.begin(); it != mDoorStates.end(); it++) - if(it->first.getCellRef().mRefID == door.getCellRef().mRefID) - return true; - return false; + bool result = mDoorStates.find(door) != mDoorStates.end(); + return result; } bool World::getPlayerStandingOn (const MWWorld::Ptr& object) From 6c7b3074f5447a60d124b42e8ab6fe9114e87a72 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 05:31:19 +0200 Subject: [PATCH 33/63] Fix self-defense for creatures when attacked with a spell --- apps/openmw/mwmechanics/spellcasting.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index e6342e661..0f5649af2 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -408,9 +408,9 @@ namespace MWMechanics target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, mSourceName, caster.getRefData().getHandle()); - if (anyHarmfulEffect && target.getClass().isActor() && target != caster - && target.getClass().getCreatureStats(target).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) - MWBase::Environment::get().getMechanicsManager()->commitCrime(caster, target, MWBase::MechanicsManager::OT_Assault); + // Notify the target actor they've been hit + if (anyHarmfulEffect && target.getClass().isActor() && target != caster) + target.getClass().onHit(target, 0.f, true, MWWorld::Ptr(), caster, true); } void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const MWMechanics::EffectKey& effect, float magnitude) From 99b4bc721b5ec17ce4cf3f1e2638337b5d1440ac Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 05:33:18 +0200 Subject: [PATCH 34/63] Don't attempt to inflict spells on dead actors --- apps/openmw/mwmechanics/spellcasting.cpp | 3 +++ apps/openmw/mwmechanics/spellcasting.hpp | 1 + 2 files changed, 4 insertions(+) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 0f5649af2..d510373ff 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -189,6 +189,9 @@ namespace MWMechanics void CastSpell::inflict(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const ESM::EffectList &effects, ESM::RangeType range, bool reflected, bool exploded) { + if (target.getClass().isActor() && target.getClass().getCreatureStats(target).isDead()) + return; + // If none of the effects need to apply, we can early-out bool found = false; for (std::vector::const_iterator iter (effects.mList.begin()); diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 44402fe7b..a930442fb 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -61,6 +61,7 @@ namespace MWMechanics /// @note Auto detects if spell, ingredient or potion bool cast (const std::string& id); + /// @note \a target can be any type of object, not just actors. void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false, bool exploded=false); From 7cd4c93fa4aa7dd63a55818de533e4dd539b270b Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 23:46:00 -0400 Subject: [PATCH 35/63] Changed getNearbyDoor to use MWWorld::Ptr --- apps/openmw/mwmechanics/aipackage.cpp | 12 ++++++------ apps/openmw/mwmechanics/aipackage.hpp | 3 ++- apps/openmw/mwmechanics/obstacle.cpp | 10 +++++----- apps/openmw/mwmechanics/obstacle.hpp | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 5ccd2c8d8..c2e8385b8 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -16,7 +16,7 @@ MWMechanics::AiPackage::~AiPackage() {} -MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(NULL), mTimer(0), mStuckTimer(0) { +MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(MWWorld::Ptr()), mTimer(0), mStuckTimer(0) { } @@ -92,11 +92,11 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //if(mObstacleCheck.check(actor, duration)) { if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10 && distance(dest, start) > 20) { //Actually stuck, and far enough away from destination to care // first check if we're walking into a door - MWWorld::LiveCellRef* door = getNearbyDoor(actor); - if(door != NULL) // NOTE: checks interior cells only + MWWorld::Ptr door = getNearbyDoor(actor); + if(door != MWWorld::Ptr()) // NOTE: checks interior cells only { - if(door->mRef.mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped - door->mClass->activate(MWWorld::Ptr(door, actor.getCell()), actor).get()->execute(actor); + if(door.getCellRef().mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped + door.getClass().activate(door, actor).get()->execute(actor); mLastDoorChecked = door; } } @@ -113,7 +113,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po else { //Not stuck, so reset things mStuckTimer = 0; mStuckPos = pos; - mLastDoorChecked = NULL; //Resets it, in case he gets stuck behind the door again + mLastDoorChecked = MWWorld::Ptr(); //Resets it, in case he gets stuck behind the door again } } else { diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index c9c8504aa..bb62a2543 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -3,6 +3,7 @@ #include "pathfinding.hpp" #include +#include "../mwbase/world.hpp" #include "obstacle.hpp" @@ -63,7 +64,7 @@ namespace MWMechanics float mStuckTimer; float mTotalTime; - MWWorld::LiveCellRef* mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door + MWWorld::Ptr mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door ESM::Position mStuckPos; }; diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 7cd85685b..fc781e637 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -20,18 +20,18 @@ namespace MWMechanics // actor is facing the door. bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) { - if(getNearbyDoor(actor, minSqr, closed)!=NULL) + if(getNearbyDoor(actor, minSqr, closed)!=MWWorld::Ptr()) return true; else return false; } - MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) + MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) { MWWorld::CellStore *cell = actor.getCell(); if(cell->getCell()->isExterior()) - return NULL; // check interior cells only + return MWWorld::Ptr(); // check interior cells only // Check all the doors in this cell MWWorld::CellRefList& doors = cell->get(); @@ -54,10 +54,10 @@ namespace MWMechanics if((closed && ref.mData.getLocalRotation().rot[2] == 0) || (!closed && ref.mData.getLocalRotation().rot[2] >= 1)) { - return &ref; // found, stop searching + return MWWorld::Ptr(&ref, actor.getCell()); // found, stop searching } } - return NULL; // none found + return MWWorld::Ptr(); // none found } ObstacleCheck::ObstacleCheck(): diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp index e737ef9cf..76ab9d029 100644 --- a/apps/openmw/mwmechanics/obstacle.hpp +++ b/apps/openmw/mwmechanics/obstacle.hpp @@ -22,7 +22,7 @@ namespace MWMechanics /// Returns door pointer within range. No guarentee is given as too which one /** \return Pointer to the door, or NULL if none exists **/ - MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, + MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minSqr = MIN_DIST_TO_DOOR_SQUARED, bool closed = true); From 7697ab37e02890d6a5bdc84dc7cfcd91be87dc9c Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 06:37:31 +0200 Subject: [PATCH 36/63] Fixes #1129: Change summoned creatures to use ActorId Gracefully handles summoned creatures that are left behind in inactive cells. --- apps/openmw/mwmechanics/actors.cpp | 46 +++++++++++++++++------ apps/openmw/mwmechanics/creaturestats.hpp | 12 ++++-- apps/openmw/mwworld/actionteleport.cpp | 1 - 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 91ef48c09..22d033f40 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -38,9 +38,12 @@ void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& a { if (bound) { - MWWorld::Ptr newPtr = *actor.getClass().getContainerStore(actor).add(item, 1, actor); - MWWorld::ActionEquip action(newPtr); - action.execute(actor); + if (actor.getClass().getContainerStore(actor).count(item) == 0) + { + MWWorld::Ptr newPtr = *actor.getClass().getContainerStore(actor).add(item, 1, actor); + MWWorld::ActionEquip action(newPtr); + action.execute(actor); + } } else { @@ -534,28 +537,49 @@ namespace MWMechanics MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1); ref.getPtr().getCellRef().mPos = ipos; - // TODO: Add AI to follow player and fight for him + MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr()); + + // Make the summoned creature follow its master and help in fights AiFollow package(ptr.getRefData().getHandle()); - MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package, ptr); + summonedCreatureStats.getAiSequence().stack(package, ref.getPtr()); + int creatureActorId = summonedCreatureStats.getActorId(); + + MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos); + // TODO: VFX_SummonStart, VFX_SummonEnd - creatureStats.mSummonedCreatures.insert(std::make_pair(it->first, - MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos).getRefData().getHandle())); + creatureStats.mSummonedCreatures.insert(std::make_pair(it->first, creatureActorId)); } } else { - std::string handle = creatureStats.mSummonedCreatures[it->first]; - // TODO: Show death animation before deleting? We shouldn't allow looting the corpse while the animation - // plays though, which is a rather lame exploit in vanilla. - MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle); + // Summon lifetime has expired. Try to delete the creature. + int actorId = creatureStats.mSummonedCreatures[it->first]; + creatureStats.mSummonedCreatures.erase(it->first); + + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(actorId); if (!ptr.isEmpty()) { + // TODO: Show death animation before deleting? We shouldn't allow looting the corpse while the animation + // plays though, which is a rather lame exploit in vanilla. MWBase::Environment::get().getWorld()->deleteObject(ptr); creatureStats.mSummonedCreatures.erase(it->first); } + else + { + // We didn't find the creature. It's probably in an inactive cell. + // Add to graveyard so we can delete it when the cell becomes active. + creatureStats.mSummonGraveyard.push_back(actorId); + } } } } + + for (std::vector::iterator it = creatureStats.mSummonGraveyard.begin(); it != creatureStats.mSummonGraveyard.end(); ++it) + { + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(*it); + if (!ptr.isEmpty()) + MWBase::Environment::get().getWorld()->deleteObject(ptr); + } } void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 7cec26fb8..79686bb97 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -223,10 +223,16 @@ namespace MWMechanics void setLastHitObject(const std::string &objectid); const std::string &getLastHitObject() const; - // Note, this is just a cache to avoid checking the whole container store every frame TODO: Put it somewhere else? + // Note, this is just a cache to avoid checking the whole container store every frame. We don't need to store it in saves. + // TODO: Put it somewhere else? std::set mBoundItems; - // Same as above - std::map mSummonedCreatures; + + // TODO: store in savegame + // TODO: encapsulate? + // + std::map mSummonedCreatures; + // Contains summoned creatures with an expired lifetime that have not been deleted yet. + std::vector mSummonGraveyard; void writeState (ESM::CreatureStats& state) const; diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 627c05251..4378e179d 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -22,7 +22,6 @@ namespace MWWorld std::list followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor); for(std::list::iterator it = followers.begin();it != followers.end();++it) { - std::cout << "teleporting someone!" << (*it).getCellRef().mRefID; executeImp(*it); } From c160a04ede26f28d1f9530a7dc0c2ba890494cb1 Mon Sep 17 00:00:00 2001 From: slothlife Date: Wed, 14 May 2014 00:03:30 -0500 Subject: [PATCH 37/63] Revert "Fixes for warnings when building with MSVC" This reverts commit 46eb20b98ce990756ad1f9af5054f0a571dca43c. --- CMakeLists.txt | 1 - apps/esmtool/esmtool.cpp | 2 + apps/mwiniimporter/main.cpp | 2 +- apps/opencs/model/doc/document.cpp | 516 +++++++++--------- apps/opencs/model/doc/document.hpp | 2 +- apps/opencs/model/doc/documentmanager.hpp | 4 +- apps/opencs/model/world/commands.hpp | 4 +- apps/opencs/model/world/idtable.hpp | 2 +- apps/opencs/model/world/infocollection.hpp | 4 +- apps/opencs/model/world/ref.hpp | 2 +- apps/opencs/model/world/refcollection.hpp | 2 +- apps/opencs/model/world/refidadapter.hpp | 4 +- apps/opencs/view/render/lightingday.cpp | 4 +- apps/opencs/view/render/lightingnight.cpp | 6 +- apps/opencs/view/render/scenewidget.cpp | 4 +- apps/opencs/view/world/vartypedelegate.cpp | 2 +- apps/openmw/mwgui/bookpage.cpp | 4 +- apps/openmw/mwgui/companionwindow.cpp | 2 +- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/spellicons.hpp | 2 - apps/openmw/mwmechanics/combat.cpp | 4 +- apps/openmw/mwmechanics/levelledlist.hpp | 2 +- apps/openmw/mwrender/localmap.cpp | 2 +- apps/openmw/mwrender/occlusionquery.cpp | 2 +- apps/openmw/mwrender/weaponanimation.hpp | 1 - .../mwscript/transformationextensions.cpp | 4 +- apps/openmw/mwsound/ffmpeg_decoder.cpp | 2 +- apps/openmw/mwsound/openal_output.cpp | 12 +- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +- .../contentselector/model/contentmodel.cpp | 1 + components/esm/esmreader.hpp | 2 +- components/esm/inventorystate.hpp | 2 - components/esm/loadcell.hpp | 2 +- components/ogreinit/ogreplugin.cpp | 6 +- components/terrain/material.cpp | 4 +- 37 files changed, 311 insertions(+), 314 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89bf75c6c..bd437ed61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -610,7 +610,6 @@ if (WIN32) 4305 # Truncating value (double to float, for example) 4309 # Variable overflow, trying to store 128 in a signed char for example 4355 # Using 'this' in member initialization list - 4505 # Unreferenced local function has been removed 4701 # Potentially uninitialized local variable used 4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt ) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 6b67cf7d5..eef96c8c9 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -218,6 +218,8 @@ int main(int argc, char**argv) std::cout << "Invalid or no mode specified, dying horribly. Have a nice day." << std::endl; return 1; } + + return 0; } void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index c2cb8117a..364a6b1a4 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) { std::cerr << "cfg file does not exist" << std::endl; MwIniImporter importer; - importer.setVerbose(vm.count("verbose") != 0); + importer.setVerbose(vm.count("verbose")); // Font encoding settings std::string encoding(vm["encoding"].as()); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 72d7f5cd8..3ef14ee7e 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -292,264 +292,264 @@ void CSMDoc::Document::addGmsts() static const float gmstFloatsValues[] = { - 0.3f, // fAIFleeFleeMult - 7.0f, // fAIFleeHealthMult - 3.0f, // fAIMagicSpellMult - 1.0f, // fAIMeleeArmorMult - 1.0f, // fAIMeleeSummWeaponMult - 2.0f, // fAIMeleeWeaponMult - 5.0f, // fAIRangeMagicSpellMult - 5.0f, // fAIRangeMeleeWeaponMult - 2000.0f, // fAlarmRadius - 1.0f, // fAthleticsRunBonus - 40.0f, // fAudioDefaultMaxDistance - 5.0f, // fAudioDefaultMinDistance - 50.0f, // fAudioMaxDistanceMult - 20.0f, // fAudioMinDistanceMult - 60.0f, // fAudioVoiceDefaultMaxDistance - 10.0f, // fAudioVoiceDefaultMinDistance - 50.0f, // fAutoPCSpellChance - 80.0f, // fAutoSpellChance - 50.0f, // fBargainOfferBase - -4.0f, // fBargainOfferMulti - 24.0f, // fBarterGoldResetDelay - 1.75f, // fBaseRunMultiplier - 1.25f, // fBlockStillBonus - 150.0f, // fBribe1000Mod - 75.0f, // fBribe100Mod - 35.0f, // fBribe10Mod - 60.0f, // fCombatAngleXY - 60.0f, // fCombatAngleZ - 0.25f, // fCombatArmorMinMult - -90.0f, // fCombatBlockLeftAngle - 30.0f, // fCombatBlockRightAngle - 4.0f, // fCombatCriticalStrikeMult - 0.1f, // fCombatDelayCreature - 0.1f, // fCombatDelayNPC - 128.0f, // fCombatDistance - 0.3f, // fCombatDistanceWerewolfMod - 30.0f, // fCombatForceSideAngle - 0.2f, // fCombatInvisoMult - 1.5f, // fCombatKODamageMult - 45.0f, // fCombatTorsoSideAngle - 0.3f, // fCombatTorsoStartPercent - 0.8f, // fCombatTorsoStopPercent - 15.0f, // fConstantEffectMult - 72.0f, // fCorpseClearDelay - 72.0f, // fCorpseRespawnDelay - 0.5f, // fCrimeGoldDiscountMult - 0.9f, // fCrimeGoldTurnInMult - 1.0f, // fCrimeStealing - 0.5f, // fDamageStrengthBase - 0.1f, // fDamageStrengthMult - 5.0f, // fDifficultyMult - 2.5f, // fDiseaseXferChance - -10.0f, // fDispAttacking - -1.0f, // fDispBargainFailMod - 1.0f, // fDispBargainSuccessMod - 0.0f, // fDispCrimeMod - -10.0f, // fDispDiseaseMod - 3.0f, // fDispFactionMod - 1.0f, // fDispFactionRankBase - 0.5f, // fDispFactionRankMult - 1.0f, // fDispositionMod - 50.0f, // fDispPersonalityBase - 0.5f, // fDispPersonalityMult - -25.0f, // fDispPickPocketMod - 5.0f, // fDispRaceMod - -0.5f, // fDispStealing - -5.0f, // fDispWeaponDrawn - 0.5f, // fEffectCostMult - 0.1f, // fElementalShieldMult - 3.0f, // fEnchantmentChanceMult - 0.5f, // fEnchantmentConstantChanceMult - 100.0f, // fEnchantmentConstantDurationMult - 0.1f, // fEnchantmentMult - 1000.0f, // fEnchantmentValueMult - 0.3f, // fEncumberedMoveEffect - 5.0f, // fEncumbranceStrMult - 0.04f, // fEndFatigueMult - 0.25f, // fFallAcroBase - 0.01f, // fFallAcroMult - 400.0f, // fFallDamageDistanceMin - 0.0f, // fFallDistanceBase - 0.07f, // fFallDistanceMult - 2.0f, // fFatigueAttackBase - 0.0f, // fFatigueAttackMult - 1.25f, // fFatigueBase - 4.0f, // fFatigueBlockBase - 0.0f, // fFatigueBlockMult - 5.0f, // fFatigueJumpBase - 0.0f, // fFatigueJumpMult - 0.5f, // fFatigueMult - 2.5f, // fFatigueReturnBase - 0.02f, // fFatigueReturnMult - 5.0f, // fFatigueRunBase - 2.0f, // fFatigueRunMult - 1.5f, // fFatigueSneakBase - 1.5f, // fFatigueSneakMult - 0.0f, // fFatigueSpellBase - 0.0f, // fFatigueSpellCostMult - 0.0f, // fFatigueSpellMult - 7.0f, // fFatigueSwimRunBase - 0.0f, // fFatigueSwimRunMult - 2.5f, // fFatigueSwimWalkBase - 0.0f, // fFatigueSwimWalkMult - 0.2f, // fFightDispMult - 0.005f, // fFightDistanceMultiplier - 50.0f, // fFightStealing - 3000.0f, // fFleeDistance - 512.0f, // fGreetDistanceReset - 0.1f, // fHandtoHandHealthPer - 1.0f, // fHandToHandReach - 0.5f, // fHoldBreathEndMult - 20.0f, // fHoldBreathTime - 0.75f, // fIdleChanceMultiplier - 1.0f, // fIngredientMult - 0.5f, // fInteriorHeadTrackMult - 128.0f, // fJumpAcrobaticsBase - 4.0f, // fJumpAcroMultiplier - 0.5f, // fJumpEncumbranceBase - 1.0f, // fJumpEncumbranceMultiplier - 0.5f, // fJumpMoveBase - 0.5f, // fJumpMoveMult - 1.0f, // fJumpRunMultiplier - 0.5f, // fKnockDownMult - 5.0f, // fLevelMod - 0.1f, // fLevelUpHealthEndMult - 0.6f, // fLightMaxMod - 10.0f, // fLuckMod - 10.0f, // fMagesGuildTravel - 1.5f, // fMagicCreatureCastDelay - 0.0167f, // fMagicDetectRefreshRate - 1.0f, // fMagicItemConstantMult - 1.0f, // fMagicItemCostMult - 1.0f, // fMagicItemOnceMult - 1.0f, // fMagicItemPriceMult - 0.05f, // fMagicItemRechargePerSecond - 1.0f, // fMagicItemStrikeMult - 1.0f, // fMagicItemUsedMult - 3.0f, // fMagicStartIconBlink - 0.5f, // fMagicSunBlockedMult - 0.75f, // fMajorSkillBonus - 300.0f, // fMaxFlySpeed - 0.5f, // fMaxHandToHandMult - 400.0f, // fMaxHeadTrackDistance - 200.0f, // fMaxWalkSpeed - 300.0f, // fMaxWalkSpeedCreature - 0.9f, // fMedMaxMod - 0.1f, // fMessageTimePerChar - 5.0f, // fMinFlySpeed - 0.1f, // fMinHandToHandMult - 1.0f, // fMinorSkillBonus - 100.0f, // fMinWalkSpeed - 5.0f, // fMinWalkSpeedCreature - 1.25f, // fMiscSkillBonus - 2.0f, // fNPCbaseMagickaMult - 0.5f, // fNPCHealthBarFade - 3.0f, // fNPCHealthBarTime - 1.0f, // fPCbaseMagickaMult - 0.3f, // fPerDieRollMult - 5.0f, // fPersonalityMod - 1.0f, // fPerTempMult - -1.0f, // fPickLockMult - 0.3f, // fPickPocketMod - 20.0f, // fPotionMinUsefulDuration - 0.5f, // fPotionStrengthMult - 0.5f, // fPotionT1DurMult - 1.5f, // fPotionT1MagMult - 20.0f, // fPotionT4BaseStrengthMult - 12.0f, // fPotionT4EquipStrengthMult - 3000.0f, // fProjectileMaxSpeed - 400.0f, // fProjectileMinSpeed - 25.0f, // fProjectileThrownStoreChance - 3.0f, // fRepairAmountMult - 1.0f, // fRepairMult - 1.0f, // fReputationMod - 0.15f, // fRestMagicMult - 0.0f, // fSeriousWoundMult - 0.25f, // fSleepRandMod - 0.3f, // fSleepRestMod - -1.0f, // fSneakBootMult - 0.5f, // fSneakDistanceBase - 0.002f, // fSneakDistanceMultiplier - 0.5f, // fSneakNoViewMult - 1.0f, // fSneakSkillMult - 0.75f, // fSneakSpeedMultiplier - 1.0f, // fSneakUseDelay - 500.0f, // fSneakUseDist - 1.5f, // fSneakViewMult - 3.0f, // fSoulGemMult - 0.8f, // fSpecialSkillBonus - 7.0f, // fSpellMakingValueMult - 2.0f, // fSpellPriceMult - 10.0f, // fSpellValueMult - 0.25f, // fStromWalkMult - 0.7f, // fStromWindSpeed - 3.0f, // fSuffocationDamage - 0.9f, // fSwimHeightScale - 0.1f, // fSwimRunAthleticsMult - 0.5f, // fSwimRunBase - 0.02f, // fSwimWalkAthleticsMult - 0.5f, // fSwimWalkBase - 1.0f, // fSwingBlockBase - 1.0f, // fSwingBlockMult - 1000.0f, // fTargetSpellMaxSpeed - 1000.0f, // fThrownWeaponMaxSpeed - 300.0f, // fThrownWeaponMinSpeed - 0.0f, // fTrapCostMult - 4000.0f, // fTravelMult - 16000.0f,// fTravelTimeMult - 0.1f, // fUnarmoredBase1 - 0.065f, // fUnarmoredBase2 - 30.0f, // fVanityDelay - 10.0f, // fVoiceIdleOdds - 0.0f, // fWaterReflectUpdateAlways - 10.0f, // fWaterReflectUpdateSeldom - 0.1f, // fWeaponDamageMult - 1.0f, // fWeaponFatigueBlockMult - 0.25f, // fWeaponFatigueMult - 150.0f, // fWereWolfAcrobatics - 150.0f, // fWereWolfAgility - 1.0f, // fWereWolfAlchemy - 1.0f, // fWereWolfAlteration - 1.0f, // fWereWolfArmorer - 150.0f, // fWereWolfAthletics - 1.0f, // fWereWolfAxe - 1.0f, // fWereWolfBlock - 1.0f, // fWereWolfBluntWeapon - 1.0f, // fWereWolfConjuration - 1.0f, // fWereWolfDestruction - 1.0f, // fWereWolfEnchant - 150.0f, // fWereWolfEndurance - 400.0f, // fWereWolfFatigue - 100.0f, // fWereWolfHandtoHand - 2.0f, // fWereWolfHealth - 1.0f, // fWereWolfHeavyArmor - 1.0f, // fWereWolfIllusion - 1.0f, // fWereWolfIntellegence - 1.0f, // fWereWolfLightArmor - 1.0f, // fWereWolfLongBlade - 1.0f, // fWereWolfLuck - 100.0f, // fWereWolfMagicka - 1.0f, // fWereWolfMarksman - 1.0f, // fWereWolfMediumArmor - 1.0f, // fWereWolfMerchantile - 1.0f, // fWereWolfMysticism - 1.0f, // fWereWolfPersonality - 1.0f, // fWereWolfRestoration - 1.5f, // fWereWolfRunMult - 1.0f, // fWereWolfSecurity - 1.0f, // fWereWolfShortBlade - 1.5f, // fWereWolfSilverWeaponDamageMult - 1.0f, // fWereWolfSneak - 1.0f, // fWereWolfSpear - 1.0f, // fWereWolfSpeechcraft - 150.0f, // fWereWolfSpeed - 150.0f, // fWereWolfStrength - 100.0f, // fWereWolfUnarmored - 1.0f, // fWereWolfWillPower - 15.0f, // fWortChanceValue + 0.3, // fAIFleeFleeMult + 7.0, // fAIFleeHealthMult + 3.0, // fAIMagicSpellMult + 1.0, // fAIMeleeArmorMult + 1.0, // fAIMeleeSummWeaponMult + 2.0, // fAIMeleeWeaponMult + 5.0, // fAIRangeMagicSpellMult + 5.0, // fAIRangeMeleeWeaponMult + 2000.0, // fAlarmRadius + 1.0, // fAthleticsRunBonus + 40.0, // fAudioDefaultMaxDistance + 5.0, // fAudioDefaultMinDistance + 50.0, // fAudioMaxDistanceMult + 20.0, // fAudioMinDistanceMult + 60.0, // fAudioVoiceDefaultMaxDistance + 10.0, // fAudioVoiceDefaultMinDistance + 50.0, // fAutoPCSpellChance + 80.0, // fAutoSpellChance + 50.0, // fBargainOfferBase + -4.0, // fBargainOfferMulti + 24.0, // fBarterGoldResetDelay + 1.75, // fBaseRunMultiplier + 1.25, // fBlockStillBonus + 150.0, // fBribe1000Mod + 75.0, // fBribe100Mod + 35.0, // fBribe10Mod + 60.0, // fCombatAngleXY + 60.0, // fCombatAngleZ + 0.25, // fCombatArmorMinMult + -90.0, // fCombatBlockLeftAngle + 30.0, // fCombatBlockRightAngle + 4.0, // fCombatCriticalStrikeMult + 0.1, // fCombatDelayCreature + 0.1, // fCombatDelayNPC + 128.0, // fCombatDistance + 0.3, // fCombatDistanceWerewolfMod + 30.0, // fCombatForceSideAngle + 0.2, // fCombatInvisoMult + 1.5, // fCombatKODamageMult + 45.0, // fCombatTorsoSideAngle + 0.3, // fCombatTorsoStartPercent + 0.8, // fCombatTorsoStopPercent + 15.0, // fConstantEffectMult + 72.0, // fCorpseClearDelay + 72.0, // fCorpseRespawnDelay + 0.5, // fCrimeGoldDiscountMult + 0.9, // fCrimeGoldTurnInMult + 1.0, // fCrimeStealing + 0.5, // fDamageStrengthBase + 0.1, // fDamageStrengthMult + 5.0, // fDifficultyMult + 2.5, // fDiseaseXferChance + -10.0, // fDispAttacking + -1.0, // fDispBargainFailMod + 1.0, // fDispBargainSuccessMod + 0.0, // fDispCrimeMod + -10.0, // fDispDiseaseMod + 3.0, // fDispFactionMod + 1.0, // fDispFactionRankBase + 0.5, // fDispFactionRankMult + 1.0, // fDispositionMod + 50.0, // fDispPersonalityBase + 0.5, // fDispPersonalityMult + -25.0, // fDispPickPocketMod + 5.0, // fDispRaceMod + -0.5, // fDispStealing + -5.0, // fDispWeaponDrawn + 0.5, // fEffectCostMult + 0.1, // fElementalShieldMult + 3.0, // fEnchantmentChanceMult + 0.5, // fEnchantmentConstantChanceMult + 100.0, // fEnchantmentConstantDurationMult + 0.1, // fEnchantmentMult + 1000.0, // fEnchantmentValueMult + 0.3, // fEncumberedMoveEffect + 5.0, // fEncumbranceStrMult + 0.04, // fEndFatigueMult + 0.25, // fFallAcroBase + 0.01, // fFallAcroMult + 400.0, // fFallDamageDistanceMin + 0.0, // fFallDistanceBase + 0.07, // fFallDistanceMult + 2.0, // fFatigueAttackBase + 0.0, // fFatigueAttackMult + 1.25, // fFatigueBase + 4.0, // fFatigueBlockBase + 0.0, // fFatigueBlockMult + 5.0, // fFatigueJumpBase + 0.0, // fFatigueJumpMult + 0.5, // fFatigueMult + 2.5, // fFatigueReturnBase + 0.02, // fFatigueReturnMult + 5.0, // fFatigueRunBase + 2.0, // fFatigueRunMult + 1.5, // fFatigueSneakBase + 1.5, // fFatigueSneakMult + 0.0, // fFatigueSpellBase + 0.0, // fFatigueSpellCostMult + 0.0, // fFatigueSpellMult + 7.0, // fFatigueSwimRunBase + 0.0, // fFatigueSwimRunMult + 2.5, // fFatigueSwimWalkBase + 0.0, // fFatigueSwimWalkMult + 0.2, // fFightDispMult + 0.005, // fFightDistanceMultiplier + 50.0, // fFightStealing + 3000.0, // fFleeDistance + 512.0, // fGreetDistanceReset + 0.1, // fHandtoHandHealthPer + 1.0, // fHandToHandReach + 0.5, // fHoldBreathEndMult + 20.0, // fHoldBreathTime + 0.75, // fIdleChanceMultiplier + 1.0, // fIngredientMult + 0.5, // fInteriorHeadTrackMult + 128.0, // fJumpAcrobaticsBase + 4.0, // fJumpAcroMultiplier + 0.5, // fJumpEncumbranceBase + 1.0, // fJumpEncumbranceMultiplier + 0.5, // fJumpMoveBase + 0.5, // fJumpMoveMult + 1.0, // fJumpRunMultiplier + 0.5, // fKnockDownMult + 5.0, // fLevelMod + 0.1, // fLevelUpHealthEndMult + 0.6, // fLightMaxMod + 10.0, // fLuckMod + 10.0, // fMagesGuildTravel + 1.5, // fMagicCreatureCastDelay + 0.0167, // fMagicDetectRefreshRate + 1.0, // fMagicItemConstantMult + 1.0, // fMagicItemCostMult + 1.0, // fMagicItemOnceMult + 1.0, // fMagicItemPriceMult + 0.05, // fMagicItemRechargePerSecond + 1.0, // fMagicItemStrikeMult + 1.0, // fMagicItemUsedMult + 3.0, // fMagicStartIconBlink + 0.5, // fMagicSunBlockedMult + 0.75, // fMajorSkillBonus + 300.0, // fMaxFlySpeed + 0.5, // fMaxHandToHandMult + 400.0, // fMaxHeadTrackDistance + 200.0, // fMaxWalkSpeed + 300.0, // fMaxWalkSpeedCreature + 0.9, // fMedMaxMod + 0.1, // fMessageTimePerChar + 5.0, // fMinFlySpeed + 0.1, // fMinHandToHandMult + 1.0, // fMinorSkillBonus + 100.0, // fMinWalkSpeed + 5.0, // fMinWalkSpeedCreature + 1.25, // fMiscSkillBonus + 2.0, // fNPCbaseMagickaMult + 0.5, // fNPCHealthBarFade + 3.0, // fNPCHealthBarTime + 1.0, // fPCbaseMagickaMult + 0.3, // fPerDieRollMult + 5.0, // fPersonalityMod + 1.0, // fPerTempMult + -1.0, // fPickLockMult + 0.3, // fPickPocketMod + 20.0, // fPotionMinUsefulDuration + 0.5, // fPotionStrengthMult + 0.5, // fPotionT1DurMult + 1.5, // fPotionT1MagMult + 20.0, // fPotionT4BaseStrengthMult + 12.0, // fPotionT4EquipStrengthMult + 3000.0, // fProjectileMaxSpeed + 400.0, // fProjectileMinSpeed + 25.0, // fProjectileThrownStoreChance + 3.0, // fRepairAmountMult + 1.0, // fRepairMult + 1.0, // fReputationMod + 0.15, // fRestMagicMult + 0.0, // fSeriousWoundMult + 0.25, // fSleepRandMod + 0.3, // fSleepRestMod + -1.0, // fSneakBootMult + 0.5, // fSneakDistanceBase + 0.002, // fSneakDistanceMultiplier + 0.5, // fSneakNoViewMult + 1.0, // fSneakSkillMult + 0.75, // fSneakSpeedMultiplier + 1.0, // fSneakUseDelay + 500.0, // fSneakUseDist + 1.5, // fSneakViewMult + 3.0, // fSoulGemMult + 0.8, // fSpecialSkillBonus + 7.0, // fSpellMakingValueMult + 2.0, // fSpellPriceMult + 10.0, // fSpellValueMult + 0.25, // fStromWalkMult + 0.7, // fStromWindSpeed + 3.0, // fSuffocationDamage + 0.9, // fSwimHeightScale + 0.1, // fSwimRunAthleticsMult + 0.5, // fSwimRunBase + 0.02, // fSwimWalkAthleticsMult + 0.5, // fSwimWalkBase + 1.0, // fSwingBlockBase + 1.0, // fSwingBlockMult + 1000.0, // fTargetSpellMaxSpeed + 1000.0, // fThrownWeaponMaxSpeed + 300.0, // fThrownWeaponMinSpeed + 0.0, // fTrapCostMult + 4000.0, // fTravelMult + 16000.0,// fTravelTimeMult + 0.1, // fUnarmoredBase1 + 0.065, // fUnarmoredBase2 + 30.0, // fVanityDelay + 10.0, // fVoiceIdleOdds + 0.0, // fWaterReflectUpdateAlways + 10.0, // fWaterReflectUpdateSeldom + 0.1, // fWeaponDamageMult + 1.0, // fWeaponFatigueBlockMult + 0.25, // fWeaponFatigueMult + 150.0, // fWereWolfAcrobatics + 150.0, // fWereWolfAgility + 1.0, // fWereWolfAlchemy + 1.0, // fWereWolfAlteration + 1.0, // fWereWolfArmorer + 150.0, // fWereWolfAthletics + 1.0, // fWereWolfAxe + 1.0, // fWereWolfBlock + 1.0, // fWereWolfBluntWeapon + 1.0, // fWereWolfConjuration + 1.0, // fWereWolfDestruction + 1.0, // fWereWolfEnchant + 150.0, // fWereWolfEndurance + 400.0, // fWereWolfFatigue + 100.0, // fWereWolfHandtoHand + 2.0, // fWereWolfHealth + 1.0, // fWereWolfHeavyArmor + 1.0, // fWereWolfIllusion + 1.0, // fWereWolfIntellegence + 1.0, // fWereWolfLightArmor + 1.0, // fWereWolfLongBlade + 1.0, // fWereWolfLuck + 100.0, // fWereWolfMagicka + 1.0, // fWereWolfMarksman + 1.0, // fWereWolfMediumArmor + 1.0, // fWereWolfMerchantile + 1.0, // fWereWolfMysticism + 1.0, // fWereWolfPersonality + 1.0, // fWereWolfRestoration + 1.5, // fWereWolfRunMult + 1.0, // fWereWolfSecurity + 1.0, // fWereWolfShortBlade + 1.5, // fWereWolfSilverWeaponDamageMult + 1.0, // fWereWolfSneak + 1.0, // fWereWolfSpear + 1.0, // fWereWolfSpeechcraft + 150.0, // fWereWolfSpeed + 150.0, // fWereWolfStrength + 100.0, // fWereWolfUnarmored + 1.0, // fWereWolfWillPower + 15.0, // fWortChanceValue }; static const char *gmstIntegers[] = diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 9f0617eb9..201fb4342 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -26,7 +26,7 @@ namespace ESM namespace Files { - struct ConfigurationManager; + class ConfigurationManager; } namespace CSMDoc diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 6c66f2c0e..b969862e9 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -8,7 +8,7 @@ namespace Files { - struct ConfigurationManager; + class ConfigurationManager; } namespace CSMDoc @@ -46,4 +46,4 @@ namespace CSMDoc }; } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index bc477e26a..ec6350658 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -20,7 +20,7 @@ namespace CSMWorld { class IdTable; class IdTable; - struct RecordBase; + class RecordBase; class ModifyCommand : public QUndoCommand { @@ -137,4 +137,4 @@ namespace CSMWorld }; } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index c5c84eeda..8b5462825 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -11,7 +11,7 @@ namespace CSMWorld { class CollectionBase; - struct RecordBase; + class RecordBase; class IdTable : public QAbstractItemModel { diff --git a/apps/opencs/model/world/infocollection.hpp b/apps/opencs/model/world/infocollection.hpp index 08024d45d..ae61f5d39 100644 --- a/apps/opencs/model/world/infocollection.hpp +++ b/apps/opencs/model/world/infocollection.hpp @@ -6,7 +6,7 @@ namespace ESM { - struct Dialogue; + class Dialogue; } namespace CSMWorld @@ -47,4 +47,4 @@ namespace CSMWorld }; } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index 4c7699185..fcf016ee2 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -10,7 +10,7 @@ namespace ESM namespace CSMWorld { - struct Cell; + class Cell; /// \brief Wrapper for CellRef sub record struct CellRef : public ESM::CellRef diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index be2f5e579..173efba05 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -8,7 +8,7 @@ namespace CSMWorld { struct Cell; - class UniversalId; + struct UniversalId; /// \brief References in cells class RefCollection : public Collection diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 74c5dfe58..0870a2d3e 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -9,7 +9,7 @@ namespace CSMWorld { class RefIdColumn; class RefIdData; - struct RecordBase; + class RecordBase; class RefIdAdapter { @@ -35,4 +35,4 @@ namespace CSMWorld }; } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/view/render/lightingday.cpp b/apps/opencs/view/render/lightingday.cpp index fa2656f89..ab0257c0c 100644 --- a/apps/opencs/view/render/lightingday.cpp +++ b/apps/opencs/view/render/lightingday.cpp @@ -13,7 +13,7 @@ void CSVRender::LightingDay::activate (Ogre::SceneManager *sceneManager, if (defaultAmbient) mSceneManager->setAmbientLight (*defaultAmbient); else - mSceneManager->setAmbientLight (Ogre::ColourValue (0.7f, 0.7f, 0.7f, 1.0f)); + mSceneManager->setAmbientLight (Ogre::ColourValue (0.7, 0.7, 0.7, 1)); mLight = mSceneManager->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); @@ -33,4 +33,4 @@ void CSVRender::LightingDay::deactivate() void CSVRender::LightingDay::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} +} \ No newline at end of file diff --git a/apps/opencs/view/render/lightingnight.cpp b/apps/opencs/view/render/lightingnight.cpp index f49171775..516bb3f40 100644 --- a/apps/opencs/view/render/lightingnight.cpp +++ b/apps/opencs/view/render/lightingnight.cpp @@ -13,12 +13,12 @@ void CSVRender::LightingNight::activate (Ogre::SceneManager *sceneManager, if (defaultAmbient) mSceneManager->setAmbientLight (*defaultAmbient); else - mSceneManager->setAmbientLight (Ogre::ColourValue (0.2f, 0.2f, 0.2f, 1.0f)); + mSceneManager->setAmbientLight (Ogre::ColourValue (0.2, 0.2, 0.2, 1)); mLight = mSceneManager->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); mLight->setDirection (Ogre::Vector3 (0, 0, -1)); - mLight->setDiffuseColour (Ogre::ColourValue (0.2f, 0.2f, 0.2f)); + mLight->setDiffuseColour (Ogre::ColourValue (0.2, 0.2, 0.2)); } void CSVRender::LightingNight::deactivate() @@ -33,4 +33,4 @@ void CSVRender::LightingNight::deactivate() void CSVRender::LightingNight::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} +} \ No newline at end of file diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index f56ba82ec..8a58b7d32 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -42,7 +42,7 @@ namespace CSVRender mCamera->setPosition (300, 0, 0); mCamera->lookAt (0, 0, 0); - mCamera->setNearClipDistance (0.1f); + mCamera->setNearClipDistance (0.1); mCamera->setFarClipDistance (30000); mCamera->roll (Ogre::Degree (90)); @@ -104,7 +104,7 @@ namespace CSVRender #endif mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, ¶ms); - mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3f,0.3f,0.3f,1.0f)); + mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3,0.3,0.3,1)); Ogre::Real aspectRatio = Ogre::Real(width()) / Ogre::Real(height()); mCamera->setAspectRatio(aspectRatio); diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index fc00f4491..15ce2dbaf 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -79,7 +79,7 @@ void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) std::vector enums = CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType); - if (static_cast(type) >= enums.size()) + if (type<0 && type>=enums.size()) throw std::logic_error ("Unsupported variable type"); mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str()))); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index b797a7742..52682342f 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -767,7 +767,7 @@ public: PageDisplay () { - mPage = static_cast(-1); + mPage = -1; mViewTop = 0; mViewBottom = 0; mFocusItem = NULL; @@ -917,7 +917,7 @@ public: else { mBook.reset (); - mPage = static_cast(-1); + mPage = -1; mViewTop = 0; mViewBottom = 0; } diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index 0044583db..a0a34108e 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -23,7 +23,7 @@ CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* ma : WindowBase("openmw_companion_window.layout") , mDragAndDrop(dragAndDrop) , mMessageBoxManager(manager) - , mSelectedItem(static_cast(-1)) + , mSelectedItem(-1) , mModel(NULL) , mSortModel(NULL) { diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 8b287a10d..585647338 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -111,7 +111,7 @@ namespace MWGui ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop) : WindowBase("openmw_container_window.layout") , mDragAndDrop(dragAndDrop) - , mSelectedItem(static_cast(-1)) + , mSelectedItem(-1) , mModel(NULL) , mSortModel(NULL) , mPickpocketDetected(false) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 3c6f99e68..6c43f47b4 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -510,7 +510,7 @@ namespace MWGui void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos) { - mHistory->setPosition(0, (~pos) + 1); + mHistory->setPosition(0,-pos); } void DialogueWindow::addResponse(const std::string &text, const std::string &title) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index af631a2fe..2bea088e3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -38,7 +38,7 @@ namespace MWGui , mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())) , mPreviewDirty(true) , mDragAndDrop(dragAndDrop) - , mSelectedItem(static_cast(-1)) + , mSelectedItem(-1) , mGuiMode(GM_Inventory) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 82d8b1f2d..1bb80f3d4 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -42,8 +42,6 @@ namespace MWGui std::map > mEffectSources; - virtual ~EffectSourceVisitor() {} - virtual void visit (MWMechanics::EffectKey key, const std::string& sourceName, const std::string& casterHandle, float magnitude, float remainingTime = -1); diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index 5ffa7a547..cdc12e210 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -146,8 +146,8 @@ namespace MWMechanics || weapon.get()->mBase->mData.mFlags & ESM::Weapon::Magical)) damage *= multiplier; - if ((weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver) - && actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) + if (weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver + & actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) damage *= MWBase::Environment::get().getWorld()->getStore().get().find("fWereWolfSilverWeaponDamageMult")->getFloat(); if (damage == 0 && attacker.getRefData().getHandle() == "player") diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 6888d88a6..120616f9f 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -70,7 +70,7 @@ namespace MWMechanics return getLevelledItem(ref.getPtr().get()->mBase, failChance); } } - catch (std::logic_error&) + catch (std::logic_error& e) { // Vanilla doesn't fail on nonexistent items in levelled lists std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 4486559ba..0f6d782a6 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -267,7 +267,7 @@ void LocalMap::render(const float x, const float y, // initialize to (0, 0, 0, 1) for (int p=0; pgetBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 92a49acc0..67bc75e02 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -35,7 +35,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0); } - catch (Ogre::Exception&) + catch (Ogre::Exception& e) { mSupported = false; } diff --git a/apps/openmw/mwrender/weaponanimation.hpp b/apps/openmw/mwrender/weaponanimation.hpp index cbe910c71..c09aa65d9 100644 --- a/apps/openmw/mwrender/weaponanimation.hpp +++ b/apps/openmw/mwrender/weaponanimation.hpp @@ -33,7 +33,6 @@ namespace MWRender { public: WeaponAnimation() : mPitchFactor(0) {} - virtual ~WeaponAnimation() {} virtual void attachArrow(MWWorld::Ptr actor); virtual void releaseArrow(MWWorld::Ptr actor); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 705193798..1efc79643 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -295,7 +295,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception&) + catch(std::exception &e) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) @@ -395,7 +395,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception&) + catch(std::exception &e) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 75f7ccae4..c595de5ae 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -204,7 +204,7 @@ void FFmpeg_Decoder::open(const std::string &fname) mFrame = avcodec_alloc_frame(); } - catch(std::exception&) + catch(std::exception &e) { if (mFormatCtx->pb->buffer != NULL) { diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index b245b9241..9a3dd7342 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -288,7 +288,7 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode mOutput.mActiveSounds.push_back(this); } - catch(std::exception&) + catch(std::exception &e) { alDeleteBuffers(sNumBuffers, mBuffers); alGetError(); @@ -471,7 +471,7 @@ bool OpenAL_SoundStream::process() mIsFinished = finished; } - catch(std::exception&) { + catch(std::exception &e) { std::cout<< "Error updating stream \""<getName()<<"\"" <open(fname); } - catch(Ogre::FileNotFoundException&) + catch(Ogre::FileNotFoundException &e) { std::string::size_type pos = fname.rfind('.'); if(pos == std::string::npos) @@ -859,7 +859,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float vol, f buf = getBuffer(fname); sound.reset(new OpenAL_Sound(*this, src, buf, Ogre::Vector3(0.0f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); } - catch(std::exception&) + catch(std::exception &e) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -898,7 +898,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre buf = getBuffer(fname); sound.reset(new OpenAL_Sound3D(*this, src, buf, pos, vol, basevol, pitch, min, max, flags)); } - catch(std::exception&) + catch(std::exception &e) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -940,7 +940,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float volume, fl { sound.reset(new OpenAL_SoundStream(*this, src, decoder, volume, pitch, flags)); } - catch(std::exception&) + catch(std::exception &e) { mFreeSources.push_back(src); throw; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 6854358f5..8ce87a25e 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -321,7 +321,7 @@ namespace MWSound sound = mOutput->playSound(file, volume, basevol, pitch, mode|type, offset); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); } - catch(std::exception&) + catch(std::exception &e) { //std::cout <<"Sound Error: "< &getGameFiles() const { return mHeader.mMaster; } diff --git a/components/esm/inventorystate.hpp b/components/esm/inventorystate.hpp index 21776f683..3cfffbccc 100644 --- a/components/esm/inventorystate.hpp +++ b/components/esm/inventorystate.hpp @@ -14,8 +14,6 @@ namespace ESM /// \brief State for inventories and containers struct InventoryState { - virtual ~InventoryState() {} - // anything but lights (type, slot) std::vector > > mItems; diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index b5eede9f5..f01c88c65 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -129,7 +129,7 @@ struct Cell bool hasWater() const { - return (mData.mFlags & HasWater) != 0; + return (mData.mFlags&HasWater); } // Restore the given reader to the stored position. Will try to open diff --git a/components/ogreinit/ogreplugin.cpp b/components/ogreinit/ogreplugin.cpp index 91f3fce95..6070c43a8 100644 --- a/components/ogreinit/ogreplugin.cpp +++ b/components/ogreinit/ogreplugin.cpp @@ -30,7 +30,8 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: return false; #endif //OGRE_PLATFORM == OGRE_PLATFORM_WIN32 } -#else //!defined(DEBUG) +#endif //defined(DEBUG) + pluginPath = pluginDir + "/" + pluginName + pluginExt; if (boost::filesystem::exists(pluginPath)) { ogreRoot.loadPlugin(pluginPath); @@ -39,7 +40,6 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: else { return false; } -#endif } -} +} \ No newline at end of file diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index a65b6b3b1..faa73a986 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -181,7 +181,7 @@ namespace Terrain // shadow. TODO: repeated, put in function if (mShadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3u : 1u); ++i) + for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); @@ -334,7 +334,7 @@ namespace Terrain // shadow if (shadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3u : 1u); ++i) + for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); From 67e942e733fc1410b967f7be045e2e892397e0c5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 07:13:12 +0200 Subject: [PATCH 38/63] Bug #869: Some fixes to the previous fix --- apps/openmw/mwclass/creature.cpp | 4 ++++ apps/openmw/mwclass/npc.cpp | 2 ++ libs/openengine/bullet/physic.cpp | 8 +++++--- libs/openengine/bullet/physic.hpp | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 4c6ab1c75..dc23b63f3 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -164,7 +164,11 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) + { physics.addActor(ptr); + if (getCreatureStats(ptr).isDead()) + MWBase::Environment::get().getWorld()->enableActorCollision(ptr, false); + } MWBase::Environment::get().getMechanicsManager()->add(ptr); } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 4c9b683a4..214e51009 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -388,6 +388,8 @@ namespace MWClass { physics.addActor(ptr); MWBase::Environment::get().getMechanicsManager()->add(ptr); + if (getCreatureStats(ptr).isDead()) + MWBase::Environment::get().getWorld()->enableActorCollision(ptr, false); } bool Npc::isPersistent(const MWWorld::Ptr &actor) const diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index c10892e52..6646ce273 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -18,6 +18,7 @@ namespace Physic PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale) : mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0) , mBody(0), mRaycastingBody(0), mOnGround(false), mCollisionMode(true), mBoxRotation(0,0,0,0) + , mCollisionBody(true) , mForce(0.0f) { mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation); @@ -49,8 +50,9 @@ namespace Physic void PhysicActor::enableCollisionBody(bool collision) { assert(mBody); - if(collision && !mCollisionMode) enableCollisionBody(); - if(!collision && mCollisionMode) disableCollisionBody(); + if(collision && !mCollisionBody) enableCollisionBody(); + if(!collision && mCollisionBody) disableCollisionBody(); + mCollisionBody = collision; } void PhysicActor::setPosition(const Ogre::Vector3 &pos) @@ -108,7 +110,7 @@ namespace Physic //Create the newly scaled rigid body mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, pos, rot); mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, pos, rot, 0, 0, true); - mEngine->addRigidBody(mBody, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map + mEngine->addRigidBody(mCollisionBody ? mBody : 0, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map } Ogre::Vector3 PhysicActor::getHalfExtents() const diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 4e035446e..16eb45306 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -175,6 +175,7 @@ namespace Physic Ogre::Vector3 mForce; bool mOnGround; bool mCollisionMode; + bool mCollisionBody; std::string mMesh; std::string mName; From dfacf8c0448710c0e64dfc83789cdd86b9fa22f4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 07:14:08 +0200 Subject: [PATCH 39/63] Change ActiveSpells to use ActorId --- apps/openmw/mwgui/spellicons.cpp | 2 +- apps/openmw/mwgui/spellicons.hpp | 2 +- apps/openmw/mwmechanics/activespells.cpp | 10 +++++----- apps/openmw/mwmechanics/activespells.hpp | 11 +++++------ apps/openmw/mwmechanics/actors.cpp | 19 +++++++++---------- apps/openmw/mwmechanics/character.cpp | 2 +- apps/openmw/mwmechanics/character.hpp | 2 ++ apps/openmw/mwmechanics/magiceffects.hpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 6 +++--- apps/openmw/mwmechanics/spells.cpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 2 +- 11 files changed, 30 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 0cd665a87..d5ece298b 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -21,7 +21,7 @@ namespace MWGui { void EffectSourceVisitor::visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& casterHandle, + const std::string& sourceName, int casterActorId, float magnitude, float remainingTime) { MagicEffectInfo newEffectSource; diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 1bb80f3d4..6aed8db71 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -43,7 +43,7 @@ namespace MWGui std::map > mEffectSources; virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& casterHandle, + const std::string& sourceName, int casterActorId, float magnitude, float remainingTime = -1); }; diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 86db207a4..95d455edb 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -133,7 +133,7 @@ namespace MWMechanics } void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector effects, - const std::string &displayName, const std::string& casterHandle) + const std::string &displayName, int casterActorId) { bool exists = false; for (TContainer::const_iterator it = begin(); it != end(); ++it) @@ -146,7 +146,7 @@ namespace MWMechanics params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp(); params.mEffects = effects; params.mDisplayName = displayName; - params.mCasterHandle = casterHandle; + params.mCasterActorId = casterActorId; if (!exists || stack) mSpells.insert (std::make_pair(id, params)); @@ -178,7 +178,7 @@ namespace MWMechanics float magnitude = effectIt->mMagnitude; if (magnitude) - visitor.visit(effectIt->mKey, name, it->second.mCasterHandle, magnitude, remainingTime); + visitor.visit(effectIt->mKey, name, it->second.mCasterActorId, magnitude, remainingTime); } } } @@ -212,7 +212,7 @@ namespace MWMechanics mSpellsChanged = true; } - void ActiveSpells::purge(const std::string &actorHandle) + void ActiveSpells::purge(int casterActorId) { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it) { @@ -221,7 +221,7 @@ namespace MWMechanics { const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->mKey.mId); if (effect->mData.mFlags & ESM::MagicEffect::CasterLinked - && it->second.mCasterHandle == actorHandle) + && it->second.mCasterActorId == casterActorId) effectIt = it->second.mEffects.erase(effectIt); else ++effectIt; diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 7a40afb4c..5f36cea2c 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -37,8 +37,8 @@ namespace MWMechanics MWWorld::TimeStamp mTimeStamp; std::string mDisplayName; - // Handle to the caster that that inflicted this spell on us - std::string mCasterHandle; + // The caster that inflicted this spell on us + int mCasterActorId; }; typedef std::multimap TContainer; @@ -76,10 +76,9 @@ namespace MWMechanics /// \param stack If false, the spell is not added if one with the same ID exists already. /// \param effects /// \param displayName Name for display in magic menu. - /// \param casterHandle /// void addSpell (const std::string& id, bool stack, std::vector effects, - const std::string& displayName, const std::string& casterHandle); + const std::string& displayName, int casterActorId); /// Removes the active effects from this spell/potion/.. with \a id void removeEffects (const std::string& id); @@ -90,8 +89,8 @@ namespace MWMechanics /// Remove all active effects, if roll succeeds (for each effect) void purgeAll (float chance); - /// Remove all effects with CASTER_LINKED flag that were cast by \a actorHandle - void purge (const std::string& actorHandle); + /// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId + void purge (int casterActorId); bool isSpellActive (std::string id) const; ///< case insensitive diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 22d033f40..e0db094d1 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -119,7 +119,7 @@ namespace MWMechanics : mCreature(trappedCreature) {} virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& casterHandle, + const std::string& sourceName, int casterActorId, float magnitude, float remainingTime = -1) { if (key.mId != ESM::MagicEffect::Soultrap) @@ -129,7 +129,7 @@ namespace MWMechanics MWBase::World* world = MWBase::Environment::get().getWorld(); - MWWorld::Ptr caster = world->searchPtrViaHandle(casterHandle); + MWWorld::Ptr caster = world->searchPtrViaActorId(casterActorId); if (caster.isEmpty() || !caster.getClass().isActor()) return; @@ -938,18 +938,17 @@ namespace MWMechanics continue; } - // Make sure spell effects with CasterLinked flag are removed - // TODO: would be nice not to do this all the time... - for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) - { - MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); - spells.purge(iter->first.getRefData().getHandle()); - } - if (iter->second->kill()) { ++mDeathCount[cls.getId(iter->first)]; + // Make sure spell effects with CasterLinked flag are removed + for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) + { + MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); + spells.purge(stats.getActorId()); + } + // Apply soultrap if (iter->first.getTypeName() == typeid(ESM::Creature).name()) { diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2b8b6eccb..bf8ce8bdc 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1372,9 +1372,9 @@ bool CharacterController::kill() { if( isDead() ) { - //player's death animation is over if( mPtr.getRefData().getHandle()=="player" && !isAnimPlaying(mCurrentDeath) ) { + //player's death animation is over MWBase::Environment::get().getStateManager()->askLoadRecent(); } return false; diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 5aea0210f..1b7caf34d 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -202,7 +202,9 @@ public: void skipAnim(); bool isAnimPlaying(const std::string &groupName); + /// @return false if the character has already been killed before bool kill(); + void resurrect(); bool isDead() const { return mDeathState != CharState_None; } diff --git a/apps/openmw/mwmechanics/magiceffects.hpp b/apps/openmw/mwmechanics/magiceffects.hpp index 45abda21d..4fd5e159a 100644 --- a/apps/openmw/mwmechanics/magiceffects.hpp +++ b/apps/openmw/mwmechanics/magiceffects.hpp @@ -56,7 +56,7 @@ namespace MWMechanics struct EffectSourceVisitor { virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& casterHandle, + const std::string& sourceName, int casterActorId, float magnitude, float remainingTime = -1) = 0; }; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index d510373ff..cb02d4655 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -349,9 +349,9 @@ namespace MWMechanics ActiveSpells::Effect effect_ = effect; effect_.mMagnitude *= -1; effects.push_back(effect_); - // Also make sure to set casterHandle = target, so that the effect on the caster gets purged when the target dies + // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, - effects, mSourceName, target.getRefData().getHandle()); + effects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); } } } @@ -409,7 +409,7 @@ namespace MWMechanics if (!appliedLastingEffects.empty()) target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, - mSourceName, caster.getRefData().getHandle()); + mSourceName, caster.getClass().getCreatureStats(caster).getActorId()); // Notify the target actor they've been hit if (anyHarmfulEffect && target.getClass().isActor() && target != caster) diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index a326b7a6d..dee1a1b05 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -211,7 +211,7 @@ namespace MWMechanics random = it->second.at(i); float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; - visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, "", magnitude); + visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, -1, magnitude); } } } diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index b18bda5e3..7127c92f3 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -599,7 +599,7 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito const EffectParams& params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID][i]; float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * params.mRandom; magnitude *= params.mMultiplier; - visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), "", magnitude); + visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), -1, magnitude); ++i; } From cbcf0f60399e5ca59513a8dcf189c3af040c7b45 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 01:44:11 -0400 Subject: [PATCH 40/63] Changed AiEScort to use new PathTo function --- apps/openmw/mwmechanics/aiescort.cpp | 57 +-------------------------- apps/openmw/mwmechanics/aipackage.cpp | 6 ++- apps/openmw/mwmechanics/aipackage.hpp | 1 + components/esm/loadpgrd.hpp | 1 + 4 files changed, 9 insertions(+), 56 deletions(-) diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index f27fada39..0430adf06 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -75,58 +75,6 @@ namespace MWMechanics return true; } - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - ESM::Position pos = actor.getRefData().getPosition(); - bool cellChange = actor.getCell()->getCell()->mData.mX != mCellX || actor.getCell()->getCell()->mData.mY != mCellY; - - if(actor.getCell()->getCell()->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(actor.getCell()->getCell()->mData.mX - player.getCell()->getCell()->mData.mX); - // Check if actor is near the border of an inactive cell. If so, pause walking. - if(sideX * (pos.pos[0] - actor.getCell()->getCell()->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE / - 2.0 - 200)) - { - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - return false; - } - } - if(actor.getCell()->getCell()->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(actor.getCell()->getCell()->mData.mY - player.getCell()->getCell()->mData.mY); - // Check if actor is near the border of an inactive cell. If so, pause walking. - if(sideY*(pos.pos[1] - actor.getCell()->getCell()->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE / - 2.0 - 200)) - { - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - return false; - } - } - - - if(!mPathFinder.isPathConstructed() || cellChange) - { - mCellX = actor.getCell()->getCell()->mData.mX; - mCellY = actor.getCell()->getCell()->mData.mY; - - ESM::Pathgrid::Point dest; - dest.mX = mX; - dest.mY = mY; - dest.mZ = mZ; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - mPathFinder.buildPath(start, dest, actor.getCell(), true); - } - - if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) - { - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - return true; - } - const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->getPtr(mActorId, false); const float* const leaderPos = actor.getRefData().getPosition().pos; const float* const followerPos = follower.getRefData().getPosition().pos; @@ -141,9 +89,8 @@ namespace MWMechanics if(distanceBetweenResult <= mMaxDist * mMaxDist) { - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - zTurn(actor, Ogre::Degree(zAngle)); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; + if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete + return true; mMaxDist = 470; } else diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index c2e8385b8..5e16ebdc8 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -69,7 +69,11 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //*********************** if(mTimer > 0.25) { - mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + if(distance(mPrevDest, dest) > 10) { //Only rebuild path if it's moved + mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + mPrevDest = dest; + } + if(!mPathFinder.getPath().empty()) //Path has points in it { ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); //Get the end of the proposed path diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index bb62a2543..055958384 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -67,6 +67,7 @@ namespace MWMechanics MWWorld::Ptr mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door ESM::Position mStuckPos; + ESM::Pathgrid::Point mPrevDest; }; } diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index 926233444..60a736991 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -34,6 +34,7 @@ struct Pathgrid Point& operator=(const float[3]); Point(const float[3]); Point(); + Point(int x, int y, int z) : mX(x), mY(y), mZ(z) {} }; // 16 bytes struct Edge // path grid edge From 51020fdb5fb2a95ec9339a331e68d04bc831f858 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 09:17:30 +0200 Subject: [PATCH 41/63] Fix a bug for NpcStats::mUsedIds in savegames, and added a compile-time guard to prevent similar errors in the future. --- components/esm/esmwriter.hpp | 12 ++++++++++++ components/esm/npcstats.cpp | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index 57faefdf4..ca4f42217 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -74,6 +74,18 @@ class ESMWriter endRecord(name); } +private: + // Prevent using writeHNT with strings. This already happened by accident and results in + // state being discarded without any error on writing or reading it. :( + // writeHNString and friends must be used instead. + void writeHNT(const std::string &name, std::string data) + { + } + void writeT(const std::string& data) + { + } +public: + template void writeHNT(const std::string& name, const T& data, int size) { diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index 21f573bc7..3fa954182 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -140,7 +140,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const for (std::vector::const_iterator iter (mUsedIds.begin()); iter!=mUsedIds.end(); ++iter) - esm.writeHNT ("USED", *iter); + esm.writeHNString ("USED", *iter); if (mTimeToStartDrowning) esm.writeHNT ("DRTI", mTimeToStartDrowning); From 61187c2fef662a9fe0217609e6e81d3b0cfd1373 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 09:47:49 +0200 Subject: [PATCH 42/63] Savegame: store actorIds --- apps/openmw/mwmechanics/creaturestats.cpp | 14 ++++++++++++++ apps/openmw/mwmechanics/creaturestats.hpp | 3 +++ apps/openmw/mwstate/statemanagerimp.cpp | 1 + apps/openmw/mwworld/worldimp.cpp | 12 +++++++++++- components/esm/creaturestats.cpp | 6 ++++++ components/esm/creaturestats.hpp | 1 + components/esm/defs.hpp | 1 + 7 files changed, 37 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 9bfea41f3..80f81ffd1 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -501,6 +501,7 @@ namespace MWMechanics state.mRecalcDynamicStats = mRecalcDynamicStats; state.mDrawState = mDrawState; state.mLevel = mLevel; + state.mActorId = mActorId; mSpells.writeState(state.mSpells); } @@ -538,6 +539,7 @@ namespace MWMechanics mRecalcDynamicStats = state.mRecalcDynamicStats; mDrawState = DrawState_(state.mDrawState); mLevel = state.mLevel; + mActorId = state.mActorId; mSpells.readState(state.mSpells); } @@ -579,4 +581,16 @@ namespace MWMechanics { sActorId = 0; } + + void CreatureStats::writeActorIdCounter (ESM::ESMWriter& esm) + { + esm.startRecord(ESM::REC_ACTC); + esm.writeHNT("COUN", sActorId); + esm.endRecord(ESM::REC_ACTC); + } + + void CreatureStats::readActorIdCounter (ESM::ESMReader& esm) + { + esm.getHNT(sActorId, "COUN"); + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 79686bb97..7d2dc1a62 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -238,6 +238,9 @@ namespace MWMechanics void readState (const ESM::CreatureStats& state); + static void writeActorIdCounter (ESM::ESMWriter& esm); + static void readActorIdCounter (ESM::ESMReader& esm); + // Relates to NPC gold reset delay void setTradeTime(MWWorld::TimeStamp tradeTime); MWWorld::TimeStamp getTradeTime() const; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index d261fe0c0..f2cda5a01 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -318,6 +318,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl case ESM::REC_CSTA: case ESM::REC_WTHR: case ESM::REC_DYNA: + case ESM::REC_ACTC: MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap); break; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index e07ee9df8..e223435dd 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -274,7 +274,8 @@ namespace MWWorld +mStore.countSavedGameRecords() +mGlobalVariables.countSavedGameRecords() +1 // player record - +1; // weather record + +1 // weather record + +1; // actorId counter } void World::write (ESM::ESMWriter& writer, Loading::Listener& progress) const @@ -287,6 +288,9 @@ namespace MWWorld mRendering->writeFog(cellstore); } + MWMechanics::CreatureStats::writeActorIdCounter(writer); + progress.increaseProgress(); + mCells.write (writer, progress); mStore.write (writer, progress); mGlobalVariables.write (writer, progress); @@ -297,6 +301,12 @@ namespace MWWorld void World::readRecord (ESM::ESMReader& reader, int32_t type, const std::map& contentFileMap) { + if (type == ESM::REC_ACTC) + { + MWMechanics::CreatureStats::readActorIdCounter(reader); + return; + } + if (!mStore.readRecord (reader, type) && !mGlobalVariables.readRecord (reader, type) && !mPlayer->readRecord (reader, type) && diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index 5bb6de662..e512ca5f8 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -72,6 +72,9 @@ void ESM::CreatureStats::load (ESMReader &esm) mLevel = 1; esm.getHNOT (mLevel, "LEVL"); + mActorId = -1; + esm.getHNOT (mActorId, "ACID"); + mSpells.load(esm); } @@ -146,5 +149,8 @@ void ESM::CreatureStats::save (ESMWriter &esm) const if (mLevel != 1) esm.writeHNT ("LEVL", mLevel); + if (mActorId != -1) + esm.writeHNT ("ACID", mActorId); + mSpells.save(esm); } diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 2cf2c5b4f..4c4c44b3f 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -24,6 +24,7 @@ namespace ESM ESM::TimeStamp mTradeTime; int mGoldPool; + int mActorId; bool mDead; bool mDied; diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 9ef4dabd2..6c388de08 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -108,6 +108,7 @@ enum RecNameInts REC_KEYS = FourCC<'K','E','Y','S'>::value, REC_DYNA = FourCC<'D','Y','N','A'>::value, REC_ASPL = FourCC<'A','S','P','L'>::value, + REC_ACTC = FourCC<'A','C','T','C'>::value, // format 1 REC_FILT = 0x544C4946 From 1141c1f3f279dea2ab446e5cc3f757d1f7ca4fe1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 09:48:16 +0200 Subject: [PATCH 43/63] Change projectiles to use actorIds --- apps/openmw/mwworld/worldimp.cpp | 10 +++++----- apps/openmw/mwworld/worldimp.hpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index e223435dd..947de0e4d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2223,7 +2223,7 @@ namespace MWWorld const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed) { ProjectileState state; - state.mActorHandle = actor.getRefData().getHandle(); + state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); state.mBow = bow; state.mVelocity = orient.yAxis() * speed; @@ -2310,7 +2310,7 @@ namespace MWWorld MagicBoltState state; state.mSourceName = sourceName; state.mId = id; - state.mActorHandle = actor.getRefData().getHandle(); + state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); state.mSpeed = speed; state.mStack = stack; @@ -2374,7 +2374,7 @@ namespace MWWorld if (obstacle == ptr) continue; - MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle); + MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); // Arrow intersects with player immediately after shooting :/ if (obstacle == caster) @@ -2460,7 +2460,7 @@ namespace MWWorld if (obstacle == ptr) continue; - MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle); + MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); if (caster.isEmpty()) caster = obstacle; @@ -2483,7 +2483,7 @@ namespace MWWorld if (explode) { - MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle); + MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); explodeSpell(Ogre::Vector3(ptr.getRefData().getPosition().pos), ptr, it->second.mEffects, caster, it->second.mId, it->second.mSourceName); deleteObject(ptr); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 2328e67a8..953045fa2 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -96,7 +96,7 @@ namespace MWWorld std::string mId; // Actor who casted this projectile - std::string mActorHandle; + int mActorId; // Name of item to display as effect source in magic menu (in case we casted an enchantment) std::string mSourceName; @@ -111,7 +111,7 @@ namespace MWWorld struct ProjectileState { // Actor who shot this projectile - std::string mActorHandle; + int mActorId; MWWorld::Ptr mBow; // bow or crossbow the projectile was fired from From 993ef1be4340dbbc6203c75342c6d5fe629d37ef Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 04:05:18 -0400 Subject: [PATCH 44/63] Actor avoiding door asks all surrounding actors to do the same. --- apps/openmw/mwmechanics/aiavoiddoor.cpp | 13 +++++++++++++ apps/openmw/mwworld/worldimp.cpp | 5 +++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 375e8fae7..c6ecc08bf 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -6,6 +6,7 @@ #include "../mwworld/cellstore.hpp" #include "creaturestats.hpp" #include "movement.hpp" +#include "mechanicsmanagerimp.hpp" #include @@ -44,6 +45,18 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration actor.getClass().getMovementSettings(actor).mPosition[1] = -1 * std::sin(dirToDoor); //I knew I'd use trig someday actor.getClass().getMovementSettings(actor).mPosition[0] = -1 * std::cos(dirToDoor); + //Make all nearby actors also avoid the door + std::vector actors; + MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),50,actors); + for(std::vector::iterator it = actors.begin(); it != actors.end(); it++) { + if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player + MWMechanics::AiSequence& seq = MWWorld::Class::get(*it).getCreatureStats(*it).getAiSequence(); + if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) { //Only add it once + seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr),*it); + } + } + } + return false; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 96dd91f82..99589b610 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1209,15 +1209,16 @@ namespace MWWorld for (std::vector::iterator cit = collisions.begin(); cit != collisions.end(); ++cit) { MWWorld::Ptr ptr = getPtrViaHandle(*cit); - if (MWWorld::Class::get(ptr).isActor()) + if (MWWorld::Class::get(ptr).isActor() && ptr != MWBase::Environment::get().getWorld()->getPlayerPtr() ) { // Collided with actor, ask actor to try to avoid door MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); - break; + //break; //Removed in case ultiple actors are touching } } From 343990023990af7c52132b86a1c958283315274f Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Wed, 14 May 2014 11:56:23 +0200 Subject: [PATCH 45/63] ignore all drops that will not create usefull filter --- apps/opencs/view/world/tablesubview.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index a5a7e8252..8da300aba 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -110,13 +110,17 @@ void CSVWorld::TableSubView::createFilterRequest (std::vector< CSMWorld::Univers { std::vector > > filterSource; - for (std::vector::iterator it = types.begin(); it != types.end(); ++it) + for (std::vector::iterator it(types.begin()); it != types.end(); ++it) { std::pair > pair( //splited long line - std::make_pair(it->getId(), mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(it->getType())))); + std::make_pair(it->getId(), mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(it->getType())))); - filterSource.push_back(pair); + if(!pair.second.empty()) + { + filterSource.push_back(pair); + } } + mFilterBox->createFilterRequest(filterSource, action); } From 2425d2c2abb27310452343f26bccb9e74a3138d2 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 13:38:10 -0400 Subject: [PATCH 46/63] Added stuck mitigation for AiAvoidDoor --- apps/openmw/mwmechanics/aiavoiddoor.cpp | 39 ++++++++++++++++--------- apps/openmw/mwmechanics/aiavoiddoor.hpp | 4 ++- apps/openmw/mwworld/worldimp.cpp | 12 ++++---- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index c6ecc08bf..26865aea4 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -13,32 +13,45 @@ #include "steering.hpp" MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::Ptr& doorPtr) -: AiPackage(), mDoorPtr(doorPtr), mDuration(1) +: AiPackage(), mDoorPtr(doorPtr), mDuration(1), mAdjAngle(0) { + } bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration) { + + ESM::Position pos = actor.getRefData().getPosition(); + if(mDuration = 1) //If it just started, get the actor position as the stuck detection thing + mLastPos = pos; + mDuration -= duration; //Update timer - if(mDuration < 0) - return true; // We have tried backing up for more than one second, we've probably cleared it + if(mDuration < 0) { + float x = pos.pos[0] - mLastPos.pos[0]; + float y = pos.pos[1] - mLastPos.pos[1]; + float z = pos.pos[2] - mLastPos.pos[2]; + int distance = x * x + y * y + z * z; + if(distance < 10 * 10) { //Got stuck, didn't move + if(mAdjAngle == 0) //Try going in various directions + mAdjAngle = 1.57079632679f; //pi/2 + else if (mAdjAngle == 1.57079632679f) + mAdjAngle = -1.57079632679; + else + mAdjAngle = 0; + mDuration = 1; //reset timer + } + else //Not stuck + return true; // We have tried backing up for more than one second, we've probably cleared it + } if(!MWBase::Environment::get().getWorld()->getIsMovingDoor(mDoorPtr)) return true; //Door is no longer opening - ESM::Position pos = actor.getRefData().getPosition(); //position of the actor ESM::Position tPos = mDoorPtr.getRefData().getPosition(); //Position of the door float x = pos.pos[0] - tPos.pos[0]; float y = pos.pos[1] - tPos.pos[1]; - float z = pos.pos[2] - tPos.pos[2]; - int distance = sqrt(x * x + y * y + z * z); - - if(distance > 300) //Stop backing up when you're far enough away - return true; -/// TODO: Calculate this from door size, not have it built in - - float dirToDoor = std::atan2(x,y) + pos.rot[2]; //Calculates the direction to the door, relative to the direction of the NPC + float dirToDoor = std::atan2(x,y) + pos.rot[2] + mAdjAngle; //Calculates the direction to the door, relative to the direction of the NPC // For example, if the NPC is directly facing the door this will be pi/2 // Make actor move away from the door @@ -47,7 +60,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration //Make all nearby actors also avoid the door std::vector actors; - MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),50,actors); + MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),100,actors); for(std::vector::iterator it = actors.begin(); it != actors.end(); it++) { if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player MWMechanics::AiSequence& seq = MWWorld::Class::get(*it).getCreatureStats(*it).getAiSequence(); diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 8d225655a..85bb09fc8 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -29,7 +29,9 @@ namespace MWMechanics private: float mDuration; - const MWWorld::Ptr& mDoorPtr; + const MWWorld::Ptr& mDoorPtr; + ESM::Position mLastPos; + float mAdjAngle; }; } #endif diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 99589b610..a3b9e64d3 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1209,16 +1209,18 @@ namespace MWWorld for (std::vector::iterator cit = collisions.begin(); cit != collisions.end(); ++cit) { MWWorld::Ptr ptr = getPtrViaHandle(*cit); - if (MWWorld::Class::get(ptr).isActor() && ptr != MWBase::Environment::get().getWorld()->getPlayerPtr() ) + if (MWWorld::Class::get(ptr).isActor()) { // Collided with actor, ask actor to try to avoid door - MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); - if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once - seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + if(ptr != MWBase::Environment::get().getWorld()->getPlayerPtr() ) { + MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); + if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once + seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + } // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); - //break; //Removed in case ultiple actors are touching + //break; //Removed in case multiple actors are touching } } From d2aada95b44785ee41092ec37a0e4a2d8ddaeb17 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 14:11:34 -0400 Subject: [PATCH 47/63] Fixed AiPursue by fixing underlying issue is Pathto() --- apps/openmw/mwmechanics/aiactivate.cpp | 1 - apps/openmw/mwmechanics/aiavoiddoor.cpp | 2 +- apps/openmw/mwmechanics/aifollow.cpp | 7 +++---- apps/openmw/mwmechanics/aipackage.cpp | 3 ++- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index 56c155ded..4b4b36ed6 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -37,7 +37,6 @@ bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) } else { pathTo(actor, dest, duration); //Go to the destination - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; } return false; diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 26865aea4..a206d27ca 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -22,7 +22,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration { ESM::Position pos = actor.getRefData().getPosition(); - if(mDuration = 1) //If it just started, get the actor position as the stuck detection thing + if(mDuration == 1) //If it just started, get the actor position as the stuck detection thing mLastPos = pos; mDuration -= duration; //Update timer diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 8d9e01939..f1296a949 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -58,12 +58,11 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) //Set the target desition from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - pathTo(actor, dest, duration); //Go to the destination - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; - else - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + else { + pathTo(actor, dest, duration); //Go to the destination + } //Check if you're far away if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) > 1000) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 5e16ebdc8..2a2f4fdc8 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -16,7 +16,7 @@ MWMechanics::AiPackage::~AiPackage() {} -MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(MWWorld::Ptr()), mTimer(0), mStuckTimer(0) { +MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(MWWorld::Ptr()), mTimer(.26), mStuckTimer(0) { //mTimer starts at .26 to force initial pathbuild } @@ -118,6 +118,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po mStuckTimer = 0; mStuckPos = pos; mLastDoorChecked = MWWorld::Ptr(); //Resets it, in case he gets stuck behind the door again + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward } } else { From 9052cc4a57c3bddefb2a8692d149c0a2947eaeed Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 22:16:39 +0200 Subject: [PATCH 48/63] Savegame: store ActiveSpells --- apps/openmw/mwclass/npc.cpp | 3 +- apps/openmw/mwmechanics/activespells.cpp | 61 ++++++++++++++++++----- apps/openmw/mwmechanics/activespells.hpp | 21 ++++---- apps/openmw/mwmechanics/actors.cpp | 1 + apps/openmw/mwmechanics/creaturestats.cpp | 4 +- apps/openmw/mwmechanics/spellcasting.cpp | 12 +++-- components/CMakeLists.txt | 2 +- components/esm/activespells.cpp | 56 +++++++++++++++++++++ components/esm/activespells.hpp | 45 +++++++++++++++++ components/esm/creaturestats.cpp | 3 +- components/esm/creaturestats.hpp | 2 + 11 files changed, 178 insertions(+), 32 deletions(-) create mode 100644 components/esm/activespells.cpp create mode 100644 components/esm/activespells.hpp diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 214e51009..845fffbc0 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -620,7 +620,8 @@ namespace MWClass // NOTE: 'object' and/or 'attacker' may be empty. // Attacking peaceful NPCs is a crime - if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) + // anything below 80 is considered peaceful (see Actors::updateActor) + if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80) MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); getCreatureStats(ptr).setAttacked(true); diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 95d455edb..e64a736c3 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -53,9 +53,9 @@ namespace MWMechanics { const MWWorld::TimeStamp& start = iter->second.mTimeStamp; - const std::vector& effects = iter->second.mEffects; + const std::vector& effects = iter->second.mEffects; - for (std::vector::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) + for (std::vector::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) { int duration = effectIt->mDuration; MWWorld::TimeStamp end = start; @@ -63,7 +63,7 @@ namespace MWMechanics MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); if (end>now) - mEffects.add(effectIt->mKey, MWMechanics::EffectParam(effectIt->mMagnitude)); + mEffects.add(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), MWMechanics::EffectParam(effectIt->mMagnitude)); } } } @@ -91,11 +91,11 @@ namespace MWMechanics double ActiveSpells::timeToExpire (const TIterator& iterator) const { - const std::vector& effects = iterator->second.mEffects; + const std::vector& effects = iterator->second.mEffects; int duration = 0; - for (std::vector::const_iterator iter (effects.begin()); + for (std::vector::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter) { if (iter->mDuration > duration) @@ -132,7 +132,7 @@ namespace MWMechanics return mSpells; } - void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector effects, + void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector effects, const std::string &displayName, int casterActorId) { bool exists = false; @@ -168,7 +168,7 @@ namespace MWMechanics { float timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor(); - for (std::vector::const_iterator effectIt = it->second.mEffects.begin(); + for (std::vector::const_iterator effectIt = it->second.mEffects.begin(); effectIt != it->second.mEffects.end(); ++effectIt) { std::string name = it->second.mDisplayName; @@ -178,7 +178,7 @@ namespace MWMechanics float magnitude = effectIt->mMagnitude; if (magnitude) - visitor.visit(effectIt->mKey, name, it->second.mCasterActorId, magnitude, remainingTime); + visitor.visit(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), name, it->second.mCasterActorId, magnitude, remainingTime); } } } @@ -200,10 +200,10 @@ namespace MWMechanics { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it) { - for (std::vector::iterator effectIt = it->second.mEffects.begin(); + for (std::vector::iterator effectIt = it->second.mEffects.begin(); effectIt != it->second.mEffects.end();) { - if (effectIt->mKey.mId == effectId) + if (effectIt->mEffectId == effectId) effectIt = it->second.mEffects.erase(effectIt); else ++effectIt; @@ -216,10 +216,10 @@ namespace MWMechanics { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it) { - for (std::vector::iterator effectIt = it->second.mEffects.begin(); + for (std::vector::iterator effectIt = it->second.mEffects.begin(); effectIt != it->second.mEffects.end();) { - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->mKey.mId); + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->mEffectId); if (effect->mData.mFlags & ESM::MagicEffect::CasterLinked && it->second.mCasterActorId == casterActorId) effectIt = it->second.mEffects.erase(effectIt); @@ -229,4 +229,41 @@ namespace MWMechanics } mSpellsChanged = true; } + + void ActiveSpells::clear() + { + mSpells.clear(); + mSpellsChanged = true; + } + + void ActiveSpells::writeState(ESM::ActiveSpells &state) const + { + for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it) + { + // Stupid copying of almost identical structures. ESM::TimeStamp <-> MWWorld::TimeStamp + ESM::ActiveSpells::ActiveSpellParams params; + params.mEffects = it->second.mEffects; + params.mCasterActorId = it->second.mCasterActorId; + params.mDisplayName = it->second.mDisplayName; + params.mTimeStamp = it->second.mTimeStamp.toEsm(); + + state.mSpells.insert (std::make_pair(it->first, params)); + } + } + + void ActiveSpells::readState(const ESM::ActiveSpells &state) + { + for (ESM::ActiveSpells::TContainer::const_iterator it = state.mSpells.begin(); it != state.mSpells.end(); ++it) + { + // Stupid copying of almost identical structures. ESM::TimeStamp <-> MWWorld::TimeStamp + ActiveSpellParams params; + params.mEffects = it->second.mEffects; + params.mCasterActorId = it->second.mCasterActorId; + params.mDisplayName = it->second.mDisplayName; + params.mTimeStamp = MWWorld::TimeStamp(it->second.mTimeStamp); + + mSpells.insert (std::make_pair(it->first, params)); + mSpellsChanged = true; + } + } } diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 5f36cea2c..6c4c93128 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -10,6 +10,7 @@ #include "magiceffects.hpp" #include +#include namespace MWMechanics { @@ -21,19 +22,11 @@ namespace MWMechanics { public: - // Parameters of an effect concerning lasting effects. - // Note we are not using ENAMstruct since the magnitude may be modified by magic resistance, etc. - // It could also be a negative magnitude, in case of inversing an effect, e.g. Absorb spell causes damage on target, but heals the caster. - struct Effect - { - float mMagnitude; - EffectKey mKey; - float mDuration; - }; + typedef ESM::ActiveEffect ActiveEffect; struct ActiveSpellParams { - std::vector mEffects; + std::vector mEffects; MWWorld::TimeStamp mTimeStamp; std::string mDisplayName; @@ -44,6 +37,9 @@ namespace MWMechanics typedef std::multimap TContainer; typedef TContainer::const_iterator TIterator; + void readState (const ESM::ActiveSpells& state); + void writeState (ESM::ActiveSpells& state) const; + private: mutable TContainer mSpells; @@ -77,7 +73,7 @@ namespace MWMechanics /// \param effects /// \param displayName Name for display in magic menu. /// - void addSpell (const std::string& id, bool stack, std::vector effects, + void addSpell (const std::string& id, bool stack, std::vector effects, const std::string& displayName, int casterActorId); /// Removes the active effects from this spell/potion/.. with \a id @@ -92,6 +88,9 @@ namespace MWMechanics /// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId void purge (int casterActorId); + /// Remove all spells + void clear(); + bool isSpellActive (std::string id) const; ///< case insensitive diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index e0db094d1..79a90c4d3 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -959,6 +959,7 @@ namespace MWMechanics // Reset magic effects and recalculate derived effects // One case where we need this is to make sure bound items are removed upon death stats.setMagicEffects(MWMechanics::MagicEffects()); + stats.getActiveSpells().clear(); calculateCreatureStatModifiers(iter->first, 0); MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 80f81ffd1..57618e6e9 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -496,7 +496,7 @@ namespace MWMechanics state.mBlock = mBlock; state.mMovementFlags = mMovementFlags; state.mAttackStrength = mAttackStrength; - state.mFallHeight = mFallHeight; + state.mFallHeight = mFallHeight; // TODO: vertical velocity (move from PhysicActor to CreatureStats?) state.mLastHitObject = mLastHitObject; state.mRecalcDynamicStats = mRecalcDynamicStats; state.mDrawState = mDrawState; @@ -504,6 +504,7 @@ namespace MWMechanics state.mActorId = mActorId; mSpells.writeState(state.mSpells); + mActiveSpells.writeState(state.mActiveSpells); } void CreatureStats::readState (const ESM::CreatureStats& state) @@ -542,6 +543,7 @@ namespace MWMechanics mActorId = state.mActorId; mSpells.readState(state.mSpells); + mActiveSpells.readState(state.mActiveSpells); } // Relates to NPC gold reset delay diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index cb02d4655..553674dd3 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -222,7 +222,7 @@ namespace MWMechanics } ESM::EffectList reflectedEffects; - std::vector appliedLastingEffects; + std::vector appliedLastingEffects; bool firstAppliedEffect = true; bool anyHarmfulEffect = false; @@ -332,8 +332,9 @@ namespace MWMechanics bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration); if (target.getClass().isActor() && hasDuration) { - ActiveSpells::Effect effect; - effect.mKey = MWMechanics::EffectKey(*effectIt); + ActiveSpells::ActiveEffect effect; + effect.mEffectId = effectIt->mEffectID; + effect.mArg = MWMechanics::EffectKey(*effectIt).mArg; effect.mDuration = effectIt->mDuration; effect.mMagnitude = magnitude; @@ -345,8 +346,8 @@ namespace MWMechanics { if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i) { - std::vector effects; - ActiveSpells::Effect effect_ = effect; + std::vector effects; + ActiveSpells::ActiveEffect effect_ = effect; effect_.mMagnitude *= -1; effects.push_back(effect_); // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies @@ -392,6 +393,7 @@ namespace MWMechanics else castStatic = MWBase::Environment::get().getWorld()->getStore().get().find ("VFX_DefaultHit"); + // TODO: VFX are no longer active after saving/reloading the game bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx; // Note: in case of non actor, a free effect should be fine as well MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 533288048..90570b260 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate spellstate + npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells ) add_component_dir (misc diff --git a/components/esm/activespells.cpp b/components/esm/activespells.cpp new file mode 100644 index 000000000..4f51a619e --- /dev/null +++ b/components/esm/activespells.cpp @@ -0,0 +1,56 @@ +#include "activespells.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void ActiveSpells::save(ESMWriter &esm) const + { + for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it) + { + esm.writeHNString ("ID__", it->first); + + const ActiveSpellParams& params = it->second; + + esm.writeHNT ("CAST", params.mCasterActorId); + esm.writeHNString ("DISP", params.mDisplayName); + esm.writeHNT ("TIME", params.mTimeStamp); + + for (std::vector::const_iterator effectIt = params.mEffects.begin(); effectIt != params.mEffects.end(); ++effectIt) + { + esm.writeHNT ("MGEF", effectIt->mEffectId); + if (effectIt->mArg != -1) + esm.writeHNT ("ARG_", effectIt->mArg); + esm.writeHNT ("MAGN", effectIt->mMagnitude); + esm.writeHNT ("DURA", effectIt->mDuration); + } + } + } + + void ActiveSpells::load(ESMReader &esm) + { + while (esm.isNextSub("ID__")) + { + std::string spellId = esm.getHString(); + + ActiveSpellParams params; + esm.getHNT (params.mCasterActorId, "CAST"); + params.mDisplayName = esm.getHNString ("DISP"); + esm.getHNT (params.mTimeStamp, "TIME"); + + while (esm.isNextSub("MGEF")) + { + ActiveEffect effect; + esm.getHT(effect.mEffectId); + effect.mArg = -1; + esm.getHNOT(effect.mArg, "ARG_"); + esm.getHNT (effect.mMagnitude, "MAGN"); + esm.getHNT (effect.mDuration, "DURA"); + params.mEffects.push_back(effect); + } + mSpells.insert(std::make_pair(spellId, params)); + } + } +} diff --git a/components/esm/activespells.hpp b/components/esm/activespells.hpp new file mode 100644 index 000000000..d9e9a8c63 --- /dev/null +++ b/components/esm/activespells.hpp @@ -0,0 +1,45 @@ +#ifndef OPENMW_ESM_ACTIVESPELLS_H +#define OPENMW_ESM_ACTIVESPELLS_H + +#include "effectlist.hpp" +#include "defs.hpp" + +#include +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + // Parameters of an effect concerning lasting effects. + // Note we are not using ENAMstruct since the magnitude may be modified by magic resistance, etc. + // It could also be a negative magnitude, in case of inversing an effect, e.g. Absorb spell causes damage on target, but heals the caster. + struct ActiveEffect + { + int mEffectId; + float mMagnitude; + int mArg; // skill or attribute + float mDuration; + }; + + // format 0, saved games only + struct ActiveSpells + { + struct ActiveSpellParams + { + std::vector mEffects; + ESM::TimeStamp mTimeStamp; + std::string mDisplayName; + int mCasterActorId; + }; + + typedef std::multimap TContainer; + TContainer mSpells; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; +} + +#endif diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index e512ca5f8..66d848124 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -1,4 +1,3 @@ - #include "creaturestats.hpp" void ESM::CreatureStats::load (ESMReader &esm) @@ -76,6 +75,7 @@ void ESM::CreatureStats::load (ESMReader &esm) esm.getHNOT (mActorId, "ACID"); mSpells.load(esm); + mActiveSpells.load(esm); } void ESM::CreatureStats::save (ESMWriter &esm) const @@ -153,4 +153,5 @@ void ESM::CreatureStats::save (ESMWriter &esm) const esm.writeHNT ("ACID", mActorId); mSpells.save(esm); + mActiveSpells.save(esm); } diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 4c4c44b3f..7814d937a 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -10,6 +10,7 @@ #include "defs.hpp" #include "spellstate.hpp" +#include "activespells.hpp" namespace ESM { @@ -49,6 +50,7 @@ namespace ESM int mLevel; SpellState mSpells; + ActiveSpells mActiveSpells; void load (ESMReader &esm); void save (ESMWriter &esm) const; From f33559fead33e19ad6f14e1934400ac7367e4b1a Mon Sep 17 00:00:00 2001 From: slothlife Date: Wed, 14 May 2014 20:12:52 -0500 Subject: [PATCH 49/63] Fixes for MSVC warnings, less overall changes Kept some fixes from the first round of review. Found out that several targets weren't being built with the same basic warnings disabled. Disabled a few warnings for external libraries specifically, rather than applying them to all targets. --- CMakeLists.txt | 23 +++++++++++--- apps/opencs/view/world/vartypedelegate.cpp | 2 +- apps/openmw/mwgui/bookpage.cpp | 30 +++++++++++++++---- apps/openmw/mwgui/companionwindow.hpp | 2 +- apps/openmw/mwgui/container.hpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/spellicons.hpp | 2 ++ apps/openmw/mwmechanics/combat.cpp | 4 +-- apps/openmw/mwmechanics/levelledlist.hpp | 2 +- apps/openmw/mwrender/localmap.cpp | 2 +- apps/openmw/mwrender/occlusionquery.cpp | 2 +- apps/openmw/mwrender/weaponanimation.hpp | 1 + .../mwscript/transformationextensions.cpp | 4 +-- apps/openmw/mwsound/ffmpeg_decoder.cpp | 2 +- apps/openmw/mwsound/openal_output.cpp | 12 ++++---- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +-- components/esm/inventorystate.hpp | 2 ++ components/terrain/material.cpp | 4 +-- 19 files changed, 71 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd437ed61..d60210b21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -594,6 +594,7 @@ if (WIN32) 4706 # Assignment in conditional expression 4738 # Storing 32-bit float result in memory, possible loss of performance 4986 # Undocumented warning that occurs in the crtdbg.h file + 4987 # nonstandard extension used (triggered by setjmp.h) 4996 # Function was declared deprecated # cause by ogre extensivly @@ -610,7 +611,9 @@ if (WIN32) 4305 # Truncating value (double to float, for example) 4309 # Variable overflow, trying to store 128 in a signed char for example 4355 # Using 'this' in member initialization list + 4505 # Unreferenced local function has been removed 4701 # Potentially uninitialized local variable used + 4702 # Unreachable code 4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt ) @@ -618,19 +621,31 @@ if (WIN32) set(WARNINGS "${WARNINGS} /wd${d}") endforeach(d) - set_target_properties(shiny PROPERTIES COMPILE_FLAGS ${WARNINGS}) - set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${WARNINGS}) + # boost::wave has a few issues with signed / unsigned conversions, so we suppress those here + set(SHINY_WARNINGS "${WARNINGS} /wd4245") + set_target_properties(shiny PROPERTIES COMPILE_FLAGS ${SHINY_WARNINGS}) + # there's an unreferenced local variable in the ogre platform, suppress it + set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101") + set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${SHINY_OGRE_WARNINGS}) + set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS ${WARNINGS}) + set_target_properties(oics PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS}) if (BUILD_LAUNCHER) set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif (BUILD_LAUNCHER) set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) - if (BUILD_BSATOOL) + if (BUILD_BSATOOL) set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS}) - endif (BUILD_BSATOOL) + endif (BUILD_BSATOOL) if (BUILD_ESMTOOL) set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif (BUILD_ESMTOOL) + if (BUILD_OPENCS) + set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${WARNINGS}) + endif (BUILD_OPENCS) + if (BUILD_MWINIIMPORTER) + set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS ${WARNINGS}) + endif (BUILD_MWINIIMPORTER) endif(MSVC) # Same for MinGW diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index 15ce2dbaf..fc00f4491 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -79,7 +79,7 @@ void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) std::vector enums = CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType); - if (type<0 && type>=enums.size()) + if (static_cast(type) >= enums.size()) throw std::logic_error ("Unsupported variable type"); mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str()))); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 52682342f..2008accc9 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -695,6 +695,8 @@ protected: typedef TypesetBookImpl::Section Section; typedef TypesetBookImpl::Line Line; typedef TypesetBookImpl::Run Run; + bool mIsPageReset; + size_t mPage; struct TextFormat : ISubWidget { @@ -745,6 +747,23 @@ protected: void destroyDrawItem() {}; }; + void resetPage() + { + mIsPageReset = true; + mPage = 0; + } + + void setPage(size_t page) + { + mIsPageReset = false; + mPage = page; + } + + bool isPageDifferent(size_t page) + { + return mIsPageReset || (mPage != page); + } + public: typedef TypesetBookImpl::StyleImpl Style; @@ -760,14 +779,13 @@ public: boost::shared_ptr mBook; - size_t mPage; MyGUI::ILayerNode* mNode; ActiveTextFormats mActiveTextFormats; PageDisplay () { - mPage = -1; + resetPage (); mViewTop = 0; mViewBottom = 0; mFocusItem = NULL; @@ -901,7 +919,7 @@ public: createActiveFormats (newBook); mBook = newBook; - mPage = newPage; + setPage (newPage); if (newPage < mBook->mPages.size ()) { @@ -917,19 +935,19 @@ public: else { mBook.reset (); - mPage = -1; + resetPage (); mViewTop = 0; mViewBottom = 0; } } else - if (mBook && mPage != newPage) + if (mBook && isPageDifferent (newPage)) { if (mNode != NULL) for (ActiveTextFormats::iterator i = mActiveTextFormats.begin (); i != mActiveTextFormats.end (); ++i) mNode->outOfDate(i->second->mRenderItem); - mPage = newPage; + setPage (newPage); if (newPage < mBook->mPages.size ()) { diff --git a/apps/openmw/mwgui/companionwindow.hpp b/apps/openmw/mwgui/companionwindow.hpp index 7fdfc069f..02e3812f0 100644 --- a/apps/openmw/mwgui/companionwindow.hpp +++ b/apps/openmw/mwgui/companionwindow.hpp @@ -25,7 +25,7 @@ namespace MWGui ItemView* mItemView; SortFilterItemModel* mSortModel; CompanionItemModel* mModel; - size_t mSelectedItem; + int mSelectedItem; DragAndDrop* mDragAndDrop; diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index ce4707af6..3aa923a23 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -62,7 +62,7 @@ namespace MWGui MWGui::ItemView* mItemView; SortFilterItemModel* mSortModel; ItemModel* mModel; - size_t mSelectedItem; + int mSelectedItem; MyGUI::Button* mDisposeCorpseButton; MyGUI::Button* mTakeButton; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 6c43f47b4..e9c51a7f8 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -510,7 +510,7 @@ namespace MWGui void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos) { - mHistory->setPosition(0,-pos); + mHistory->setPosition(0, pos * -1); } void DialogueWindow::addResponse(const std::string &text, const std::string &title) diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index c23a74efa..17a25e502 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -52,7 +52,7 @@ namespace MWGui DragAndDrop* mDragAndDrop; bool mPreviewDirty; - size_t mSelectedItem; + int mSelectedItem; MWWorld::Ptr mPtr; diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 1bb80f3d4..82d8b1f2d 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -42,6 +42,8 @@ namespace MWGui std::map > mEffectSources; + virtual ~EffectSourceVisitor() {} + virtual void visit (MWMechanics::EffectKey key, const std::string& sourceName, const std::string& casterHandle, float magnitude, float remainingTime = -1); diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index cdc12e210..5ffa7a547 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -146,8 +146,8 @@ namespace MWMechanics || weapon.get()->mBase->mData.mFlags & ESM::Weapon::Magical)) damage *= multiplier; - if (weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver - & actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) + if ((weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver) + && actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) damage *= MWBase::Environment::get().getWorld()->getStore().get().find("fWereWolfSilverWeaponDamageMult")->getFloat(); if (damage == 0 && attacker.getRefData().getHandle() == "player") diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 120616f9f..6888d88a6 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -70,7 +70,7 @@ namespace MWMechanics return getLevelledItem(ref.getPtr().get()->mBase, failChance); } } - catch (std::logic_error& e) + catch (std::logic_error&) { // Vanilla doesn't fail on nonexistent items in levelled lists std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 0f6d782a6..a22beff23 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -267,7 +267,7 @@ void LocalMap::render(const float x, const float y, // initialize to (0, 0, 0, 1) for (int p=0; pgetBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 67bc75e02..92a49acc0 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -35,7 +35,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0); } - catch (Ogre::Exception& e) + catch (Ogre::Exception&) { mSupported = false; } diff --git a/apps/openmw/mwrender/weaponanimation.hpp b/apps/openmw/mwrender/weaponanimation.hpp index c09aa65d9..cbe910c71 100644 --- a/apps/openmw/mwrender/weaponanimation.hpp +++ b/apps/openmw/mwrender/weaponanimation.hpp @@ -33,6 +33,7 @@ namespace MWRender { public: WeaponAnimation() : mPitchFactor(0) {} + virtual ~WeaponAnimation() {} virtual void attachArrow(MWWorld::Ptr actor); virtual void releaseArrow(MWWorld::Ptr actor); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 1efc79643..705193798 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -295,7 +295,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception &e) + catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) @@ -395,7 +395,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception &e) + catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index c595de5ae..75f7ccae4 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -204,7 +204,7 @@ void FFmpeg_Decoder::open(const std::string &fname) mFrame = avcodec_alloc_frame(); } - catch(std::exception &e) + catch(std::exception&) { if (mFormatCtx->pb->buffer != NULL) { diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 9a3dd7342..b245b9241 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -288,7 +288,7 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode mOutput.mActiveSounds.push_back(this); } - catch(std::exception &e) + catch(std::exception&) { alDeleteBuffers(sNumBuffers, mBuffers); alGetError(); @@ -471,7 +471,7 @@ bool OpenAL_SoundStream::process() mIsFinished = finished; } - catch(std::exception &e) { + catch(std::exception&) { std::cout<< "Error updating stream \""<getName()<<"\"" <open(fname); } - catch(Ogre::FileNotFoundException &e) + catch(Ogre::FileNotFoundException&) { std::string::size_type pos = fname.rfind('.'); if(pos == std::string::npos) @@ -859,7 +859,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float vol, f buf = getBuffer(fname); sound.reset(new OpenAL_Sound(*this, src, buf, Ogre::Vector3(0.0f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -898,7 +898,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre buf = getBuffer(fname); sound.reset(new OpenAL_Sound3D(*this, src, buf, pos, vol, basevol, pitch, min, max, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -940,7 +940,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float volume, fl { sound.reset(new OpenAL_SoundStream(*this, src, decoder, volume, pitch, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); throw; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 8ce87a25e..6854358f5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -321,7 +321,7 @@ namespace MWSound sound = mOutput->playSound(file, volume, basevol, pitch, mode|type, offset); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); } - catch(std::exception &e) + catch(std::exception&) { //std::cout <<"Sound Error: "< > mLights; + virtual ~InventoryState() {} + virtual void load (ESMReader &esm); virtual void save (ESMWriter &esm) const; }; diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index faa73a986..b56f70680 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -181,7 +181,7 @@ namespace Terrain // shadow. TODO: repeated, put in function if (mShadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) + for (int i = 0; i < (mSplitShadows ? 3 : 1); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); @@ -334,7 +334,7 @@ namespace Terrain // shadow if (shadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) + for (int i = 0; i < (mSplitShadows ? 3 : 1); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); From 471bbd0021789c3882fc95a5069ed7ed830fcaea Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 00:23:53 +0200 Subject: [PATCH 50/63] Savegame: store levelled creature state and move to actorIds (Closes #1332) --- apps/openmw/mwclass/creaturelevlist.cpp | 59 ++++++++++++++++++------- apps/openmw/mwclass/creaturelevlist.hpp | 8 ++++ apps/openmw/mwworld/cellstore.cpp | 5 ++- components/CMakeLists.txt | 2 +- components/esm/creaturelevliststate.cpp | 25 +++++++++++ components/esm/creaturelevliststate.hpp | 19 ++++++++ 6 files changed, 100 insertions(+), 18 deletions(-) create mode 100644 components/esm/creaturelevliststate.cpp create mode 100644 components/esm/creaturelevliststate.hpp diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index 732038b2f..be01b848a 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -2,6 +2,7 @@ #include "creaturelevlist.hpp" #include +#include #include "../mwmechanics/levelledlist.hpp" @@ -11,7 +12,9 @@ namespace { struct CreatureLevListCustomData : public MWWorld::CustomData { - // TODO: save the creature we spawned here + // actorId of the creature we spawned + int mSpawnActorId; + virtual MWWorld::CustomData *clone() const; }; @@ -38,6 +41,25 @@ namespace MWClass void CreatureLevList::insertObjectRendering(const MWWorld::Ptr &ptr, MWRender::RenderingInterface &renderingInterface) const { ensureCustomData(ptr); + + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + if (customData.mSpawnActorId != -1) + return; // TODO: handle respawning + + + MWWorld::LiveCellRef *ref = + ptr.get(); + + std::string id = MWMechanics::getLevelledItem(ref->mBase, true); + + if (!id.empty()) + { + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + MWWorld::ManualRef ref(store, id); + ref.getPtr().getCellRef().mPos = ptr.getCellRef().mPos; + MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().mPos); + customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId(); + } } void CreatureLevList::ensureCustomData(const MWWorld::Ptr &ptr) const @@ -45,22 +67,29 @@ namespace MWClass if (!ptr.getRefData().getCustomData()) { std::auto_ptr data (new CreatureLevListCustomData); - - MWWorld::LiveCellRef *ref = - ptr.get(); - - std::string id = MWMechanics::getLevelledItem(ref->mBase, true); - - if (!id.empty()) - { - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - MWWorld::ManualRef ref(store, id); - ref.getPtr().getCellRef().mPos = ptr.getCellRef().mPos; - // TODO: hold on to this for respawn purposes later - MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().mPos); - } + data->mSpawnActorId = -1; ptr.getRefData().setCustomData(data.release()); } } + + void CreatureLevList::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const + { + const ESM::CreatureLevListState& state2 = dynamic_cast (state); + + ensureCustomData(ptr); + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + customData.mSpawnActorId = state2.mSpawnActorId; + } + + void CreatureLevList::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) + const + { + ESM::CreatureLevListState& state2 = dynamic_cast (state); + + ensureCustomData(ptr); + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + state2.mSpawnActorId = customData.mSpawnActorId; + } } diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index d2c02043e..b67fb5523 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -19,6 +19,14 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + + virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const; + ///< Read additional state from \a state into \a ptr. + + virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) + const; + ///< Write additional state from \a ptr into \a state. }; } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 67ab44b77..3f94a77c4 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -592,7 +593,7 @@ namespace MWWorld writeReferenceCollection (writer, mCreatures); writeReferenceCollection (writer, mDoors); writeReferenceCollection (writer, mIngreds); - writeReferenceCollection (writer, mCreatureLists); + writeReferenceCollection (writer, mCreatureLists); writeReferenceCollection (writer, mItemLists); writeReferenceCollection (writer, mLights); writeReferenceCollection (writer, mLockpicks); @@ -668,7 +669,7 @@ namespace MWWorld case ESM::REC_LEVC: - readReferenceCollection (reader, mCreatureLists, contentFileMap); + readReferenceCollection (reader, mCreatureLists, contentFileMap); break; case ESM::REC_LEVI: diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 90570b260..0f2ef1301 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells + npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate ) add_component_dir (misc diff --git a/components/esm/creaturelevliststate.cpp b/components/esm/creaturelevliststate.cpp new file mode 100644 index 000000000..164dae96e --- /dev/null +++ b/components/esm/creaturelevliststate.cpp @@ -0,0 +1,25 @@ +#include "creaturelevliststate.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void CreatureLevListState::load(ESMReader &esm) + { + ObjectState::load(esm); + + mSpawnActorId = -1; + esm.getHNOT (mSpawnActorId, "SPAW"); + } + + void CreatureLevListState::save(ESMWriter &esm, bool inInventory) const + { + ObjectState::save(esm, inInventory); + + if (mSpawnActorId != -1) + esm.writeHNT ("SPAW", mSpawnActorId); + } + +} diff --git a/components/esm/creaturelevliststate.hpp b/components/esm/creaturelevliststate.hpp new file mode 100644 index 000000000..99b5a7fa2 --- /dev/null +++ b/components/esm/creaturelevliststate.hpp @@ -0,0 +1,19 @@ +#ifndef OPENMW_ESM_CREATURELEVLISTSTATE_H +#define OPENMW_ESM_CREATURELEVLISTSTATE_H + +#include "objectstate.hpp" + +namespace ESM +{ + // format 0, saved games only + + struct CreatureLevListState : public ObjectState + { + int mSpawnActorId; + + virtual void load (ESMReader &esm); + virtual void save (ESMWriter &esm, bool inInventory = false) const; + }; +} + +#endif From 37b9d2fb0cac2960466554021a8f94f0942471cc Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 01:53:52 +0200 Subject: [PATCH 51/63] Fix a wrong use of reference that causes potential crash --- apps/openmw/mwmechanics/aiavoiddoor.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 85bb09fc8..c1b326198 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -11,9 +11,9 @@ namespace MWMechanics { /// \brief AiPackage to have an actor avoid an opening door /** The AI will retreat from the door until it has finished opening, walked far away from it, or one second has passed, in an attempt to avoid it - **/ - class AiAvoidDoor : public AiPackage - { + **/ + class AiAvoidDoor : public AiPackage + { public: /// Avoid door until the door is fully open AiAvoidDoor(const MWWorld::Ptr& doorPtr); @@ -29,10 +29,10 @@ namespace MWMechanics private: float mDuration; - const MWWorld::Ptr& mDoorPtr; + MWWorld::Ptr mDoorPtr; ESM::Position mLastPos; - float mAdjAngle; - }; -} -#endif + float mAdjAngle; + }; +} +#endif From a76e391ad038c99b9e8b72c08949931c9dd3c395 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 01:58:44 +0200 Subject: [PATCH 52/63] Savegame: store door movement state (Closes #747) --- apps/openmw/mwbase/world.hpp | 10 +--- apps/openmw/mwclass/door.cpp | 78 ++++++++++++++++++++++++- apps/openmw/mwclass/door.hpp | 17 +++++- apps/openmw/mwmechanics/aiavoiddoor.cpp | 2 +- apps/openmw/mwworld/cellstore.cpp | 5 +- apps/openmw/mwworld/class.cpp | 10 ++++ apps/openmw/mwworld/class.hpp | 5 ++ apps/openmw/mwworld/worldimp.cpp | 57 +++++++++++------- apps/openmw/mwworld/worldimp.hpp | 10 ++-- components/CMakeLists.txt | 2 +- components/esm/doorstate.cpp | 25 ++++++++ components/esm/doorstate.hpp | 19 ++++++ 12 files changed, 199 insertions(+), 41 deletions(-) create mode 100644 components/esm/doorstate.cpp create mode 100644 components/esm/doorstate.hpp diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 5c8a2d2dd..0459d5341 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -393,14 +393,10 @@ namespace MWBase virtual void setupPlayer() = 0; virtual void renderPlayer() = 0; - /// if activated, should this door be opened or closed? - virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door) = 0; - - /// activate (open or close) an non-teleport door + /// open or close a non-teleport door (depending on current state) virtual void activateDoor(const MWWorld::Ptr& door) = 0; - - /// Is door currently opening/closing? - virtual bool getIsMovingDoor(const MWWorld::Ptr& door) = 0; + /// open or close a non-teleport door as specified + virtual void activateDoor(const MWWorld::Ptr& door, bool open) = 0; virtual bool getPlayerStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 984e21e72..06f0619ce 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -2,6 +2,7 @@ #include "door.hpp" #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -17,12 +18,28 @@ #include "../mwworld/physicssystem.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/actiontrap.hpp" +#include "../mwworld/customdata.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" +namespace +{ + struct DoorCustomData : public MWWorld::CustomData + { + int mDoorState; // 0 = nothing, 1 = opening, 2 = closing + + virtual MWWorld::CustomData *clone() const; + }; + + MWWorld::CustomData *DoorCustomData::clone() const + { + return new DoorCustomData (*this); + } +} + namespace MWClass { void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -38,6 +55,14 @@ namespace MWClass const std::string model = getModel(ptr); if(!model.empty()) physics.addObject(ptr); + + // Resume the door's opening/closing animation if it wasn't finished + ensureCustomData(ptr); + const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + if (customData.mDoorState > 0) + { + MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState == 1 ? true : false); + } } std::string Door::getModel(const MWWorld::Ptr &ptr) const @@ -125,7 +150,14 @@ namespace MWClass { // animated door boost::shared_ptr action(new MWWorld::ActionDoor(ptr)); - if (MWBase::Environment::get().getWorld()->getOpenOrCloseDoor(ptr)) + int doorstate = getDoorState(ptr); + bool opening = true; + if (doorstate == 1) + opening = false; + if (doorstate == 0 && ptr.getRefData().getLocalRotation().rot[2] != 0) + opening = false; + + if (opening) { MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr, closeSound, 0.5); @@ -262,4 +294,48 @@ namespace MWClass return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } + + void Door::ensureCustomData(const MWWorld::Ptr &ptr) const + { + if (!ptr.getRefData().getCustomData()) + { + std::auto_ptr data(new DoorCustomData); + + data->mDoorState = 0; + ptr.getRefData().setCustomData(data.release()); + } + } + + int Door::getDoorState (const MWWorld::Ptr &ptr) const + { + ensureCustomData(ptr); + const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + return customData.mDoorState; + } + + void Door::setDoorState (const MWWorld::Ptr &ptr, int state) const + { + ensureCustomData(ptr); + DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + customData.mDoorState = state; + } + + void Door::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const + { + ensureCustomData(ptr); + DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + + const ESM::DoorState& state2 = dynamic_cast(state); + customData.mDoorState = state2.mDoorState; + } + + void Door::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const + { + ensureCustomData(ptr); + const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + + ESM::DoorState& state2 = dynamic_cast(state); + state2.mDoorState = customData.mDoorState; + } + } diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index bddc46728..12b360aa8 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -9,6 +9,8 @@ namespace MWClass { class Door : public MWWorld::Class { + void ensureCustomData (const MWWorld::Ptr& ptr) const; + virtual MWWorld::Ptr copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; @@ -48,7 +50,20 @@ namespace MWClass static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; - private: + + /// 0 = nothing, 1 = opening, 2 = closing + virtual int getDoorState (const MWWorld::Ptr &ptr) const; + /// This does not actually cause the door to move. Use World::activateDoor instead. + virtual void setDoorState (const MWWorld::Ptr &ptr, int state) const; + + + virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const; + ///< Read additional state from \a state into \a ptr. + + virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) + const; + ///< Write additional state from \a ptr into \a state. }; } diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index a206d27ca..44eacb0d1 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -45,7 +45,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration return true; // We have tried backing up for more than one second, we've probably cleared it } - if(!MWBase::Environment::get().getWorld()->getIsMovingDoor(mDoorPtr)) + if (!mDoorPtr.getClass().getDoorState(mDoorPtr)) return true; //Door is no longer opening ESM::Position tPos = mDoorPtr.getRefData().getPosition(); //Position of the door diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 3f94a77c4..a5f166374 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -591,7 +592,7 @@ namespace MWWorld writeReferenceCollection (writer, mClothes); writeReferenceCollection (writer, mContainers); writeReferenceCollection (writer, mCreatures); - writeReferenceCollection (writer, mDoors); + writeReferenceCollection (writer, mDoors); writeReferenceCollection (writer, mIngreds); writeReferenceCollection (writer, mCreatureLists); writeReferenceCollection (writer, mItemLists); @@ -659,7 +660,7 @@ namespace MWWorld case ESM::REC_DOOR: - readReferenceCollection (reader, mDoors, contentFileMap); + readReferenceCollection (reader, mDoors, contentFileMap); break; case ESM::REC_INGR: diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index f20c5f6d2..951ba7865 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -406,4 +406,14 @@ namespace MWWorld { return false; } + + int Class::getDoorState (const MWWorld::Ptr &ptr) const + { + throw std::runtime_error("this is not a door"); + } + + void Class::setDoorState (const MWWorld::Ptr &ptr, int state) const + { + throw std::runtime_error("this is not a door"); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 27b842348..057bc906e 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -336,6 +336,11 @@ namespace MWWorld virtual int getBaseGold(const MWWorld::Ptr& ptr) const; virtual bool isClass(const MWWorld::Ptr& ptr, const std::string &className) const; + + /// 0 = nothing, 1 = opening, 2 = closing + virtual int getDoorState (const MWWorld::Ptr &ptr) const; + /// This does not actually cause the door to move. Use World::activateDoor instead. + virtual void setDoorState (const MWWorld::Ptr &ptr, int state) const; }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 4ba3e0009..97b0767fa 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1202,36 +1202,48 @@ namespace MWWorld while (it != mDoorStates.end()) { if (!mWorldScene->isCellActive(*it->first.getCell()) || !it->first.getRefData().getBaseNode()) + { + // The door is no longer in an active cell, or it was disabled. + // Erase from mDoorStates, since we no longer need to move it. + // Once we load the door's cell again (or re-enable the door), Door::insertObject will reinsert to mDoorStates. mDoorStates.erase(it++); + } else { float oldRot = Ogre::Radian(it->first.getRefData().getLocalRotation().rot[2]).valueDegrees(); float diff = duration * 90; - float targetRot = std::min(std::max(0.f, oldRot + diff * (it->second ? 1 : -1)), 90.f); + float targetRot = std::min(std::max(0.f, oldRot + diff * (it->second == 1 ? 1 : -1)), 90.f); localRotateObject(it->first, 0, 0, targetRot); + bool reached = (targetRot == 90.f && it->second) || targetRot == 0.f; + /// \todo should use convexSweepTest here std::vector collisions = mPhysics->getCollisions(it->first); for (std::vector::iterator cit = collisions.begin(); cit != collisions.end(); ++cit) { MWWorld::Ptr ptr = getPtrViaHandle(*cit); - if (MWWorld::Class::get(ptr).isActor()) + if (ptr.getClass().isActor()) { // Collided with actor, ask actor to try to avoid door if(ptr != MWBase::Environment::get().getWorld()->getPlayerPtr() ) { - MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); + MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence(); if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); } // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); + reached = false; //break; //Removed in case multiple actors are touching } } - if ((targetRot == 90.f && it->second) || targetRot == 0.f) + if (reached) + { + // Mark as non-moving + it->first.getClass().setDoorState(it->first, 0); mDoorStates.erase(it++); + } else ++it; } @@ -1849,31 +1861,32 @@ namespace MWWorld void World::activateDoor(const MWWorld::Ptr& door) { - if (mDoorStates.find(door) != mDoorStates.end()) - { - // if currently opening, then close, if closing, then open - mDoorStates[door] = !mDoorStates[door]; - } - else + int state = door.getClass().getDoorState(door); + switch (state) { + case 0: if (door.getRefData().getLocalRotation().rot[2] == 0) - mDoorStates[door] = 1; // open + state = 1; // if closed, then open else - mDoorStates[door] = 0; // close + state = 2; // if open, then close + break; + case 2: + state = 1; // if closing, then open + break; + case 1: + default: + state = 2; // if opening, then close + break; } + door.getClass().setDoorState(door, state); + mDoorStates[door] = state; } - bool World::getOpenOrCloseDoor(const Ptr &door) + void World::activateDoor(const Ptr &door, bool open) { - if (mDoorStates.find(door) != mDoorStates.end()) - return !mDoorStates[door]; // if currently opening or closing, then do the opposite - return door.getRefData().getLocalRotation().rot[2] == 0; - } - - bool World::getIsMovingDoor(const Ptr& door) - { - bool result = mDoorStates.find(door) != mDoorStates.end(); - return result; + int state = open ? 1 : 2; + door.getClass().setDoorState(door, state); + mDoorStates[door] = state; } bool World::getPlayerStandingOn (const MWWorld::Ptr& object) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index eee69e81c..7b85c3ed8 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -88,7 +88,7 @@ namespace MWWorld float mFacedDistance; std::map mDoorStates; - ///< only holds doors that are currently moving. 0 means closing, 1 opening + ///< only holds doors that are currently moving. 1 = opening, 2 = closing struct MagicBoltState { @@ -496,13 +496,11 @@ namespace MWWorld virtual void setupPlayer(); virtual void renderPlayer(); - /// if activated, should this door be opened or closed? - virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door); - - /// activate (open or close) an non-teleport door + /// open or close a non-teleport door (depending on current state) virtual void activateDoor(const MWWorld::Ptr& door); - virtual bool getIsMovingDoor(const MWWorld::Ptr& door); + /// open or close a non-teleport door as specified + virtual void activateDoor(const MWWorld::Ptr& door, bool open); virtual bool getPlayerStandingOn (const MWWorld::Ptr& object); ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 0f2ef1301..d7bdaf36c 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate + npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate ) add_component_dir (misc diff --git a/components/esm/doorstate.cpp b/components/esm/doorstate.cpp new file mode 100644 index 000000000..0487be7a4 --- /dev/null +++ b/components/esm/doorstate.cpp @@ -0,0 +1,25 @@ +#include "doorstate.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void DoorState::load(ESMReader &esm) + { + ObjectState::load(esm); + + mDoorState = 0; + esm.getHNOT (mDoorState, "ANIM"); + } + + void DoorState::save(ESMWriter &esm, bool inInventory) const + { + ObjectState::save(esm, inInventory); + + if (mDoorState != 0) + esm.writeHNT ("ANIM", mDoorState); + } + +} diff --git a/components/esm/doorstate.hpp b/components/esm/doorstate.hpp new file mode 100644 index 000000000..0df30afb0 --- /dev/null +++ b/components/esm/doorstate.hpp @@ -0,0 +1,19 @@ +#ifndef OPENMW_ESM_DOORSTATE_H +#define OPENMW_ESM_DOORSTATE_H + +#include "objectstate.hpp" + +namespace ESM +{ + // format 0, saved games only + + struct DoorState : public ObjectState + { + int mDoorState; + + virtual void load (ESMReader &esm); + virtual void save (ESMWriter &esm, bool inInventory = false) const; + }; +} + +#endif From a609dc56749831b2011f80c56cd8a0d319b89207 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 02:03:42 +0200 Subject: [PATCH 53/63] Fix exception when getting hit by a trap --- apps/openmw/mwmechanics/spellcasting.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 553674dd3..3f6cc4103 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -410,11 +410,16 @@ namespace MWMechanics inflict(caster, target, reflectedEffects, range, true); if (!appliedLastingEffects.empty()) + { + int casterActorId = -1; + if (caster.getClass().isActor()) + casterActorId = caster.getClass().getCreatureStats(caster).getActorId(); target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, - mSourceName, caster.getClass().getCreatureStats(caster).getActorId()); + mSourceName, casterActorId); + } // Notify the target actor they've been hit - if (anyHarmfulEffect && target.getClass().isActor() && target != caster) + if (anyHarmfulEffect && target.getClass().isActor() && target != caster && caster.getClass().isActor()) target.getClass().onHit(target, 0.f, true, MWWorld::Ptr(), caster, true); } From f2c193ce3d7bcb868249322c99fece14c729ee32 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 02:36:30 +0200 Subject: [PATCH 54/63] Fix searching the player's actorId --- apps/openmw/mwworld/worldimp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 97b0767fa..2b1cbe4c7 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -563,6 +563,10 @@ namespace MWWorld Ptr World::searchPtrViaActorId (int actorId) { + // The player is not registered in any CellStore so must be checked manually + if (actorId == getPlayerPtr().getClass().getCreatureStats(getPlayerPtr()).getActorId()) + return getPlayerPtr(); + // Now search cells return mWorldScene->searchPtrViaActorId (actorId); } From 2f13a17a39a1c11d31b9e45dd7c37f6a993564f5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 02:37:20 +0200 Subject: [PATCH 55/63] Add some more safety checks to spellcasting --- .../mwmechanics/mechanicsmanagerimp.cpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 36 +++++++++++-------- apps/openmw/mwmechanics/spellcasting.hpp | 2 ++ 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 5c2ee30e1..41374c1a3 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -29,7 +29,7 @@ namespace const std::string& faction = item.getCellRef().mFaction; bool isFactionOwned = false; - if (!faction.empty()) + if (!faction.empty() && ptr.getClass().isNpc()) { const std::map& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks(); if (factions.find(Misc::StringUtils::lowerCase(faction)) == factions.end()) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 3f6cc4103..0843e3e54 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -140,7 +140,7 @@ namespace MWMechanics float x = (willpower + 0.1 * luck) * stats.getFatigueTerm(); // This makes spells that are easy to cast harder to resist and vice versa - if (spell != NULL && caster.getClass().isActor()) + if (spell != NULL && !caster.isEmpty() && caster.getClass().isActor()) { float castChance = getSpellSuccessChance(spell, caster); if (castChance > 0) @@ -226,6 +226,8 @@ namespace MWMechanics bool firstAppliedEffect = true; bool anyHarmfulEffect = false; + bool castByPlayer = (!caster.isEmpty() && caster.getRefData().getHandle() == "player"); + for (std::vector::const_iterator effectIt (effects.mList.begin()); effectIt!=effects.mList.end(); ++effectIt) { @@ -238,7 +240,7 @@ namespace MWMechanics if (!MWBase::Environment::get().getWorld()->isLevitationEnabled() && effectIt->mEffectID == ESM::MagicEffect::Levitate) { - if (caster.getRefData().getHandle() == "player") + if (castByPlayer) MWBase::Environment::get().getWindowManager()->messageBox("#{sLevitateDisabled}"); continue; } @@ -249,13 +251,13 @@ namespace MWMechanics effectIt->mEffectID == ESM::MagicEffect::Mark || effectIt->mEffectID == ESM::MagicEffect::Recall)) { - if (caster.getRefData().getHandle() == "player") + if (castByPlayer) MWBase::Environment::get().getWindowManager()->messageBox("#{sTeleportDisabled}"); continue; } // If player is healing someone, show the target's HP bar - if (caster.getRefData().getHandle() == "player" && target != caster + if (castByPlayer && target != caster && effectIt->mEffectID == ESM::MagicEffect::RestoreHealth && target.getClass().isActor()) MWBase::Environment::get().getWindowManager()->setEnemy(target); @@ -266,7 +268,7 @@ namespace MWMechanics anyHarmfulEffect = true; // If player is attempting to cast a harmful spell, show the target's HP bar - if (caster.getRefData().getHandle() == "player" && target != caster) + if (castByPlayer && target != caster) MWBase::Environment::get().getWindowManager()->setEnemy(target); // Try absorbing if it's a spell @@ -342,17 +344,20 @@ namespace MWMechanics // For absorb effects, also apply the effect to the caster - but with a negative // magnitude, since we're transfering stats from the target to the caster - for (int i=0; i<5; ++i) + if (!caster.isEmpty() && caster.getClass().isActor()) { - if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i) + for (int i=0; i<5; ++i) { - std::vector effects; - ActiveSpells::ActiveEffect effect_ = effect; - effect_.mMagnitude *= -1; - effects.push_back(effect_); - // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies - caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, - effects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); + if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i) + { + std::vector effects; + ActiveSpells::ActiveEffect effect_ = effect; + effect_.mMagnitude *= -1; + effects.push_back(effect_); + // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies + caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, + effects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); + } } } } @@ -441,7 +446,8 @@ namespace MWMechanics if (target.getCellRef().mLockLevel > 0) { MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock", 1.f, 1.f); - MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); + if (!caster.isEmpty() && caster.getClass().isActor()) + MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); } target.getCellRef().mLockLevel = -abs(target.getCellRef().mLockLevel); //unlocks the door } diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index a930442fb..dce4b792e 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -62,9 +62,11 @@ namespace MWMechanics bool cast (const std::string& id); /// @note \a target can be any type of object, not just actors. + /// @note \a caster can be any type of object, or even an empty object. void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false, bool exploded=false); + /// @note \a caster can be any type of object, or even an empty object. void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude); }; From 2e9985c1a371b0e5970f3791cc6d8298a624380a Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 03:01:48 +0200 Subject: [PATCH 56/63] Change all AI packages (except AiActivate) to use ActorIds More robust in case the target changes cell or there are multiple targets with the same RefId --- apps/openmw/mwmechanics/actors.cpp | 6 +++--- apps/openmw/mwmechanics/aicombat.cpp | 29 +++++++++++++++----------- apps/openmw/mwmechanics/aicombat.hpp | 6 +++--- apps/openmw/mwmechanics/aiescort.cpp | 21 +++++++++++++------ apps/openmw/mwmechanics/aiescort.hpp | 6 +++--- apps/openmw/mwmechanics/aifollow.cpp | 20 +++++++++++------- apps/openmw/mwmechanics/aifollow.hpp | 22 +++++++++---------- apps/openmw/mwmechanics/aipursue.cpp | 11 +++++----- apps/openmw/mwmechanics/aipursue.hpp | 6 +++--- apps/openmw/mwmechanics/aisequence.cpp | 6 ++++-- apps/openmw/mwscript/aiextensions.cpp | 14 ++++++++----- 11 files changed, 86 insertions(+), 61 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 79a90c4d3..af6cac12f 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -540,7 +540,7 @@ namespace MWMechanics MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr()); // Make the summoned creature follow its master and help in fights - AiFollow package(ptr.getRefData().getHandle()); + AiFollow package(ptr); summonedCreatureStats.getAiSequence().stack(package, ref.getPtr()); int creatureActorId = summonedCreatureStats.getActorId(); @@ -754,7 +754,7 @@ namespace MWMechanics && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player), ptr); creatureStats.setAlarmed(true); npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId()); } @@ -783,7 +783,7 @@ namespace MWMechanics else if (!creatureStats.isHostile()) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player), ptr); else { MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 8464cc419..72cb8f574 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -81,7 +81,7 @@ namespace MWMechanics // NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp AiCombat::AiCombat(const MWWorld::Ptr& actor) : - mTarget(actor), + mTargetActorId(actor.getClass().getCreatureStats(actor).getActorId()), mTimerAttack(0), mTimerReact(0), mTimerCombatMove(0), @@ -153,7 +153,9 @@ namespace MWMechanics || actor.getClass().getCreatureStats(actor).getHealth().getCurrent() <= 0) return true; - if(mTarget.getClass().getCreatureStats(mTarget).isDead()) + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); + + if(target.getClass().getCreatureStats(target).isDead()) return true; //Update every frame @@ -325,7 +327,7 @@ namespace MWMechanics ESM::Position pos = actor.getRefData().getPosition(); Ogre::Vector3 vActorPos(pos.pos); - Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos); + Ogre::Vector3 vTargetPos(target.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; bool isStuck = false; @@ -396,7 +398,7 @@ namespace MWMechanics else // remote pathfinding { bool preferShortcut = false; - bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget); + bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); if(mReadyToAttack) isStuck = false; @@ -432,7 +434,7 @@ namespace MWMechanics mFollowTarget = false; - buildNewPath(actor); //may fail to build a path, check before use + buildNewPath(actor, target); //may fail to build a path, check before use //delete visited path node mPathFinder.checkWaypoint(pos.pos[0],pos.pos[1],pos.pos[2]); @@ -476,9 +478,9 @@ namespace MWMechanics //less than in time of playing weapon anim from 'start' to 'hit' tags (t_swing) //then start attacking float speed1 = actorCls.getSpeed(actor); - float speed2 = mTarget.getClass().getSpeed(mTarget); - if(mTarget.getClass().getMovementSettings(mTarget).mPosition[0] == 0 - && mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0) + float speed2 = target.getClass().getSpeed(target); + if(target.getClass().getMovementSettings(target).mPosition[0] == 0 + && target.getClass().getMovementSettings(target).mPosition[1] == 0) speed2 = 0; float s1 = distToTarget - weapRange; @@ -570,9 +572,9 @@ namespace MWMechanics return false; } - void AiCombat::buildNewPath(const MWWorld::Ptr& actor) + void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) { - Ogre::Vector3 newPathTarget = Ogre::Vector3(mTarget.getRefData().getPosition().pos); + Ogre::Vector3 newPathTarget = Ogre::Vector3(target.getRefData().getPosition().pos); float dist; @@ -627,9 +629,12 @@ namespace MWMechanics return 1; } - const std::string &AiCombat::getTargetId() const + std::string AiCombat::getTargetId() const { - return mTarget.getRefData().getHandle(); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); + if (target.isEmpty()) + return ""; + return target.getRefData().getHandle(); } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 833b0063c..9125e2832 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -31,7 +31,7 @@ namespace MWMechanics virtual unsigned int getPriority() const; ///Returns target ID - const std::string &getTargetId() const; + std::string getTargetId() const; private: PathFinder mPathFinder; @@ -53,7 +53,7 @@ namespace MWMechanics ESM::Position mLastPos; MWMechanics::Movement mMovement; - MWWorld::Ptr mTarget; + int mTargetActorId; const MWWorld::CellStore* mCell; ObstacleCheck mObstacleCheck; @@ -63,7 +63,7 @@ namespace MWMechanics MWWorld::CellRefList::List::iterator mDoorIter; MWWorld::CellRefList& mDoors; - void buildNewPath(const MWWorld::Ptr& actor); + void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target); }; } diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 0430adf06..f3ce7143a 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -8,6 +8,8 @@ #include "../mwworld/class.hpp" #include "../mwworld/timestamp.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "steering.hpp" #include "movement.hpp" @@ -19,8 +21,8 @@ namespace MWMechanics { - AiEscort::AiEscort(const std::string &actorId, int duration, float x, float y, float z) - : mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration) + AiEscort::AiEscort(const MWWorld::Ptr& actor, int duration, float x, float y, float z) + : mActorId(actor.getClass().getCreatureStats(actor).getActorId()), mX(x), mY(y), mZ(z), mDuration(duration) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { @@ -38,8 +40,8 @@ namespace MWMechanics } } - AiEscort::AiEscort(const std::string &actorId, const std::string &cellId,int duration, float x, float y, float z) - : mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration) + AiEscort::AiEscort(const MWWorld::Ptr& actor, const std::string &cellId,int duration, float x, float y, float z) + : mActorId(actor.getClass().getCreatureStats(actor).getActorId()), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { @@ -75,7 +77,14 @@ namespace MWMechanics return true; } - const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->getPtr(mActorId, false); + const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); + if (follower.isEmpty()) + { + // The follower disappeared + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; + return true; + } + const float* const leaderPos = actor.getRefData().getPosition().pos; const float* const followerPos = follower.getRefData().getPosition().pos; double differenceBetween[3]; @@ -89,7 +98,7 @@ namespace MWMechanics if(distanceBetweenResult <= mMaxDist * mMaxDist) { - if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete + if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete return true; mMaxDist = 470; } diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index 3771417fa..b8dc9d6e0 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -15,11 +15,11 @@ namespace MWMechanics /// Implementation of AiEscort /** The Actor will escort the specified actor to the world position x, y, z until they reach their position, or they run out of time \implement AiEscort **/ - AiEscort(const std::string &actorId,int duration, float x, float y, float z); + AiEscort(const MWWorld::Ptr& actor,int duration, float x, float y, float z); /// Implementation of AiEscortCell /** The Actor will escort the specified actor to the cell position x, y, z until they reach their position, or they run out of time \implement AiEscortCell **/ - AiEscort(const std::string &actorId,const std::string &cellId,int duration, float x, float y, float z); + AiEscort(const MWWorld::Ptr& actor,const std::string &cellId,int duration, float x, float y, float z); virtual AiEscort *clone() const; @@ -28,7 +28,7 @@ namespace MWMechanics virtual int getTypeId() const; private: - std::string mActorId; + int mActorId; std::string mCellId; float mX; float mY; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index f1296a949..d747781a3 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -11,23 +11,26 @@ #include "steering.hpp" -MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), AiPackage() +MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor,float duration, float x, float y, float z) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mCellId(""), AiPackage() { + mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } -MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), AiPackage() +MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor,const std::string &cellId,float duration, float x, float y, float z) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mCellId(cellId), AiPackage() { + mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } -MWMechanics::AiFollow::AiFollow(const std::string &actorId) -: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId(""), AiPackage() +MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor) +: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mCellId(""), AiPackage() { + mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mActorId, false); //The target to follow + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow if(target == MWWorld::Ptr()) return true; //Target doesn't exist @@ -75,7 +78,8 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) std::string MWMechanics::AiFollow::getFollowedActor() { - return mActorId; + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow + return target.getCellRef().mRefID; } MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 10a381410..91bdbdac2 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -10,16 +10,16 @@ namespace MWMechanics { /// \brief AiPackage for an actor to follow another actor/the PC /** The AI will follow the target until a condition (time, or position) are set. Both can be disabled to cause the actor to follow the other indefinitely - **/ - class AiFollow : public AiPackage - { + **/ + class AiFollow : public AiPackage + { public: /// Follow Actor for duration or until you arrive at a world position - AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z); + AiFollow(const MWWorld::Ptr& actor,float duration, float X, float Y, float Z); /// Follow Actor for duration or until you arrive at a position in a cell - AiFollow(const std::string &ActorId,const std::string &CellId,float duration, float X, float Y, float Z); + AiFollow(const MWWorld::Ptr& actor,const std::string &CellId,float duration, float X, float Y, float Z); /// Follow Actor indefinitively - AiFollow(const std::string &ActorId); + AiFollow(const MWWorld::Ptr& actor); virtual AiFollow *clone() const; @@ -38,8 +38,8 @@ namespace MWMechanics float mX; float mY; float mZ; - std::string mActorId; - std::string mCellId; - }; -} -#endif + int mActorId; // The actor we should follow + std::string mCellId; + }; +} +#endif diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 6e91ccb71..aa71af465 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -7,12 +7,14 @@ #include "../mwworld/action.hpp" #include "../mwworld/cellstore.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "steering.hpp" #include "movement.hpp" #include "creaturestats.hpp" -MWMechanics::AiPursue::AiPursue(const std::string &objectId) - : mObjectId(objectId) +MWMechanics::AiPursue::AiPursue(const MWWorld::Ptr& actor) + : mActorId(actor.getClass().getCreatureStats(actor).getActorId()) { } MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const @@ -23,7 +25,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) { ESM::Position pos = actor.getRefData().getPosition(); //position of the actor - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow if(target == MWWorld::Ptr()) return true; //Target doesn't exist @@ -33,8 +35,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; - MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player + target.getClass().activate(target,actor).get()->execute(actor); //Arrest player return true; } else { diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 2eb533d62..90ff8df93 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -16,14 +16,14 @@ namespace MWMechanics { public: ///Constructor - /** \param objectId Actor to pursue **/ - AiPursue(const std::string &objectId); + /** \param actor Actor to pursue **/ + AiPursue(const MWWorld::Ptr& actor); virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); virtual int getTypeId() const; private: - std::string mObjectId; + int mActorId; // The actor to pursue int mCellX; int mCellY; }; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 0b1da180d..8afe8402f 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -175,7 +175,8 @@ void MWMechanics::AiSequence::fill(const ESM::AIPackageList &list) else if (it->mType == ESM::AI_Escort) { ESM::AITarget data = it->mTarget; - package = new MWMechanics::AiEscort(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(data.mId.toString(), false); + package = new MWMechanics::AiEscort(target, data.mDuration, data.mX, data.mY, data.mZ); } else if (it->mType == ESM::AI_Travel) { @@ -190,7 +191,8 @@ void MWMechanics::AiSequence::fill(const ESM::AIPackageList &list) else //if (it->mType == ESM::AI_Follow) { ESM::AITarget data = it->mTarget; - package = new MWMechanics::AiFollow(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(data.mId.toString(), false); + package = new MWMechanics::AiFollow(target, data.mDuration, data.mX, data.mY, data.mZ); } mPackages.push_back(package); } diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index e53b53e58..8ed19925e 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -91,6 +91,7 @@ namespace MWScript std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); + MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true); Interpreter::Type_Float duration = runtime[0].mFloat; runtime.pop(); @@ -107,7 +108,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); std::string cellID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -145,7 +147,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); Interpreter::Type_Float duration = runtime[0].mFloat; runtime.pop(); @@ -297,7 +300,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); std::string cellID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -335,8 +339,8 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; i Date: Thu, 15 May 2014 03:07:25 +0200 Subject: [PATCH 57/63] AiCombat: Removed obsolete door back-off code (now handled in AiAvoidDoor) --- apps/openmw/mwmechanics/aicombat.cpp | 83 +++++----------------------- apps/openmw/mwmechanics/aicombat.hpp | 6 -- 2 files changed, 13 insertions(+), 76 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 72cb8f574..ff9c0f8c4 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -92,11 +92,7 @@ namespace MWMechanics mMovement(), mForceNoShortcut(false), mShortcutFailPos(), - mBackOffDoor(false), - mCell(NULL), - mDoorIter(actor.getCell()->get().mList.end()), - mDoors(actor.getCell()->get()), - mDoorCheckDuration(0) + mBackOffDoor(false) { } @@ -198,12 +194,6 @@ namespace MWMechanics mTimerReact = 0; - bool cellChange = mCell && (actor.getCell() != mCell); - if(!mCell || cellChange) - { - mCell = actor.getCell(); - } - //actual attacking logic //TODO: Some skills affect period of strikes.For berserk-like style period ~ 0.25f float attacksPeriod = 1.0f; @@ -503,70 +493,23 @@ namespace MWMechanics // coded at 250ms or 1/4 second // // TODO: Add a parameter to vary DURATION_SAME_SPOT? - MWWorld::CellStore *cell = actor.getCell(); if((distToTarget > rangeAttack || mFollowTarget) && mObstacleCheck.check(actor, tReaction)) // check if evasive action needed { - // first check if we're walking into a door - mDoorCheckDuration += 1.0f; // add time taken for obstacle check - if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL && !cell->getCell()->isExterior()) - { - mDoorCheckDuration = 0; - // Check all the doors in this cell - mDoors = cell->get(); // update - mDoorIter = mDoors.mList.begin(); - for (; mDoorIter != mDoors.mList.end(); ++mDoorIter) - { - MWWorld::LiveCellRef& ref = *mDoorIter; - float minSqr = 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED; // for legibility - if(vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && - ref.mData.getLocalRotation().rot[2] < 0.4f) // even small opening - { - //std::cout<<"closed door id \""<getCell()->isExterior() && !mDoors.mList.empty()) - { - MWWorld::LiveCellRef& ref = *mDoorIter; - float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility - // TODO: add reaction to checking open doors - if(mBackOffDoor && - vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) - { - mMovement.mPosition[1] = -0.2; // back off, but slowly - } - else if(mBackOffDoor && - mDoorIter != mDoors.mList.end() && - ref.mData.getLocalRotation().rot[2] >= 1) - { - mDoorIter = mDoors.mList.end(); - mBackOffDoor = false; - //std::cout<<"open door id \""<::List::iterator mDoorIter; - MWWorld::CellRefList& mDoors; void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target); }; From bac4d875df97c0f797ba874101ceeae78a08387c Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 04:20:40 +0200 Subject: [PATCH 58/63] Fix a potential exploit that made it possible to reset the owner of any item --- apps/openmw/mwgui/inventoryitemmodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index c0847929b..390c0768c 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -64,7 +64,10 @@ void InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel bool setNewOwner = false; // Are you dead? Then you wont need that anymore - if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead()) + if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead() + // Make sure that the item is actually owned by the dead actor + // Prevents a potential exploit for resetting the owner of any item, by placing the item in a corpse + && Misc::StringUtils::ciEqual(item.mBase.getCellRef().mOwner, mActor.getCellRef().mRefID)) setNewOwner = true; otherModel->copyItem(item, count, setNewOwner); From eb40032bde675ac3baa7634c2b6fa3cf650bf789 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 04:41:31 +0200 Subject: [PATCH 59/63] Fix item owner not resetting when dragging an item from a corpse to the player avatar --- apps/openmw/mwgui/companionitemmodel.cpp | 12 ++++++------ apps/openmw/mwgui/companionitemmodel.hpp | 2 +- apps/openmw/mwgui/containeritemmodel.cpp | 4 ++-- apps/openmw/mwgui/containeritemmodel.hpp | 2 +- apps/openmw/mwgui/inventoryitemmodel.cpp | 9 +++++---- apps/openmw/mwgui/inventoryitemmodel.hpp | 4 ++-- apps/openmw/mwgui/inventorywindow.cpp | 10 ++-------- apps/openmw/mwgui/itemmodel.cpp | 10 +++++----- apps/openmw/mwgui/itemmodel.hpp | 6 +++--- 9 files changed, 27 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwgui/companionitemmodel.cpp b/apps/openmw/mwgui/companionitemmodel.cpp index 9c4ea2d29..b8be9dcb8 100644 --- a/apps/openmw/mwgui/companionitemmodel.cpp +++ b/apps/openmw/mwgui/companionitemmodel.cpp @@ -10,23 +10,23 @@ namespace MWGui { } - void CompanionItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) + MWWorld::Ptr CompanionItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) { if (mActor.getClass().isNpc()) { - MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor); - stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); + MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats(mActor); + stats.modifyProfit(item.mBase.getClass().getValue(item.mBase) * count); } - InventoryItemModel::copyItem(item, count, setNewOwner); + return InventoryItemModel::copyItem(item, count, setNewOwner); } void CompanionItemModel::removeItem (const ItemStack& item, size_t count) { if (mActor.getClass().isNpc()) { - MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor); - stats.modifyProfit(-MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); + MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats(mActor); + stats.modifyProfit(-item.mBase.getClass().getValue(item.mBase) * count); } InventoryItemModel::removeItem(item, count); diff --git a/apps/openmw/mwgui/companionitemmodel.hpp b/apps/openmw/mwgui/companionitemmodel.hpp index 49c58c896..172fa9508 100644 --- a/apps/openmw/mwgui/companionitemmodel.hpp +++ b/apps/openmw/mwgui/companionitemmodel.hpp @@ -13,7 +13,7 @@ namespace MWGui public: CompanionItemModel (const MWWorld::Ptr& actor); - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner); + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner); virtual void removeItem (const ItemStack& item, size_t count); }; diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index e702c073d..b5b498e5e 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -71,12 +71,12 @@ ItemModel::ModelIndex ContainerItemModel::getIndex (ItemStack item) return -1; } -void ContainerItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) +MWWorld::Ptr ContainerItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1]; if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source)) throw std::runtime_error("Item to copy needs to be from a different container!"); - source.getClass().getContainerStore(source).add(item.mBase, count, source); + return *source.getClass().getContainerStore(source).add(item.mBase, count, source); } void ContainerItemModel::removeItem (const ItemStack& item, size_t count) diff --git a/apps/openmw/mwgui/containeritemmodel.hpp b/apps/openmw/mwgui/containeritemmodel.hpp index 4b9b4ff99..7ced6ae34 100644 --- a/apps/openmw/mwgui/containeritemmodel.hpp +++ b/apps/openmw/mwgui/containeritemmodel.hpp @@ -21,7 +21,7 @@ namespace MWGui virtual ModelIndex getIndex (ItemStack item); virtual size_t getItemCount(); - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); virtual void update(); diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index 390c0768c..718c6d991 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -40,11 +40,11 @@ ItemModel::ModelIndex InventoryItemModel::getIndex (ItemStack item) return -1; } -void InventoryItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) +MWWorld::Ptr InventoryItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor)) throw std::runtime_error("Item to copy needs to be from a different container!"); - mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor, setNewOwner); + return *mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor, setNewOwner); } @@ -59,7 +59,7 @@ void InventoryItemModel::removeItem (const ItemStack& item, size_t count) throw std::runtime_error("Not enough items in the stack to remove"); } -void InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) +MWWorld::Ptr InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) { bool setNewOwner = false; @@ -70,8 +70,9 @@ void InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel && Misc::StringUtils::ciEqual(item.mBase.getCellRef().mOwner, mActor.getCellRef().mRefID)) setNewOwner = true; - otherModel->copyItem(item, count, setNewOwner); + MWWorld::Ptr ret = otherModel->copyItem(item, count, setNewOwner); removeItem(item, count); + return ret; } void InventoryItemModel::update() diff --git a/apps/openmw/mwgui/inventoryitemmodel.hpp b/apps/openmw/mwgui/inventoryitemmodel.hpp index 78dcc9497..f58ee2939 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.hpp +++ b/apps/openmw/mwgui/inventoryitemmodel.hpp @@ -15,11 +15,11 @@ namespace MWGui virtual ModelIndex getIndex (ItemStack item); virtual size_t getItemCount(); - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); /// Move items from this model to \a otherModel. - virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); + virtual MWWorld::Ptr moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); virtual void update(); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index d6da3b30e..4d52d59bb 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -408,14 +408,8 @@ namespace MWGui if (mDragAndDrop->mSourceModel != mTradeModel) { - // add item to the player's inventory - MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); - MWWorld::ContainerStoreIterator it = invStore.begin(); - - it = invStore.add(ptr, mDragAndDrop->mDraggedCount, mPtr); - - mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount); - ptr = *it; + // Move item to the player's inventory + ptr = mDragAndDrop->mSourceModel->moveItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount, mTradeModel); } useItem(ptr); } diff --git a/apps/openmw/mwgui/itemmodel.cpp b/apps/openmw/mwgui/itemmodel.cpp index 7b2ea4d4a..2cdd8a2e6 100644 --- a/apps/openmw/mwgui/itemmodel.cpp +++ b/apps/openmw/mwgui/itemmodel.cpp @@ -71,10 +71,11 @@ namespace MWGui { } - void ItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) + MWWorld::Ptr ItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) { - otherModel->copyItem(item, count); + MWWorld::Ptr ret = otherModel->copyItem(item, count); removeItem(item, count); + return ret; } @@ -83,10 +84,9 @@ namespace MWGui delete mSourceModel; } - void ProxyItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) + MWWorld::Ptr ProxyItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { - // no need to use mapToSource since itemIndex refers to an index in the sourceModel - mSourceModel->copyItem (item, count, setNewOwner); + return mSourceModel->copyItem (item, count, setNewOwner); } void ProxyItemModel::removeItem (const ItemStack& item, size_t count) diff --git a/apps/openmw/mwgui/itemmodel.hpp b/apps/openmw/mwgui/itemmodel.hpp index 684771b86..21c5477d0 100644 --- a/apps/openmw/mwgui/itemmodel.hpp +++ b/apps/openmw/mwgui/itemmodel.hpp @@ -56,10 +56,10 @@ namespace MWGui virtual void update() = 0; /// Move items from this model to \a otherModel. - virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); + virtual MWWorld::Ptr moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); /// @param setNewOwner Set the copied item's owner to the actor we are copying to, or keep the original owner? - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0; + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0; virtual void removeItem (const ItemStack& item, size_t count) = 0; private: @@ -73,7 +73,7 @@ namespace MWGui { public: virtual ~ProxyItemModel(); - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); virtual ModelIndex getIndex (ItemStack item); From b6a7aee42e15e45d1a251a0b02c2ad6bf514f551 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 04:52:35 +0200 Subject: [PATCH 60/63] Fix player not being allowed to use his own items --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 41374c1a3..bf9a11d6e 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -25,7 +25,7 @@ namespace bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim) { const std::string& owner = item.getCellRef().mOwner; - bool isOwned = !owner.empty(); + bool isOwned = !owner.empty() && owner != "player"; const std::string& faction = item.getCellRef().mFaction; bool isFactionOwned = false; From 6de7e165504981fef276a93ea6c7980b3d53ec82 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 06:08:55 +0200 Subject: [PATCH 61/63] Fix searchPtrViaActorId not skipping over deleted references Fixes an issue when an actor has moved cell: searchPtrViaActorId would randomly return the deleted Ptr from the old cell. --- apps/openmw/mwworld/cellstore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index a5f166374..5d2d8a517 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -54,7 +54,7 @@ namespace { MWWorld::Ptr actor (&*iter, cell); - if (MWWorld::Class::get (actor).getCreatureStats (actor).matchesActorId (actorId)) + if (actor.getClass().getCreatureStats (actor).matchesActorId (actorId) && actor.getRefData().getCount() > 0) return actor; } From b16d444f0ff03f77c403a657afca58556cd0b950 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 10:05:35 +0200 Subject: [PATCH 62/63] Fix never clearing graveyard. Oops --- apps/openmw/mwmechanics/actors.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index af6cac12f..a0616258c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -574,11 +574,16 @@ namespace MWMechanics } } - for (std::vector::iterator it = creatureStats.mSummonGraveyard.begin(); it != creatureStats.mSummonGraveyard.end(); ++it) + for (std::vector::iterator it = creatureStats.mSummonGraveyard.begin(); it != creatureStats.mSummonGraveyard.end(); ) { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(*it); if (!ptr.isEmpty()) + { + it = creatureStats.mSummonGraveyard.erase(it); MWBase::Environment::get().getWorld()->deleteObject(ptr); + } + else + ++it; } } From 0bc33fa86a0dc6bb6fc59ce2092d0efdc0e42dc2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 10:14:47 +0200 Subject: [PATCH 63/63] Revert "AiCombat: Removed obsolete door back-off code (now handled in AiAvoidDoor)" Apparently not working for AiCombat due to its higher getPriority(). What should we do here? This reverts commit a6e1d7ffd6daf4af4750d1478048733428db4a5b. --- apps/openmw/mwmechanics/aicombat.cpp | 83 +++++++++++++++++++++++----- apps/openmw/mwmechanics/aicombat.hpp | 6 ++ 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index ff9c0f8c4..72cb8f574 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -92,7 +92,11 @@ namespace MWMechanics mMovement(), mForceNoShortcut(false), mShortcutFailPos(), - mBackOffDoor(false) + mBackOffDoor(false), + mCell(NULL), + mDoorIter(actor.getCell()->get().mList.end()), + mDoors(actor.getCell()->get()), + mDoorCheckDuration(0) { } @@ -194,6 +198,12 @@ namespace MWMechanics mTimerReact = 0; + bool cellChange = mCell && (actor.getCell() != mCell); + if(!mCell || cellChange) + { + mCell = actor.getCell(); + } + //actual attacking logic //TODO: Some skills affect period of strikes.For berserk-like style period ~ 0.25f float attacksPeriod = 1.0f; @@ -493,23 +503,70 @@ namespace MWMechanics // coded at 250ms or 1/4 second // // TODO: Add a parameter to vary DURATION_SAME_SPOT? + MWWorld::CellStore *cell = actor.getCell(); if((distToTarget > rangeAttack || mFollowTarget) && mObstacleCheck.check(actor, tReaction)) // check if evasive action needed { - // probably walking into another NPC TODO: untested in combat situation + // first check if we're walking into a door + mDoorCheckDuration += 1.0f; // add time taken for obstacle check + if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL && !cell->getCell()->isExterior()) + { + mDoorCheckDuration = 0; + // Check all the doors in this cell + mDoors = cell->get(); // update + mDoorIter = mDoors.mList.begin(); + for (; mDoorIter != mDoors.mList.end(); ++mDoorIter) + { + MWWorld::LiveCellRef& ref = *mDoorIter; + float minSqr = 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED; // for legibility + if(vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && + ref.mData.getLocalRotation().rot[2] < 0.4f) // even small opening + { + //std::cout<<"closed door id \""<getCell()->isExterior() && !mDoors.mList.empty()) + { + MWWorld::LiveCellRef& ref = *mDoorIter; + float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility + // TODO: add reaction to checking open doors + if(mBackOffDoor && + vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) + { + mMovement.mPosition[1] = -0.2; // back off, but slowly + } + else if(mBackOffDoor && + mDoorIter != mDoors.mList.end() && + ref.mData.getLocalRotation().rot[2] >= 1) + { + mDoorIter = mDoors.mList.end(); + mBackOffDoor = false; + //std::cout<<"open door id \""<::List::iterator mDoorIter; + MWWorld::CellRefList& mDoors; void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target); };