Add logic for NPC wandering without pathgrids

pull/1/head
Austin Salgat 9 years ago
parent c02881a4f8
commit 92b352989a

@ -232,6 +232,12 @@ namespace MWMechanics
return true;
}
if (!mStoredInitialActorPosition)
{
mInitialActorPosition = actor.getRefData().getPosition().asVec3();
mStoredInitialActorPosition = true;
}
// Initialization to discover & store allowed node points for this actor.
if (mPopulateAvailableNodes)
{
@ -239,11 +245,12 @@ namespace MWMechanics
}
// Actor becomes stationary - see above URL's for previous research
// If not an NPC and no pathgrid is available, randomly idle or wander around near spawn point
if(mAllowedNodes.empty() && !actor.getBase()->mClass->isNpc() && !storage.mIsWanderingManually) {
// If a creature or an NPC with a wander distance and no pathgrid is available,
// randomly idle or wander around near spawn point
if(mAllowedNodes.empty() && (mDistance > 0 || !actor.getClass().isNpc()) && !storage.mIsWanderingManually) {
// Typically want to idle for a short time before the next wander
if (Misc::Rng::rollDice(100) >= 96) {
wanderNearSpawn(actor, storage);
wanderNearStart(actor, storage, mDistance, actor.getClass().isNpc());
}
} else if (mAllowedNodes.empty() && !storage.mIsWanderingManually) {
mDistance = 0;
@ -334,18 +341,22 @@ namespace MWMechanics
/*
* Commands actor to walk to a random location near original spawn location.
*
* Creatures simply wander a certain distance from their starting location, while NPCs wander a scripted
* distance (mDistance) from the position where they started the wander package.
* http://www.uesp.net/wiki/Tes3Mod:AIWander
*/
void AiWander::wanderNearSpawn(const MWWorld::Ptr& actor, AiWanderStorage& storage) {
void AiWander::wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance, bool isNpc) {
const ESM::Pathgrid::Point currentPosition = actor.getRefData().getPosition().pos;
const ESM::Pathgrid::Point originalPosition = actor.getCellRef().getPosition().pos;
// Determine a random location within radius of original position
const float pi = 3.14159265359f;
const float randomRadius = Misc::Rng::rollClosedProbability() * MINIMUM_WANDER_DISTANCE * 14.0f;
const float maxWanderDistance = isNpc ? wanderDistance : MINIMUM_WANDER_DISTANCE * 14.0f;
const float wanderRadius = Misc::Rng::rollClosedProbability() * maxWanderDistance;
const float randomDirection = Misc::Rng::rollClosedProbability() * 2.0f * pi;
const float destinationX = originalPosition.mX + randomRadius * std::cos(randomDirection);
const float destinationY = originalPosition.mY + randomRadius * std::sin(randomDirection);
ESM::Pathgrid::Point destinationPosition = ESM::Pathgrid::Point(destinationX, destinationY, originalPosition.mZ);
const float destinationX = mInitialActorPosition.x() + wanderRadius * std::cos(randomDirection);
const float destinationY = mInitialActorPosition.y() + wanderRadius * std::sin(randomDirection);
ESM::Pathgrid::Point destinationPosition = ESM::Pathgrid::Point(destinationX, destinationY, mInitialActorPosition.z());
storage.mPathFinder.buildSyncedPath(currentPosition, destinationPosition, actor.getCell(), true);
storage.mPathFinder.addPointToPath(destinationPosition);
@ -787,12 +798,6 @@ namespace MWMechanics
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell)
{
if (!mStoredInitialActorPosition)
{
mInitialActorPosition = actor.getRefData().getPosition().asVec3();
mStoredInitialActorPosition = true;
}
// infrequently used, therefore no benefit in caching it as a member
const ESM::Pathgrid *
pathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell);

@ -94,7 +94,7 @@ namespace MWMechanics
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos);
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
void returnToStartLocation(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
void wanderNearSpawn(const MWWorld::Ptr& actor, AiWanderStorage& storage);
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance, bool isNpc);
void detectManualWanderingObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
int mDistance; // how far the actor can wander from the spawn point

Loading…
Cancel
Save