1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 18:49:54 +00:00
openmw-tes3mp/apps/openmw/mwmechanics/aiescort.cpp

151 lines
5.7 KiB
C++
Raw Normal View History

2012-11-14 17:42:04 +00:00
#include "aiescort.hpp"
2014-06-12 21:27:04 +00:00
#include <components/esm/aisequence.hpp>
2015-12-06 22:32:20 +00:00
#include <components/esm/loadcell.hpp>
2014-06-12 21:27:04 +00:00
2013-05-09 03:02:24 +00:00
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
2013-05-09 03:02:24 +00:00
#include "../mwbase/mechanicsmanager.hpp"
2014-02-23 19:11:05 +00:00
#include "../mwworld/class.hpp"
2015-12-06 22:32:20 +00:00
#include "../mwworld/cellstore.hpp"
2014-02-23 19:11:05 +00:00
2016-06-17 14:07:16 +00:00
#include "creaturestats.hpp"
2014-01-29 19:29:07 +00:00
#include "steering.hpp"
2014-02-23 19:11:05 +00:00
#include "movement.hpp"
2014-01-29 19:29:07 +00:00
2013-05-09 03:02:24 +00:00
/*
TODO: Different behavior for AIEscort a d x y z and AIEscortCell a c d x y z.
TODO: Take account for actors being in different cells.
*/
namespace MWMechanics
{
AiEscort::AiEscort(const std::string &actorId, int duration, float x, float y, float z)
: mX(x), mY(y), mZ(z), mDuration(duration), mRemainingDuration(static_cast<float>(duration))
2014-01-12 21:47:22 +00:00
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = actorId;
2014-09-19 03:46:59 +00:00
mMaxDist = 450;
}
2012-11-30 00:16:16 +00:00
AiEscort::AiEscort(const std::string &actorId, const std::string &cellId, int duration, float x, float y, float z)
: mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration), mRemainingDuration(static_cast<float>(duration))
2014-01-12 21:47:22 +00:00
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = actorId;
2014-09-19 03:46:59 +00:00
mMaxDist = 450;
2014-06-12 21:27:04 +00:00
}
2014-06-12 21:27:04 +00:00
AiEscort::AiEscort(const ESM::AiSequence::AiEscort *escort)
: mCellId(escort->mCellId), mX(escort->mData.mX), mY(escort->mData.mY), mZ(escort->mData.mZ)
, mMaxDist(450)
, mRemainingDuration(escort->mRemainingDuration)
2014-06-12 21:27:04 +00:00
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = escort->mTargetId;
mTargetActorId = escort->mTargetActorId;
2016-06-11 13:34:49 +00:00
// mDuration isn't saved in the save file, so just giving it "1" for now if the package has a duration.
// The exact value of mDuration only matters for repeating packages.
if (mRemainingDuration > 0) // Previously mRemainingDuration could be negative even when mDuration was 0. Checking for > 0 should fix old saves.
2016-06-11 13:34:49 +00:00
mDuration = 1;
else
mDuration = 0;
}
AiEscort *MWMechanics::AiEscort::clone() const
{
return new AiEscort(*this);
}
bool AiEscort::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
{
// If AiEscort has ran for as long or longer then the duration specified
// and the duration is not infinite, the package is complete.
if (mDuration > 0)
{
2016-06-11 13:34:49 +00:00
mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
if (mRemainingDuration <= 0)
{
2016-06-11 13:34:49 +00:00
mRemainingDuration = mDuration;
return true;
}
}
2015-12-06 22:32:20 +00:00
if (!mCellId.empty() && mCellId != actor.getCell()->getCell()->getCellId().mWorldspace)
return false; // Not in the correct cell, pause and rely on the player to go back through a teleport door
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false);
const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->getPtr(mTargetActorRefId, false);
const float* const leaderPos = actor.getRefData().getPosition().pos;
const float* const followerPos = follower.getRefData().getPosition().pos;
double differenceBetween[3];
for (short counter = 0; counter < 3; counter++)
differenceBetween[counter] = (leaderPos[counter] - followerPos[counter]);
double distanceBetweenResult =
(differenceBetween[0] * differenceBetween[0]) + (differenceBetween[1] * differenceBetween[1]) + (differenceBetween[2] *
differenceBetween[2]);
if (distanceBetweenResult <= mMaxDist * mMaxDist)
{
ESM::Pathgrid::Point point(static_cast<int>(mX), static_cast<int>(mY), static_cast<int>(mZ));
2014-09-28 10:44:47 +00:00
point.mAutogenerated = 0;
point.mConnectionNum = 0;
point.mUnknown = 0;
if (pathTo(actor,point,duration)) //Returns true on path complete
{
2016-06-11 13:34:49 +00:00
mRemainingDuration = mDuration;
return true;
}
2014-09-19 03:46:59 +00:00
mMaxDist = 450;
}
else
{
2016-06-15 18:43:09 +00:00
// Stop moving if the player is too far away
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1);
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
2014-09-19 03:46:59 +00:00
mMaxDist = 250;
}
return false;
}
int AiEscort::getTypeId() const
{
return TypeIdEscort;
}
2014-06-12 21:27:04 +00:00
void AiEscort::writeState(ESM::AiSequence::AiSequence &sequence) const
{
std::unique_ptr<ESM::AiSequence::AiEscort> escort(new ESM::AiSequence::AiEscort());
2014-06-12 21:27:04 +00:00
escort->mData.mX = mX;
escort->mData.mY = mY;
escort->mData.mZ = mZ;
escort->mTargetId = mTargetActorRefId;
escort->mTargetActorId = mTargetActorId;
2014-06-12 21:27:04 +00:00
escort->mRemainingDuration = mRemainingDuration;
escort->mCellId = mCellId;
ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Escort;
package.mPackage = escort.release();
sequence.mPackages.push_back(package);
}
2016-06-11 13:34:49 +00:00
void AiEscort::fastForward(const MWWorld::Ptr& actor, AiState &state)
{
// Update duration counter if this package has a duration
if (mDuration > 0)
mRemainingDuration--;
}
2012-11-30 00:16:16 +00:00
}