mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-20 19:39:41 +00:00
Merge branch 'master' into 'AnyOldName3-master-patch-15901'
# Conflicts: # CI/before_script.msvc.sh
This commit is contained in:
commit
09537ed312
17 changed files with 206 additions and 79 deletions
|
@ -1007,6 +1007,9 @@ if [ -z $VERBOSE ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
echo "Script completed successfully."
|
||||
echo "You now have an OpenMW build system at $(unixPathAsWindows "$(pwd)")"
|
||||
|
||||
if [ -n "$ACTIVATE_MSVC" ]; then
|
||||
echo
|
||||
echo "Note: you must manually activate MSVC for the shell in which you want to do the build."
|
||||
|
|
|
@ -507,23 +507,16 @@ namespace MWClass
|
|||
|
||||
float Creature::getSpeed(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||
|
||||
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead())
|
||||
return 0.f;
|
||||
|
||||
const GMST& gmst = getGmst();
|
||||
|
||||
float walkSpeed = gmst.fMinWalkSpeedCreature->mValue.getFloat() + 0.01f * stats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||
* (gmst.fMaxWalkSpeedCreature->mValue.getFloat() - gmst.fMinWalkSpeedCreature->mValue.getFloat());
|
||||
|
||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
||||
|
||||
bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run);
|
||||
|
||||
// The Run speed difference for creatures comes from the animation speed difference (see runStateToWalkState in character.cpp)
|
||||
float runSpeed = walkSpeed;
|
||||
|
||||
float moveSpeed;
|
||||
|
||||
if(getEncumbrance(ptr) > getCapacity(ptr))
|
||||
|
@ -540,19 +533,9 @@ namespace MWClass
|
|||
moveSpeed = flySpeed;
|
||||
}
|
||||
else if(world->isSwimming(ptr))
|
||||
{
|
||||
float swimSpeed = walkSpeed;
|
||||
if(running)
|
||||
swimSpeed = runSpeed;
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
|
||||
swimSpeed *= gmst.fSwimRunBase->mValue.getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
|
||||
gmst.fSwimRunAthleticsMult->mValue.getFloat();
|
||||
moveSpeed = swimSpeed;
|
||||
}
|
||||
else if(running)
|
||||
moveSpeed = runSpeed;
|
||||
moveSpeed = getSwimSpeed(ptr);
|
||||
else
|
||||
moveSpeed = walkSpeed;
|
||||
moveSpeed = getWalkSpeed(ptr);
|
||||
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
||||
moveSpeed *= 0.75f;
|
||||
|
||||
|
@ -889,4 +872,31 @@ namespace MWClass
|
|||
{
|
||||
MWMechanics::setBaseAISetting<ESM::Creature>(id, setting, value);
|
||||
}
|
||||
|
||||
float Creature::getWalkSpeed(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||
const GMST& gmst = getGmst();
|
||||
|
||||
return gmst.fMinWalkSpeedCreature->mValue.getFloat()
|
||||
+ 0.01f * stats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||
* (gmst.fMaxWalkSpeedCreature->mValue.getFloat() - gmst.fMinWalkSpeedCreature->mValue.getFloat());
|
||||
}
|
||||
|
||||
float Creature::getRunSpeed(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return getWalkSpeed(ptr);
|
||||
}
|
||||
|
||||
float Creature::getSwimSpeed(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||
const GMST& gmst = getGmst();
|
||||
const MWMechanics::MagicEffects& mageffects = stats.getMagicEffects();
|
||||
|
||||
return getWalkSpeed(ptr)
|
||||
* (1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude())
|
||||
* (gmst.fSwimRunBase->mValue.getFloat()
|
||||
+ 0.01f * getSkill(ptr, ESM::Skill::Athletics) * gmst.fSwimRunAthleticsMult->mValue.getFloat());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,6 +131,12 @@ namespace MWClass
|
|||
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
|
||||
|
||||
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||
|
||||
float getWalkSpeed(const MWWorld::Ptr& ptr) const final;
|
||||
|
||||
float getRunSpeed(const MWWorld::Ptr& ptr) const final;
|
||||
|
||||
float getSwimSpeed(const MWWorld::Ptr& ptr) const final;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -947,16 +947,6 @@ namespace MWClass
|
|||
bool inair = !world->isOnGround(ptr) && !swimming && !world->isFlying(ptr);
|
||||
running = running && (inair || MWBase::Environment::get().getMechanicsManager()->isRunning(ptr));
|
||||
|
||||
float walkSpeed = gmst.fMinWalkSpeed->mValue.getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
|
||||
(gmst.fMaxWalkSpeed->mValue.getFloat() - gmst.fMinWalkSpeed->mValue.getFloat());
|
||||
walkSpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat()*normalizedEncumbrance;
|
||||
walkSpeed = std::max(0.0f, walkSpeed);
|
||||
if(sneaking)
|
||||
walkSpeed *= gmst.fSneakSpeedMultiplier->mValue.getFloat();
|
||||
|
||||
float runSpeed = walkSpeed*(0.01f * getSkill(ptr, ESM::Skill::Athletics) *
|
||||
gmst.fAthleticsRunBonus->mValue.getFloat() + gmst.fBaseRunMultiplier->mValue.getFloat());
|
||||
|
||||
float moveSpeed;
|
||||
if(getEncumbrance(ptr) > getCapacity(ptr))
|
||||
moveSpeed = 0.0f;
|
||||
|
@ -971,19 +961,11 @@ namespace MWClass
|
|||
moveSpeed = flySpeed;
|
||||
}
|
||||
else if (swimming)
|
||||
{
|
||||
float swimSpeed = walkSpeed;
|
||||
if(running)
|
||||
swimSpeed = runSpeed;
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
|
||||
swimSpeed *= gmst.fSwimRunBase->mValue.getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics)*
|
||||
gmst.fSwimRunAthleticsMult->mValue.getFloat();
|
||||
moveSpeed = swimSpeed;
|
||||
}
|
||||
moveSpeed = getSwimSpeed(ptr);
|
||||
else if (running && !sneaking)
|
||||
moveSpeed = runSpeed;
|
||||
moveSpeed = getRunSpeed(ptr);
|
||||
else
|
||||
moveSpeed = walkSpeed;
|
||||
moveSpeed = getWalkSpeed(ptr);
|
||||
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
||||
moveSpeed *= 0.75f;
|
||||
|
||||
|
@ -1448,4 +1430,56 @@ namespace MWClass
|
|||
{
|
||||
MWMechanics::setBaseAISetting<ESM::NPC>(id, setting, value);
|
||||
}
|
||||
|
||||
float Npc::getWalkSpeed(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
const GMST& gmst = getGmst();
|
||||
const NpcCustomData* npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
|
||||
const bool sneaking = MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr);
|
||||
|
||||
float walkSpeed = gmst.fMinWalkSpeed->mValue.getFloat()
|
||||
+ 0.01f * npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||
* (gmst.fMaxWalkSpeed->mValue.getFloat() - gmst.fMinWalkSpeed->mValue.getFloat());
|
||||
walkSpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat()*normalizedEncumbrance;
|
||||
walkSpeed = std::max(0.0f, walkSpeed);
|
||||
if(sneaking)
|
||||
walkSpeed *= gmst.fSneakSpeedMultiplier->mValue.getFloat();
|
||||
|
||||
return walkSpeed;
|
||||
}
|
||||
|
||||
float Npc::getRunSpeed(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
const GMST& gmst = getGmst();
|
||||
return getWalkSpeed(ptr)
|
||||
* (0.01f * getSkill(ptr, ESM::Skill::Athletics) * gmst.fAthleticsRunBonus->mValue.getFloat()
|
||||
+ gmst.fBaseRunMultiplier->mValue.getFloat());
|
||||
}
|
||||
|
||||
float Npc::getSwimSpeed(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
const GMST& gmst = getGmst();
|
||||
const MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||
const NpcCustomData* npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||
const MWMechanics::MagicEffects& mageffects = npcdata->mNpcStats.getMagicEffects();
|
||||
const bool swimming = world->isSwimming(ptr);
|
||||
const bool inair = !world->isOnGround(ptr) && !swimming && !world->isFlying(ptr);
|
||||
const bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run)
|
||||
&& (inair || MWBase::Environment::get().getMechanicsManager()->isRunning(ptr));
|
||||
|
||||
float swimSpeed;
|
||||
|
||||
if (running)
|
||||
swimSpeed = getRunSpeed(ptr);
|
||||
else
|
||||
swimSpeed = getWalkSpeed(ptr);
|
||||
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
|
||||
swimSpeed *= gmst.fSwimRunBase->mValue.getFloat()
|
||||
+ 0.01f * getSkill(ptr, ESM::Skill::Athletics) * gmst.fSwimRunAthleticsMult->mValue.getFloat();
|
||||
|
||||
return swimSpeed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,6 +166,12 @@ namespace MWClass
|
|||
virtual int getPrimaryFactionRank(const MWWorld::ConstPtr &ptr) const;
|
||||
|
||||
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||
|
||||
float getWalkSpeed(const MWWorld::Ptr& ptr) const final;
|
||||
|
||||
float getRunSpeed(const MWWorld::Ptr& ptr) const final;
|
||||
|
||||
float getSwimSpeed(const MWWorld::Ptr& ptr) const final;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f&
|
|||
{
|
||||
const auto pathfindingHalfExtents = world->getPathfindingHalfExtents(actor);
|
||||
mPathFinder.buildPath(actor, position, dest, actor.getCell(), getPathGridGraph(actor.getCell()),
|
||||
pathfindingHalfExtents, getNavigatorFlags(actor));
|
||||
pathfindingHalfExtents, getNavigatorFlags(actor), getAreaCosts(actor));
|
||||
mRotateOnTheRunChecks = 3;
|
||||
|
||||
// give priority to go directly on target if there is minimal opportunity
|
||||
|
@ -402,3 +402,27 @@ DetourNavigator::Flags MWMechanics::AiPackage::getNavigatorFlags(const MWWorld::
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
DetourNavigator::AreaCosts MWMechanics::AiPackage::getAreaCosts(const MWWorld::Ptr& actor) const
|
||||
{
|
||||
DetourNavigator::AreaCosts costs;
|
||||
const DetourNavigator::Flags flags = getNavigatorFlags(actor);
|
||||
const MWWorld::Class& actorClass = actor.getClass();
|
||||
|
||||
if (flags & DetourNavigator::Flag_swim)
|
||||
costs.mWater = costs.mWater / actorClass.getSwimSpeed(actor);
|
||||
|
||||
if (flags & DetourNavigator::Flag_walk)
|
||||
{
|
||||
float walkCost;
|
||||
if (getTypeId() == TypeIdWander)
|
||||
walkCost = 1.0 / actorClass.getWalkSpeed(actor);
|
||||
else
|
||||
walkCost = 1.0 / actorClass.getRunSpeed(actor);
|
||||
costs.mDoor = costs.mDoor * walkCost;
|
||||
costs.mPathgrid = costs.mPathgrid * walkCost;
|
||||
costs.mGround = costs.mGround * walkCost;
|
||||
}
|
||||
|
||||
return costs;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/detournavigator/areatype.hpp>
|
||||
|
||||
#include "pathfinding.hpp"
|
||||
#include "obstacle.hpp"
|
||||
|
@ -167,6 +168,8 @@ namespace MWMechanics
|
|||
|
||||
DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const;
|
||||
|
||||
DetourNavigator::AreaCosts getAreaCosts(const MWWorld::Ptr& actor) const;
|
||||
|
||||
const TypeId mTypeId;
|
||||
const Options mOptions;
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ namespace MWMechanics
|
|||
{
|
||||
const osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getPathfindingHalfExtents(actor);
|
||||
mPathFinder.buildPath(actor, pos.asVec3(), mDestination, actor.getCell(),
|
||||
getPathGridGraph(actor.getCell()), halfExtents, getNavigatorFlags(actor));
|
||||
getPathGridGraph(actor.getCell()), halfExtents, getNavigatorFlags(actor), getAreaCosts(actor));
|
||||
}
|
||||
|
||||
if (mPathFinder.isPathConstructed())
|
||||
|
@ -337,6 +337,7 @@ namespace MWMechanics
|
|||
const auto halfExtents = world->getPathfindingHalfExtents(actor);
|
||||
const auto navigator = world->getNavigator();
|
||||
const auto navigatorFlags = getNavigatorFlags(actor);
|
||||
const auto areaCosts = getAreaCosts(actor);
|
||||
|
||||
do {
|
||||
// Determine a random location within radius of original position
|
||||
|
@ -365,7 +366,8 @@ namespace MWMechanics
|
|||
if (isWaterCreature || isFlyingCreature)
|
||||
mPathFinder.buildStraightPath(mDestination);
|
||||
else
|
||||
mPathFinder.buildPathByNavMesh(actor, currentPosition, mDestination, halfExtents, navigatorFlags);
|
||||
mPathFinder.buildPathByNavMesh(actor, currentPosition, mDestination, halfExtents, navigatorFlags,
|
||||
areaCosts);
|
||||
|
||||
if (mPathFinder.isPathConstructed())
|
||||
{
|
||||
|
@ -496,7 +498,8 @@ namespace MWMechanics
|
|||
if (mUsePathgrid)
|
||||
{
|
||||
const auto halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
|
||||
mPathFinder.buildPathByNavMeshToNextPoint(actor, halfExtents, getNavigatorFlags(actor));
|
||||
mPathFinder.buildPathByNavMeshToNextPoint(actor, halfExtents, getNavigatorFlags(actor),
|
||||
getAreaCosts(actor));
|
||||
}
|
||||
|
||||
if (mObstacleCheck.isEvading())
|
||||
|
|
|
@ -309,12 +309,13 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
void PathFinder::buildPathByNavMesh(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint,
|
||||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags)
|
||||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||
const DetourNavigator::AreaCosts& areaCosts)
|
||||
{
|
||||
mPath.clear();
|
||||
|
||||
// If it's not possible to build path over navmesh due to disabled navmesh generation fallback to straight path
|
||||
if (!buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, std::back_inserter(mPath)))
|
||||
if (!buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath)))
|
||||
mPath.push_back(endPoint);
|
||||
|
||||
mConstructed = true;
|
||||
|
@ -322,7 +323,7 @@ namespace MWMechanics
|
|||
|
||||
void PathFinder::buildPath(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
|
||||
const MWWorld::CellStore* cell, const PathgridGraph& pathgridGraph, const osg::Vec3f& halfExtents,
|
||||
const DetourNavigator::Flags flags)
|
||||
const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts)
|
||||
{
|
||||
mPath.clear();
|
||||
mCell = cell;
|
||||
|
@ -330,11 +331,11 @@ namespace MWMechanics
|
|||
bool hasNavMesh = false;
|
||||
|
||||
if (!actor.getClass().isPureWaterCreature(actor) && !actor.getClass().isPureFlyingCreature(actor))
|
||||
hasNavMesh = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, std::back_inserter(mPath));
|
||||
hasNavMesh = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath));
|
||||
|
||||
if (hasNavMesh && mPath.empty())
|
||||
buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents,
|
||||
flags | DetourNavigator::Flag_usePathgrid, std::back_inserter(mPath));
|
||||
flags | DetourNavigator::Flag_usePathgrid, areaCosts, std::back_inserter(mPath));
|
||||
|
||||
if (mPath.empty())
|
||||
buildPathByPathgridImpl(startPoint, endPoint, pathgridGraph, std::back_inserter(mPath));
|
||||
|
@ -347,12 +348,12 @@ namespace MWMechanics
|
|||
|
||||
bool PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint,
|
||||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||
std::back_insert_iterator<std::deque<osg::Vec3f>> out)
|
||||
const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator<std::deque<osg::Vec3f>> out)
|
||||
{
|
||||
const auto world = MWBase::Environment::get().getWorld();
|
||||
const auto stepSize = getPathStepSize(actor);
|
||||
const auto navigator = world->getNavigator();
|
||||
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out);
|
||||
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, areaCosts, out);
|
||||
|
||||
if (status == DetourNavigator::Status::NavMeshNotFound)
|
||||
return false;
|
||||
|
@ -369,7 +370,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
||||
const DetourNavigator::Flags flags)
|
||||
const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts)
|
||||
{
|
||||
if (mPath.empty())
|
||||
return;
|
||||
|
@ -383,7 +384,7 @@ namespace MWMechanics
|
|||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||
std::deque<osg::Vec3f> prePath;
|
||||
auto prePathInserter = std::back_inserter(prePath);
|
||||
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags,
|
||||
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags, areaCosts,
|
||||
prePathInserter);
|
||||
|
||||
if (status == DetourNavigator::Status::NavMeshNotFound)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <iterator>
|
||||
|
||||
#include <components/detournavigator/flags.hpp>
|
||||
#include <components/detournavigator/areatype.hpp>
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/esm/loadpgrd.hpp>
|
||||
|
||||
|
@ -90,14 +91,15 @@ namespace MWMechanics
|
|||
const MWWorld::CellStore* cell, const PathgridGraph& pathgridGraph);
|
||||
|
||||
void buildPathByNavMesh(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint,
|
||||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags);
|
||||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||
const DetourNavigator::AreaCosts& areaCosts);
|
||||
|
||||
void buildPath(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
|
||||
const MWWorld::CellStore* cell, const PathgridGraph& pathgridGraph, const osg::Vec3f& halfExtents,
|
||||
const DetourNavigator::Flags flags);
|
||||
const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts);
|
||||
|
||||
void buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
||||
const DetourNavigator::Flags flags);
|
||||
const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts);
|
||||
|
||||
/// Remove front point if exist and within tolerance
|
||||
void update(const osg::Vec3f& position, const float pointTolerance, const float destinationTolerance);
|
||||
|
@ -203,7 +205,7 @@ namespace MWMechanics
|
|||
|
||||
bool buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint,
|
||||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||
std::back_insert_iterator<std::deque<osg::Vec3f>> out);
|
||||
const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator<std::deque<osg::Vec3f>> out);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -521,4 +521,19 @@ namespace MWWorld
|
|||
{
|
||||
throw std::runtime_error ("class does not have creature stats");
|
||||
}
|
||||
|
||||
float Class::getWalkSpeed(const Ptr& /*ptr*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Class::getRunSpeed(const Ptr& /*ptr*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Class::getSwimSpeed(const Ptr& /*ptr*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,6 +362,12 @@ namespace MWWorld
|
|||
virtual osg::Vec4f getEnchantmentColor(const MWWorld::ConstPtr& item) const;
|
||||
|
||||
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||
|
||||
virtual float getWalkSpeed(const Ptr& ptr) const;
|
||||
|
||||
virtual float getRunSpeed(const Ptr& ptr) const;
|
||||
|
||||
virtual float getSwimSpeed(const Ptr& ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace
|
|||
std::deque<osg::Vec3f> mPath;
|
||||
std::back_insert_iterator<std::deque<osg::Vec3f>> mOut;
|
||||
float mStepSize;
|
||||
AreaCosts mAreaCosts;
|
||||
|
||||
DetourNavigatorNavigatorTest()
|
||||
: mPlayerPosition(0, 0, 0)
|
||||
|
@ -80,7 +81,7 @@ namespace
|
|||
|
||||
TEST_F(DetourNavigatorNavigatorTest, find_path_for_empty_should_return_empty)
|
||||
{
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut),
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut),
|
||||
Status::NavMeshNotFound);
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>());
|
||||
}
|
||||
|
@ -88,7 +89,7 @@ namespace
|
|||
TEST_F(DetourNavigatorNavigatorTest, find_path_for_existing_agent_with_no_navmesh_should_throw_exception)
|
||||
{
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut),
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut),
|
||||
Status::StartPolygonNotFound);
|
||||
}
|
||||
|
||||
|
@ -97,7 +98,7 @@ namespace
|
|||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->removeAgent(mAgentHalfExtents);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut),
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut),
|
||||
Status::StartPolygonNotFound);
|
||||
}
|
||||
|
||||
|
@ -118,7 +119,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.85963428020477294921875),
|
||||
|
@ -168,7 +169,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.85963428020477294921875),
|
||||
|
@ -202,7 +203,7 @@ namespace
|
|||
|
||||
mPath.clear();
|
||||
mOut = std::back_inserter(mPath);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.87826788425445556640625),
|
||||
|
@ -253,7 +254,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.87826788425445556640625),
|
||||
|
@ -289,7 +290,7 @@ namespace
|
|||
|
||||
mPath.clear();
|
||||
mOut = std::back_inserter(mPath);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.85963428020477294921875),
|
||||
|
@ -346,7 +347,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.96328866481781005859375),
|
||||
|
@ -402,7 +403,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.9393787384033203125),
|
||||
|
@ -455,7 +456,7 @@ namespace
|
|||
mEnd.x() = 0;
|
||||
mEnd.z() = 300;
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(0, 215, 185.33331298828125),
|
||||
|
@ -501,7 +502,7 @@ namespace
|
|||
mStart.x() = 0;
|
||||
mEnd.x() = 0;
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut),
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mOut),
|
||||
Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
|
@ -548,7 +549,7 @@ namespace
|
|||
mStart.x() = 0;
|
||||
mEnd.x() = 0;
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut),
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mOut),
|
||||
Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
|
@ -595,7 +596,7 @@ namespace
|
|||
mStart.x() = 0;
|
||||
mEnd.x() = 0;
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(0, 215, -94.75363922119140625),
|
||||
|
@ -644,7 +645,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.85963428020477294921875),
|
||||
|
@ -739,7 +740,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
|
||||
|
||||
EXPECT_THAT(mPath, ElementsAre(
|
||||
Vec3fEq(-215, 215, 1.8782780170440673828125),
|
||||
|
|
|
@ -13,6 +13,14 @@ namespace DetourNavigator
|
|||
AreaType_pathgrid,
|
||||
AreaType_ground = RC_WALKABLE_AREA,
|
||||
};
|
||||
|
||||
struct AreaCosts
|
||||
{
|
||||
float mWater = 1.0f;
|
||||
float mDoor = 2.0f;
|
||||
float mPathgrid = 1.0f;
|
||||
float mGround = 1.0f;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "settingsutils.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "status.hpp"
|
||||
#include "areatype.hpp"
|
||||
|
||||
#include <DetourCommon.h>
|
||||
#include <DetourNavMesh.h>
|
||||
|
@ -269,7 +270,7 @@ namespace DetourNavigator
|
|||
|
||||
template <class OutputIterator>
|
||||
Status findSmoothPath(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const float stepSize,
|
||||
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags,
|
||||
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, const AreaCosts& areaCosts,
|
||||
const Settings& settings, OutputIterator& out)
|
||||
{
|
||||
dtNavMeshQuery navMeshQuery;
|
||||
|
@ -278,6 +279,10 @@ namespace DetourNavigator
|
|||
|
||||
dtQueryFilter queryFilter;
|
||||
queryFilter.setIncludeFlags(includeFlags);
|
||||
queryFilter.setAreaCost(AreaType_water, areaCosts.mWater);
|
||||
queryFilter.setAreaCost(AreaType_door, areaCosts.mDoor);
|
||||
queryFilter.setAreaCost(AreaType_pathgrid, areaCosts.mPathgrid);
|
||||
queryFilter.setAreaCost(AreaType_ground, areaCosts.mGround);
|
||||
|
||||
dtPolyRef startRef = 0;
|
||||
osg::Vec3f startPolygonPosition;
|
||||
|
|
|
@ -172,7 +172,8 @@ namespace DetourNavigator
|
|||
*/
|
||||
template <class OutputIterator>
|
||||
Status findPath(const osg::Vec3f& agentHalfExtents, const float stepSize, const osg::Vec3f& start,
|
||||
const osg::Vec3f& end, const Flags includeFlags, OutputIterator& out) const
|
||||
const osg::Vec3f& end, const Flags includeFlags, const DetourNavigator::AreaCosts& areaCosts,
|
||||
OutputIterator& out) const
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<
|
||||
|
@ -187,7 +188,7 @@ namespace DetourNavigator
|
|||
const auto settings = getSettings();
|
||||
return findSmoothPath(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings, agentHalfExtents),
|
||||
toNavMeshCoordinates(settings, stepSize), toNavMeshCoordinates(settings, start),
|
||||
toNavMeshCoordinates(settings, end), includeFlags, settings, out);
|
||||
toNavMeshCoordinates(settings, end), includeFlags, areaCosts, settings, out);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,7 +64,6 @@ namespace DetourNavigator
|
|||
std::map<osg::Vec3f, std::size_t> mAgents;
|
||||
std::unordered_map<ObjectId, ObjectId> mAvoidIds;
|
||||
std::unordered_map<ObjectId, ObjectId> mWaterIds;
|
||||
std::multimap<ObjectId, ObjectId> mOffMeshConnectionIds;
|
||||
|
||||
void updateAvoidShapeId(const ObjectId id, const ObjectId avoidId);
|
||||
void updateWaterShapeId(const ObjectId id, const ObjectId waterId);
|
||||
|
|
Loading…
Reference in a new issue