From fc03216d488a18d7b6d92bce4f83422f235302ec Mon Sep 17 00:00:00 2001 From: Austin Salgat Date: Sat, 16 Apr 2016 12:14:00 -0500 Subject: [PATCH] Refactor to reuse existing obstacle detection --- apps/openmw/mwmechanics/aiwander.cpp | 42 ++++------------------------ apps/openmw/mwmechanics/aiwander.hpp | 9 +----- apps/openmw/mwmechanics/obstacle.cpp | 4 +-- apps/openmw/mwmechanics/obstacle.hpp | 2 +- 4 files changed, 9 insertions(+), 48 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index e9957dd60..e47105055 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -69,11 +69,7 @@ namespace MWMechanics // AiWander states AiWander::WanderState mState; - // Wandering near spawn logic bool mIsWanderingManually; - ESM::Pathgrid::Point mPreviousWanderingNearSpawnLocation; - int mStuckTimer; - bool mCanWanderAlongPathGrid; unsigned short mIdleAnimation; @@ -90,7 +86,6 @@ namespace MWMechanics mCell(NULL), mState(AiWander::Wander_ChooseAction), mIsWanderingManually(false), - mStuckTimer(0), mCanWanderAlongPathGrid(true), mIdleAnimation(0), mBadIdles() @@ -222,14 +217,14 @@ namespace MWMechanics if (REACTION_INTERVAL <= lastReaction) { lastReaction = 0; - return reactionTimeActions(actor, storage, currentCell, cellChange, pos); + return reactionTimeActions(actor, storage, currentCell, cellChange, pos, duration); } else return false; } bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, - const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos) + const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos, float duration) { if (mDistance <= 0) storage.mCanWanderAlongPathGrid = false; @@ -263,9 +258,9 @@ namespace MWMechanics storage.mCanWanderAlongPathGrid = false; } - // Detect obstacles if wandering manually - if (storage.mIsWanderingManually) { - detectManualWanderingObstacles(actor, storage); + // If Wandering manually and hit an obstacle, stop + if (storage.mIsWanderingManually && mObstacleCheck.check(actor, duration*10.0f, 2.5f)) { + stopWalking(actor, storage); } // Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles. @@ -348,10 +343,6 @@ 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::wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance) { const ESM::Pathgrid::Point currentPosition = actor.getRefData().getPosition().pos; @@ -366,32 +357,9 @@ namespace MWMechanics storage.mPathFinder.buildSyncedPath(currentPosition, destinationPosition, actor.getCell(), true); storage.mPathFinder.addPointToPath(destinationPosition); - storage.mPreviousWanderingNearSpawnLocation = currentPosition; - storage.mStuckTimer = 0; storage.setState(Wander_Walking, true); } - /* - * Detects if a manually wandering actor has spent too much time at one spot (stuck by an obstacle) - * and stops wandering when that occurs. Uses the unit's speed to help determine how long they should - * not be in one spot. - */ - void AiWander::detectManualWanderingObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage) { - const ESM::Pathgrid::Point currentPosition = actor.getRefData().getPosition().pos; - const float actorSpeed = actor.getClass().getSpeed(actor); - const float minimumDistanceTraveled = actorSpeed / 5.0f; - if (distanceApart2d(storage.mPreviousWanderingNearSpawnLocation, currentPosition) < minimumDistanceTraveled) { - // Hit an obstacle and haven't moved much - if (++(storage.mStuckTimer) > 8) { - // Stuck too long, wander elsewhere - storage.setState(Wander_ChooseAction); - wanderNearStart(actor, storage, mDistance); - } - } else { - storage.mPreviousWanderingNearSpawnLocation = currentPosition; - } - } - void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos) { switch (storage.mState) diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 32fda3331..af2349989 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -91,11 +91,10 @@ namespace MWMechanics void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos); 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); + const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos, float duration); 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); - void detectManualWanderingObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage); int mDistance; // how far the actor can wander from the spawn point int mDuration; @@ -160,12 +159,6 @@ namespace MWMechanics static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1]; static int OffsetToPreventOvercrowding(); - - float distanceApart2d(const ESM::Pathgrid::Point& first, const ESM::Pathgrid::Point& second) { - const float deltaX = second.mX - first.mX; - const float deltaY = second.mY - first.mY; - return std::sqrt(deltaX*deltaX + deltaY*deltaY); - } }; diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 11bbd1e31..4394168a5 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -115,13 +115,13 @@ namespace MWMechanics * u = how long to move sideways * */ - bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration) + bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration, float scaleMinimumDistance) { const MWWorld::Class& cls = actor.getClass(); ESM::Position pos = actor.getRefData().getPosition(); if(mDistSameSpot == -1) - mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor); + mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor) * scaleMinimumDistance; float distSameSpot = mDistSameSpot * duration; diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp index 98cc4e7a0..c8c83d68f 100644 --- a/apps/openmw/mwmechanics/obstacle.hpp +++ b/apps/openmw/mwmechanics/obstacle.hpp @@ -36,7 +36,7 @@ namespace MWMechanics // Returns true if there is an obstacle and an evasive action // should be taken - bool check(const MWWorld::Ptr& actor, float duration); + bool check(const MWWorld::Ptr& actor, float duration, float scaleMinimumDistance = 1.0f); // change direction to try to fix "stuck" actor void takeEvasiveAction(MWMechanics::Movement& actorMovement);