mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 08:23:53 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
f0778e22dd
10 changed files with 131 additions and 41 deletions
|
@ -428,7 +428,7 @@ namespace MWBase
|
||||||
virtual bool getLOS(const MWWorld::ConstPtr& actor,const MWWorld::ConstPtr& targetActor) = 0;
|
virtual bool getLOS(const MWWorld::ConstPtr& actor,const MWWorld::ConstPtr& targetActor) = 0;
|
||||||
///< get Line of Sight (morrowind stupid implementation)
|
///< get Line of Sight (morrowind stupid implementation)
|
||||||
|
|
||||||
virtual float getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist) = 0;
|
virtual float getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist, bool includeWater = false) = 0;
|
||||||
|
|
||||||
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0;
|
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0;
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,9 @@ namespace MWMechanics
|
||||||
// AiWander states
|
// AiWander states
|
||||||
AiWander::WanderState mState;
|
AiWander::WanderState mState;
|
||||||
|
|
||||||
|
bool mIsWanderingManually;
|
||||||
|
bool mCanWanderAlongPathGrid;
|
||||||
|
|
||||||
unsigned short mIdleAnimation;
|
unsigned short mIdleAnimation;
|
||||||
std::vector<unsigned short> mBadIdles; // Idle animations that when called cause errors
|
std::vector<unsigned short> mBadIdles; // Idle animations that when called cause errors
|
||||||
|
|
||||||
|
@ -81,9 +84,16 @@ namespace MWMechanics
|
||||||
mGreetingTimer(0),
|
mGreetingTimer(0),
|
||||||
mCell(NULL),
|
mCell(NULL),
|
||||||
mState(AiWander::Wander_ChooseAction),
|
mState(AiWander::Wander_ChooseAction),
|
||||||
|
mIsWanderingManually(false),
|
||||||
|
mCanWanderAlongPathGrid(true),
|
||||||
mIdleAnimation(0),
|
mIdleAnimation(0),
|
||||||
mBadIdles()
|
mBadIdles()
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
void setState(const AiWander::WanderState wanderState, const bool isManualWander = false) {
|
||||||
|
mState = wanderState;
|
||||||
|
mIsWanderingManually = isManualWander;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
||||||
|
@ -206,29 +216,53 @@ namespace MWMechanics
|
||||||
if (REACTION_INTERVAL <= lastReaction)
|
if (REACTION_INTERVAL <= lastReaction)
|
||||||
{
|
{
|
||||||
lastReaction = 0;
|
lastReaction = 0;
|
||||||
return reactionTimeActions(actor, storage, currentCell, cellChange, pos);
|
return reactionTimeActions(actor, storage, currentCell, cellChange, pos, duration);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
|
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
|
||||||
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos)
|
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos, float duration)
|
||||||
{
|
{
|
||||||
|
if (mDistance <= 0)
|
||||||
|
storage.mCanWanderAlongPathGrid = false;
|
||||||
|
|
||||||
if (isPackageCompleted(actor, storage))
|
if (isPackageCompleted(actor, storage))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mStoredInitialActorPosition)
|
||||||
|
{
|
||||||
|
mInitialActorPosition = actor.getRefData().getPosition().asVec3();
|
||||||
|
mStoredInitialActorPosition = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialization to discover & store allowed node points for this actor.
|
// Initialization to discover & store allowed node points for this actor.
|
||||||
if (mPopulateAvailableNodes)
|
if (mPopulateAvailableNodes)
|
||||||
{
|
{
|
||||||
getAllowedNodes(actor, currentCell->getCell());
|
getAllowedNodes(actor, currentCell->getCell(), storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actor becomes stationary - see above URL's for previous research
|
// Actor becomes stationary - see above URL's for previous research
|
||||||
if(mAllowedNodes.empty())
|
// If a creature or an NPC with a wander distance and no pathgrid is available,
|
||||||
mDistance = 0;
|
// randomly idle or wander around near spawn point
|
||||||
|
if(mAllowedNodes.empty() && mDistance > 0 && !storage.mIsWanderingManually) {
|
||||||
|
// Typically want to idle for a short time before the next wander
|
||||||
|
if (Misc::Rng::rollDice(100) >= 96) {
|
||||||
|
wanderNearStart(actor, storage, mDistance);
|
||||||
|
} else {
|
||||||
|
storage.setState(Wander_IdleNow);
|
||||||
|
}
|
||||||
|
} else if (mAllowedNodes.empty() && !storage.mIsWanderingManually) {
|
||||||
|
storage.mCanWanderAlongPathGrid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Wandering manually and hit an obstacle, stop
|
||||||
|
if (storage.mIsWanderingManually && mObstacleCheck.check(actor, duration, 2.0f)) {
|
||||||
|
completeManualWalking(actor, storage);
|
||||||
|
}
|
||||||
|
|
||||||
// Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
|
// Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
|
||||||
if(mDistance && cellChange)
|
if(mDistance && cellChange)
|
||||||
|
@ -250,7 +284,7 @@ namespace MWMechanics
|
||||||
playGreetingIfPlayerGetsTooClose(actor, storage);
|
playGreetingIfPlayerGetsTooClose(actor, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((wanderState == Wander_MoveNow) && mDistance)
|
if ((wanderState == Wander_MoveNow) && storage.mCanWanderAlongPathGrid)
|
||||||
{
|
{
|
||||||
// Construct a new path if there isn't one
|
// Construct a new path if there isn't one
|
||||||
if(!storage.mPathFinder.isPathConstructed())
|
if(!storage.mPathFinder.isPathConstructed())
|
||||||
|
@ -260,6 +294,8 @@ namespace MWMechanics
|
||||||
setPathToAnAllowedNode(actor, storage, pos);
|
setPathToAnAllowedNode(actor, storage, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (storage.mIsWanderingManually && storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], DESTINATION_TOLERANCE)) {
|
||||||
|
completeManualWalking(actor, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // AiWander package not yet completed
|
return false; // AiWander package not yet completed
|
||||||
|
@ -303,11 +339,68 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (storage.mPathFinder.isPathConstructed())
|
if (storage.mPathFinder.isPathConstructed())
|
||||||
{
|
{
|
||||||
storage.mState = Wander_Walking;
|
storage.setState(Wander_Walking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commands actor to walk to a random location near original spawn location.
|
||||||
|
*/
|
||||||
|
void AiWander::wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance) {
|
||||||
|
const ESM::Pathgrid::Point currentPosition = actor.getRefData().getPosition().pos;
|
||||||
|
const osg::Vec3f currentPositionVec3f = osg::Vec3f(currentPosition.mX, currentPosition.mY, currentPosition.mZ);
|
||||||
|
|
||||||
|
std::size_t attempts = 10; // If a unit can't wander out of water, don't want to hang here
|
||||||
|
osg::Vec3f destination;
|
||||||
|
ESM::Pathgrid::Point destinationPosition;
|
||||||
|
bool isWaterCreature = actor.getClass().isPureWaterCreature(actor);
|
||||||
|
do {
|
||||||
|
// Determine a random location within radius of original position
|
||||||
|
const float pi = 3.14159265359f;
|
||||||
|
const float wanderRadius = Misc::Rng::rollClosedProbability() * wanderDistance;
|
||||||
|
const float randomDirection = Misc::Rng::rollClosedProbability() * 2.0f * pi;
|
||||||
|
const float destinationX = mInitialActorPosition.x() + wanderRadius * std::cos(randomDirection);
|
||||||
|
const float destinationY = mInitialActorPosition.y() + wanderRadius * std::sin(randomDirection);
|
||||||
|
const float destinationZ = mInitialActorPosition.z();
|
||||||
|
destinationPosition = ESM::Pathgrid::Point(destinationX, destinationY, destinationZ);
|
||||||
|
destination = osg::Vec3f(destinationX, destinationY, destinationZ);
|
||||||
|
|
||||||
|
// Check if land creature will walk onto water or if water creature will swim onto land
|
||||||
|
if ((!isWaterCreature && !destinationIsAtWater(actor, destination)) ||
|
||||||
|
(isWaterCreature && !destinationThroughGround(currentPositionVec3f, destination))) {
|
||||||
|
storage.mPathFinder.buildSyncedPath(currentPosition, destinationPosition, actor.getCell(), true);
|
||||||
|
storage.mPathFinder.addPointToPath(destinationPosition);
|
||||||
|
storage.setState(Wander_Walking, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (--attempts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if the position provided is above water.
|
||||||
|
*/
|
||||||
|
bool AiWander::destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination) {
|
||||||
|
float heightToGroundOrWater = MWBase::Environment::get().getWorld()->getDistToNearestRayHit(destination, osg::Vec3f(0,0,-1), 1000.0, true);
|
||||||
|
osg::Vec3f positionBelowSurface = destination;
|
||||||
|
positionBelowSurface[2] = positionBelowSurface[2] - heightToGroundOrWater - 1.0f;
|
||||||
|
return MWBase::Environment::get().getWorld()->isUnderwater(actor.getCell(), positionBelowSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if the start to end point travels through a collision point (land).
|
||||||
|
*/
|
||||||
|
bool AiWander::destinationThroughGround(const osg::Vec3f& startPoint, const osg::Vec3f& destination) {
|
||||||
|
return MWBase::Environment::get().getWorld()->castRay(startPoint.x(), startPoint.y(), startPoint.z(),
|
||||||
|
destination.x(), destination.y(), destination.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) {
|
||||||
|
stopWalking(actor, storage);
|
||||||
|
mObstacleCheck.clear();
|
||||||
|
storage.setState(Wander_IdleNow);
|
||||||
|
}
|
||||||
|
|
||||||
void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos)
|
void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos)
|
||||||
{
|
{
|
||||||
switch (storage.mState)
|
switch (storage.mState)
|
||||||
|
@ -344,7 +437,7 @@ namespace MWMechanics
|
||||||
if (mDistance && // actor is not intended to be stationary
|
if (mDistance && // actor is not intended to be stationary
|
||||||
proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6f*1.6f)) // NOTE: checks interior cells only
|
proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6f*1.6f)) // NOTE: checks interior cells only
|
||||||
{
|
{
|
||||||
storage.mState = Wander_MoveNow;
|
storage.setState(Wander_MoveNow);
|
||||||
mTrimCurrentNode = false; // just in case
|
mTrimCurrentNode = false; // just in case
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -364,7 +457,7 @@ namespace MWMechanics
|
||||||
GreetingState& greetingState = storage.mSaidGreeting;
|
GreetingState& greetingState = storage.mSaidGreeting;
|
||||||
if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None))
|
if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None))
|
||||||
{
|
{
|
||||||
storage.mState = Wander_ChooseAction;
|
storage.setState(Wander_ChooseAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +468,7 @@ namespace MWMechanics
|
||||||
if (storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], DESTINATION_TOLERANCE))
|
if (storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], DESTINATION_TOLERANCE))
|
||||||
{
|
{
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor, storage);
|
||||||
storage.mState = Wander_ChooseAction;
|
storage.setState(Wander_ChooseAction);
|
||||||
mHasReturnPosition = false;
|
mHasReturnPosition = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -393,7 +486,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (!idleAnimation && mDistance)
|
if (!idleAnimation && mDistance)
|
||||||
{
|
{
|
||||||
storage.mState = Wander_MoveNow;
|
storage.setState(Wander_MoveNow);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(idleAnimation)
|
if(idleAnimation)
|
||||||
|
@ -403,14 +496,14 @@ namespace MWMechanics
|
||||||
if(!playIdle(actor, idleAnimation))
|
if(!playIdle(actor, idleAnimation))
|
||||||
{
|
{
|
||||||
storage.mBadIdles.push_back(idleAnimation);
|
storage.mBadIdles.push_back(idleAnimation);
|
||||||
storage.mState = Wander_ChooseAction;
|
storage.setState(Wander_ChooseAction);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Recreate vanilla (broken?) behavior of resetting start time of AIWander:
|
// Recreate vanilla (broken?) behavior of resetting start time of AIWander:
|
||||||
mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp();
|
mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||||
storage.mState = Wander_IdleNow;
|
storage.setState(Wander_IdleNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration, ESM::Position& pos)
|
void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration, ESM::Position& pos)
|
||||||
|
@ -429,7 +522,7 @@ namespace MWMechanics
|
||||||
trimAllowedNodes(mAllowedNodes, storage.mPathFinder);
|
trimAllowedNodes(mAllowedNodes, storage.mPathFinder);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
storage.mPathFinder.clearPath();
|
storage.mPathFinder.clearPath();
|
||||||
storage.mState = Wander_MoveNow;
|
storage.setState(Wander_MoveNow);
|
||||||
}
|
}
|
||||||
else // probably walking into another NPC
|
else // probably walking into another NPC
|
||||||
{
|
{
|
||||||
|
@ -451,7 +544,7 @@ namespace MWMechanics
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
|
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor, storage);
|
||||||
storage.mState = Wander_ChooseAction;
|
storage.setState(Wander_ChooseAction);
|
||||||
mStuckCount = 0;
|
mStuckCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,7 +619,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor, storage);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
storage.mState = Wander_IdleNow;
|
storage.setState(Wander_IdleNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
turnActorToFacePlayer(actorPos, playerPos, storage);
|
turnActorToFacePlayer(actorPos, playerPos, storage);
|
||||||
|
@ -579,7 +672,7 @@ namespace MWMechanics
|
||||||
mAllowedNodes.push_back(mCurrentNode);
|
mAllowedNodes.push_back(mCurrentNode);
|
||||||
mCurrentNode = temp;
|
mCurrentNode = temp;
|
||||||
|
|
||||||
storage.mState = Wander_Walking;
|
storage.setState(Wander_Walking);
|
||||||
}
|
}
|
||||||
// Choose a different node and delete this one from possible nodes because it is uncreachable:
|
// Choose a different node and delete this one from possible nodes because it is uncreachable:
|
||||||
else
|
else
|
||||||
|
@ -691,7 +784,7 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mPopulateAvailableNodes)
|
if (mPopulateAvailableNodes)
|
||||||
getAllowedNodes(actor, actor.getCell()->getCell());
|
getAllowedNodes(actor, actor.getCell()->getCell(), state.get<AiWanderStorage>());
|
||||||
|
|
||||||
if (mAllowedNodes.empty())
|
if (mAllowedNodes.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -718,14 +811,8 @@ namespace MWMechanics
|
||||||
return static_cast<int>(DESTINATION_TOLERANCE * (Misc::Rng::rollProbability() * 2.0f - 1.0f));
|
return static_cast<int>(DESTINATION_TOLERANCE * (Misc::Rng::rollProbability() * 2.0f - 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell)
|
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage)
|
||||||
{
|
{
|
||||||
if (!mStoredInitialActorPosition)
|
|
||||||
{
|
|
||||||
mInitialActorPosition = actor.getRefData().getPosition().asVec3();
|
|
||||||
mStoredInitialActorPosition = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// infrequently used, therefore no benefit in caching it as a member
|
// infrequently used, therefore no benefit in caching it as a member
|
||||||
const ESM::Pathgrid *
|
const ESM::Pathgrid *
|
||||||
pathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell);
|
pathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell);
|
||||||
|
@ -738,14 +825,14 @@ namespace MWMechanics
|
||||||
// http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833
|
// http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833
|
||||||
// Note: In order to wander, need at least two points.
|
// Note: In order to wander, need at least two points.
|
||||||
if(!pathgrid || (pathgrid->mPoints.size() < 2))
|
if(!pathgrid || (pathgrid->mPoints.size() < 2))
|
||||||
mDistance = 0;
|
storage.mCanWanderAlongPathGrid = false;
|
||||||
|
|
||||||
// A distance value passed into the constructor indicates how far the
|
// A distance value passed into the constructor indicates how far the
|
||||||
// actor can wander from the spawn position. AiWander assumes that
|
// actor can wander from the spawn position. AiWander assumes that
|
||||||
// pathgrid points are available, and uses them to randomly select wander
|
// pathgrid points are available, and uses them to randomly select wander
|
||||||
// destinations within the allowed set of pathgrid points (nodes).
|
// destinations within the allowed set of pathgrid points (nodes).
|
||||||
// ... pathgrids don't usually include water, so swimmers ignore them
|
// ... pathgrids don't usually include water, so swimmers ignore them
|
||||||
if (mDistance && !actor.getClass().isPureWaterCreature(actor))
|
if (mDistance && storage.mCanWanderAlongPathGrid && !actor.getClass().isPureWaterCreature(actor))
|
||||||
{
|
{
|
||||||
// get NPC's position in local (i.e. cell) co-ordinates
|
// get NPC's position in local (i.e. cell) co-ordinates
|
||||||
osg::Vec3f npcPos(mInitialActorPosition);
|
osg::Vec3f npcPos(mInitialActorPosition);
|
||||||
|
|
|
@ -91,9 +91,13 @@ namespace MWMechanics
|
||||||
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos);
|
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos);
|
||||||
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);
|
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos, float duration);
|
||||||
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
void returnToStartLocation(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
void returnToStartLocation(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
||||||
|
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
|
||||||
|
bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination);
|
||||||
|
bool destinationThroughGround(const osg::Vec3f& startPoint, const osg::Vec3f& destination);
|
||||||
|
void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage);
|
||||||
|
|
||||||
int mDistance; // how far the actor can wander from the spawn point
|
int mDistance; // how far the actor can wander from the spawn point
|
||||||
int mDuration;
|
int mDuration;
|
||||||
|
@ -124,7 +128,7 @@ namespace MWMechanics
|
||||||
// FIXME: move to AiWanderStorage
|
// FIXME: move to AiWanderStorage
|
||||||
std::vector<ESM::Pathgrid::Point> mAllowedNodes;
|
std::vector<ESM::Pathgrid::Point> mAllowedNodes;
|
||||||
|
|
||||||
void getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell);
|
void getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage);
|
||||||
|
|
||||||
// FIXME: move to AiWanderStorage
|
// FIXME: move to AiWanderStorage
|
||||||
ESM::Pathgrid::Point mCurrentNode;
|
ESM::Pathgrid::Point mCurrentNode;
|
||||||
|
|
|
@ -115,13 +115,13 @@ namespace MWMechanics
|
||||||
* u = how long to move sideways
|
* u = how long to move sideways
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration)
|
bool ObstacleCheck::check(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();
|
||||||
|
|
||||||
if(mDistSameSpot == -1)
|
if(mDistSameSpot == -1)
|
||||||
mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor);
|
mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor) * scaleMinimumDistance;
|
||||||
|
|
||||||
float distSameSpot = mDistSameSpot * duration;
|
float distSameSpot = mDistSameSpot * duration;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
// Returns true if there is an obstacle and an evasive action
|
// Returns true if there is an obstacle and an evasive action
|
||||||
// should be taken
|
// should be taken
|
||||||
bool check(const MWWorld::Ptr& actor, float duration);
|
bool check(const MWWorld::Ptr& actor, float duration, float scaleMinimumDistance = 1.0f);
|
||||||
|
|
||||||
// change direction to try to fix "stuck" actor
|
// change direction to try to fix "stuck" actor
|
||||||
void takeEvasiveAction(MWMechanics::Movement& actorMovement);
|
void takeEvasiveAction(MWMechanics::Movement& actorMovement);
|
||||||
|
|
|
@ -2389,14 +2389,17 @@ namespace MWWorld
|
||||||
return mPhysics->getLineOfSight(actor, targetActor);
|
return mPhysics->getLineOfSight(actor, targetActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
float World::getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist)
|
float World::getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist, bool includeWater)
|
||||||
{
|
{
|
||||||
osg::Vec3f to (dir);
|
osg::Vec3f to (dir);
|
||||||
to.normalize();
|
to.normalize();
|
||||||
to = from + (to * maxDist);
|
to = from + (to * maxDist);
|
||||||
|
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(from, to, MWWorld::Ptr(),
|
int collisionTypes = MWPhysics::CollisionType_World | MWPhysics::CollisionType_HeightMap | MWPhysics::CollisionType_Door;
|
||||||
MWPhysics::CollisionType_World|MWPhysics::CollisionType_HeightMap|MWPhysics::CollisionType_Door);
|
if (includeWater) {
|
||||||
|
collisionTypes |= MWPhysics::CollisionType_Water;
|
||||||
|
}
|
||||||
|
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(from, to, MWWorld::Ptr(), collisionTypes);
|
||||||
|
|
||||||
if (!result.mHit)
|
if (!result.mHit)
|
||||||
return maxDist;
|
return maxDist;
|
||||||
|
|
|
@ -527,7 +527,7 @@ namespace MWWorld
|
||||||
virtual bool getLOS(const MWWorld::ConstPtr& actor,const MWWorld::ConstPtr& targetActor);
|
virtual bool getLOS(const MWWorld::ConstPtr& actor,const MWWorld::ConstPtr& targetActor);
|
||||||
///< get Line of Sight (morrowind stupid implementation)
|
///< get Line of Sight (morrowind stupid implementation)
|
||||||
|
|
||||||
virtual float getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist);
|
virtual float getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist, bool includeWater = false);
|
||||||
|
|
||||||
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable);
|
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ static const char* const applicationName = "OpenMW";
|
||||||
static const char* const applicationName = "openmw";
|
static const char* const applicationName = "openmw";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char* const mwToken = "?mw?";
|
|
||||||
const char* const localToken = "?local?";
|
const char* const localToken = "?local?";
|
||||||
const char* const userDataToken = "?userdata?";
|
const char* const userDataToken = "?userdata?";
|
||||||
const char* const globalToken = "?global?";
|
const char* const globalToken = "?global?";
|
||||||
|
@ -45,7 +44,6 @@ ConfigurationManager::~ConfigurationManager()
|
||||||
|
|
||||||
void ConfigurationManager::setupTokensMapping()
|
void ConfigurationManager::setupTokensMapping()
|
||||||
{
|
{
|
||||||
mTokensMapping.insert(std::make_pair(mwToken, &FixedPath<>::getInstallPath));
|
|
||||||
mTokensMapping.insert(std::make_pair(localToken, &FixedPath<>::getLocalPath));
|
mTokensMapping.insert(std::make_pair(localToken, &FixedPath<>::getLocalPath));
|
||||||
mTokensMapping.insert(std::make_pair(userDataToken, &FixedPath<>::getUserDataPath));
|
mTokensMapping.insert(std::make_pair(userDataToken, &FixedPath<>::getUserDataPath));
|
||||||
mTokensMapping.insert(std::make_pair(globalToken, &FixedPath<>::getGlobalDataPath));
|
mTokensMapping.insert(std::make_pair(globalToken, &FixedPath<>::getGlobalDataPath));
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
# Modifications should be done on the user openmw.cfg file instead
|
# Modifications should be done on the user openmw.cfg file instead
|
||||||
# (see: https://wiki.openmw.org/index.php?title=Paths)
|
# (see: https://wiki.openmw.org/index.php?title=Paths)
|
||||||
|
|
||||||
data="?mw?Data Files"
|
|
||||||
data=${MORROWIND_DATA_FILES}
|
data=${MORROWIND_DATA_FILES}
|
||||||
data-local="?userdata?data"
|
data-local="?userdata?data"
|
||||||
resources=${OPENMW_RESOURCE_FILES}
|
resources=${OPENMW_RESOURCE_FILES}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
# (see: https://wiki.openmw.org/index.php?title=Paths)
|
# (see: https://wiki.openmw.org/index.php?title=Paths)
|
||||||
|
|
||||||
data="?global?data"
|
data="?global?data"
|
||||||
data="?mw?Data Files"
|
|
||||||
data=./data
|
data=./data
|
||||||
data-local="?userdata?data"
|
data-local="?userdata?data"
|
||||||
resources=./resources
|
resources=./resources
|
||||||
|
|
Loading…
Reference in a new issue