1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-30 09:06:43 +00:00

Merge pull request #2852 from elsid/aiwander_cleanup

AiWander cleanup
This commit is contained in:
Alexei Dobrohotov 2020-05-17 00:37:22 +03:00 committed by GitHub
commit b168544445
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 37 deletions

View file

@ -89,6 +89,11 @@ namespace MWMechanics
const auto maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z())); const auto maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
return world->isAreaOccupiedByOtherActor(destination, 2 * maxHalfExtent, actor); return world->isAreaOccupiedByOtherActor(destination, 2 * maxHalfExtent, actor);
} }
void stopMovement(const MWWorld::Ptr& actor)
{
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
}
} }
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):
@ -165,7 +170,7 @@ namespace MWMechanics
* actors will enter combat (i.e. no longer wandering) and different pathfinding * actors will enter combat (i.e. no longer wandering) and different pathfinding
* will kick in. * will kick in.
*/ */
bool AiWander::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) bool AiWander::execute (const MWWorld::Ptr& actor, CharacterController& /*characterController*/, AiState& state, float duration)
{ {
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor); MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
if (cStats.isDead() || cStats.getHealth().getCurrent() <= 0) if (cStats.isDead() || cStats.getHealth().getCurrent() <= 0)
@ -206,7 +211,7 @@ namespace MWMechanics
{ {
if (storage.mState == AiWanderStorage::Wander_Walking) if (storage.mState == AiWanderStorage::Wander_Walking)
{ {
stopWalking(actor, storage, false); stopMovement(actor);
mObstacleCheck.clear(); mObstacleCheck.clear();
storage.setState(AiWanderStorage::Wander_IdleNow); storage.setState(AiWanderStorage::Wander_IdleNow);
} }
@ -230,8 +235,9 @@ namespace MWMechanics
if (mDistance <= 0) if (mDistance <= 0)
storage.mCanWanderAlongPathGrid = false; storage.mCanWanderAlongPathGrid = false;
if (isPackageCompleted(actor, storage)) if (isPackageCompleted())
{ {
stopWalking(actor);
// Reset package so it can be used again // Reset package so it can be used again
mRemainingDuration=mDuration; mRemainingDuration=mDuration;
init(); init();
@ -315,19 +321,10 @@ namespace MWMechanics
return actor.getRefData().getPosition().asVec3(); return actor.getRefData().getPosition().asVec3();
} }
bool AiWander::isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage) bool AiWander::isPackageCompleted() const
{ {
if (mDuration) // End package if duration is complete
{ return mDuration && mRemainingDuration <= 0;
// End package if duration is complete
if (mRemainingDuration <= 0)
{
stopWalking(actor, storage);
return true;
}
}
// if get here, not yet completed
return false;
} }
/* /*
@ -395,7 +392,7 @@ namespace MWMechanics
} }
void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) { void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) {
stopWalking(actor, storage); stopWalking(actor);
mObstacleCheck.clear(); mObstacleCheck.clear();
storage.setState(AiWanderStorage::Wander_IdleNow); storage.setState(AiWanderStorage::Wander_IdleNow);
} }
@ -460,13 +457,13 @@ namespace MWMechanics
// Is there no destination or are we there yet? // Is there no destination or are we there yet?
if ((!mPathFinder.isPathConstructed()) || pathTo(actor, osg::Vec3f(mPathFinder.getPath().back()), duration, DESTINATION_TOLERANCE)) if ((!mPathFinder.isPathConstructed()) || pathTo(actor, osg::Vec3f(mPathFinder.getPath().back()), duration, DESTINATION_TOLERANCE))
{ {
stopWalking(actor, storage); stopWalking(actor);
storage.setState(AiWanderStorage::Wander_ChooseAction); storage.setState(AiWanderStorage::Wander_ChooseAction);
} }
else else
{ {
// have not yet reached the destination // have not yet reached the destination
evadeObstacles(actor, duration, storage); evadeObstacles(actor, storage);
} }
} }
@ -497,15 +494,12 @@ namespace MWMechanics
storage.setState(AiWanderStorage::Wander_IdleNow); storage.setState(AiWanderStorage::Wander_IdleNow);
} }
void AiWander::evadeObstacles(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage) void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage)
{ {
if (mUsePathgrid) if (mUsePathgrid)
{ {
const auto halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor); const auto halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
const float actorTolerance = 2 * actor.getClass().getSpeed(actor) * duration mPathFinder.buildPathByNavMeshToNextPoint(actor, halfExtents, getNavigatorFlags(actor));
+ 1.2 * std::max(halfExtents.x(), halfExtents.y());
const float pointTolerance = std::max(MIN_TOLERANCE, actorTolerance);
mPathFinder.buildPathByNavMeshToNextPoint(actor, halfExtents, getNavigatorFlags(actor), pointTolerance);
} }
if (mObstacleCheck.isEvading()) if (mObstacleCheck.isEvading())
@ -518,7 +512,7 @@ namespace MWMechanics
storage.mTrimCurrentNode = true; storage.mTrimCurrentNode = true;
trimAllowedNodes(storage.mAllowedNodes, mPathFinder); trimAllowedNodes(storage.mAllowedNodes, mPathFinder);
mObstacleCheck.clear(); mObstacleCheck.clear();
stopWalking(actor, storage); stopWalking(actor);
storage.setState(AiWanderStorage::Wander_MoveNow); storage.setState(AiWanderStorage::Wander_MoveNow);
} }
@ -529,7 +523,7 @@ namespace MWMechanics
if (storage.mStuckCount >= getCountBeforeReset(actor)) // something has gone wrong, reset if (storage.mStuckCount >= getCountBeforeReset(actor)) // something has gone wrong, reset
{ {
mObstacleCheck.clear(); mObstacleCheck.clear();
stopWalking(actor, storage); stopWalking(actor);
storage.setState(AiWanderStorage::Wander_ChooseAction); storage.setState(AiWanderStorage::Wander_ChooseAction);
storage.mStuckCount = 0; storage.mStuckCount = 0;
} }
@ -609,14 +603,11 @@ namespace MWMechanics
return TypeIdWander; return TypeIdWander;
} }
void AiWander::stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage, bool clearPath) void AiWander::stopWalking(const MWWorld::Ptr& actor)
{ {
if (clearPath) mPathFinder.clearPath();
{ mHasDestination = false;
mPathFinder.clearPath(); stopMovement(actor);
mHasDestination = false;
}
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
} }
bool AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect) bool AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)

View file

@ -118,7 +118,7 @@ namespace MWMechanics
private: private:
// NOTE: mDistance and mDuration must be set already // NOTE: mDistance and mDuration must be set already
void init(); void init();
void stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage, bool clearPath = true); void stopWalking(const MWWorld::Ptr& actor);
/// Have the given actor play an idle animation /// Have the given actor play an idle animation
/// @return Success or error /// @return Success or error
@ -126,14 +126,14 @@ namespace MWMechanics
bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect); bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
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 evadeObstacles(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage); void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
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); 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); 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, ESM::Position& pos); bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage); inline bool isPackageCompleted() const;
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);
void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage); void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage);

View file

@ -361,7 +361,7 @@ namespace MWMechanics
} }
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents, void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
const DetourNavigator::Flags flags, const float pointTolerance) const DetourNavigator::Flags flags)
{ {
if (mPath.empty()) if (mPath.empty())
return; return;

View file

@ -97,7 +97,7 @@ namespace MWMechanics
const DetourNavigator::Flags flags); const DetourNavigator::Flags flags);
void buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents, void buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
const DetourNavigator::Flags flags, const float pointTolerance); const DetourNavigator::Flags flags);
/// Remove front point if exist and within tolerance /// Remove front point if exist and within tolerance
void update(const osg::Vec3f& position, const float pointTolerance, const float destinationTolerance); void update(const osg::Vec3f& position, const float pointTolerance, const float destinationTolerance);