Re-work wandering outside of initial cell (bug #5261, bug #5262)

pull/2687/head
Andrei Kortunov 4 years ago
parent 2652b10b9c
commit 1db51a9e08

@ -195,6 +195,7 @@
Bug #5249: Wandering NPCs start walking too soon after they hello
Bug #5250: Creatures display shield ground mesh instead of shield body part
Bug #5255: "GetTarget, player" doesn't return 1 during NPC hello
Bug #5261: Creatures can sometimes become stuck playing idles and never wander again
Feature #1774: Handle AvoidNode
Feature #2229: Improve pathfinding AI
Feature #3025: Analogue gamepad movement controls

@ -54,8 +54,9 @@ namespace MWMechanics
stats.setMovementFlag(CreatureStats::Flag_Run, false);
stats.setDrawState(DrawState_Nothing);
// Note: we should cancel internal "return after combat" package, if original location is too far away
if (!isWithinMaxRange(targetPos, actorPos))
return false;
return mHidden;
// Unfortunately, with vanilla assets destination is sometimes blocked by other actor.
// If we got close to target, check for actors nearby. If they are, finish AI package.

@ -145,15 +145,6 @@ namespace MWMechanics
// get or create temporary storage
AiWanderStorage& storage = state.get<AiWanderStorage>();
const MWWorld::CellStore*& currentCell = storage.mCell;
bool cellChange = currentCell && (actor.getCell() != currentCell);
if(!currentCell || cellChange)
{
stopWalking(actor, storage);
currentCell = actor.getCell();
storage.mPopulateAvailableNodes = true;
mStoredInitialActorPosition = false;
}
mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
@ -200,14 +191,13 @@ namespace MWMechanics
if (AI_REACTION_TIME <= lastReaction)
{
lastReaction = 0;
return reactionTimeActions(actor, storage, currentCell, cellChange, pos);
return reactionTimeActions(actor, storage, pos);
}
else
return false;
}
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos)
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos)
{
if (mDistance <= 0)
storage.mCanWanderAlongPathGrid = false;
@ -229,7 +219,7 @@ namespace MWMechanics
// Initialization to discover & store allowed node points for this actor.
if (storage.mPopulateAvailableNodes)
{
getAllowedNodes(actor, currentCell->getCell(), storage);
getAllowedNodes(actor, actor.getCell()->getCell(), storage);
}
if (canActorMoveByZAxis(actor) && mDistance > 0) {
@ -258,10 +248,6 @@ namespace MWMechanics
completeManualWalking(actor, storage);
}
// Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
if(mDistance && cellChange)
mDistance = 0;
AiWanderStorage::WanderState& wanderState = storage.mState;
if ((wanderState == AiWanderStorage::Wander_MoveNow) && storage.mCanWanderAlongPathGrid)
{
@ -529,7 +515,7 @@ namespace MWMechanics
unsigned int randNode = Misc::Rng::rollDice(storage.mAllowedNodes.size());
ESM::Pathgrid::Point dest(storage.mAllowedNodes[randNode]);
ToWorldCoordinates(dest, storage.mCell->getCell());
ToWorldCoordinates(dest, actor.getCell()->getCell());
// actor position is already in world coordinates
const osg::Vec3f start = actorPos.asVec3();

@ -27,8 +27,6 @@ namespace MWMechanics
{
float mReaction; // update some actions infrequently
const MWWorld::CellStore* mCell; // for detecting cell change
// AiWander states
enum WanderState
{
@ -60,7 +58,6 @@ namespace MWMechanics
AiWanderStorage():
mReaction(0),
mCell(nullptr),
mState(Wander_ChooseAction),
mIsWanderingManually(false),
mCanWanderAlongPathGrid(true),
@ -125,8 +122,7 @@ namespace MWMechanics
void onIdleStatePerFrameActions(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);
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos);
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination);
@ -141,7 +137,7 @@ namespace MWMechanics
bool mRepeat;
bool mStoredInitialActorPosition;
osg::Vec3f mInitialActorPosition;
osg::Vec3f mInitialActorPosition; // Note: an original engine does not reset coordinates even when actor changes a cell
bool mHasDestination;
osg::Vec3f mDestination;

Loading…
Cancel
Save