From 573a14993ac1d41979c805cd6298bd9f82227a64 Mon Sep 17 00:00:00 2001 From: dteviot Date: Thu, 10 Sep 2015 21:53:31 +1200 Subject: [PATCH] Moved isActorNearInactiveCell() logic to own function. Also, triggers when actor is near edge of cell, not when less than 1/2 way to edge. --- apps/openmw/mwmechanics/aipackage.cpp | 62 ++++++++++++++------------- apps/openmw/mwmechanics/aipackage.hpp | 1 + 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index b6b2408338..e5da16865f 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -16,6 +16,7 @@ #include "steering.hpp" #include "actorutil.hpp" +#include "coordinateconverter.hpp" MWMechanics::AiPackage::~AiPackage() {} @@ -32,45 +33,24 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po ESM::Position pos = actor.getRefData().getPosition(); //position of the actor /// Stops the actor when it gets too close to a unloaded cell - const ESM::Cell *cell = actor.getCell()->getCell(); + //... At current time, this test is unnecessary. AI shuts down when actor is more than 7168 + //... units from player, and exterior cells are 8192 units long and wide. + //... But AI processing distance may increase in the future. + if (isActorNearInactiveCell(pos)) { - MWWorld::Ptr player = getPlayer(); - Movement &movement = actor.getClass().getMovementSettings(actor); - - //Ensure pursuer doesn't leave loaded cells - if(cell->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - if(cell->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + return false; } - //Start position - ESM::Pathgrid::Point start = pos.pos; - //*********************** /// Checks if you can't get to the end position at all, adds end position to end of path /// Rebuilds path every quarter of a second, in case the target has moved //*********************** if(mTimer > 0.25) { + const ESM::Cell *cell = actor.getCell()->getCell(); if (doesPathNeedRecalc(dest, cell)) { //Only rebuild path if it's moved - mPathFinder.buildSyncedPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + mPathFinder.buildSyncedPath(pos.pos, dest, actor.getCell(), true); //Rebuild path, in case the target has moved mPrevDest = dest; } @@ -133,3 +113,27 @@ bool MWMechanics::AiPackage::isTargetMagicallyHidden(const MWWorld::Ptr& target) return (magicEffects.get(ESM::MagicEffect::Invisibility).getMagnitude() > 0) || (magicEffects.get(ESM::MagicEffect::Chameleon).getMagnitude() > 75); } + +bool MWMechanics::AiPackage::isActorNearInactiveCell(const ESM::Position& actorPos) +{ + const ESM::Cell* playerCell(getPlayer().getCell()->getCell()); + if (playerCell->isExterior()) + { + // get actor's distance from origin of center cell + osg::Vec3f actorOffset(actorPos.asVec3()); + CoordinateConverter(playerCell).ToLocal(actorOffset); + + // currently assumes 3 x 3 grid for exterior cells, with player at center cell. + // ToDo: (Maybe) use "exterior cell load distance" setting to get count of actual active cells + // While AI Process distance is 7168, AI shuts down actors before they reach edges of 3 x 3 grid. + const float distanceFromEdge = 200.0; + float minThreshold = (-1.0f * ESM::Land::REAL_SIZE) + distanceFromEdge; + float maxThreshold = (2.0f * ESM::Land::REAL_SIZE) - distanceFromEdge; + return (actorOffset[0] < minThreshold) || (maxThreshold < actorOffset[0]) + || (actorOffset[1] < minThreshold) || (maxThreshold < actorOffset[1]); + } + else + { + return false; + } +} \ No newline at end of file diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 4f919edbc6..befd159bf0 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -88,6 +88,7 @@ namespace MWMechanics private: void evadeObstacles(const MWWorld::Ptr& actor, float duration, ESM::Position& pos); + bool isActorNearInactiveCell(const ESM::Position& actorPos); }; }