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): 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) mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
, mStoredInitialActorPosition(false)
{ {
mIdle.resize(8, 0); mIdle.resize(8, 0);
init(); init();
@ -675,6 +676,12 @@ namespace MWMechanics
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell) 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 // infrequently used, therefore no benefit in caching it as a member
const ESM::Pathgrid * const ESM::Pathgrid *
pathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell); 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; 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 // 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[0] = npcPos[0] - cellXOffset;
npcPos[1] = npcPos[1] - cellYOffset; npcPos[1] = npcPos[1] - cellYOffset;
@ -750,6 +752,9 @@ namespace MWMechanics
for (int i=0; i<8; ++i) for (int i=0; i<8; ++i)
wander->mData.mIdle[i] = mIdle[i]; wander->mData.mIdle[i] = mIdle[i];
wander->mData.mShouldRepeat = mRepeat; wander->mData.mShouldRepeat = mRepeat;
wander->mStoredInitialActorPosition = mStoredInitialActorPosition;
if (mStoredInitialActorPosition)
wander->mInitialActorPosition = mInitialActorPosition;
ESM::AiSequence::AiPackageContainer package; ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Wander; package.mType = ESM::AiSequence::Ai_Wander;
@ -763,6 +768,7 @@ namespace MWMechanics
, mStartTime(MWWorld::TimeStamp(wander->mStartTime)) , mStartTime(MWWorld::TimeStamp(wander->mStartTime))
, mTimeOfDay(wander->mData.mTimeOfDay) , mTimeOfDay(wander->mData.mTimeOfDay)
, mRepeat(wander->mData.mShouldRepeat) , mRepeat(wander->mData.mShouldRepeat)
, mStoredInitialActorPosition(wander->mStoredInitialActorPosition)
{ {
for (int i=0; i<8; ++i) for (int i=0; i<8; ++i)
mIdle.push_back(wander->mData.mIdle[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... // if we had the actor in the AiWander constructor...
Ogre::Vector3 mReturnPosition; 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 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 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 npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
aisequence magiceffects aisequence magiceffects util
) )
add_component_dir (esmterrain add_component_dir (esmterrain

View file

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

View file

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

View file

@ -8,48 +8,13 @@
#include "effectlist.hpp" #include "effectlist.hpp"
#include "util.hpp"
namespace ESM namespace ESM
{ {
// format 0, savegames only // 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 struct BaseProjectileState
{ {
std::string mId; 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