1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-30 21:32:42 +00:00
OpenMW/apps/openmw/mwmechanics/aiescort.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

140 lines
5.1 KiB
C++
Raw Normal View History

2012-11-14 18:42:04 +01:00
#include "aiescort.hpp"
#include <components/esm3/aisequence.hpp>
#include <components/esm3/loadcell.hpp>
#include "../mwbase/environment.hpp"
2013-05-08 20:02:24 -07:00
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/world.hpp"
2015-12-06 23:32:20 +01:00
#include "../mwworld/cellstore.hpp"
2014-02-23 20:11:05 +01:00
#include "../mwworld/class.hpp"
2016-06-17 23:07:16 +09:00
#include "creaturestats.hpp"
2014-02-23 20:11:05 +01:00
#include "movement.hpp"
2013-05-08 20:02:24 -07: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(std::string_view actorId, int duration, float x, float y, float z, bool repeat)
: TypedAiPackage<AiEscort>(repeat)
, mX(x)
, mY(y)
, mZ(z)
, mDuration(duration)
, mRemainingDuration(static_cast<float>(duration))
2014-01-12 22:47:22 +01:00
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = std::string(actorId);
}
AiEscort::AiEscort(
std::string_view actorId, std::string_view cellId, int duration, float x, float y, float z, bool repeat)
: TypedAiPackage<AiEscort>(repeat)
, mCellId(cellId)
, mX(x)
, mY(y)
, mZ(z)
, mDuration(duration)
, mRemainingDuration(static_cast<float>(duration))
2014-01-12 22:47:22 +01:00
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = std::string(actorId);
2014-06-12 23:27:04 +02:00
}
2014-06-12 23:27:04 +02:00
AiEscort::AiEscort(const ESM::AiSequence::AiEscort* escort)
2021-11-17 20:44:55 +01:00
: TypedAiPackage<AiEscort>(escort->mRepeat)
, mCellId(escort->mCellId)
, mX(escort->mData.mX)
, mY(escort->mData.mY)
, mZ(escort->mData.mZ)
, mDuration(escort->mData.mDuration)
, mRemainingDuration(escort->mRemainingDuration)
2014-06-12 23:27:04 +02:00
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = escort->mTargetId;
mTargetActorId = escort->mTargetActorId;
}
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 22:34:49 +09:00
mRemainingDuration -= ((duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
if (mRemainingDuration <= 0)
{
2016-06-11 22:34:49 +09:00
mRemainingDuration = mDuration;
return true;
}
}
2015-12-06 23:32:20 +01: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);
2018-11-02 14:24:43 +03:00
const osg::Vec3f leaderPos = actor.getRefData().getPosition().asVec3();
const osg::Vec3f followerPos = follower.getRefData().getPosition().asVec3();
const osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
const float maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
2018-11-02 14:24:43 +03:00
if ((leaderPos - followerPos).length2() <= mMaxDist * mMaxDist)
{
2018-11-02 14:24:43 +03:00
const osg::Vec3f dest(mX, mY, mZ);
if (pathTo(actor, dest, duration, maxHalfExtent)) // Returns true on path complete
{
2016-06-11 22:34:49 +09:00
mRemainingDuration = mDuration;
return true;
}
mMaxDist = maxHalfExtent + 450.0f;
}
else
{
2016-06-16 03:43:09 +09: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;
mMaxDist = maxHalfExtent + 250.0f;
}
return false;
}
2014-06-12 23:27:04 +02:00
void AiEscort::writeState(ESM::AiSequence::AiSequence& sequence) const
{
2022-05-29 13:24:48 +02:00
auto escort = std::make_unique<ESM::AiSequence::AiEscort>();
2014-06-12 23:27:04 +02:00
escort->mData.mX = mX;
escort->mData.mY = mY;
escort->mData.mZ = mZ;
2021-11-17 20:44:55 +01:00
escort->mData.mDuration = mDuration;
escort->mTargetId = mTargetActorRefId;
escort->mTargetActorId = mTargetActorId;
2014-06-12 23:27:04 +02:00
escort->mRemainingDuration = mRemainingDuration;
escort->mCellId = mCellId;
2021-11-17 20:44:55 +01:00
escort->mRepeat = getRepeat();
2014-06-12 23:27:04 +02:00
ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Escort;
package.mPackage = std::move(escort);
sequence.mPackages.push_back(std::move(package));
2014-06-12 23:27:04 +02: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 02:16:16 +02:00
}