diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 25ed4694b..31687edf2 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -216,7 +216,7 @@ namespace MWMechanics // Are we there yet? bool& chooseAction = storage.mChooseAction; if(walking && - storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1])) + storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], DestinationTolerance)) { stopWalking(actor, storage); moveNow = false; @@ -645,9 +645,8 @@ namespace MWMechanics int index = Misc::Rng::rollDice(mAllowedNodes.size()); ESM::Pathgrid::Point dest = mAllowedNodes[index]; - // apply a slight offset to prevent overcrowding - dest.mX += static_cast(Misc::Rng::rollProbability() * 128 - 64); - dest.mY += static_cast(Misc::Rng::rollProbability() * 128 - 64); + dest.mX += OffsetToPreventOvercrowding(); + dest.mY += OffsetToPreventOvercrowding(); ToWorldCoordinates(dest, actor.getCell()->getCell()); MWBase::Environment::get().getWorld()->moveObject(actor, static_cast(dest.mX), @@ -658,6 +657,11 @@ namespace MWMechanics mStoredAvailableNodes = false; } + int AiWander::OffsetToPreventOvercrowding() + { + return static_cast(DestinationTolerance * (Misc::Rng::rollProbability() * 2.0f - 1.0f)); + } + void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell) { if (!mStoredInitialActorPosition) @@ -739,13 +743,10 @@ namespace MWMechanics float length = delta.length(); delta.normalize(); - // destination must be far enough away that NPC will need to move to get there. - const int threshold = PathFinder::PathTolerance * 2; - int distance = std::max(mDistance / 2, threshold); + int distance = std::max(mDistance / 2, MinimumWanderDistance); - // must not travel more than 1/2 way between waypoints, - // otherwise, NPC goes to far endpoint then comes back. Looks weird. - distance = std::min(distance, static_cast(length / 2)); + // must not travel longer than distance between waypoints or NPC goes past waypoint + distance = std::min(distance, static_cast(length)); delta *= distance; mAllowedNodes.push_back(PathFinder::MakePathgridPoint(vectorStart + delta)); } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 18f98cfd5..c15ec7c3c 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -118,6 +118,12 @@ namespace MWMechanics GroupIndex_MaxIdle = 9 }; + // to prevent overcrowding + static const int DestinationTolerance = 64; + + // distance must be long enough that NPC will need to move to get there. + static const int MinimumWanderDistance = DestinationTolerance * 2; + /// convert point from local (i.e. cell) to world co-ordinates void ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell); @@ -129,6 +135,8 @@ namespace MWMechanics /// lookup table for converting idleSelect value to groupName static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1]; + + static int OffsetToPreventOvercrowding(); };