mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-20 09:11:35 +00:00
Pathfinding Overhaul - Master cleanup! Cleaned pathfinding entirely, all AI packages that are implemented as well, Increased buffer! This makes the intro guard no longer walk into you or go to far into the room (not tested against vanilla distances but it seems accurate enough until the next itteration of pathfinding fixes).
This commit is contained in:
parent
a4caec56cf
commit
09beafd044
4 changed files with 515 additions and 494 deletions
|
@ -13,8 +13,9 @@ namespace
|
||||||
{
|
{
|
||||||
float sgn(float a)
|
float sgn(float a)
|
||||||
{
|
{
|
||||||
if(a > 0) return 1.0;
|
if(a > 0)
|
||||||
else return -1.0;
|
return 1.0;
|
||||||
|
return -1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,9 +25,11 @@ namespace
|
||||||
TODO: Take account for actors being in different cells.
|
TODO: Take account for actors being in different cells.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MWMechanics::AiEscort::AiEscort(const std::string &actorId,int duration, float x, float y, float z)
|
namespace MWMechanics
|
||||||
: mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration)
|
|
||||||
{
|
{
|
||||||
|
AiEscort::AiEscort(const std::string &actorId, int duration, float x, float y, float z)
|
||||||
|
: mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration)
|
||||||
|
{
|
||||||
mMaxDist = 470;
|
mMaxDist = 470;
|
||||||
|
|
||||||
// The CS Help File states that if a duration is givin, the AI package will run for that long
|
// The CS Help File states that if a duration is givin, the AI package will run for that long
|
||||||
|
@ -39,11 +42,11 @@ MWMechanics::AiEscort::AiEscort(const std::string &actorId,int duration, float x
|
||||||
MWWorld::TimeStamp startTime = MWBase::Environment::get().getWorld()->getTimeStamp();
|
MWWorld::TimeStamp startTime = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||||
mStartingSecond = ((startTime.getHour() - int(startTime.getHour())) * 100);
|
mStartingSecond = ((startTime.getHour() - int(startTime.getHour())) * 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiEscort::AiEscort(const std::string &actorId,const std::string &cellId,int duration, float x, float y, float z)
|
AiEscort::AiEscort(const std::string &actorId, const std::string &cellId,int duration, float x, float y, float z)
|
||||||
: mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration)
|
: mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration)
|
||||||
{
|
{
|
||||||
mMaxDist = 470;
|
mMaxDist = 470;
|
||||||
|
|
||||||
// The CS Help File states that if a duration is givin, the AI package will run for that long
|
// The CS Help File states that if a duration is givin, the AI package will run for that long
|
||||||
|
@ -56,16 +59,16 @@ MWMechanics::AiEscort::AiEscort(const std::string &actorId,const std::string &ce
|
||||||
MWWorld::TimeStamp startTime = MWBase::Environment::get().getWorld()->getTimeStamp();
|
MWWorld::TimeStamp startTime = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||||
mStartingSecond = ((startTime.getHour() - int(startTime.getHour())) * 100);
|
mStartingSecond = ((startTime.getHour() - int(startTime.getHour())) * 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MWMechanics::AiEscort *MWMechanics::AiEscort::clone() const
|
AiEscort *MWMechanics::AiEscort::clone() const
|
||||||
{
|
{
|
||||||
return new AiEscort(*this);
|
return new AiEscort(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor)
|
bool AiEscort::execute (const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
// If AiEscort has ran for as long or longer then the duration specified
|
// If AiEscort has ran for as long or longer then the duration specified
|
||||||
// and the duration is not infinite, the package is complete.
|
// and the duration is not infinite, the package is complete.
|
||||||
if(mDuration != 0)
|
if(mDuration != 0)
|
||||||
|
@ -76,19 +79,19 @@ bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||||
ESM::Position pos = actor.getRefData().getPosition();
|
ESM::Position pos = actor.getRefData().getPosition();
|
||||||
bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY;
|
bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY;
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
|
||||||
const ESM::Pathgrid *pathgrid =
|
const ESM::Pathgrid *pathgrid =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
|
||||||
|
|
||||||
|
|
||||||
if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
|
if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
|
||||||
{
|
{
|
||||||
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
|
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
|
||||||
// Check if actor is near the border of an inactive cell. If so, disable AiEscort.
|
// Check if actor is near the border of an inactive cell. If so, disable AiEscort.
|
||||||
// FIXME: This *should* pause the AiEscort package instead of terminating it.
|
// FIXME: This *should* pause the AiEscort package instead of terminating it.
|
||||||
if(sideX*(pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE / 2. - 200))
|
if(sideX * (pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE /
|
||||||
|
2.0 - 200))
|
||||||
{
|
{
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
||||||
return true;
|
return true;
|
||||||
|
@ -99,7 +102,8 @@ bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor)
|
||||||
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
|
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
|
||||||
// Check if actor is near the border of an inactive cell. If so, disable AiEscort.
|
// Check if actor is near the border of an inactive cell. If so, disable AiEscort.
|
||||||
// FIXME: This *should* pause the AiEscort package instead of terminating it.
|
// FIXME: This *should* pause the AiEscort package instead of terminating it.
|
||||||
if(sideY*(pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE / 2. - 200))
|
if(sideY*(pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE /
|
||||||
|
2.0 - 200))
|
||||||
{
|
{
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
||||||
return true;
|
return true;
|
||||||
|
@ -129,7 +133,7 @@ bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor)
|
||||||
start.mY = pos.pos[1];
|
start.mY = pos.pos[1];
|
||||||
start.mZ = pos.pos[2];
|
start.mZ = pos.pos[2];
|
||||||
|
|
||||||
mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, 1);
|
mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]))
|
if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]))
|
||||||
|
@ -143,16 +147,17 @@ bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor)
|
||||||
const float* const followerPos = follower.getRefData().getPosition().pos;
|
const float* const followerPos = follower.getRefData().getPosition().pos;
|
||||||
double differenceBetween[3];
|
double differenceBetween[3];
|
||||||
|
|
||||||
for (short i = 0; i < 3; ++i)
|
for (short counter = 0; counter < 3; counter++)
|
||||||
differenceBetween[i] = (leaderPos[i] - followerPos[i]);
|
differenceBetween[counter] = (leaderPos[counter] - followerPos[counter]);
|
||||||
|
|
||||||
float distanceBetweenResult =
|
float distanceBetweenResult =
|
||||||
(differenceBetween[0] * differenceBetween[0]) + (differenceBetween[1] * differenceBetween[1]) + (differenceBetween[2] * differenceBetween[2]);
|
(differenceBetween[0] * differenceBetween[0]) + (differenceBetween[1] * differenceBetween[1]) + (differenceBetween[2] *
|
||||||
|
differenceBetween[2]);
|
||||||
|
|
||||||
if(distanceBetweenResult <= mMaxDist * mMaxDist)
|
if(distanceBetweenResult <= mMaxDist * mMaxDist)
|
||||||
{
|
{
|
||||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0],pos.pos[1]);
|
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(actor,0,0,zAngle,false);
|
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||||
mMaxDist = 470;
|
mMaxDist = 470;
|
||||||
}
|
}
|
||||||
|
@ -165,10 +170,11 @@ bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::AiEscort::getTypeId() const
|
int AiEscort::getTypeId() const
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,44 +2,47 @@
|
||||||
|
|
||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
float sgn(float a)
|
float sgn(float a)
|
||||||
{
|
{
|
||||||
if(a > 0) return 1.;
|
if(a > 0)
|
||||||
else return -1.;
|
return 1.0;
|
||||||
|
return -1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiTravel::AiTravel(float x, float y, float z)
|
namespace MWMechanics
|
||||||
: mX(x),mY(y),mZ(z),mPathFinder()
|
|
||||||
{
|
{
|
||||||
}
|
AiTravel::AiTravel(float x, float y, float z)
|
||||||
|
: mX(x),mY(y),mZ(z),mPathFinder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
MWMechanics::AiTravel *MWMechanics::AiTravel::clone() const
|
AiTravel *MWMechanics::AiTravel::clone() const
|
||||||
{
|
{
|
||||||
return new AiTravel(*this);
|
return new AiTravel(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWMechanics::AiTravel::execute (const MWWorld::Ptr& actor)
|
bool AiTravel::execute (const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||||
|
ESM::Position pos = actor.getRefData().getPosition();
|
||||||
|
bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY;
|
||||||
const ESM::Pathgrid *pathgrid =
|
const ESM::Pathgrid *pathgrid =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
|
||||||
|
|
||||||
ESM::Position pos = actor.getRefData().getPosition();
|
|
||||||
bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY;
|
|
||||||
|
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
|
||||||
if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
|
if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
|
||||||
{
|
{
|
||||||
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
|
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
|
||||||
//check if actor is near the border of an inactive cell. If so, disable aitravel.
|
//check if actor is near the border of an inactive cell. If so, disable aitravel.
|
||||||
if(sideX*(pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX*(ESM::Land::REAL_SIZE/2. - 200))
|
if(sideX * (pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE /
|
||||||
|
2.0 - 200))
|
||||||
{
|
{
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
||||||
return true;
|
return true;
|
||||||
|
@ -49,19 +52,21 @@ bool MWMechanics::AiTravel::execute (const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
|
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
|
||||||
//check if actor is near the border of an inactive cell. If so, disable aitravel.
|
//check if actor is near the border of an inactive cell. If so, disable aitravel.
|
||||||
if(sideY*(pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY*(ESM::Land::REAL_SIZE/2. - 200))
|
if(sideY * (pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE /
|
||||||
|
2.0 - 200))
|
||||||
{
|
{
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mPathFinder.isPathConstructed() ||cellChange)
|
if(!mPathFinder.isPathConstructed() || cellChange)
|
||||||
{
|
{
|
||||||
cellX = actor.getCell()->mCell->mData.mX;
|
cellX = actor.getCell()->mCell->mData.mX;
|
||||||
cellY = actor.getCell()->mCell->mData.mY;
|
cellY = actor.getCell()->mCell->mData.mY;
|
||||||
float xCell = 0;
|
float xCell = 0;
|
||||||
float yCell = 0;
|
float yCell = 0;
|
||||||
|
|
||||||
if (actor.getCell()->mCell->isExterior())
|
if (actor.getCell()->mCell->isExterior())
|
||||||
{
|
{
|
||||||
xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE;
|
xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE;
|
||||||
|
@ -78,23 +83,25 @@ bool MWMechanics::AiTravel::execute (const MWWorld::Ptr& actor)
|
||||||
start.mY = pos.pos[1];
|
start.mY = pos.pos[1];
|
||||||
start.mZ = pos.pos[2];
|
start.mZ = pos.pos[2];
|
||||||
|
|
||||||
mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, 1);
|
mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]))
|
if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
|
||||||
{
|
{
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0],pos.pos[1]);
|
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(actor,0,0,zAngle,false);
|
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AiTravel::getTypeId() const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::AiTravel::getTypeId() const
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,14 +14,17 @@ namespace
|
||||||
{
|
{
|
||||||
float sgn(float a)
|
float sgn(float a)
|
||||||
{
|
{
|
||||||
if(a > 0) return 1.0;
|
if(a > 0)
|
||||||
else return -1.0;
|
return 1.0;
|
||||||
|
return -1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle, bool repeat):
|
namespace MWMechanics
|
||||||
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
|
|
||||||
{
|
{
|
||||||
|
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle, bool repeat):
|
||||||
|
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
|
||||||
|
{
|
||||||
for(unsigned short counter = 0; counter < mIdle.size(); counter++)
|
for(unsigned short counter = 0; counter < mIdle.size(); counter++)
|
||||||
{
|
{
|
||||||
if(mIdle[counter] >= 127 || mIdle[counter] < 0)
|
if(mIdle[counter] >= 127 || mIdle[counter] < 0)
|
||||||
|
@ -47,15 +50,15 @@ MWMechanics::AiWander::AiWander(int distance, int duration, int timeOfDay, const
|
||||||
mIdleNow = false;
|
mIdleNow = false;
|
||||||
mMoveNow = false;
|
mMoveNow = false;
|
||||||
mWalking = false;
|
mWalking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiPackage * MWMechanics::AiWander::clone() const
|
AiPackage * MWMechanics::AiWander::clone() const
|
||||||
{
|
{
|
||||||
return new AiWander(*this);
|
return new AiWander(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
|
bool AiWander::execute (const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
if(mDuration)
|
if(mDuration)
|
||||||
{
|
{
|
||||||
// End package if duration is complete or mid-night hits:
|
// End package if duration is complete or mid-night hits:
|
||||||
|
@ -114,7 +117,8 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
|
||||||
|
|
||||||
for(unsigned int counter = 0; counter < mPathgrid->mPoints.size(); counter++)
|
for(unsigned int counter = 0; counter < mPathgrid->mPoints.size(); counter++)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 nodePos(mPathgrid->mPoints[counter].mX, mPathgrid->mPoints[counter].mY, mPathgrid->mPoints[counter].mZ);
|
Ogre::Vector3 nodePos(mPathgrid->mPoints[counter].mX, mPathgrid->mPoints[counter].mY,
|
||||||
|
mPathgrid->mPoints[counter].mZ);
|
||||||
if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance)
|
if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance)
|
||||||
mAllowedNodes.push_back(mPathgrid->mPoints[counter]);
|
mAllowedNodes.push_back(mPathgrid->mPoints[counter]);
|
||||||
}
|
}
|
||||||
|
@ -125,7 +129,8 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++)
|
for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY, mAllowedNodes[counterThree].mZ);
|
Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY,
|
||||||
|
mAllowedNodes[counterThree].mZ);
|
||||||
float tempDist = npcPos.squaredDistance(nodePos);
|
float tempDist = npcPos.squaredDistance(nodePos);
|
||||||
if(tempDist < closestNode)
|
if(tempDist < closestNode)
|
||||||
index = counterThree;
|
index = counterThree;
|
||||||
|
@ -147,7 +152,8 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
|
||||||
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
|
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
|
||||||
// Check if actor is near the border of an inactive cell. If so, disable AiWander.
|
// Check if actor is near the border of an inactive cell. If so, disable AiWander.
|
||||||
// FIXME: This *should* pause the AiWander package instead of terminating it.
|
// FIXME: This *should* pause the AiWander package instead of terminating it.
|
||||||
if(sideX*(pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE / 2.0 - 200))
|
if(sideX * (pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE /
|
||||||
|
2.0 - 200))
|
||||||
{
|
{
|
||||||
stopWalking(actor);
|
stopWalking(actor);
|
||||||
return true;
|
return true;
|
||||||
|
@ -159,7 +165,8 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
|
||||||
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
|
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
|
||||||
// Check if actor is near the border of an inactive cell. If so, disable AiWander.
|
// Check if actor is near the border of an inactive cell. If so, disable AiWander.
|
||||||
// FIXME: This *should* pause the AiWander package instead of terminating it.
|
// FIXME: This *should* pause the AiWander package instead of terminating it.
|
||||||
if(sideY*(pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE / 2.0 - 200))
|
if(sideY * (pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE /
|
||||||
|
2.0 - 200))
|
||||||
{
|
{
|
||||||
stopWalking(actor);
|
stopWalking(actor);
|
||||||
return true;
|
return true;
|
||||||
|
@ -229,7 +236,7 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
|
||||||
start.mY = pos.pos[1];
|
start.mY = pos.pos[1];
|
||||||
start.mZ = pos.pos[2];
|
start.mZ = pos.pos[2];
|
||||||
|
|
||||||
mPathFinder.buildPath(start, dest, mPathgrid, mXCell, mYCell, 0);
|
mPathFinder.buildPath(start, dest, mPathgrid, mXCell, mYCell, false);
|
||||||
|
|
||||||
if(mPathFinder.isPathConstructed())
|
if(mPathFinder.isPathConstructed())
|
||||||
{
|
{
|
||||||
|
@ -250,8 +257,8 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
|
||||||
|
|
||||||
if(mWalking)
|
if(mWalking)
|
||||||
{
|
{
|
||||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0],pos.pos[1]);
|
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(actor,0,0,zAngle,false);
|
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle,false);
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||||
|
|
||||||
// Unclog path nodes by allowing the NPC to be a small distance away from the center. This way two NPCs can be
|
// Unclog path nodes by allowing the NPC to be a small distance away from the center. This way two NPCs can be
|
||||||
|
@ -272,21 +279,21 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::AiWander::getTypeId() const
|
int AiWander::getTypeId() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWMechanics::AiWander::stopWalking(const MWWorld::Ptr& actor)
|
void AiWander::stopWalking(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
mPathFinder.clearPath();
|
mPathFinder.clearPath();
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWMechanics::AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
void AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
||||||
{
|
{
|
||||||
if(idleSelect == 2)
|
if(idleSelect == 2)
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle2", 0, 1);
|
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle2", 0, 1);
|
||||||
else if(idleSelect == 3)
|
else if(idleSelect == 3)
|
||||||
|
@ -303,10 +310,10 @@ void MWMechanics::AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short i
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle8", 0, 1);
|
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle8", 0, 1);
|
||||||
else if(idleSelect == 9)
|
else if(idleSelect == 9)
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle9", 0, 1);
|
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle9", 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWMechanics::AiWander::checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
bool AiWander::checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
||||||
{
|
{
|
||||||
if(idleSelect == 2)
|
if(idleSelect == 2)
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle2");
|
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle2");
|
||||||
else if(idleSelect == 3)
|
else if(idleSelect == 3)
|
||||||
|
@ -325,5 +332,6 @@ bool MWMechanics::AiWander::checkIdle(const MWWorld::Ptr& actor, unsigned short
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle9");
|
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle9");
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ namespace MWMechanics
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
ESM::Pathgrid::Point nextPoint = *mPath.begin();
|
ESM::Pathgrid::Point nextPoint = *mPath.begin();
|
||||||
if(distanceZCorrected(nextPoint, x, y, z) < 20)
|
if(distanceZCorrected(nextPoint, x, y, z) < 40)
|
||||||
{
|
{
|
||||||
mPath.pop_front();
|
mPath.pop_front();
|
||||||
if(mPath.empty())
|
if(mPath.empty())
|
||||||
|
|
Loading…
Reference in a new issue