Store original actor position in AiWander package (Fixes #2200)

This commit is contained in:
scrawl 2014-12-31 21:27:19 +01:00
parent 5d7eb11596
commit 01652bbcc5
7 changed files with 81 additions and 45 deletions

View file

@ -70,6 +70,7 @@ namespace MWMechanics
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
, mStoredInitialActorPosition(false)
{
mIdle.resize(8, 0);
init();
@ -675,6 +676,12 @@ namespace MWMechanics
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell)
{
if (!mStoredInitialActorPosition)
{
mInitialActorPosition = Ogre::Vector3(actor.getRefData().getPosition().pos);
mStoredInitialActorPosition = true;
}
// infrequently used, therefore no benefit in caching it as a member
const ESM::Pathgrid *
pathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell);
@ -699,13 +706,8 @@ namespace MWMechanics
cellYOffset = cell->mData.mY * ESM::Land::REAL_SIZE;
}
// FIXME: There might be a bug here. The allowed node points are
// based on the actor's current position rather than the actor's
// spawn point. As a result the allowed nodes for wander can change
// between saves, for example.
//
// convert npcPos to local (i.e. cell) co-ordinates
Ogre::Vector3 npcPos(actor.getRefData().getPosition().pos);
Ogre::Vector3 npcPos(mInitialActorPosition);
npcPos[0] = npcPos[0] - cellXOffset;
npcPos[1] = npcPos[1] - cellYOffset;
@ -750,6 +752,9 @@ namespace MWMechanics
for (int i=0; i<8; ++i)
wander->mData.mIdle[i] = mIdle[i];
wander->mData.mShouldRepeat = mRepeat;
wander->mStoredInitialActorPosition = mStoredInitialActorPosition;
if (mStoredInitialActorPosition)
wander->mInitialActorPosition = mInitialActorPosition;
ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Wander;
@ -763,6 +768,7 @@ namespace MWMechanics
, mStartTime(MWWorld::TimeStamp(wander->mStartTime))
, mTimeOfDay(wander->mData.mTimeOfDay)
, mRepeat(wander->mData.mShouldRepeat)
, mStoredInitialActorPosition(wander->mStoredInitialActorPosition)
{
for (int i=0; i<8; ++i)
mIdle.push_back(wander->mData.mIdle[i]);

View file

@ -84,7 +84,8 @@ namespace MWMechanics
// if we had the actor in the AiWander constructor...
Ogre::Vector3 mReturnPosition;
Ogre::Vector3 mInitialActorPosition;
bool mStoredInitialActorPosition;

View file

@ -46,7 +46,7 @@ add_component_dir (esm
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
aisequence magiceffects
aisequence magiceffects util
)
add_component_dir (esmterrain

View file

@ -16,12 +16,20 @@ namespace AiSequence
{
esm.getHNT (mData, "DATA");
esm.getHNT(mStartTime, "STAR");
mStoredInitialActorPosition = false;
if (esm.isNextSub("POS_"))
{
mStoredInitialActorPosition = true;
esm.getHT(mInitialActorPosition);
}
}
void AiWander::save(ESMWriter &esm) const
{
esm.writeHNT ("DATA", mData);
esm.writeHNT ("STAR", mStartTime);
if (mStoredInitialActorPosition)
esm.writeHNT ("POS_", mInitialActorPosition);
}
void AiTravel::load(ESMReader &esm)

View file

@ -6,6 +6,8 @@
#include "defs.hpp"
#include "util.hpp"
namespace ESM
{
class ESMReader;
@ -61,6 +63,9 @@ namespace ESM
AiWanderData mData;
ESM::TimeStamp mStartTime;
bool mStoredInitialActorPosition;
ESM::Vector3 mInitialActorPosition;
/// \todo add more AiWander state
void load(ESMReader &esm);

View file

@ -8,48 +8,13 @@
#include "effectlist.hpp"
#include "util.hpp"
namespace ESM
{
// format 0, savegames only
struct Quaternion
{
float mValues[4];
Quaternion() {}
Quaternion (Ogre::Quaternion q)
{
mValues[0] = q.w;
mValues[1] = q.x;
mValues[2] = q.y;
mValues[3] = q.z;
}
operator Ogre::Quaternion () const
{
return Ogre::Quaternion(mValues[0], mValues[1], mValues[2], mValues[3]);
}
};
struct Vector3
{
float mValues[3];
Vector3() {}
Vector3 (Ogre::Vector3 v)
{
mValues[0] = v.x;
mValues[1] = v.y;
mValues[2] = v.z;
}
operator Ogre::Vector3 () const
{
return Ogre::Vector3(&mValues[0]);
}
};
struct BaseProjectileState
{
std::string mId;

51
components/esm/util.hpp Normal file
View file

@ -0,0 +1,51 @@
#ifndef OPENMW_ESM_UTIL_H
#define OPENMW_ESM_UTIL_H
#include <OgreVector3.h>
#include <OgreQuaternion.h>
namespace ESM
{
// format 0, savegames only
struct Quaternion
{
float mValues[4];
Quaternion() {}
Quaternion (Ogre::Quaternion q)
{
mValues[0] = q.w;
mValues[1] = q.x;
mValues[2] = q.y;
mValues[3] = q.z;
}
operator Ogre::Quaternion () const
{
return Ogre::Quaternion(mValues[0], mValues[1], mValues[2], mValues[3]);
}
};
struct Vector3
{
float mValues[3];
Vector3() {}
Vector3 (Ogre::Vector3 v)
{
mValues[0] = v.x;
mValues[1] = v.y;
mValues[2] = v.z;
}
operator Ogre::Vector3 () const
{
return Ogre::Vector3(&mValues[0]);
}
};
}
#endif