Fix mDistance being reset prematurely

This was causing wandering without pathgrids to become disabled for most wandering units. Additionally, wandering now behaves the same for both NPCs and creatures.
pull/1/head
Austin Salgat 9 years ago
parent 92b352989a
commit 34726c24d9

@ -16,6 +16,7 @@
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/customdata.hpp"
#include "creaturestats.hpp"
#include "steering.hpp"
@ -72,6 +73,8 @@ namespace MWMechanics
bool mIsWanderingManually;
ESM::Pathgrid::Point mPreviousWanderingNearSpawnLocation;
int mStuckTimer;
bool mCanWanderAlongPathGrid;
unsigned short mIdleAnimation;
std::vector<unsigned short> mBadIdles; // Idle animations that when called cause errors
@ -88,6 +91,7 @@ namespace MWMechanics
mState(AiWander::Wander_ChooseAction),
mIsWanderingManually(false),
mStuckTimer(0),
mCanWanderAlongPathGrid(true),
mIdleAnimation(0),
mBadIdles()
{};
@ -227,6 +231,9 @@ namespace MWMechanics
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos)
{
if (mDistance <= 0)
storage.mCanWanderAlongPathGrid = false;
if (isPackageCompleted(actor, storage))
{
return true;
@ -241,19 +248,19 @@ namespace MWMechanics
// Initialization to discover & store allowed node points for this actor.
if (mPopulateAvailableNodes)
{
getAllowedNodes(actor, currentCell->getCell());
getAllowedNodes(actor, currentCell->getCell(), storage);
}
// Actor becomes stationary - see above URL's for previous research
// 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) {
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, actor.getClass().isNpc());
wanderNearStart(actor, storage, mDistance);
}
} else if (mAllowedNodes.empty() && !storage.mIsWanderingManually) {
mDistance = 0;
storage.mCanWanderAlongPathGrid = false;
}
// Detect obstacles if wandering manually
@ -281,7 +288,7 @@ namespace MWMechanics
playGreetingIfPlayerGetsTooClose(actor, storage);
}
if ((wanderState == Wander_MoveNow) && mDistance)
if ((wanderState == Wander_MoveNow) && storage.mCanWanderAlongPathGrid)
{
// Construct a new path if there isn't one
if(!storage.mPathFinder.isPathConstructed())
@ -346,13 +353,12 @@ namespace MWMechanics
* distance (mDistance) from the position where they started the wander package.
* http://www.uesp.net/wiki/Tes3Mod:AIWander
*/
void AiWander::wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance, bool isNpc) {
void AiWander::wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance) {
const ESM::Pathgrid::Point currentPosition = actor.getRefData().getPosition().pos;
// Determine a random location within radius of original position
const float pi = 3.14159265359f;
const float maxWanderDistance = isNpc ? wanderDistance : MINIMUM_WANDER_DISTANCE * 14.0f;
const float wanderRadius = Misc::Rng::rollClosedProbability() * maxWanderDistance;
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);
@ -376,10 +382,10 @@ namespace MWMechanics
const float minimumDistanceTraveled = actorSpeed / 5.0f;
if (distanceApart2d(storage.mPreviousWanderingNearSpawnLocation, currentPosition) < minimumDistanceTraveled) {
// Hit an obstacle and haven't moved much
if (++(storage.mStuckTimer) > 10) {
// Stuck too long, stop wandering
if (++(storage.mStuckTimer) > 8) {
// Stuck too long, wander elsewhere
storage.setState(Wander_ChooseAction);
mDistance = 0;
wanderNearStart(actor, storage, mDistance);
}
} else {
storage.mPreviousWanderingNearSpawnLocation = currentPosition;
@ -769,7 +775,7 @@ namespace MWMechanics
return;
if (mPopulateAvailableNodes)
getAllowedNodes(actor, actor.getCell()->getCell());
getAllowedNodes(actor, actor.getCell()->getCell(), state.get<AiWanderStorage>());
if (mAllowedNodes.empty())
return;
@ -796,7 +802,7 @@ namespace MWMechanics
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)
{
// infrequently used, therefore no benefit in caching it as a member
const ESM::Pathgrid *
@ -810,14 +816,14 @@ namespace MWMechanics
// http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833
// Note: In order to wander, need at least two points.
if(!pathgrid || (pathgrid->mPoints.size() < 2))
mDistance = 0;
storage.mCanWanderAlongPathGrid = false;
// A distance value passed into the constructor indicates how far the
// actor can wander from the spawn position. AiWander assumes that
// pathgrid points are available, and uses them to randomly select wander
// destinations within the allowed set of pathgrid points (nodes).
// ... 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
osg::Vec3f npcPos(mInitialActorPosition);

@ -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 wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance, bool isNpc);
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
void detectManualWanderingObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
int mDistance; // how far the actor can wander from the spawn point
@ -126,7 +126,7 @@ namespace MWMechanics
// FIXME: move to AiWanderStorage
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
ESM::Pathgrid::Point mCurrentNode;

Loading…
Cancel
Save