Unverified Commit d6c67466 authored by Bret Curtis's avatar Bret Curtis Committed by GitHub

Merge pull request #1633 from elsid/pathfinder_detour

Use recastnavigation for pathfinding (#2229)
parents 854d85cb 49d81241
Pipeline #34872801 passed with stage
#!/bin/sh #!/bin/sh -e
sudo ln -s /usr/bin/clang-3.6 /usr/local/bin/clang sudo ln -s /usr/bin/clang-3.6 /usr/local/bin/clang
sudo ln -s /usr/bin/clang++-3.6 /usr/local/bin/clang++ sudo ln -s /usr/bin/clang++-3.6 /usr/local/bin/clang++
#!/bin/sh #!/bin/sh -e
brew update brew update
......
...@@ -5,6 +5,9 @@ free -m ...@@ -5,6 +5,9 @@ free -m
env GENERATOR='Unix Makefiles' CONFIGURATION=Release CI/build_googletest.sh env GENERATOR='Unix Makefiles' CONFIGURATION=Release CI/build_googletest.sh
GOOGLETEST_DIR="$(pwd)/googletest/build" GOOGLETEST_DIR="$(pwd)/googletest/build"
env GENERATOR='Unix Makefiles' CONFIGURATION=Release CI/build_recastnavigation.sh
RECASTNAVIGATION_DIR="$(pwd)/recastnavigation/build"
mkdir build mkdir build
cd build cd build
export CODE_COVERAGE=1 export CODE_COVERAGE=1
...@@ -18,4 +21,5 @@ ${ANALYZE}cmake \ ...@@ -18,4 +21,5 @@ ${ANALYZE}cmake \
-DUSE_SYSTEM_TINYXML=TRUE \ -DUSE_SYSTEM_TINYXML=TRUE \
-DGTEST_ROOT="${GOOGLETEST_DIR}" \ -DGTEST_ROOT="${GOOGLETEST_DIR}" \
-DGMOCK_ROOT="${GOOGLETEST_DIR}" \ -DGMOCK_ROOT="${GOOGLETEST_DIR}" \
-DRecastNavigation_ROOT="${RECASTNAVIGATION_DIR}" \
.. ..
...@@ -304,6 +304,10 @@ if ! [ -z $UNITY_BUILD ]; then ...@@ -304,6 +304,10 @@ if ! [ -z $UNITY_BUILD ]; then
add_cmake_opts "-DOPENMW_UNITY_BUILD=True" add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
fi fi
if [ ${BITS} -eq 64 ]; then
GENERATOR="${GENERATOR} Win64"
fi
echo echo
echo "===================================" echo "==================================="
echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}" echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}"
...@@ -449,7 +453,7 @@ fi ...@@ -449,7 +453,7 @@ fi
else else
LIB_SUFFIX="0" LIB_SUFFIX="0"
fi fi
add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \
-DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.${LIB_SUFFIX}" -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.${LIB_SUFFIX}"
add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" add_cmake_opts -DBoost_COMPILER="-${TOOLSET}"
...@@ -644,6 +648,13 @@ printf "SDL 2.0.7... " ...@@ -644,6 +648,13 @@ printf "SDL 2.0.7... "
echo Done. echo Done.
} }
echo echo
# recastnavigation
printf 'recastnavigation...'
{
env GENERATOR="${GENERATOR}" CONFIGURATION="${CONFIGURATION}" ${DEPS_INSTALL}/../../CI/build_recastnavigation.sh
add_cmake_opts -DRecastNavigation_ROOT="$(pwd)/recastnavigation/build"
}
echo
cd $DEPS_INSTALL/.. cd $DEPS_INSTALL/..
echo echo
echo "Setting up OpenMW build..." echo "Setting up OpenMW build..."
......
#!/bin/sh #!/bin/sh -e
export CXX=clang++ export CXX=clang++
export CC=clang export CC=clang
env GENERATOR='Unix Makefiles' CONFIGURATION=Release CI/build_recastnavigation.sh
RECASTNAVIGATION_DIR="$(pwd)/recastnavigation/build"
DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps" DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps"
QT_PATH=`brew --prefix qt` QT_PATH=`brew --prefix qt`
mkdir build mkdir build
...@@ -17,5 +20,6 @@ cmake \ ...@@ -17,5 +20,6 @@ cmake \
-D DESIRED_QT_VERSION=5 \ -D DESIRED_QT_VERSION=5 \
-D BUILD_ESMTOOL=FALSE \ -D BUILD_ESMTOOL=FALSE \
-D BUILD_MYGUI_PLUGIN=FALSE \ -D BUILD_MYGUI_PLUGIN=FALSE \
-D RecastNavigation_ROOT="${RECASTNAVIGATION_DIR}" \
-G"Unix Makefiles" \ -G"Unix Makefiles" \
.. ..
#!/bin/sh -e
git clone https://github.com/recastnavigation/recastnavigation.git
cd recastnavigation
mkdir build
cd build
cmake \
-DCMAKE_BUILD_TYPE="${CONFIGURATION}" \
-DRECASTNAVIGATION_DEMO=OFF \
-DRECASTNAVIGATION_TESTS=OFF \
-DRECASTNAVIGATION_EXAMPLES=OFF \
-DRECASTNAVIGATION_STATIC=ON \
-DCMAKE_INSTALL_PREFIX=. \
-G "${GENERATOR}" \
..
cmake --build . --config "${CONFIGURATION}"
cmake --build . --target install --config "${CONFIGURATION}"
...@@ -21,7 +21,7 @@ add_openmw_dir (mwrender ...@@ -21,7 +21,7 @@ add_openmw_dir (mwrender
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
renderbin actoranimation landmanager renderbin actoranimation landmanager navmesh actorspaths
) )
add_openmw_dir (mwinput add_openmw_dir (mwinput
...@@ -70,7 +70,7 @@ add_openmw_dir (mwworld ...@@ -70,7 +70,7 @@ add_openmw_dir (mwworld
) )
add_openmw_dir (mwphysics add_openmw_dir (mwphysics
physicssystem trace collisiontype actor convert physicssystem trace collisiontype actor convert object heightfield
) )
add_openmw_dir (mwclass add_openmw_dir (mwclass
...@@ -117,6 +117,10 @@ include_directories( ...@@ -117,6 +117,10 @@ include_directories(
${FFmpeg_INCLUDE_DIRS} ${FFmpeg_INCLUDE_DIRS}
) )
find_package(RecastNavigation COMPONENTS DebugUtils Detour Recast REQUIRED)
include_directories(SYSTEM ${RecastNavigation_INCLUDE_DIRS})
target_link_libraries(openmw target_link_libraries(openmw
${OSG_LIBRARIES} ${OSG_LIBRARIES}
${OPENTHREADS_LIBRARIES} ${OPENTHREADS_LIBRARIES}
...@@ -133,6 +137,7 @@ target_link_libraries(openmw ...@@ -133,6 +137,7 @@ target_link_libraries(openmw
${FFmpeg_LIBRARIES} ${FFmpeg_LIBRARIES}
${MyGUI_LIBRARIES} ${MyGUI_LIBRARIES}
${SDL2_LIBRARY} ${SDL2_LIBRARY}
${RecastNavigation_LIBRARIES}
"osg-ffmpeg-videoplayer" "osg-ffmpeg-videoplayer"
"oics" "oics"
components components
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <set> #include <set>
#include <deque>
#include <components/esm/cellid.hpp> #include <components/esm/cellid.hpp>
...@@ -54,6 +55,11 @@ namespace MWMechanics ...@@ -54,6 +55,11 @@ namespace MWMechanics
struct Movement; struct Movement;
} }
namespace DetourNavigator
{
class Navigator;
}
namespace MWWorld namespace MWWorld
{ {
class CellStore; class CellStore;
...@@ -595,6 +601,13 @@ namespace MWBase ...@@ -595,6 +601,13 @@ namespace MWBase
/// Preload VFX associated with this effect list /// Preload VFX associated with this effect list
virtual void preloadEffects(const ESM::EffectList* effectList) = 0; virtual void preloadEffects(const ESM::EffectList* effectList) = 0;
virtual DetourNavigator::Navigator* getNavigator() const = 0;
virtual void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const = 0;
virtual void setNavMeshNumberToRender(const std::size_t value) = 0;
}; };
} }
......
...@@ -36,7 +36,7 @@ namespace MWMechanics ...@@ -36,7 +36,7 @@ namespace MWMechanics
return true; //Target doesn't exist return true; //Target doesn't exist
//Set the target destination for the actor //Set the target destination for the actor
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; const auto dest = target.getRefData().getPosition().asVec3();
if (pathTo(actor, dest, duration, MWBase::Environment::get().getWorld()->getMaxActivationDistance())) //Stop when you get in activation range if (pathTo(actor, dest, duration, MWBase::Environment::get().getWorld()->getMaxActivationDistance())) //Stop when you get in activation range
{ {
......
...@@ -37,7 +37,7 @@ bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::Charac ...@@ -37,7 +37,7 @@ bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::Charac
if (!target) if (!target)
return true; return true;
if (!mManual && !pathTo(actor, target.getRefData().getPosition().pos, duration, mDistance)) if (!mManual && !pathTo(actor, target.getRefData().getPosition().asVec3(), duration, mDistance))
{ {
return false; return false;
} }
......
...@@ -128,7 +128,7 @@ namespace MWMechanics ...@@ -128,7 +128,7 @@ namespace MWMechanics
float targetReachedTolerance = 0.0f; float targetReachedTolerance = 0.0f;
if (storage.mLOS) if (storage.mLOS)
targetReachedTolerance = storage.mAttackRange; targetReachedTolerance = storage.mAttackRange;
bool is_target_reached = pathTo(actor, target.getRefData().getPosition().pos, duration, targetReachedTolerance); const bool is_target_reached = pathTo(actor, target.getRefData().getPosition().asVec3(), duration, targetReachedTolerance);
if (is_target_reached) storage.mReadyToAttack = true; if (is_target_reached) storage.mReadyToAttack = true;
} }
...@@ -307,7 +307,7 @@ namespace MWMechanics ...@@ -307,7 +307,7 @@ namespace MWMechanics
osg::Vec3f localPos = actor.getRefData().getPosition().asVec3(); osg::Vec3f localPos = actor.getRefData().getPosition().asVec3();
coords.toLocal(localPos); coords.toLocal(localPos);
int closestPointIndex = PathFinder::GetClosestPoint(pathgrid, localPos); int closestPointIndex = PathFinder::getClosestPoint(pathgrid, localPos);
for (int i = 0; i < static_cast<int>(pathgrid->mPoints.size()); i++) for (int i = 0; i < static_cast<int>(pathgrid->mPoints.size()); i++)
{ {
if (i != closestPointIndex && getPathGridGraph(storage.mCell).isPointConnected(closestPointIndex, i)) if (i != closestPointIndex && getPathGridGraph(storage.mCell).isPointConnected(closestPointIndex, i))
...@@ -359,7 +359,7 @@ namespace MWMechanics ...@@ -359,7 +359,7 @@ namespace MWMechanics
float dist = (actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length(); float dist = (actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length();
if ((dist > fFleeDistance && !storage.mLOS) if ((dist > fFleeDistance && !storage.mLOS)
|| pathTo(actor, storage.mFleeDest, duration)) || pathTo(actor, PathFinder::makeOsgVec3(storage.mFleeDest), duration))
{ {
state = AiCombatStorage::FleeState_Idle; state = AiCombatStorage::FleeState_Idle;
} }
......
...@@ -100,7 +100,7 @@ namespace MWMechanics ...@@ -100,7 +100,7 @@ namespace MWMechanics
point.mAutogenerated = 0; point.mAutogenerated = 0;
point.mConnectionNum = 0; point.mConnectionNum = 0;
point.mUnknown = 0; point.mUnknown = 0;
if (pathTo(actor,point,duration)) //Returns true on path complete if (pathTo(actor, osg::Vec3f(mX, mY, mZ), duration)) //Returns true on path complete
{ {
mRemainingDuration = mDuration; mRemainingDuration = mDuration;
return true; return true;
......
...@@ -163,7 +163,7 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte ...@@ -163,7 +163,7 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte
} }
//Set the target destination from the actor //Set the target destination from the actor
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; const auto dest = target.getRefData().getPosition().asVec3();
short baseFollowDistance = followDistance; short baseFollowDistance = followDistance;
short threshold = 30; // to avoid constant switching between moving/stopping short threshold = 30; // to avoid constant switching between moving/stopping
...@@ -196,7 +196,7 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte ...@@ -196,7 +196,7 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte
if (storage.mMoving) if (storage.mMoving)
{ {
//Check if you're far away //Check if you're far away
float dist = distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]); float dist = distance(dest, pos.asVec3());
if (dist > 450) if (dist > 450)
actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run
......
This diff is collapsed.
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "obstacle.hpp" #include "obstacle.hpp"
#include "aistate.hpp" #include "aistate.hpp"
#include <boost/optional.hpp>
namespace MWWorld namespace MWWorld
{ {
class Ptr; class Ptr;
...@@ -105,29 +107,35 @@ namespace MWMechanics ...@@ -105,29 +107,35 @@ namespace MWMechanics
bool isTargetMagicallyHidden(const MWWorld::Ptr& target); bool isTargetMagicallyHidden(const MWWorld::Ptr& target);
/// Return if actor's rotation speed is sufficient to rotate to the destination pathpoint on the run. Otherwise actor should rotate while standing. /// Return if actor's rotation speed is sufficient to rotate to the destination pathpoint on the run. Otherwise actor should rotate while standing.
static bool isReachableRotatingOnTheRun(const MWWorld::Ptr& actor, const ESM::Pathgrid::Point& dest); static bool isReachableRotatingOnTheRun(const MWWorld::Ptr& actor, const osg::Vec3f& dest);
protected: protected:
/// Handles path building and shortcutting with obstacles avoiding /// Handles path building and shortcutting with obstacles avoiding
/** \return If the actor has arrived at his destination **/ /** \return If the actor has arrived at his destination **/
bool pathTo(const MWWorld::Ptr& actor, const ESM::Pathgrid::Point& dest, float duration, float destTolerance = 0.0f); bool pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& dest, float duration, float destTolerance = 0.0f);
/// Check if there aren't any obstacles along the path to make shortcut possible /// Check if there aren't any obstacles along the path to make shortcut possible
/// If a shortcut is possible then path will be cleared and filled with the destination point. /// If a shortcut is possible then path will be cleared and filled with the destination point.
/// \param destInLOS If not nullptr function will return ray cast check result /// \param destInLOS If not nullptr function will return ray cast check result
/// \return If can shortcut the path /// \return If can shortcut the path
bool shortcutPath(const ESM::Pathgrid::Point& startPoint, const ESM::Pathgrid::Point& endPoint, const MWWorld::Ptr& actor, bool *destInLOS, bool isPathClear); bool shortcutPath(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const MWWorld::Ptr& actor,
bool *destInLOS, bool isPathClear);
/// Check if the way to the destination is clear, taking into account actor speed /// Check if the way to the destination is clear, taking into account actor speed
bool checkWayIsClearForActor(const ESM::Pathgrid::Point& startPoint, const ESM::Pathgrid::Point& endPoint, const MWWorld::Ptr& actor); bool checkWayIsClearForActor(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const MWWorld::Ptr& actor);
bool doesPathNeedRecalc(const osg::Vec3f& newDest, const MWWorld::CellStore* currentCell);
virtual bool doesPathNeedRecalc(const ESM::Pathgrid::Point& newDest, const MWWorld::CellStore* currentCell); void evadeObstacles(const MWWorld::Ptr& actor);
void evadeObstacles(const MWWorld::Ptr& actor, float duration, const ESM::Position& pos);
void openDoors(const MWWorld::Ptr& actor); void openDoors(const MWWorld::Ptr& actor);
const PathgridGraph& getPathGridGraph(const MWWorld::CellStore* cell); const PathgridGraph& getPathGridGraph(const MWWorld::CellStore* cell);
DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const;
bool canActorMoveByZAxis(const MWWorld::Ptr& actor) const;
// TODO: all this does not belong here, move into temporary storage // TODO: all this does not belong here, move into temporary storage
PathFinder mPathFinder; PathFinder mPathFinder;
ObstacleCheck mObstacleCheck; ObstacleCheck mObstacleCheck;
...@@ -137,16 +145,14 @@ namespace MWMechanics ...@@ -137,16 +145,14 @@ namespace MWMechanics
std::string mTargetActorRefId; std::string mTargetActorRefId;
mutable int mTargetActorId; mutable int mTargetActorId;
osg::Vec3f mLastActorPos;
short mRotateOnTheRunChecks; // attempts to check rotation to the pathpoint on the run possibility short mRotateOnTheRunChecks; // attempts to check rotation to the pathpoint on the run possibility
bool mIsShortcutting; // if shortcutting at the moment bool mIsShortcutting; // if shortcutting at the moment
bool mShortcutProhibited; // shortcutting may be prohibited after unsuccessful attempt bool mShortcutProhibited; // shortcutting may be prohibited after unsuccessful attempt
ESM::Pathgrid::Point mShortcutFailPos; // position of last shortcut fail osg::Vec3f mShortcutFailPos; // position of last shortcut fail
private: private:
bool isNearInactiveCell(const ESM::Position& actorPos); bool isNearInactiveCell(osg::Vec3f position);
}; };
} }
......
...@@ -49,13 +49,13 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte ...@@ -49,13 +49,13 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
//Set the target desition from the actor //Set the target desition from the actor
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; const auto dest = target.getRefData().getPosition().asVec3();
ESM::Position aPos = actor.getRefData().getPosition(); ESM::Position aPos = actor.getRefData().getPosition();
float pathTolerance = 100.0; float pathTolerance = 100.0;
if (pathTo(actor, dest, duration, pathTolerance) && if (pathTo(actor, dest, duration, pathTolerance) &&
std::abs(dest.mZ - aPos.pos[2]) < pathTolerance) // check the true distance in case the target is far away in Z-direction std::abs(dest.z() - aPos.pos[2]) < pathTolerance) // check the true distance in case the target is far away in Z-direction
{ {
target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached
return true; return true;
......
...@@ -58,8 +58,7 @@ namespace MWMechanics ...@@ -58,8 +58,7 @@ namespace MWMechanics
// Unfortunately, with vanilla assets destination is sometimes blocked by other actor. // Unfortunately, with vanilla assets destination is sometimes blocked by other actor.
// If we got close to target, check for actors nearby. If they are, finish AI package. // If we got close to target, check for actors nearby. If they are, finish AI package.
int destinationTolerance = 64; int destinationTolerance = 64;
ESM::Pathgrid::Point dest(static_cast<int>(mX), static_cast<int>(mY), static_cast<int>(mZ)); if (distance(pos.asVec3(), osg::Vec3f(mX, mY, mZ)) <= destinationTolerance)
if (distance(pos.pos, dest) <= destinationTolerance)
{ {
std::vector<MWWorld::Ptr> targetActors; std::vector<MWWorld::Ptr> targetActors;
std::pair<MWWorld::Ptr, osg::Vec3f> result = MWBase::Environment::get().getWorld()->getHitContact(actor, destinationTolerance, targetActors); std::pair<MWWorld::Ptr, osg::Vec3f> result = MWBase::Environment::get().getWorld()->getHitContact(actor, destinationTolerance, targetActors);
...@@ -71,7 +70,7 @@ namespace MWMechanics ...@@ -71,7 +70,7 @@ namespace MWMechanics
} }
} }
if (pathTo(actor, dest, duration)) if (pathTo(actor, osg::Vec3f(mX, mY, mZ), duration))
{ {
actor.getClass().getMovementSettings(actor).mPosition[1] = 0; actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
return true; return true;
......
This diff is collapsed.
...@@ -137,15 +137,15 @@ namespace MWMechanics ...@@ -137,15 +137,15 @@ namespace MWMechanics
short unsigned getRandomIdle(); short unsigned getRandomIdle();
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos); void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
void playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage); void playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage);
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration, ESM::Position& pos); void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
void playIdleDialogueRandomly(const MWWorld::Ptr& actor); void playIdleDialogueRandomly(const MWWorld::Ptr& actor);
void turnActorToFacePlayer(const osg::Vec3f& actorPosition, const osg::Vec3f& playerPosition, AiWanderStorage& storage); void turnActorToFacePlayer(const osg::Vec3f& actorPosition, const osg::Vec3f& playerPosition, AiWanderStorage& storage);
void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos); void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage); void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos); void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage); void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos, float duration); const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos);
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage); bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance); void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination); bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination);
...@@ -164,6 +164,7 @@ namespace MWMechanics ...@@ -164,6 +164,7 @@ namespace MWMechanics
bool mHasDestination; bool mHasDestination;
osg::Vec3f mDestination; osg::Vec3f mDestination;
bool mUsePathgrid;
void getNeighbouringNodes(ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points); void getNeighbouringNodes(ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points);
......
...@@ -33,11 +33,12 @@ namespace MWMechanics ...@@ -33,11 +33,12 @@ namespace MWMechanics
point.y() -= static_cast<float>(mCellY); point.y() -= static_cast<float>(mCellY);
} }
osg::Vec3f CoordinateConverter::toLocalVec3(const ESM::Pathgrid::Point& point) osg::Vec3f CoordinateConverter::toLocalVec3(const osg::Vec3f& point)
{ {
return osg::Vec3f( return osg::Vec3f(
static_cast<float>(point.mX - mCellX), point.x() - static_cast<float>(mCellX),
static_cast<float>(point.mY - mCellY), point.y() - static_cast<float>(mCellY),
static_cast<float>(point.mZ)); point.z()
);
} }
} }
...@@ -26,7 +26,7 @@ namespace MWMechanics ...@@ -26,7 +26,7 @@ namespace MWMechanics
/// in-place conversion from world to local /// in-place conversion from world to local
void toLocal(osg::Vec3f& point); void toLocal(osg::Vec3f& point);
osg::Vec3f toLocalVec3(const ESM::Pathgrid::Point& point); osg::Vec3f toLocalVec3(const osg::Vec3f& point);
private: private:
int mCellX; int mCellX;
......
...@@ -96,11 +96,6 @@ namespace MWMechanics ...@@ -96,11 +96,6 @@ namespace MWMechanics
mEvadeDuration = 0; mEvadeDuration = 0;
} }
bool ObstacleCheck::isNormalState() const
{
return mWalkState == State_Norm;
}
bool ObstacleCheck::isEvading() const bool ObstacleCheck::isEvading() const
{ {
return mWalkState == State_Evade; return mWalkState == State_Evade;
...@@ -128,7 +123,7 @@ namespace MWMechanics ...@@ -128,7 +123,7 @@ namespace MWMechanics
* u = how long to move sideways * u = how long to move sideways
* *
*/ */
bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration, float scaleMinimumDistance) void ObstacleCheck::update(const MWWorld::Ptr& actor, float duration, float scaleMinimumDistance)
{ {
const MWWorld::Class& cls = actor.getClass(); const MWWorld::Class& cls = actor.getClass();
ESM::Position pos = actor.getRefData().getPosition(); ESM::Position pos = actor.getRefData().getPosition();
...@@ -180,9 +175,7 @@ namespace MWMechanics ...@@ -180,9 +175,7 @@ namespace MWMechanics
case State_Evade: case State_Evade:
{ {
mEvadeDuration += duration; mEvadeDuration += duration;
if(mEvadeDuration < DURATION_TO_EVADE) if(mEvadeDuration >= DURATION_TO_EVADE)
return true;
else
{ {
// tried to evade, assume all is ok and start again // tried to evade, assume all is ok and start again
mWalkState = State_Norm; mWalkState = State_Norm;
...@@ -191,10 +184,9 @@ namespace MWMechanics ...@@ -191,10 +184,9 @@ namespace MWMechanics
} }
/* NO DEFAULT CASE */ /* NO DEFAULT CASE */
} }
return false; // no obstacles to evade (yet)
} }
void ObstacleCheck::takeEvasiveAction(MWMechanics::Movement& actorMovement) void ObstacleCheck::takeEvasiveAction(MWMechanics::Movement& actorMovement) const
{ {
actorMovement.mPosition[0] = evadeDirections[mEvadeDirectionIndex][0]; actorMovement.mPosition[0] = evadeDirections[mEvadeDirectionIndex][0];
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][1]; actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][