Merge pull request #954 from Allofich/AIWanderDuration

Improve duration calculations in Wander AI
This commit is contained in:
scrawl 2016-06-09 23:46:37 +02:00 committed by GitHub
commit a14f1bc222
4 changed files with 35 additions and 20 deletions

View file

@ -97,8 +97,8 @@ 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), mRemainingDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle),
, mStoredInitialActorPosition(false) mRepeat(repeat), mStoredInitialActorPosition(false)
{ {
mIdle.resize(8, 0); mIdle.resize(8, 0);
init(); init();
@ -122,6 +122,11 @@ namespace MWMechanics
mDuration = 0; mDuration = 0;
if(mDuration == 0) if(mDuration == 0)
mTimeOfDay = 0; mTimeOfDay = 0;
if(mDuration > 24)
{
mDuration = 24;
mRemainingDuration = (mDuration);
}
mPopulateAvailableNodes = true; mPopulateAvailableNodes = true;
@ -200,12 +205,7 @@ namespace MWMechanics
mPopulateAvailableNodes = true; mPopulateAvailableNodes = true;
} }
if (!mStarted) mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
{
// Set mStartTime once this package starts being executed
mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp();
mStarted = true;
}
cStats.setDrawState(DrawState_Nothing); cStats.setDrawState(DrawState_Nothing);
cStats.setMovementFlag(CreatureStats::Flag_Run, false); cStats.setMovementFlag(CreatureStats::Flag_Run, false);
@ -235,8 +235,9 @@ namespace MWMechanics
if (isPackageCompleted(actor, storage)) if (isPackageCompleted(actor, storage))
{ {
// Reset mStarted so that package will get a new mStarttime when it repeats // Reset package so it can be used again
mStarted = false; mRemainingDuration=mDuration;
init();
return true; return true;
} }
@ -317,10 +318,8 @@ namespace MWMechanics
{ {
if (mDuration) if (mDuration)
{ {
// End package if duration is complete or mid-night hits: // End package if duration is complete
MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp(); if (mRemainingDuration <= 0)
if ((currentTime.getHour() >= mStartTime.getHour() + mDuration) ||
(int(currentTime.getHour()) == 0 && currentTime.getDay() != mStartTime.getDay()))
{ {
stopWalking(actor, storage); stopWalking(actor, storage);
return true; return true;
@ -784,6 +783,8 @@ namespace MWMechanics
void AiWander::fastForward(const MWWorld::Ptr& actor, AiState &state) void AiWander::fastForward(const MWWorld::Ptr& actor, AiState &state)
{ {
// Update duration counter
mRemainingDuration--;
if (mDistance == 0) if (mDistance == 0)
return; return;
@ -923,11 +924,17 @@ namespace MWMechanics
void AiWander::writeState(ESM::AiSequence::AiSequence &sequence) const void AiWander::writeState(ESM::AiSequence::AiSequence &sequence) const
{ {
float remainingDuration;
if (mRemainingDuration > 0 && mRemainingDuration < 24)
remainingDuration = mRemainingDuration;
else
remainingDuration = mDuration;
std::auto_ptr<ESM::AiSequence::AiWander> wander(new ESM::AiSequence::AiWander()); std::auto_ptr<ESM::AiSequence::AiWander> wander(new ESM::AiSequence::AiWander());
wander->mData.mDistance = mDistance; wander->mData.mDistance = mDistance;
wander->mData.mDuration = mDuration; wander->mData.mDuration = mDuration;
wander->mData.mTimeOfDay = mTimeOfDay; wander->mData.mTimeOfDay = mTimeOfDay;
wander->mStartTime = mStartTime.toEsm(); wander->mDurationData.mRemainingDuration = remainingDuration;
assert (mIdle.size() == 8); assert (mIdle.size() == 8);
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];
@ -945,15 +952,18 @@ namespace MWMechanics
AiWander::AiWander (const ESM::AiSequence::AiWander* wander) AiWander::AiWander (const ESM::AiSequence::AiWander* wander)
: mDistance(wander->mData.mDistance) : mDistance(wander->mData.mDistance)
, mDuration(wander->mData.mDuration) , mDuration(wander->mData.mDuration)
, mRemainingDuration(wander->mDurationData.mRemainingDuration)
, mTimeOfDay(wander->mData.mTimeOfDay) , mTimeOfDay(wander->mData.mTimeOfDay)
, mRepeat(wander->mData.mShouldRepeat != 0) , mRepeat(wander->mData.mShouldRepeat != 0)
, mStoredInitialActorPosition(wander->mStoredInitialActorPosition) , mStoredInitialActorPosition(wander->mStoredInitialActorPosition)
, mStartTime(MWWorld::TimeStamp(wander->mStartTime))
{ {
if (mStoredInitialActorPosition) if (mStoredInitialActorPosition)
mInitialActorPosition = wander->mInitialActorPosition; mInitialActorPosition = wander->mInitialActorPosition;
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]);
if (mRemainingDuration <= 0 || mRemainingDuration >= 24)
mRemainingDuration = mDuration;
init(); init();
} }

View file

@ -103,6 +103,7 @@ namespace MWMechanics
int mDistance; // how far the actor can wander from the spawn point int mDistance; // how far the actor can wander from the spawn point
int mDuration; int mDuration;
float mRemainingDuration;
int mTimeOfDay; int mTimeOfDay;
std::vector<unsigned char> mIdle; std::vector<unsigned char> mIdle;
bool mRepeat; bool mRepeat;
@ -123,7 +124,6 @@ namespace MWMechanics
MWWorld::TimeStamp mStartTime;
// allowed pathgrid nodes based on mDistance from the spawn point // allowed pathgrid nodes based on mDistance from the spawn point
// in local coordinates of mCell // in local coordinates of mCell

View file

@ -15,7 +15,7 @@ namespace AiSequence
void AiWander::load(ESMReader &esm) void AiWander::load(ESMReader &esm)
{ {
esm.getHNT (mData, "DATA"); esm.getHNT (mData, "DATA");
esm.getHNT(mStartTime, "STAR"); esm.getHNT(mDurationData, "STAR");
mStoredInitialActorPosition = false; mStoredInitialActorPosition = false;
if (esm.isNextSub("POS_")) if (esm.isNextSub("POS_"))
{ {
@ -27,7 +27,7 @@ namespace AiSequence
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", mDurationData);
if (mStoredInitialActorPosition) if (mStoredInitialActorPosition)
esm.writeHNT ("POS_", mInitialActorPosition); esm.writeHNT ("POS_", mInitialActorPosition);
} }

View file

@ -46,6 +46,11 @@ namespace ESM
unsigned char mIdle[8]; unsigned char mIdle[8];
unsigned char mShouldRepeat; unsigned char mShouldRepeat;
}; };
struct AiWanderDuration
{
float mRemainingDuration;
int unused;
};
struct AiTravelData struct AiTravelData
{ {
float mX, mY, mZ; float mX, mY, mZ;
@ -61,7 +66,7 @@ namespace ESM
struct AiWander : AiPackage struct AiWander : AiPackage
{ {
AiWanderData mData; AiWanderData mData;
ESM::TimeStamp mStartTime; AiWanderDuration mDurationData; // was ESM::TimeStamp mStartTime;
bool mStoredInitialActorPosition; bool mStoredInitialActorPosition;
ESM::Vector3 mInitialActorPosition; ESM::Vector3 mInitialActorPosition;