From 8f90dd43ecb62676323fb507ba7d014faa6d22f7 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 29 Apr 2014 12:52:08 -0400 Subject: [PATCH 01/25] 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 c09abcbafd..c2b11c6156 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 18bb24ed09..5be81ac080 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 10a5bb946461ec6d48e184a36b76fbb7e8ef9652 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 29 Apr 2014 23:40:59 -0400 Subject: [PATCH 02/25] 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 3787a9c071..ace4cc6d0e 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 fd54869f6c..b6ce9f85d9 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 30b72acd92..833b0063c9 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 53b57c0580..3771417fa2 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 48a8eb4c26..4eb3e3757a 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 8e015da158..30eab7f8b5 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 3fd708ab32..bf5410676d 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 cb1b0de02f..a751e03970 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 72f3e02983..ea7f1dc329 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 2975c8315f..6481b2a01c 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 31cafa4dc7..b2b0fe1ee0 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 804bf523bac3be304e3a83512c8a8b8fd225d40d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 17:35:11 +0200 Subject: [PATCH 03/25] removed two unused files --- apps/opencs/view/doc/opendialog.cpp | 62 ----------------------------- apps/opencs/view/doc/opendialog.hpp | 17 -------- 2 files changed, 79 deletions(-) delete mode 100644 apps/opencs/view/doc/opendialog.cpp delete mode 100644 apps/opencs/view/doc/opendialog.hpp diff --git a/apps/opencs/view/doc/opendialog.cpp b/apps/opencs/view/doc/opendialog.cpp deleted file mode 100644 index d107b198c6..0000000000 --- a/apps/opencs/view/doc/opendialog.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include - -#include - -#include "opendialog.hpp" - -OpenDialog::OpenDialog(QWidget * parent) : QDialog(parent) -{ - QVBoxLayout *layout = new QVBoxLayout(this); - mFileSelector = new DataFilesList(mCfgMgr, this); - layout->addWidget(mFileSelector); - - /// \todo move config to Editor class and add command line options. - // We use the Configuration Manager to retrieve the configuration values - boost::program_options::variables_map variables; - boost::program_options::options_description desc; - - desc.add_options() - ("data", boost::program_options::value()->default_value(Files::PathContainer(), "data")->multitoken()) - ("data-local", boost::program_options::value()->default_value("")) - ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) - ("encoding", boost::program_options::value()->default_value("win1252")); - - boost::program_options::notify(variables); - - mCfgMgr.readConfiguration(variables, desc); - - Files::PathContainer mDataDirs, mDataLocal; - if (!variables["data"].empty()) { - mDataDirs = Files::PathContainer(variables["data"].as()); - } - - std::string local = variables["data-local"].as(); - if (!local.empty()) { - mDataLocal.push_back(Files::PathContainer::value_type(local)); - } - - mCfgMgr.processPaths(mDataDirs); - mCfgMgr.processPaths(mDataLocal); - - // Set the charset for reading the esm/esp files - QString encoding = QString::fromUtf8 (variables["encoding"].as().c_str()); - - Files::PathContainer dataDirs; - dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end()); - dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end()); - mFileSelector->setupDataFiles(dataDirs, encoding); - - buttonBox = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel, Qt::Horizontal, this); - connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - layout->addWidget(buttonBox); - - setLayout(layout); - setWindowTitle(tr("Open")); -} - -void OpenDialog::getFileList(std::vector& paths) -{ - mFileSelector->selectedFiles(paths); -} diff --git a/apps/opencs/view/doc/opendialog.hpp b/apps/opencs/view/doc/opendialog.hpp deleted file mode 100644 index 6355aea44f..0000000000 --- a/apps/opencs/view/doc/opendialog.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -class DataFilesList; -class QDialogButtonBox; - -class OpenDialog : public QDialog { - Q_OBJECT -public: - OpenDialog(QWidget * parent = 0); - - void getFileList(std::vector& paths); -private: - DataFilesList * mFileSelector; - QDialogButtonBox * buttonBox; - Files::ConfigurationManager mCfgMgr; -}; \ No newline at end of file From 5b5bf6f37e4573babac9dd97adfc254869791c61 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 17:46:10 +0200 Subject: [PATCH 04/25] removed a redundant (and unsufficiently configured) copy of ConfigurationManager --- apps/opencs/editor.cpp | 2 +- apps/opencs/model/settings/usersettings.cpp | 3 ++- apps/opencs/model/settings/usersettings.hpp | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index ad6c4be3d7..57d2f4730e 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -20,7 +20,7 @@ #include "model/world/data.hpp" CS::Editor::Editor (OgreInit::OgreInit& ogreInit) -: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), +: mUserSettings (mCfgMgr), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), mIpcServerName ("org.openmw.OpenCS") { std::pair > config = readConfig(); diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 1a91254390..04f98f0d6c 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -28,7 +28,8 @@ namespace boost CSMSettings::UserSettings *CSMSettings::UserSettings::mUserSettingsInstance = 0; -CSMSettings::UserSettings::UserSettings() +CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager) +: mCfgMgr (configurationManager) { assert(!mUserSettingsInstance); mUserSettingsInstance = this; diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 830cc8c69f..7e553caf6e 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -30,7 +30,7 @@ namespace CSMSettings { Q_OBJECT static UserSettings *mUserSettingsInstance; - Files::ConfigurationManager mCfgMgr; + const Files::ConfigurationManager& mCfgMgr; QSettings *mSettingDefinitions; QList mSettings; @@ -40,11 +40,11 @@ namespace CSMSettings { /// Singleton implementation static UserSettings& instance(); - UserSettings(); + UserSettings (const Files::ConfigurationManager& configurationManager); ~UserSettings(); - UserSettings (UserSettings const &); //not implemented - void operator= (UserSettings const &); //not implemented + UserSettings (UserSettings const &); //not implemented + UserSettings& operator= (UserSettings const &); //not implemented /// Retrieves the settings file at all three levels (global, local and user). void loadSettings (const QString &fileName); From 050fe9ebe1190c0ca9ac0c9b4cc8fa519b100a92 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 12 May 2014 08:58:55 +0200 Subject: [PATCH 05/25] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 499c55eebd..6f0561490b 100644 --- a/credits.txt +++ b/credits.txt @@ -33,6 +33,7 @@ Edmondo Tommasina (edmondo) Eduard Cot (trombonecot) Eli2 Emanuel Guével (potatoesmaster) +Fil Krynicki (filkry) gugus/gus Jacob Essex (Yacoby) Jannik Heller (scrawl) From 8279d307c4b53a13acf339594bd3703300ee17b6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 12 May 2014 10:32:57 +0200 Subject: [PATCH 06/25] text encoding configuration (was using hardcoded settings before) --- apps/opencs/editor.cpp | 3 +++ apps/opencs/model/doc/document.cpp | 8 +++++--- apps/opencs/model/doc/document.hpp | 5 ++++- apps/opencs/model/doc/documentmanager.cpp | 9 +++++++-- apps/opencs/model/doc/documentmanager.hpp | 5 +++++ apps/opencs/model/doc/saving.cpp | 5 +++-- apps/opencs/model/doc/saving.hpp | 5 ++++- apps/opencs/model/doc/savingstate.cpp | 8 +++----- apps/opencs/model/doc/savingstate.hpp | 5 ++++- apps/opencs/model/world/data.cpp | 6 ++---- apps/opencs/model/world/data.hpp | 4 +++- 11 files changed, 43 insertions(+), 20 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 57d2f4730e..b003735874 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -90,6 +90,9 @@ std::pair > CS::Editor::readConfi mCfgMgr.readConfiguration(variables, desc); + mDocumentManager.setEncoding ( + ToUTF8::calculateEncoding (variables["encoding"].as())); + mDocumentManager.setResourceDir (mResources = variables["resources"].as()); mFsStrict = variables["fs-strict"].as(); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 06c4a09887..f452008ac9 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2204,11 +2204,13 @@ void CSMDoc::Document::createBase() CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, - const boost::filesystem::path& savePath, const boost::filesystem::path& resDir) -: mSavePath (savePath), mContentFiles (files), mNew (new_), mTools (mData), mResDir(resDir), + const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, + ToUTF8::FromType encoding) +: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding), mTools (mData), + mResDir(resDir), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), - mSaving (*this, mProjectPath) + mSaving (*this, mProjectPath, encoding) { if (mContentFiles.empty()) throw std::runtime_error ("Empty content file sequence"); diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 000f6761a0..a6f8aaae28 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -9,6 +9,8 @@ #include #include +#include + #include "../world/data.hpp" #include "../tools/tools.hpp" @@ -70,7 +72,8 @@ namespace CSMDoc Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, - const boost::filesystem::path& savePath, const boost::filesystem::path& resDir); + const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, + ToUTF8::FromType encoding); ~Document(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index d4f8eb110c..096864b772 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -13,7 +13,7 @@ #include "document.hpp" CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration) -: mConfiguration (configuration) +: mConfiguration (configuration), mEncoding (ToUTF8::WINDOWS_1252) { boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects"; @@ -52,7 +52,7 @@ CSMDoc::DocumentManager::~DocumentManager() void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (mConfiguration, files, new_, savePath, mResDir); + Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding); mDocuments.push_back (document); @@ -80,6 +80,11 @@ void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& par mResDir = boost::filesystem::system_complete(parResDir); } +void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding) +{ + mEncoding = encoding; +} + void CSMDoc::DocumentManager::documentLoaded (Document *document) { emit documentAdded (document); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 7b3a811fad..9b675826a2 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -9,6 +9,8 @@ #include #include +#include + #include "loader.hpp" namespace Files @@ -28,6 +30,7 @@ namespace CSMDoc const Files::ConfigurationManager& mConfiguration; QThread mLoaderThread; Loader mLoader; + ToUTF8::FromType mEncoding; DocumentManager (const DocumentManager&); DocumentManager& operator= (const DocumentManager&); @@ -45,6 +48,8 @@ namespace CSMDoc void setResourceDir (const boost::filesystem::path& parResDir); + void setEncoding (ToUTF8::FromType encoding); + private: boost::filesystem::path mResDir; diff --git a/apps/opencs/model/doc/saving.cpp b/apps/opencs/model/doc/saving.cpp index 73278ba975..27d21635eb 100644 --- a/apps/opencs/model/doc/saving.cpp +++ b/apps/opencs/model/doc/saving.cpp @@ -8,8 +8,9 @@ #include "savingstages.hpp" #include "document.hpp" -CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath) -: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath) +CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath, + ToUTF8::FromType encoding) +: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath, encoding) { // save project file appendStage (new OpenSaveStage (mDocument, mState, true)); diff --git a/apps/opencs/model/doc/saving.hpp b/apps/opencs/model/doc/saving.hpp index cd1bbef980..44239b21b5 100644 --- a/apps/opencs/model/doc/saving.hpp +++ b/apps/opencs/model/doc/saving.hpp @@ -3,6 +3,8 @@ #include +#include + #include "operation.hpp" #include "savingstate.hpp" @@ -19,7 +21,8 @@ namespace CSMDoc public: - Saving (Document& document, const boost::filesystem::path& projectPath); + Saving (Document& document, const boost::filesystem::path& projectPath, + ToUTF8::FromType encoding); }; } diff --git a/apps/opencs/model/doc/savingstate.cpp b/apps/opencs/model/doc/savingstate.cpp index 4a1abb8883..8742148226 100644 --- a/apps/opencs/model/doc/savingstate.cpp +++ b/apps/opencs/model/doc/savingstate.cpp @@ -4,11 +4,9 @@ #include "operation.hpp" #include "document.hpp" -CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath) -: mOperation (operation), - /// \todo set encoding properly, once config implementation has been fixed. - mEncoder (ToUTF8::calculateEncoding ("win1252")), - mProjectPath (projectPath), mProjectFile (false) +CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath, + ToUTF8::FromType encoding) +: mOperation (operation), mEncoder (encoding), mProjectPath (projectPath), mProjectFile (false) { mWriter.setEncoder (&mEncoder); } diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp index 8cf7883e50..6b45655846 100644 --- a/apps/opencs/model/doc/savingstate.hpp +++ b/apps/opencs/model/doc/savingstate.hpp @@ -7,6 +7,8 @@ #include +#include + namespace CSMDoc { class Operation; @@ -25,7 +27,8 @@ namespace CSMDoc public: - SavingState (Operation& operation, const boost::filesystem::path& projectPath); + SavingState (Operation& operation, const boost::filesystem::path& projectPath, + ToUTF8::FromType encoding); bool hasError() const; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 3e9fe11eb0..ff33b46655 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -55,10 +55,8 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec return number; } -CSMWorld::Data::Data() -/// \todo set encoding properly, once config implementation has been fixed. -: mEncoder (ToUTF8::calculateEncoding ("win1252")), - mRefs (mCells), mReader (0), mDialogue (0) +CSMWorld::Data::Data (ToUTF8::FromType encoding) +: mEncoder (encoding), mRefs (mCells), mReader (0), mDialogue (0) { mGlobals.addColumn (new StringIdColumn); mGlobals.addColumn (new RecordStateColumn); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 4f7c624e68..ab247b6a34 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -22,6 +22,8 @@ #include #include +#include + #include "../filter/filter.hpp" #include "../doc/stage.hpp" @@ -91,7 +93,7 @@ namespace CSMWorld public: - Data(); + Data (ToUTF8::FromType encoding); virtual ~Data(); From 2c74ea381e1bf290ac67fe062f085dc77f0c7d75 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 12 May 2014 21:05:32 -0400 Subject: [PATCH 07/25] 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 161c9700f1..98ac5ee149 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 4eb3e3757a..531082357a 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 8193a670be..afe99e2c0b 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 b3a7facee2..e36b51f691 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 0c10bd81dd..4e0bc71046 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 8a471228ed..7d1ea5bb9d 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 cd03939bd0..d77a35ea48 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 29577542e6..603a04f8c5 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 3b5330e9fd..5b8ce3eb2c 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 9ee49552db..b940c27e60 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 08/25] 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 7a52831251..aee5cbeacc 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 44c8c96bed..2dfa34ba32 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 eeedc0d7aa..1463dff7ee 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 b6ce9f85d9..f684388727 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 98ac5ee149..8d9e019394 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 531082357a..43681c1634 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 afe99e2c0b..90f0505a4d 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 e36b51f691..37de32d8d9 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 4e0bc71046..6e91ccb719 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 7d1ea5bb9d..2eb533d625 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 1815609357..7cd85685b2 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 12030b2bee..e737ef9cfd 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 ba36d4a869..5d1657a348 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 645330683b..d111d00083 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 09/25] 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 90f0505a4d..872eecb62b 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 598221a8e77a937ad7ff3ea144709046f5955eaf Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:07:27 -0400 Subject: [PATCH 10/25] 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 0000000000..375e8fae7f --- /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 0000000000..6c90e36d61 --- /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 11/25] 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 5b8ce3eb2c..efdbdd86be 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 b940c27e60..9262334442 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 ee36ace00b7f351e3525c156df80b456daaf3c5f Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:43:50 -0400 Subject: [PATCH 12/25] 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 ace4cc6d0e..3787a9c071 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 6c90e36d61..6e9a1bdf5b 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 43681c1634..10a381410a 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 37de32d8d9..c9c8504aa1 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 b2b0fe1ee0..31cafa4dc7 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 09c9954288..5aea0210f2 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 13/25] 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 5be81ac080..908165ee60 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 14/25] 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 5a4cb743aa..8196262f5b 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 15/25] 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 6a4e1be2ff..93e0d1c366 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 908165ee60..3f91ca357d 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 16/25] 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 8196262f5b..3d524a6862 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 17/25] 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 3d524a6862..7ac68dd677 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 203ef580cf3cfae01c3dcedb34842a1b71d99c14 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 20:32:29 -0400 Subject: [PATCH 18/25] 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 f684388727..0e660e967d 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 872eecb62b..1bc3503832 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 19/25] 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 1463dff7ee..56c155ded0 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 6e9a1bdf5b..8d225655a0 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 1bc3503832..5ccd2c8d89 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 82489adacc..96dd91f821 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 7cd4c93fa4aa7dd63a55818de533e4dd539b270b Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 23:46:00 -0400 Subject: [PATCH 20/25] 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 5ccd2c8d89..c2e8385b82 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 c9c8504aa1..bb62a2543a 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 7cd85685b2..fc781e6377 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 e737ef9cfd..76ab9d029b 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 cbcf0f60399e5ca59513a8dcf189c3af040c7b45 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 01:44:11 -0400 Subject: [PATCH 21/25] 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 f27fada39f..0430adf06a 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 c2e8385b82..5e16ebdc8f 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 bb62a2543a..055958384a 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 9262334442..60a7369917 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 993ef1be4340dbbc6203c75342c6d5fe629d37ef Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 04:05:18 -0400 Subject: [PATCH 22/25] 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 375e8fae7f..c6ecc08bf3 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 96dd91f821..99589b6101 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 23/25] 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 a5a7e8252e..8da300aba8 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 24/25] 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 c6ecc08bf3..26865aea40 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 8d225655a0..85bb09fc83 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 99589b6101..a3b9e64d35 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 25/25] 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 56c155ded0..4b4b36ed65 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 26865aea40..a206d27ca0 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 8d9e019394..f1296a9493 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 5e16ebdc8f..2a2f4fdc86 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 {