From 3780503275d2e3380ff10c2e91231e25402db4a0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Apr 2014 07:07:03 +0200 Subject: [PATCH 1/3] Removed quicksave/quickload message boxes, now that the same text is shown in the progress bar --- apps/openmw/mwstate/statemanagerimp.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 635ad1ff4..33f2dce7c 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -253,8 +253,6 @@ void MWState::StateManager::quickSave (std::string name) slot = &*it; } - MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage4}"); - saveGame(name, slot); } @@ -368,10 +366,7 @@ void MWState::StateManager::quickLoad() { if (Character* mCurrentCharacter = getCurrentCharacter (false)) if (const MWState::Slot* slot = &*mCurrentCharacter->begin()) //Get newest save - { - //MWBase::Environment::get().getWindowManager()->messageBox("#{sLoadingMessage14}"); //it overlaps loadGame (mCurrentCharacter, slot); - } } void MWState::StateManager::deleteGame(const MWState::Character *character, const MWState::Slot *slot) From 9b36a138217389315f8be4c7b85878f1a4998c68 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Apr 2014 09:09:51 +0200 Subject: [PATCH 2/3] Feature #1289: NPCs return to default position Make stationary NPCs return to their previous position once combat/crime AI finishes. --- apps/openmw/mwmechanics/actors.cpp | 12 ++++---- apps/openmw/mwmechanics/aisequence.cpp | 12 +++++++- apps/openmw/mwmechanics/aisequence.hpp | 2 +- apps/openmw/mwmechanics/aiwander.cpp | 40 +++++++++++++++++++++++++- apps/openmw/mwmechanics/aiwander.hpp | 11 +++++++ apps/openmw/mwscript/aiextensions.cpp | 16 +++++------ 6 files changed, 76 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 2de5e268f..b87bc453c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -206,7 +206,7 @@ namespace MWMechanics if (LOS) { - creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr())); + creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()), ptr); creatureStats.setHostile(true); } } @@ -537,7 +537,7 @@ namespace MWMechanics // TODO: Add AI to follow player and fight for him AiFollow package(ptr.getRefData().getHandle()); - MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package); + MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package, ptr); // TODO: VFX_SummonStart, VFX_SummonEnd creatureStats.mSummonedCreatures.insert(std::make_pair(it->first, MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos).getRefData().getHandle())); @@ -732,7 +732,7 @@ namespace MWMechanics && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiCombat(player)); + creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.setHostile(true); npcStats.setCrimeId( MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() ); } @@ -761,9 +761,9 @@ namespace MWMechanics else if (!creatureStats.isHostile()) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player))); + creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)), ptr); else - creatureStats.getAiSequence().stack(AiCombat(player)); + creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.setHostile(true); } } @@ -771,7 +771,7 @@ namespace MWMechanics // if I didn't report a crime was I attacked? else if (creatureStats.getAttacked() && !creatureStats.isHostile()) { - creatureStats.getAiSequence().stack(AiCombat(player)); + creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.setHostile(true); } } diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index c67367a6c..2581d52c9 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -116,8 +116,18 @@ void MWMechanics::AiSequence::clear() mPackages.clear(); } -void MWMechanics::AiSequence::stack (const AiPackage& package) +void MWMechanics::AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor) { + if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPersue) + { + // Notify AiWander of our current position so we can return to it after combat finished + for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) + { + if ((*iter)->getTypeId() == AiPackage::TypeIdWander) + static_cast(*iter)->setReturnPosition(Ogre::Vector3(actor.getRefData().getPosition().pos)); + } + } + for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); it++) { if(mPackages.front()->getPriority() <= package.getPriority()) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 07b7c898c..cb1b0de02 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -62,7 +62,7 @@ namespace MWMechanics void clear(); ///< Remove all packages. - void stack (const AiPackage& package); + void stack (const AiPackage& package, const MWWorld::Ptr& actor); ///< Add \a package to the front of the sequence (suspends current package) void queue (const AiPackage& package); diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index ad94be0eb..972c4553d 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -37,6 +37,8 @@ namespace MWMechanics , mRotate(false) , mTargetAngle(0) , mSaidGreeting(false) + , mHasReturnPosition(false) + , mReturnPosition(0,0,0) { for(unsigned short counter = 0; counter < mIdle.size(); counter++) { @@ -330,6 +332,37 @@ namespace MWMechanics if(mDistance && cellChange) mDistance = 0; + // For stationary NPCs, move back to the starting location if another AiPackage moved us elsewhere + if (cellChange) + mHasReturnPosition = false; + if (mDistance == 0 && mHasReturnPosition && Ogre::Vector3(pos.pos).squaredDistance(mReturnPosition) > 20*20) + { + mChooseAction = false; + mIdleNow = false; + + Ogre::Vector3 destNodePos = mReturnPosition; + + ESM::Pathgrid::Point dest; + dest.mX = destNodePos[0]; + dest.mY = destNodePos[1]; + dest.mZ = destNodePos[2]; + + // actor position is already in world co-ordinates + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + // don't take shortcuts for wandering + mPathFinder.buildPath(start, dest, actor.getCell(), false); + + if(mPathFinder.isPathConstructed()) + { + mMoveNow = false; + mWalking = true; + } + } + if(mChooseAction) { mPlayedIdle = 0; @@ -375,7 +408,7 @@ namespace MWMechanics } // Allow interrupting a walking actor to trigger a greeting - if(mIdleNow || (mWalking && !mObstacleCheck.isNormalState())) + if(mIdleNow || (mWalking && !mObstacleCheck.isNormalState() && mDistance)) { // Play a random voice greeting if the player gets too close int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); @@ -586,5 +619,10 @@ namespace MWMechanics else return false; } + + void AiWander::setReturnPosition(const Ogre::Vector3& position) + { + mHasReturnPosition = true; mReturnPosition = position; + } } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index fe14abeb6..a789a372e 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -2,8 +2,11 @@ #define GAME_MWMECHANICS_AIWANDER_H #include "aipackage.hpp" + #include +#include + #include "pathfinding.hpp" #include "obstacle.hpp" @@ -22,6 +25,10 @@ namespace MWMechanics virtual int getTypeId() const; ///< 0: Wander + 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); void playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect); @@ -38,6 +45,10 @@ namespace MWMechanics float mGreetDistanceReset; float mChance; + bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position, + // if we had the actor in the AiWander constructor... + Ogre::Vector3 mReturnPosition; + // Cached current cell location int mCellX; int mCellY; diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index a34c5476c..43da111bf 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -48,7 +48,7 @@ namespace MWScript for (unsigned int i=0; igetPtr(targetID, true) )); + MWMechanics::AiCombat(MWBase::Environment::get().getWorld()->getPtr(targetID, true) ), actor); } }; From 28ef236f0e878523f0c36544136d2516d14764ee Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Apr 2014 11:17:07 +0200 Subject: [PATCH 3/3] Don't allow setting a new return position if there already is one and we haven't reached it yet --- apps/openmw/mwmechanics/aiwander.cpp | 42 +++++++++++++++++----------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 722010686..7120ff5af 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -341,26 +341,29 @@ namespace MWMechanics mChooseAction = false; mIdleNow = false; - Ogre::Vector3 destNodePos = mReturnPosition; + if (!mPathFinder.isPathConstructed()) + { + Ogre::Vector3 destNodePos = mReturnPosition; - ESM::Pathgrid::Point dest; - dest.mX = destNodePos[0]; - dest.mY = destNodePos[1]; - dest.mZ = destNodePos[2]; + ESM::Pathgrid::Point dest; + dest.mX = destNodePos[0]; + dest.mY = destNodePos[1]; + dest.mZ = destNodePos[2]; - // actor position is already in world co-ordinates - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; + // actor position is already in world co-ordinates + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; - // don't take shortcuts for wandering - mPathFinder.buildPath(start, dest, actor.getCell(), false); + // don't take shortcuts for wandering + mPathFinder.buildPath(start, dest, actor.getCell(), false); - if(mPathFinder.isPathConstructed()) - { - mMoveNow = false; - mWalking = true; + if(mPathFinder.isPathConstructed()) + { + mMoveNow = false; + mWalking = true; + } } } @@ -529,6 +532,7 @@ namespace MWMechanics mMoveNow = false; mWalking = false; mChooseAction = true; + mHasReturnPosition = false; } return false; // AiWander package not yet completed @@ -615,7 +619,11 @@ namespace MWMechanics void AiWander::setReturnPosition(const Ogre::Vector3& position) { - mHasReturnPosition = true; mReturnPosition = position; + if (!mHasReturnPosition) + { + mHasReturnPosition = true; + mReturnPosition = position; + } } void AiWander::getRandomIdle()