From f41f08c352962a2e00ce809027f6715748597c5f Mon Sep 17 00:00:00 2001 From: gus Date: Thu, 5 Dec 2013 14:00:50 +0100 Subject: [PATCH 01/17] Wrong logic... should improve performances --- apps/openmw/mwmechanics/aicombat.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 32b0063b6..3ca522dc7 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -77,13 +77,14 @@ namespace MWMechanics mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); else { - mPathFinder2.buildPath(start, dest, pathgrid, xCell, yCell, true); - ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); - if((mTimer2 > 0.25)&&(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || - (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200)) + if(mTimer2 > 0.25) { mTimer2 = 0; - mPathFinder = mPathFinder2; + mPathFinder2.buildPath(start, dest, pathgrid, xCell, yCell, true); + ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); + if(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || + (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200) + mPathFinder = mPathFinder2; } } From 2d66b2c4fa7ca03a096a3be54fc6e19d6cdc8f83 Mon Sep 17 00:00:00 2001 From: gus Date: Sat, 11 Jan 2014 12:06:36 +0100 Subject: [PATCH 02/17] AiFollow. Npc get stuck often (no stuck dtection yet) --- apps/openmw/mwmechanics/aicombat.cpp | 3 +- apps/openmw/mwmechanics/aifollow.cpp | 44 ++++++++++++++++++++++++++-- apps/openmw/mwmechanics/aifollow.hpp | 7 +++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 3ca522dc7..6a1ab68d8 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -3,7 +3,7 @@ #include "movement.hpp" #include "../mwworld/class.hpp" -#include "../mwworld/timestamp.hpp" + #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -87,6 +87,7 @@ namespace MWMechanics mPathFinder = mPathFinder2; } } + ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 73bf9259a..2f9a7a843 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -1,12 +1,16 @@ #include "aifollow.hpp" #include +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/class.hpp" +#include "movement.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) : mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId) { } MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId) +: mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), mTimer(0), mStuckTimer(0) { } @@ -17,8 +21,44 @@ MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mActorId, false); + + mTimer = mTimer + duration; + mStuckTimer = mStuckTimer + duration; + mTotalTime = mTotalTime + duration; + + if(mTotalTime > mDuration) return true; + + 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]; + + if(mTimer > 0.25) + { + ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); + + 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) + mPathFinder.getPath().push_back(dest); + + mTimer = 0; + } + + ESM::Position pos = actor.getRefData().getPosition(); + float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + + 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) + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; + else + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; + std::cout << "AiFollow completed.\n"; - return true; + return false; } int MWMechanics::AiFollow::getTypeId() const diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 39df024e4..b149c55f5 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -3,6 +3,7 @@ #include "aipackage.hpp" #include +#include "pathfinding.hpp" namespace MWMechanics { @@ -24,6 +25,12 @@ namespace MWMechanics float mZ; std::string mActorId; std::string mCellId; + + float mTimer; + float mStuckTimer; + float mTotalTime; + + PathFinder mPathFinder; }; } #endif From ccf07f940662daf2ebbf5498293202d6f178a13d Mon Sep 17 00:00:00 2001 From: gus Date: Tue, 7 Jan 2014 21:10:57 +0100 Subject: [PATCH 03/17] Bugfix --- apps/openmw/mwmechanics/aifollow.cpp | 63 +++++++++++++++++++++---- apps/openmw/mwmechanics/aifollow.hpp | 3 ++ apps/openmw/mwmechanics/pathfinding.hpp | 5 ++ 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 2f9a7a843..b2c322331 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -6,7 +6,7 @@ #include "movement.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId) +: mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mTimer(0), mStuckTimer(0) { } MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) @@ -34,22 +34,66 @@ MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const dest.mY = target.getRefData().getPosition().pos[1]; dest.mZ = target.getRefData().getPosition().pos[2]; + //std::cout << dest.mX; + + ESM::Position pos = actor.getRefData().getPosition(); + if(mTimer > 0.25) { - ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); + if(!mPathFinder.getPath().empty()) + { + ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); - 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) + 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) - mPathFinder.getPath().push_back(dest); + mPathFinder.addPointToPath(dest); + } + else + mPathFinder.addPointToPath(dest); mTimer = 0; } - ESM::Position pos = actor.getRefData().getPosition(); - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + if(mStuckTimer>0.5) + { + 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 + { + std::cout << "stck\n"; + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + const ESM::Pathgrid *pathgrid = + MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); + + float xCell = 0; + float yCell = 0; + + if (actor.getCell()->mCell->isExterior()) + { + xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; + yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; + } + mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + } + mStuckTimer = 0; + mStuckPos = pos; + } + + if(mPathFinder.getPath().empty()) + mPathFinder.addPointToPath(dest); + + if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) + { + float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + } 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) @@ -57,7 +101,6 @@ MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const else MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - std::cout << "AiFollow completed.\n"; return false; } diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index b149c55f5..135ba9aac 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -4,6 +4,7 @@ #include "aipackage.hpp" #include #include "pathfinding.hpp" +#include "../../../components/esm/defs.hpp" namespace MWMechanics { @@ -30,6 +31,8 @@ namespace MWMechanics float mStuckTimer; float mTotalTime; + ESM::Position mStuckPos; + PathFinder mPathFinder; }; } diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 916df850b..f9c2c5cc7 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -37,6 +37,11 @@ namespace MWMechanics return mPath; } + void addPointToPath(ESM::Pathgrid::Point &point) + { + mPath.push_back(point); + } + private: std::list mPath; bool mIsPathConstructed; From 051d7141be83e13d7f53a0f9987de5bf350a6713 Mon Sep 17 00:00:00 2001 From: gus Date: Sat, 11 Jan 2014 20:32:38 +0100 Subject: [PATCH 04/17] check position to stop AIFollow --- apps/openmw/mwmechanics/aifollow.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index b2c322331..e9495f859 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -27,17 +27,19 @@ MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const mStuckTimer = mStuckTimer + duration; mTotalTime = mTotalTime + duration; - if(mTotalTime > mDuration) return true; + ESM::Position pos = actor.getRefData().getPosition(); + + if(mTotalTime > mDuration || + (pos.pos[0]-mX)*(pos.pos[0]-mX) + + (pos.pos[1]-mY)*(pos.pos[1]-mY) + + (pos.pos[2]-mZ)*(pos.pos[2]-mZ) < 100*100) + return true; 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]; - //std::cout << dest.mX; - - ESM::Position pos = actor.getRefData().getPosition(); - if(mTimer > 0.25) { if(!mPathFinder.getPath().empty()) @@ -63,7 +65,6 @@ MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const +(mStuckPos.pos[2] - pos.pos[2])*(mStuckPos.pos[2] - pos.pos[2]) < 100) //NPC is stuck { - std::cout << "stck\n"; ESM::Pathgrid::Point start; start.mX = pos.pos[0]; start.mY = pos.pos[1]; From 7066844e52f10752ca77db00f8e1dbaaa20b0d43 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 12 Jan 2014 11:38:58 +0100 Subject: [PATCH 05/17] Follow you until a certain cell is reached --- apps/openmw/mwmechanics/aifollow.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index e9495f859..6e19cc182 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -6,7 +6,7 @@ #include "movement.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mTimer(0), mStuckTimer(0) +: 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) @@ -19,7 +19,7 @@ MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const return new AiFollow(*this); } - bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) +bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mActorId, false); @@ -29,11 +29,24 @@ MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const ESM::Position pos = actor.getRefData().getPosition(); - if(mTotalTime > mDuration || - (pos.pos[0]-mX)*(pos.pos[0]-mX) + + if(mTotalTime > mDuration) + return true; + + if((pos.pos[0]-mX)*(pos.pos[0]-mX) + (pos.pos[1]-mY)*(pos.pos[1]-mY) + (pos.pos[2]-mZ)*(pos.pos[2]-mZ) < 100*100) - return true; + { + if(actor.getCell()->isExterior()) + { + if(mCellId == "") + return true; + } + else + { + if(mCellId == actor.getCell()->mCell->mName) + return true; + } + } ESM::Pathgrid::Point dest; dest.mX = target.getRefData().getPosition().pos[0]; From 7e96a391da79df0fa4ea5e71e766e6d7140b6d26 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 12 Jan 2014 11:39:42 +0100 Subject: [PATCH 06/17] FollowCell duration = 0 -> infinite time --- apps/openmw/mwmechanics/aifollow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 6e19cc182..61994a865 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -29,7 +29,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) ESM::Position pos = actor.getRefData().getPosition(); - if(mTotalTime > mDuration) + if(mTotalTime > mDuration && mDuration != 0) return true; if((pos.pos[0]-mX)*(pos.pos[0]-mX) + From 2446abe07633675a8cf3180b187a6bc1812abb45 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 12 Jan 2014 14:01:54 +0100 Subject: [PATCH 07/17] Allow getting current active package --- apps/openmw/mwmechanics/aisequence.cpp | 8 ++++++++ apps/openmw/mwmechanics/aisequence.hpp | 3 +++ 2 files changed, 11 insertions(+) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 139f54489..616e54bd8 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -102,6 +102,14 @@ void MWMechanics::AiSequence::queue (const AiPackage& package) mPackages.push_back (package.clone()); } +MWMechanics::AiPackage* MWMechanics::AiSequence::getActivePackage() +{ + if(mPackages.empty()) + throw std::runtime_error(std::string("No AI Package!")); + else + return mPackages.front(); +} + void MWMechanics::AiSequence::fill(const ESM::AIPackageList &list) { for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 0976ef099..d44a4975e 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -52,6 +52,9 @@ namespace MWMechanics ///< Add \a package to the end of the sequence (executed after all other packages have been /// completed) + AiPackage* getActivePackage(); + ///< return the current active package. If there is no active package, throw an exeption + void fill (const ESM::AIPackageList& list); }; } From dd870e35dbd19463d7f16af7216b80be9f8d1abd Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 12 Jan 2014 14:02:15 +0100 Subject: [PATCH 08/17] get all actors following a given actor --- apps/openmw/mwbase/mechanicsmanager.hpp | 4 ++++ apps/openmw/mwmechanics/actors.cpp | 19 +++++++++++++++++++ apps/openmw/mwmechanics/actors.hpp | 3 +++ .../mwmechanics/mechanicsmanagerimp.cpp | 5 +++++ .../mwmechanics/mechanicsmanagerimp.hpp | 2 ++ 5 files changed, 33 insertions(+) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 24e955cdf..ce5c62ee4 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace Ogre { @@ -151,6 +152,9 @@ namespace MWBase virtual void toggleAI() = 0; virtual bool isAIActive() = 0; + + ///return the list of actors which are following the given actor (ie AiFollow is active and the target is the actor) + virtual std::list getActorsFollowing(const MWWorld::Ptr& actor) = 0; }; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 0a4adb6e2..a019aeb30 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -27,6 +27,7 @@ #include "../mwbase/mechanicsmanager.hpp" #include "aicombat.hpp" +#include "aifollow.hpp" namespace { @@ -877,4 +878,22 @@ namespace MWMechanics return iter->second->isAnimPlaying(groupName); return false; } + + std::list Actors::getActorsFollowing(const MWWorld::Ptr& actor) + { + std::list list; + for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) + { + const MWWorld::Class &cls = MWWorld::Class::get(iter->first); + CreatureStats &stats = cls.getCreatureStats(iter->first); + + if(stats.getAiSequence().getTypeId() == 3) + { + MWMechanics::AiFollow* package = static_cast(stats.getAiSequence().getActivePackage()); + if(package->getFollowedActor() == actor.getCellRef().mRefID) + list.push_front(iter->first); + } + } + return list; + } } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 7046543e6..c8abd3525 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -91,6 +91,9 @@ namespace MWMechanics void skipAnimation(const MWWorld::Ptr& ptr); bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName); + std::list getActorsFollowing(const MWWorld::Ptr& actor); + ///= target); } + + std::list MechanicsManager::getActorsFollowing(const MWWorld::Ptr& actor) + { + return mActors.getActorsFollowing(actor); + } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index cec08fa92..50d9289cc 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -129,6 +129,8 @@ namespace MWMechanics virtual void toggleAI(); virtual bool isAIActive(); + + virtual std::list getActorsFollowing(const MWWorld::Ptr& actor); }; } From 1ae62665d65472507a21a2aa91e582f71547899f Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 12 Jan 2014 14:02:40 +0100 Subject: [PATCH 09/17] get all actors following a given actor --- apps/openmw/mwmechanics/aifollow.cpp | 5 +++++ apps/openmw/mwmechanics/aifollow.hpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 61994a865..399504ff1 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -122,3 +122,8 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { return 3; } + +std::string MWMechanics::AiFollow::getFollowedActor() +{ + return mActorId; +} diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 135ba9aac..9d77b903d 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -19,6 +19,8 @@ namespace MWMechanics ///< \return Package completed? virtual int getTypeId() const; + std::string getFollowedActor(); + private: float mDuration; float mX; From 0e46c40cb5812bb40dfa454db9fab4167c1a9c25 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 12 Jan 2014 14:03:11 +0100 Subject: [PATCH 10/17] Make ACtionTeleport non player specific and teleport actors following the teleporting actor --- apps/openmw/mwworld/actionteleport.cpp | 33 ++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 773fde81e..b4c572ba9 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -3,6 +3,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "player.hpp" namespace MWWorld @@ -16,11 +17,35 @@ namespace MWWorld void ActionTeleport::executeImp (const Ptr& actor) { MWBase::World* world = MWBase::Environment::get().getWorld(); - world->getPlayer().setTeleported(true); - if (mCellName.empty()) - world->changeToExteriorCell (mPosition); + //find any NPC that is following the actor and teleport him too + std::list followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor); + for(std::list::iterator it = followers.begin();it != followers.end();it++) + { + std::cout << "teleporting someone!" << (*it).getCellRef().mRefID; + executeImp(*it); + } + + if(actor == world->getPlayerPtr()) + { + world->getPlayer().setTeleported(true); + if (mCellName.empty()) + world->changeToExteriorCell (mPosition); + else + world->changeToInteriorCell (mCellName, mPosition); + } else - world->changeToInteriorCell (mCellName, mPosition); + { + if (mCellName.empty()) + { + int cellX; + int cellY; + world->positionToIndex(mPosition.pos[0],mPosition.pos[1],cellX,cellY); + world->moveObject(actor,*world->getExterior(cellX,cellY), + mPosition.pos[0],mPosition.pos[1],mPosition.pos[2]); + } + else + world->moveObject(actor,*world->getInterior(mCellName),mPosition.pos[0],mPosition.pos[1],mPosition.pos[2]); + } } } From 5d038423ec8936b0a84eb469c2cca93b5b78887a Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 12 Jan 2014 18:42:31 +0100 Subject: [PATCH 11/17] attempt to solve Bug #1009 by not building graph every frame --- apps/openmw/mwmechanics/aicombat.cpp | 7 ++---- apps/openmw/mwmechanics/aiescort.cpp | 4 +--- apps/openmw/mwmechanics/aifollow.cpp | 7 ++---- apps/openmw/mwmechanics/aitravel.cpp | 3 +-- apps/openmw/mwmechanics/aiwander.cpp | 2 +- apps/openmw/mwmechanics/pathfinding.cpp | 29 ++++++++++++++++++++----- apps/openmw/mwmechanics/pathfinding.hpp | 19 ++++++++++++++-- 7 files changed, 48 insertions(+), 23 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 6a1ab68d8..19c3fa2f3 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -49,8 +49,6 @@ namespace MWMechanics //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); } ESM::Position pos = actor.getRefData().getPosition(); - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); float xCell = 0; float yCell = 0; @@ -74,20 +72,19 @@ namespace MWMechanics mTimer2 = mTimer2 + duration; if(!mPathFinder.isPathConstructed()) - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder.buildPath(start, dest, actor.getCell(), true); else { if(mTimer2 > 0.25) { mTimer2 = 0; - mPathFinder2.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder2.buildPath(start, dest, actor.getCell(), true); ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); if(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200) mPathFinder = mPathFinder2; } } - ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 35f9f1993..0d44dd6fc 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -85,8 +85,6 @@ namespace MWMechanics MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); ESM::Position pos = actor.getRefData().getPosition(); bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY; - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX) { @@ -136,7 +134,7 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder.buildPath(start, dest, actor.getCell(), true); } if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 399504ff1..a711ebe7c 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -81,10 +81,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) ESM::Pathgrid::Point start; start.mX = pos.pos[0]; start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); + start.mZ = pos.pos[2]; float xCell = 0; float yCell = 0; @@ -94,7 +91,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; } - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder.buildPath(start, dest, actor.getCell(), true); } mStuckTimer = 0; mStuckPos = pos; diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index 73b38dd13..24a61310b 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -61,7 +61,6 @@ namespace MWMechanics } } - const ESM::Pathgrid *pathgrid = world->getStore().get().search(*cell); bool cellChange = cell->mData.mX != cellX || cell->mData.mY != cellY; if(!mPathFinder.isPathConstructed() || cellChange) { @@ -86,7 +85,7 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder.buildPath(start, dest, actor.getCell(), true); } if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 7df88c076..353121a3e 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -213,7 +213,7 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start, dest, mPathgrid, mXCell, mYCell, false); + mPathFinder.buildPath(start, dest, actor.getCell(), false); if(mPathFinder.isPathConstructed()) { diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index c8bc9b49c..86019fe54 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -6,7 +6,6 @@ #include "OgreMath.h" #include -#include namespace { @@ -136,8 +135,8 @@ namespace namespace MWMechanics { PathFinder::PathFinder() + :mIsPathConstructed(false),mIsGraphConstructed(false) { - mIsPathConstructed = false; } void PathFinder::clearPath() @@ -147,10 +146,19 @@ namespace MWMechanics mIsPathConstructed = false; } + void PathFinder::buildPathgridGraph(const ESM::Pathgrid* pathGrid,float xCell, float yCell) + { + mGraph = buildGraph(pathGrid, xCell, yCell); + mIsGraphConstructed = true; + } + void PathFinder::buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, - const ESM::Pathgrid *pathGrid, float xCell, float yCell, bool allowShortcuts) + const MWWorld::CellStore* cell, bool allowShortcuts) { mPath.clear(); + if(mCell != cell) mIsGraphConstructed = false; + mCell = cell; + if(allowShortcuts) { if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ, @@ -160,13 +168,24 @@ namespace MWMechanics if(!allowShortcuts) { + const ESM::Pathgrid *pathGrid = + MWBase::Environment::get().getWorld()->getStore().get().search(*mCell->mCell); + float xCell = 0; + float yCell = 0; + + if (mCell->isExterior()) + { + xCell = mCell->mCell->mData.mX * ESM::Land::REAL_SIZE; + yCell = mCell->mCell->mData.mY * ESM::Land::REAL_SIZE; + } int startNode = getClosestPoint(pathGrid, startPoint.mX - xCell, startPoint.mY - yCell,startPoint.mZ); int endNode = getClosestPoint(pathGrid, endPoint.mX - xCell, endPoint.mY - yCell, endPoint.mZ); if(startNode != -1 && endNode != -1) { - PathGridGraph graph = buildGraph(pathGrid, xCell, yCell); - mPath = findPath(startNode, endNode, graph); + if(!mIsGraphConstructed) buildPathgridGraph(pathGrid, xCell, yCell); + + mPath = findPath(startNode, endNode, mGraph); if(!mPath.empty()) { diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index f9c2c5cc7..687031491 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -3,6 +3,12 @@ #include #include +#include + +namespace MWWorld +{ + class CellStore; +} namespace MWMechanics { @@ -12,9 +18,11 @@ namespace MWMechanics PathFinder(); void clearPath(); + + void buildPathgridGraph(const ESM::Pathgrid* pathGrid,float xCell = 0, float yCell = 0); + void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, - const ESM::Pathgrid* pathGrid, float xCell = 0, float yCell = 0, - bool allowShortcuts = true); + const MWWorld::CellStore* cell, bool allowShortcuts = true); bool checkPathCompleted(float x, float y, float z); ///< \Returns true if the last point of the path has been reached. @@ -45,6 +53,13 @@ namespace MWMechanics private: std::list mPath; bool mIsPathConstructed; + + typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, + boost::property, boost::property > + PathGridGraph; + PathGridGraph mGraph; + bool mIsGraphConstructed; + const MWWorld::CellStore* mCell; }; } From 5d4e148063c6e5480d571355872d5fb410f48074 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 12 Jan 2014 22:47:22 +0100 Subject: [PATCH 12/17] some clean up --- apps/openmw/mwmechanics/aicombat.cpp | 9 --------- apps/openmw/mwmechanics/aiescort.cpp | 21 +++++++-------------- apps/openmw/mwmechanics/aiescort.hpp | 4 ++-- apps/openmw/mwmechanics/aifollow.cpp | 10 +--------- apps/openmw/mwmechanics/pathfinding.cpp | 2 +- 5 files changed, 11 insertions(+), 35 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 19c3fa2f3..b9dc2f7db 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -50,15 +50,6 @@ namespace MWMechanics } ESM::Position pos = actor.getRefData().getPosition(); - float xCell = 0; - float yCell = 0; - - if (actor.getCell()->mCell->isExterior()) - { - xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; - yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; - } - ESM::Pathgrid::Point dest; dest.mX = target.getRefData().getPosition().pos[0]; dest.mY = target.getRefData().getPosition().pos[1]; diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 0d44dd6fc..f31d86140 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -28,8 +28,8 @@ namespace MWMechanics { AiEscort::AiEscort(const std::string &actorId, int duration, float x, float y, float z) : mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration) - , cellX(std::numeric_limits::max()) - , cellY(std::numeric_limits::max()) + , mCellX(std::numeric_limits::max()) + , mCellY(std::numeric_limits::max()) { mMaxDist = 470; @@ -47,8 +47,8 @@ namespace MWMechanics AiEscort::AiEscort(const std::string &actorId, const std::string &cellId,int duration, float x, float y, float z) : mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration) - , cellX(std::numeric_limits::max()) - , cellY(std::numeric_limits::max()) + , mCellX(std::numeric_limits::max()) + , mCellY(std::numeric_limits::max()) { mMaxDist = 470; @@ -84,7 +84,7 @@ namespace MWMechanics MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); ESM::Position pos = actor.getRefData().getPosition(); - bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY; + bool cellChange = actor.getCell()->mCell->mData.mX != mCellX || actor.getCell()->mCell->mData.mY != mCellY; if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX) { @@ -114,15 +114,8 @@ namespace MWMechanics if(!mPathFinder.isPathConstructed() || cellChange) { - cellX = actor.getCell()->mCell->mData.mX; - cellY = actor.getCell()->mCell->mData.mY; - float xCell = 0; - float yCell = 0; - if (actor.getCell()->mCell->isExterior()) - { - xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; - yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; - } + mCellX = actor.getCell()->mCell->mData.mX; + mCellY = actor.getCell()->mCell->mData.mY; ESM::Pathgrid::Point dest; dest.mX = mX; diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index f3f6d2bd9..53b57c058 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -34,8 +34,8 @@ namespace MWMechanics unsigned int mDuration; PathFinder mPathFinder; - int cellX; - int cellY; + int mCellX; + int mCellY; }; } #endif diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index a711ebe7c..898f91e7c 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -82,15 +82,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) start.mX = pos.pos[0]; start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - - float xCell = 0; - float yCell = 0; - - if (actor.getCell()->mCell->isExterior()) - { - xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; - yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; - } + mPathFinder.buildPath(start, dest, actor.getCell(), true); } mStuckTimer = 0; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 86019fe54..f8908fbd9 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -106,7 +106,7 @@ namespace return graph; } - std::list findPath(PointID start, PointID end, PathGridGraph graph) + std::list findPath(PointID start, PointID end,const PathGridGraph& graph) { std::vector p(boost::num_vertices(graph)); std::vector d(boost::num_vertices(graph)); From 5ca59467603edd5f8723a72c47786e63e0012b81 Mon Sep 17 00:00:00 2001 From: gus Date: Fri, 24 Jan 2014 19:13:23 +0100 Subject: [PATCH 13/17] WIP --- apps/openmw/mwmechanics/aicombat.cpp | 3 ++- apps/openmw/mwmechanics/aifollow.cpp | 34 +++++++++++++++------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index b9dc2f7db..0eff943d4 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -97,7 +97,8 @@ namespace MWMechanics zAngle = Ogre::Radian( Ogre::Math::ACos(directionY / directionResult) * sgn(Ogre::Math::ASin(directionX / directionResult)) ).valueDegrees(); // TODO: use movement settings instead of rotating directly - MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + //MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + MWWorld::Class::get(actor).getMovementSettings(actor).mRotation[2] = 10*(Ogre::Degree(zAngle).valueRadians()-pos.rot[2]); mPathFinder.clearPath(); diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 898f91e7c..21a629d90 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -4,6 +4,8 @@ #include "../mwbase/environment.hpp" #include "../mwworld/class.hpp" #include "movement.hpp" + +#include MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) : mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), mTimer(0), mStuckTimer(0) @@ -53,6 +55,15 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) dest.mY = target.getRefData().getPosition().pos[1]; dest.mZ = target.getRefData().getPosition().pos[2]; + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + if(mPathFinder.getPath().empty()) + mPathFinder.buildPath(start, dest, actor.getCell(), true); + + if(mTimer > 0.25) { if(!mPathFinder.getPath().empty()) @@ -63,10 +74,8 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) +(dest.mY - lastPos.mY)*(dest.mY - lastPos.mY) +(dest.mZ - lastPos.mZ)*(dest.mZ - lastPos.mZ) > 100*100) - mPathFinder.addPointToPath(dest); + mPathFinder.addPointToPath(dest); } - else - mPathFinder.addPointToPath(dest); mTimer = 0; } @@ -75,27 +84,20 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { 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 - { - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - + +(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; } - if(mPathFinder.getPath().empty()) - mPathFinder.addPointToPath(dest); - if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) { float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + //MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + MWWorld::Class::get(actor).getMovementSettings(actor).mRotation[2] = 10*(Ogre::Degree(zAngle).valueRadians()-pos.rot[2]); + //std::cout << Ogre::Degree(zAngle).valueDegrees()-Ogre::Radian(actor.getRefData().getPosition().rot[2]).valueDegrees() << " "<< pos.rot[2] << " " << zAngle << "\n"; + //MWWorld::Class::get(actor).get } 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]) From 7cb47aa6350ad49ba7e4954463427a9308c2171c Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 26 Jan 2014 21:26:19 +0100 Subject: [PATCH 14/17] new implementation of pathfinding. Works, but need clean up --- apps/openmw/mwmechanics/aifollow.cpp | 5 -- apps/openmw/mwmechanics/pathfinding.cpp | 110 +++++++++++++++++++++++- 2 files changed, 108 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index be57adadc..10bff8356 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -104,11 +104,6 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) return false; } - int MWMechanics::AiFollow::getTypeId() const -{ - return 3; -} - std::string MWMechanics::AiFollow::getFollowedActor() { return mActorId; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index f8908fbd9..1b42b11a4 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -6,6 +6,7 @@ #include "OgreMath.h" #include +#include namespace { @@ -132,6 +133,111 @@ namespace } } +namespace +{ + struct Edge + { + int destination; + float cost; + }; + struct Node + { + int label; + std::vector edges; + int parent;//used in pathfinding + }; + + std::list reconstructPath(const std::vector& graph,const ESM::Pathgrid* pathgrid, int lastNode,float xCell, float yCell) + { + std::list path; + while(graph[lastNode].parent != -1) + { + //std::cout << "not empty" << xCell; + ESM::Pathgrid::Point pt = pathgrid->mPoints[lastNode]; + pt.mX += xCell; + pt.mY += yCell; + path.push_front(pt); + lastNode = graph[lastNode].parent; + } + return path; + } + + std::list buildPath2(const ESM::Pathgrid* pathgrid,int start,int goal,float xCell = 0, float yCell = 0) + { + std::vector graph; + for(unsigned int i = 0; i < pathgrid->mPoints.size(); i++) + { + Node node; + node.label = i; + node.parent = -1; + graph.push_back(node); + } + for(unsigned int i = 0; i < pathgrid->mEdges.size(); i++) + { + Edge edge; + edge.destination = pathgrid->mEdges[i].mV1; + edge.cost = distance(pathgrid->mPoints[pathgrid->mEdges[i].mV0],pathgrid->mPoints[pathgrid->mEdges[i].mV1]); + graph[pathgrid->mEdges[i].mV0].edges.push_back(edge); + edge.destination = pathgrid->mEdges[i].mV0; + graph[pathgrid->mEdges[i].mV1].edges.push_back(edge); + } + + std::vector g_score(pathgrid->mPoints.size(),-1.); + std::vector f_score(pathgrid->mPoints.size(),-1.); + + g_score[start] = 0; + f_score[start] = distance(pathgrid->mPoints[start],pathgrid->mPoints[goal]); + + std::list openset; + std::list closedset; + openset.push_back(start); + + int current = -1; + + while(!openset.empty()) + { + current = openset.front(); + openset.pop_front(); + + if(current == goal) break; + + closedset.push_back(current); + + for(int j = 0;jmPoints[dest],pathgrid->mPoints[goal]); + if(!isInOpenSet) + { + std::list::iterator it = openset.begin(); + for(it = openset.begin();it!= openset.end();it++) + { + if(g_score[*it]>g_score[dest]) + break; + } + openset.insert(it,dest); + } + } + } + } + + } + return reconstructPath(graph,pathgrid,current,xCell,yCell); + + } + +} + namespace MWMechanics { PathFinder::PathFinder() @@ -183,9 +289,9 @@ namespace MWMechanics if(startNode != -1 && endNode != -1) { - if(!mIsGraphConstructed) buildPathgridGraph(pathGrid, xCell, yCell); + //if(!mIsGraphConstructed) buildPathgridGraph(pathGrid, xCell, yCell); - mPath = findPath(startNode, endNode, mGraph); + mPath = buildPath2(pathGrid,startNode,endNode,xCell,yCell);//findPath(startNode, endNode, mGraph); if(!mPath.empty()) { From 764011dd1b8a5856fc1a83a892d2fd4754f656e7 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 26 Jan 2014 21:53:55 +0100 Subject: [PATCH 15/17] clean up --- apps/openmw/mwmechanics/pathfinding.cpp | 201 +++++++++++++----------- apps/openmw/mwmechanics/pathfinding.hpp | 29 +++- 2 files changed, 129 insertions(+), 101 deletions(-) diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 1b42b11a4..dcf47ca33 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -5,30 +5,10 @@ #include "OgreMath.h" -#include #include namespace { - struct found_path {}; - - typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, - boost::property, boost::property > - PathGridGraph; - typedef boost::property_map::type WeightMap; - typedef PathGridGraph::vertex_descriptor PointID; - typedef PathGridGraph::edge_descriptor PointConnectionID; - - class goalVisited : public boost::default_dijkstra_visitor - { - public: - goalVisited(PointID goal) {mGoal = goal;}; - void examine_vertex(PointID u, const PathGridGraph g) {if(u == mGoal) throw found_path();}; - - private: - PointID mGoal; - }; - float distanceZCorrected(ESM::Pathgrid::Point point, float x, float y, float z) { x -= point.mX; @@ -80,74 +60,7 @@ namespace return closestIndex; } - PathGridGraph buildGraph(const ESM::Pathgrid* pathgrid, float xCell = 0, float yCell = 0) - { - PathGridGraph graph; - - for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++) - { - PointID pID = boost::add_vertex(graph); - graph[pID].mX = pathgrid->mPoints[counter].mX + xCell; - graph[pID].mY = pathgrid->mPoints[counter].mY + yCell; - graph[pID].mZ = pathgrid->mPoints[counter].mZ; - } - - for(unsigned int counterTwo = 0; counterTwo < pathgrid->mEdges.size(); counterTwo++) - { - PointID u = pathgrid->mEdges[counterTwo].mV0; - PointID v = pathgrid->mEdges[counterTwo].mV1; - - PointConnectionID edge; - bool done; - boost::tie(edge, done) = boost::add_edge(u, v, graph); - WeightMap weightmap = boost::get(boost::edge_weight, graph); - weightmap[edge] = distance(graph[u], graph[v]); - } - - return graph; - } - - std::list findPath(PointID start, PointID end,const PathGridGraph& graph) - { - std::vector p(boost::num_vertices(graph)); - std::vector d(boost::num_vertices(graph)); - std::list shortest_path; - - try - { - boost::dijkstra_shortest_paths(graph, start, - boost::predecessor_map(&p[0]).distance_map(&d[0]).visitor(goalVisited(end))); - } - - catch(found_path& fg) - { - for(PointID v = end; ; v = p[v]) - { - shortest_path.push_front(graph[v]); - if(p[v] == v) - break; - } - } - - return shortest_path; - } -} - -namespace -{ - struct Edge - { - int destination; - float cost; - }; - struct Node - { - int label; - std::vector edges; - int parent;//used in pathfinding - }; - - std::list reconstructPath(const std::vector& graph,const ESM::Pathgrid* pathgrid, int lastNode,float xCell, float yCell) + /*std::list reconstructPath(const std::vector& graph,const ESM::Pathgrid* pathgrid, int lastNode,float xCell, float yCell) { std::list path; while(graph[lastNode].parent != -1) @@ -160,9 +73,11 @@ namespace lastNode = graph[lastNode].parent; } return path; - } + }*/ - std::list buildPath2(const ESM::Pathgrid* pathgrid,int start,int goal,float xCell = 0, float yCell = 0) + + + /*std::list buildPath2(const ESM::Pathgrid* pathgrid,int start,int goal,float xCell = 0, float yCell = 0) { std::vector graph; for(unsigned int i = 0; i < pathgrid->mPoints.size(); i++) @@ -234,7 +149,7 @@ namespace } return reconstructPath(graph,pathgrid,current,xCell,yCell); - } + }*/ } @@ -252,12 +167,108 @@ namespace MWMechanics mIsPathConstructed = false; } - void PathFinder::buildPathgridGraph(const ESM::Pathgrid* pathGrid,float xCell, float yCell) + void PathFinder::buildPathgridGraph(const ESM::Pathgrid* pathGrid) { - mGraph = buildGraph(pathGrid, xCell, yCell); + mGraph.clear(); + mGScore.resize(pathGrid->mPoints.size(),-1); + mFScore.resize(pathGrid->mPoints.size(),-1); + Node defaultNode; + defaultNode.label = -1; + defaultNode.parent = -1; + mGraph.resize(pathGrid->mPoints.size(),defaultNode); + for(unsigned int i = 0; i < pathGrid->mPoints.size(); i++) + { + Node node; + node.label = i; + node.parent = -1; + mGraph[i] = node; + } + for(unsigned int i = 0; i < pathGrid->mEdges.size(); i++) + { + Edge edge; + edge.destination = pathGrid->mEdges[i].mV1; + edge.cost = distance(pathGrid->mPoints[pathGrid->mEdges[i].mV0],pathGrid->mPoints[pathGrid->mEdges[i].mV1]); + mGraph[pathGrid->mEdges[i].mV0].edges.push_back(edge); + edge.destination = pathGrid->mEdges[i].mV0; + mGraph[pathGrid->mEdges[i].mV1].edges.push_back(edge); + } mIsGraphConstructed = true; } + void PathFinder::cleanUpAStar() + { + for(int i=0;i PathFinder::aStarSearch(const ESM::Pathgrid* pathGrid,int start,int goal,float xCell, float yCell) + { + cleanUpAStar(); + mGScore[start] = 0; + mFScore[start] = distance(pathGrid->mPoints[start],pathGrid->mPoints[goal]); + + std::list openset; + std::list closedset; + openset.push_back(start); + + int current = -1; + + while(!openset.empty()) + { + current = openset.front(); + openset.pop_front(); + + if(current == goal) break; + + closedset.push_back(current); + + for(int j = 0;jmPoints[dest],pathGrid->mPoints[goal]); + if(!isInOpenSet) + { + std::list::iterator it = openset.begin(); + for(it = openset.begin();it!= openset.end();it++) + { + if(mGScore[*it]>mGScore[dest]) + break; + } + openset.insert(it,dest); + } + } + } + } + + } + + std::list path; + while(mGraph[current].parent != -1) + { + //std::cout << "not empty" << xCell; + ESM::Pathgrid::Point pt = pathGrid->mPoints[current]; + pt.mX += xCell; + pt.mY += yCell; + path.push_front(pt); + current = mGraph[current].parent; + } + return path; + } + void PathFinder::buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, const MWWorld::CellStore* cell, bool allowShortcuts) { @@ -289,9 +300,9 @@ namespace MWMechanics if(startNode != -1 && endNode != -1) { - //if(!mIsGraphConstructed) buildPathgridGraph(pathGrid, xCell, yCell); + if(!mIsGraphConstructed) buildPathgridGraph(pathGrid); - mPath = buildPath2(pathGrid,startNode,endNode,xCell,yCell);//findPath(startNode, endNode, mGraph); + mPath = aStarSearch(pathGrid,startNode,endNode,xCell,yCell);//findPath(startNode, endNode, mGraph); if(!mPath.empty()) { diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 687031491..5bc9d7493 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -19,7 +19,7 @@ namespace MWMechanics void clearPath(); - void buildPathgridGraph(const ESM::Pathgrid* pathGrid,float xCell = 0, float yCell = 0); + void buildPathgridGraph(const ESM::Pathgrid* pathGrid); void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, const MWWorld::CellStore* cell, bool allowShortcuts = true); @@ -51,13 +51,30 @@ namespace MWMechanics } private: - std::list mPath; + + struct Edge + { + int destination; + float cost; + }; + struct Node + { + int label; + std::vector edges; + int parent;//used in pathfinding + }; + + std::vector mGScore; + std::vector mFScore; + + std::list aStarSearch(const ESM::Pathgrid* pathGrid,int start,int goal,float xCell = 0, float yCell = 0); + void cleanUpAStar(); + + std::vector mGraph; bool mIsPathConstructed; - typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, - boost::property, boost::property > - PathGridGraph; - PathGridGraph mGraph; + + std::list mPath; bool mIsGraphConstructed; const MWWorld::CellStore* mCell; }; From f5d589388ccbb6ec02b22dd6d9d4a8a41627a65e Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 26 Jan 2014 22:06:54 +0100 Subject: [PATCH 16/17] bug fix --- apps/openmw/mwmechanics/pathfinding.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index dcf47ca33..668b4f2b1 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -266,6 +266,15 @@ namespace MWMechanics path.push_front(pt); current = mGraph[current].parent; } + + if(path.empty()) + { + ESM::Pathgrid::Point pt = pathGrid->mPoints[goal]; + pt.mX += xCell; + pt.mY += yCell; + path.push_front(pt); + } + return path; } From 846276f747c7ff62712e8224ba5c442b2b508c21 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 27 Jan 2014 15:14:24 +0100 Subject: [PATCH 17/17] clean up --- apps/openmw/mwmechanics/actors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ed3c343a5..38b11c0ac 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -927,7 +927,7 @@ namespace MWMechanics const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); - if(stats.getAiSequence().getTypeId() == 3) + if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow) { MWMechanics::AiFollow* package = static_cast(stats.getAiSequence().getActivePackage()); if(package->getFollowedActor() == actor.getCellRef().mRefID)