mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-28 16:39:39 +00:00
Replace AiPackage virtual methods by options
This commit is contained in:
parent
3b1c717ab9
commit
5b34ef224b
26 changed files with 218 additions and 196 deletions
|
@ -44,11 +44,6 @@ namespace MWMechanics
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiActivate::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdActivate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AiActivate::writeState(ESM::AiSequence::AiSequence &sequence) const
|
void AiActivate::writeState(ESM::AiSequence::AiSequence &sequence) const
|
||||||
{
|
{
|
||||||
std::unique_ptr<ESM::AiSequence::AiActivate> activate(new ESM::AiSequence::AiActivate());
|
std::unique_ptr<ESM::AiSequence::AiActivate> activate(new ESM::AiSequence::AiActivate());
|
||||||
|
|
|
@ -29,7 +29,8 @@ namespace MWMechanics
|
||||||
AiActivate(const ESM::AiSequence::AiActivate* activate);
|
AiActivate(const ESM::AiSequence::AiActivate* activate);
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
int getTypeId() const final;
|
|
||||||
|
static constexpr TypeId getTypeId() { return TypeIdActivate; }
|
||||||
|
|
||||||
void writeState(ESM::AiSequence::AiSequence& sequence) const final;
|
void writeState(ESM::AiSequence::AiSequence& sequence) const final;
|
||||||
|
|
||||||
|
|
|
@ -72,16 +72,6 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterCont
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::AiAvoidDoor::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdAvoidDoor;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MWMechanics::AiAvoidDoor::getPriority() const
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MWMechanics::AiAvoidDoor::isStuck(const osg::Vec3f& actorPos) const
|
bool MWMechanics::AiAvoidDoor::isStuck(const osg::Vec3f& actorPos) const
|
||||||
{
|
{
|
||||||
return (actorPos - mLastPos).length2() < 10 * 10;
|
return (actorPos - mLastPos).length2() < 10 * 10;
|
||||||
|
|
|
@ -24,12 +24,16 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdAvoidDoor; }
|
||||||
|
|
||||||
unsigned int getPriority() const final;
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
bool canCancel() const final { return false; }
|
AiPackage::Options options;
|
||||||
bool shouldCancelPreviousAi() const final { return false; }
|
options.mPriority = 2;
|
||||||
|
options.mCanCancel = false;
|
||||||
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mDuration;
|
float mDuration;
|
||||||
|
|
|
@ -31,13 +31,3 @@ bool MWMechanics::AiBreathe::execute (const MWWorld::Ptr& actor, CharacterContro
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::AiBreathe::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdBreathe;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MWMechanics::AiBreathe::getPriority() const
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,13 +12,16 @@ namespace MWMechanics
|
||||||
public:
|
public:
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdBreathe; }
|
||||||
|
|
||||||
unsigned int getPriority() const final;
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
bool canCancel() const final { return false; }
|
AiPackage::Options options;
|
||||||
bool shouldCancelPreviousAi() const final { return false; }
|
options.mPriority = 2;
|
||||||
|
options.mCanCancel = false;
|
||||||
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -89,13 +89,3 @@ MWWorld::Ptr MWMechanics::AiCast::getTarget() const
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::AiCast::getTypeId() const
|
|
||||||
{
|
|
||||||
return AiPackage::TypeIdCast;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MWMechanics::AiCast::getPriority() const
|
|
||||||
{
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,14 +17,18 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdCast; }
|
||||||
|
|
||||||
MWWorld::Ptr getTarget() const final;
|
MWWorld::Ptr getTarget() const final;
|
||||||
|
|
||||||
unsigned int getPriority() const final;
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
bool canCancel() const final { return false; }
|
AiPackage::Options options;
|
||||||
bool shouldCancelPreviousAi() const final { return false; }
|
options.mPriority = 3;
|
||||||
|
options.mCanCancel = false;
|
||||||
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string mTargetId;
|
const std::string mTargetId;
|
||||||
|
|
|
@ -406,16 +406,6 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiCombat::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdCombat;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int AiCombat::getPriority() const
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MWWorld::Ptr AiCombat::getTarget() const
|
MWWorld::Ptr AiCombat::getTarget() const
|
||||||
{
|
{
|
||||||
return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId);
|
return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId);
|
||||||
|
|
|
@ -104,18 +104,22 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdCombat; }
|
||||||
|
|
||||||
unsigned int getPriority() const final;
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
|
AiPackage::Options options;
|
||||||
|
options.mPriority = 1;
|
||||||
|
options.mCanCancel = false;
|
||||||
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
///Returns target ID
|
///Returns target ID
|
||||||
MWWorld::Ptr getTarget() const final;
|
MWWorld::Ptr getTarget() const final;
|
||||||
|
|
||||||
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
||||||
|
|
||||||
bool canCancel() const final { return false; }
|
|
||||||
bool shouldCancelPreviousAi() const final { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Returns true if combat should end
|
/// Returns true if combat should end
|
||||||
bool attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController);
|
bool attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController);
|
||||||
|
|
|
@ -95,11 +95,6 @@ namespace MWMechanics
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiEscort::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdEscort;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AiEscort::writeState(ESM::AiSequence::AiSequence &sequence) const
|
void AiEscort::writeState(ESM::AiSequence::AiSequence &sequence) const
|
||||||
{
|
{
|
||||||
std::unique_ptr<ESM::AiSequence::AiEscort> escort(new ESM::AiSequence::AiEscort());
|
std::unique_ptr<ESM::AiSequence::AiEscort> escort(new ESM::AiSequence::AiEscort());
|
||||||
|
|
|
@ -32,11 +32,15 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdEscort; }
|
||||||
|
|
||||||
bool useVariableSpeed() const final { return true; }
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
bool sideWithTarget() const final { return true; }
|
AiPackage::Options options;
|
||||||
|
options.mUseVariableSpeed = true;
|
||||||
|
options.mSideWithTarget = true;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,3 @@ bool MWMechanics::AiFace::execute(const MWWorld::Ptr& actor, MWMechanics::Charac
|
||||||
osg::Vec3f dir = osg::Vec3f(mTargetX, mTargetY, 0) - actor.getRefData().getPosition().asVec3();
|
osg::Vec3f dir = osg::Vec3f(mTargetX, mTargetY, 0) - actor.getRefData().getPosition().asVec3();
|
||||||
return zTurn(actor, std::atan2(dir.x(), dir.y()), osg::DegreesToRadians(3.f));
|
return zTurn(actor, std::atan2(dir.x(), dir.y()), osg::DegreesToRadians(3.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::AiFace::getTypeId() const
|
|
||||||
{
|
|
||||||
return AiPackage::TypeIdFace;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MWMechanics::AiFace::getPriority() const
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,12 +12,16 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdFace; }
|
||||||
|
|
||||||
unsigned int getPriority() const final;
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
bool canCancel() const final { return false; }
|
AiPackage::Options options;
|
||||||
bool shouldCancelPreviousAi() const final { return false; }
|
options.mPriority = 2;
|
||||||
|
options.mCanCancel = false;
|
||||||
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const float mTargetX;
|
const float mTargetX;
|
||||||
|
|
|
@ -16,25 +16,24 @@
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
|
||||||
int AiFollow::mFollowIndexCounter = 0;
|
int AiFollow::mFollowIndexCounter = 0;
|
||||||
|
|
||||||
AiFollow::AiFollow(const std::string &actorId, float duration, float x, float y, float z)
|
AiFollow::AiFollow(const std::string &actorId, float duration, float x, float y, float z)
|
||||||
: mAlwaysFollow(false), mCommanded(false), mDuration(duration), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
: mAlwaysFollow(false), mDuration(duration), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
||||||
, mCellId(""), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
, mCellId(""), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
||||||
{
|
{
|
||||||
mTargetActorRefId = actorId;
|
mTargetActorRefId = actorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
AiFollow::AiFollow(const std::string &actorId, const std::string &cellId, float duration, float x, float y, float z)
|
AiFollow::AiFollow(const std::string &actorId, const std::string &cellId, float duration, float x, float y, float z)
|
||||||
: mAlwaysFollow(false), mCommanded(false), mDuration(duration), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
: mAlwaysFollow(false), mDuration(duration), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
||||||
, mCellId(cellId), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
, mCellId(cellId), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
||||||
{
|
{
|
||||||
mTargetActorRefId = actorId;
|
mTargetActorRefId = actorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
AiFollow::AiFollow(const MWWorld::Ptr& actor, float duration, float x, float y, float z)
|
AiFollow::AiFollow(const MWWorld::Ptr& actor, float duration, float x, float y, float z)
|
||||||
: mAlwaysFollow(false), mCommanded(false), mDuration(duration), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
: mAlwaysFollow(false), mDuration(duration), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
||||||
, mCellId(""), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
, mCellId(""), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
||||||
{
|
{
|
||||||
mTargetActorRefId = actor.getCellRef().getRefId();
|
mTargetActorRefId = actor.getCellRef().getRefId();
|
||||||
|
@ -42,7 +41,7 @@ AiFollow::AiFollow(const MWWorld::Ptr& actor, float duration, float x, float y,
|
||||||
}
|
}
|
||||||
|
|
||||||
AiFollow::AiFollow(const MWWorld::Ptr& actor, const std::string &cellId, float duration, float x, float y, float z)
|
AiFollow::AiFollow(const MWWorld::Ptr& actor, const std::string &cellId, float duration, float x, float y, float z)
|
||||||
: mAlwaysFollow(false), mCommanded(false), mDuration(duration), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
: mAlwaysFollow(false), mDuration(duration), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
||||||
, mCellId(cellId), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
, mCellId(cellId), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
||||||
{
|
{
|
||||||
mTargetActorRefId = actor.getCellRef().getRefId();
|
mTargetActorRefId = actor.getCellRef().getRefId();
|
||||||
|
@ -50,7 +49,8 @@ AiFollow::AiFollow(const MWWorld::Ptr& actor, const std::string &cellId, float d
|
||||||
}
|
}
|
||||||
|
|
||||||
AiFollow::AiFollow(const MWWorld::Ptr& actor, bool commanded)
|
AiFollow::AiFollow(const MWWorld::Ptr& actor, bool commanded)
|
||||||
: mAlwaysFollow(true), mCommanded(commanded), mDuration(0), mRemainingDuration(0), mX(0), mY(0), mZ(0)
|
: TypedAiPackage<AiFollow>(makeDefaultOptions().withShouldCancelPreviousAi(!commanded))
|
||||||
|
, mAlwaysFollow(true), mDuration(0), mRemainingDuration(0), mX(0), mY(0), mZ(0)
|
||||||
, mCellId(""), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
, mCellId(""), mActive(false), mFollowIndex(mFollowIndexCounter++)
|
||||||
{
|
{
|
||||||
mTargetActorRefId = actor.getCellRef().getRefId();
|
mTargetActorRefId = actor.getCellRef().getRefId();
|
||||||
|
@ -58,7 +58,8 @@ AiFollow::AiFollow(const MWWorld::Ptr& actor, bool commanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow)
|
AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow)
|
||||||
: mAlwaysFollow(follow->mAlwaysFollow), mCommanded(follow->mCommanded)
|
: TypedAiPackage<AiFollow>(makeDefaultOptions().withShouldCancelPreviousAi(!follow->mCommanded))
|
||||||
|
, mAlwaysFollow(follow->mAlwaysFollow)
|
||||||
// mDuration isn't saved in the save file, so just giving it "1" for now if the package had a duration.
|
// mDuration isn't saved in the save file, so just giving it "1" for now if the package had a duration.
|
||||||
// The exact value of mDuration only matters for repeating packages.
|
// The exact value of mDuration only matters for repeating packages.
|
||||||
// Previously mRemainingDuration could be negative even when mDuration was 0. Checking for > 0 should fix old saves.
|
// Previously mRemainingDuration could be negative even when mDuration was 0. Checking for > 0 should fix old saves.
|
||||||
|
@ -200,14 +201,9 @@ std::string AiFollow::getFollowedActor()
|
||||||
return mTargetActorRefId;
|
return mTargetActorRefId;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiFollow::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdFollow;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AiFollow::isCommanded() const
|
bool AiFollow::isCommanded() const
|
||||||
{
|
{
|
||||||
return mCommanded;
|
return !mOptions.mShouldCancelPreviousAi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiFollow::writeState(ESM::AiSequence::AiSequence &sequence) const
|
void AiFollow::writeState(ESM::AiSequence::AiSequence &sequence) const
|
||||||
|
@ -221,7 +217,7 @@ void AiFollow::writeState(ESM::AiSequence::AiSequence &sequence) const
|
||||||
follow->mRemainingDuration = mRemainingDuration;
|
follow->mRemainingDuration = mRemainingDuration;
|
||||||
follow->mCellId = mCellId;
|
follow->mCellId = mCellId;
|
||||||
follow->mAlwaysFollow = mAlwaysFollow;
|
follow->mAlwaysFollow = mAlwaysFollow;
|
||||||
follow->mCommanded = mCommanded;
|
follow->mCommanded = isCommanded();
|
||||||
follow->mActive = mActive;
|
follow->mActive = mActive;
|
||||||
|
|
||||||
ESM::AiSequence::AiPackageContainer package;
|
ESM::AiSequence::AiPackageContainer package;
|
||||||
|
|
|
@ -53,15 +53,18 @@ namespace MWMechanics
|
||||||
|
|
||||||
AiFollow(const ESM::AiSequence::AiFollow* follow);
|
AiFollow(const ESM::AiSequence::AiFollow* follow);
|
||||||
|
|
||||||
bool sideWithTarget() const final { return true; }
|
|
||||||
bool followTargetThroughDoors() const final { return true; }
|
|
||||||
bool shouldCancelPreviousAi() const final { return !mCommanded; }
|
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdFollow; }
|
||||||
|
|
||||||
bool useVariableSpeed() const final { return true; }
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
|
AiPackage::Options options;
|
||||||
|
options.mUseVariableSpeed = true;
|
||||||
|
options.mSideWithTarget = true;
|
||||||
|
options.mFollowTargetThroughDoors = true;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the actor being followed
|
/// Returns the actor being followed
|
||||||
std::string getFollowedActor();
|
std::string getFollowedActor();
|
||||||
|
@ -87,7 +90,6 @@ namespace MWMechanics
|
||||||
/// This will make the actor always follow.
|
/// This will make the actor always follow.
|
||||||
/** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/
|
/** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/
|
||||||
const bool mAlwaysFollow;
|
const bool mAlwaysFollow;
|
||||||
const bool mCommanded;
|
|
||||||
const float mDuration; // Hours
|
const float mDuration; // Hours
|
||||||
float mRemainingDuration; // Hours
|
float mRemainingDuration; // Hours
|
||||||
const float mX;
|
const float mX;
|
||||||
|
|
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
#include <osg/Quat>
|
#include <osg/Quat>
|
||||||
|
|
||||||
MWMechanics::AiPackage::AiPackage() :
|
MWMechanics::AiPackage::AiPackage(TypeId typeId, const Options& options) :
|
||||||
|
mTypeId(typeId),
|
||||||
|
mOptions(options),
|
||||||
mTimer(AI_REACTION_TIME + 1.0f), // to force initial pathbuild
|
mTimer(AI_REACTION_TIME + 1.0f), // to force initial pathbuild
|
||||||
mTargetActorRefId(""),
|
mTargetActorRefId(""),
|
||||||
mTargetActorId(-1),
|
mTargetActorId(-1),
|
||||||
|
@ -58,31 +60,6 @@ MWWorld::Ptr MWMechanics::AiPackage::getTarget() const
|
||||||
return MWWorld::Ptr();
|
return MWWorld::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWMechanics::AiPackage::sideWithTarget() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MWMechanics::AiPackage::followTargetThroughDoors() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MWMechanics::AiPackage::canCancel() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MWMechanics::AiPackage::shouldCancelPreviousAi() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MWMechanics::AiPackage::getRepeat() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWMechanics::AiPackage::reset()
|
void MWMechanics::AiPackage::reset()
|
||||||
{
|
{
|
||||||
// reset all members
|
// reset all members
|
||||||
|
|
|
@ -55,11 +55,39 @@ namespace MWMechanics
|
||||||
TypeIdCast = 11
|
TypeIdCast = 11
|
||||||
};
|
};
|
||||||
|
|
||||||
///Default constructor
|
struct Options
|
||||||
AiPackage();
|
{
|
||||||
|
unsigned int mPriority = 0;
|
||||||
|
bool mUseVariableSpeed = false;
|
||||||
|
bool mSideWithTarget = false;
|
||||||
|
bool mFollowTargetThroughDoors = false;
|
||||||
|
bool mCanCancel = true;
|
||||||
|
bool mShouldCancelPreviousAi = true;
|
||||||
|
bool mRepeat = false;
|
||||||
|
bool mAlwaysActive = false;
|
||||||
|
|
||||||
|
constexpr Options withRepeat(bool value)
|
||||||
|
{
|
||||||
|
mRepeat = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Options withShouldCancelPreviousAi(bool value)
|
||||||
|
{
|
||||||
|
mShouldCancelPreviousAi = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AiPackage(TypeId typeId, const Options& options);
|
||||||
|
|
||||||
virtual ~AiPackage() = default;
|
virtual ~AiPackage() = default;
|
||||||
|
|
||||||
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
|
return Options{};
|
||||||
|
}
|
||||||
|
|
||||||
///Clones the package
|
///Clones the package
|
||||||
virtual std::unique_ptr<AiPackage> clone() const = 0;
|
virtual std::unique_ptr<AiPackage> clone() const = 0;
|
||||||
|
|
||||||
|
@ -69,13 +97,13 @@ namespace MWMechanics
|
||||||
|
|
||||||
/// Returns the TypeID of the AiPackage
|
/// Returns the TypeID of the AiPackage
|
||||||
/// \see enum TypeId
|
/// \see enum TypeId
|
||||||
virtual int getTypeId() const = 0;
|
TypeId getTypeId() const { return mTypeId; }
|
||||||
|
|
||||||
/// Higher number is higher priority (0 being the lowest)
|
/// Higher number is higher priority (0 being the lowest)
|
||||||
virtual unsigned int getPriority() const {return 0;}
|
unsigned int getPriority() const { return mOptions.mPriority; }
|
||||||
|
|
||||||
/// Check if package use movement with variable speed
|
/// Check if package use movement with variable speed
|
||||||
virtual bool useVariableSpeed() const { return false;}
|
bool useVariableSpeed() const { return mOptions.mUseVariableSpeed; }
|
||||||
|
|
||||||
virtual void writeState (ESM::AiSequence::AiSequence& sequence) const {}
|
virtual void writeState (ESM::AiSequence::AiSequence& sequence) const {}
|
||||||
|
|
||||||
|
@ -89,24 +117,24 @@ namespace MWMechanics
|
||||||
virtual osg::Vec3f getDestination(const MWWorld::Ptr& actor) const { return osg::Vec3f(0, 0, 0); };
|
virtual osg::Vec3f getDestination(const MWWorld::Ptr& actor) const { return osg::Vec3f(0, 0, 0); };
|
||||||
|
|
||||||
/// Return true if having this AiPackage makes the actor side with the target in fights (default false)
|
/// Return true if having this AiPackage makes the actor side with the target in fights (default false)
|
||||||
virtual bool sideWithTarget() const;
|
bool sideWithTarget() const { return mOptions.mSideWithTarget; }
|
||||||
|
|
||||||
/// Return true if the actor should follow the target through teleport doors (default false)
|
/// Return true if the actor should follow the target through teleport doors (default false)
|
||||||
virtual bool followTargetThroughDoors() const;
|
bool followTargetThroughDoors() const { return mOptions.mFollowTargetThroughDoors; }
|
||||||
|
|
||||||
/// Can this Ai package be canceled? (default true)
|
/// Can this Ai package be canceled? (default true)
|
||||||
virtual bool canCancel() const;
|
bool canCancel() const { return mOptions.mCanCancel; }
|
||||||
|
|
||||||
/// Upon adding this Ai package, should the Ai Sequence attempt to cancel previous Ai packages (default true)?
|
/// Upon adding this Ai package, should the Ai Sequence attempt to cancel previous Ai packages (default true)?
|
||||||
virtual bool shouldCancelPreviousAi() const;
|
bool shouldCancelPreviousAi() const { return mOptions.mShouldCancelPreviousAi; }
|
||||||
|
|
||||||
/// Return true if this package should repeat. Currently only used for Wander packages.
|
/// Return true if this package should repeat. Currently only used for Wander packages.
|
||||||
virtual bool getRepeat() const;
|
bool getRepeat() const { return mOptions.mRepeat; }
|
||||||
|
|
||||||
virtual osg::Vec3f getDestination() const { return osg::Vec3f(0, 0, 0); }
|
virtual osg::Vec3f getDestination() const { return osg::Vec3f(0, 0, 0); }
|
||||||
|
|
||||||
// Return true if any loaded actor with this AI package must be active.
|
/// Return true if any loaded actor with this AI package must be active.
|
||||||
virtual bool alwaysActive() const { return false; }
|
bool alwaysActive() const { return mOptions.mAlwaysActive; }
|
||||||
|
|
||||||
/// Reset pathfinding state
|
/// Reset pathfinding state
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -139,6 +167,9 @@ namespace MWMechanics
|
||||||
|
|
||||||
DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const;
|
DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const;
|
||||||
|
|
||||||
|
const TypeId mTypeId;
|
||||||
|
const Options mOptions;
|
||||||
|
|
||||||
// TODO: all this does not belong here, move into temporary storage
|
// TODO: all this does not belong here, move into temporary storage
|
||||||
PathFinder mPathFinder;
|
PathFinder mPathFinder;
|
||||||
ObstacleCheck mObstacleCheck;
|
ObstacleCheck mObstacleCheck;
|
||||||
|
|
|
@ -66,11 +66,6 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiPursue::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdPursue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MWWorld::Ptr AiPursue::getTarget() const
|
MWWorld::Ptr AiPursue::getTarget() const
|
||||||
{
|
{
|
||||||
return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId);
|
return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId);
|
||||||
|
|
|
@ -27,14 +27,20 @@ namespace MWMechanics
|
||||||
AiPursue(const ESM::AiSequence::AiPursue* pursue);
|
AiPursue(const ESM::AiSequence::AiPursue* pursue);
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
int getTypeId() const final;
|
|
||||||
|
static constexpr TypeId getTypeId() { return TypeIdPursue; }
|
||||||
|
|
||||||
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
|
AiPackage::Options options;
|
||||||
|
options.mCanCancel = false;
|
||||||
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
MWWorld::Ptr getTarget() const final;
|
MWWorld::Ptr getTarget() const final;
|
||||||
|
|
||||||
void writeState (ESM::AiSequence::AiSequence& sequence) const final;
|
void writeState (ESM::AiSequence::AiSequence& sequence) const final;
|
||||||
|
|
||||||
bool canCancel() const final { return false; }
|
|
||||||
bool shouldCancelPreviousAi() const final { return false; }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -338,7 +338,7 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo
|
||||||
dest = actor.getRefData().getPosition().asVec3();
|
dest = actor.getRefData().getPosition().asVec3();
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiTravel travelPackage(dest.x(), dest.y(), dest.z(), true);
|
MWMechanics::AiInternalTravel travelPackage(dest.x(), dest.y(), dest.z());
|
||||||
stack(travelPackage, actor, false);
|
stack(travelPackage, actor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,7 +478,11 @@ void AiSequence::readState(const ESM::AiSequence::AiSequence &sequence)
|
||||||
}
|
}
|
||||||
case ESM::AiSequence::Ai_Travel:
|
case ESM::AiSequence::Ai_Travel:
|
||||||
{
|
{
|
||||||
package.reset(new AiTravel(static_cast<ESM::AiSequence::AiTravel*>(it->mPackage)));
|
const auto source = static_cast<const ESM::AiSequence::AiTravel*>(it->mPackage);
|
||||||
|
if (source->mHidden)
|
||||||
|
package.reset(new AiInternalTravel(source));
|
||||||
|
else
|
||||||
|
package.reset(new AiTravel(source));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESM::AiSequence::Ai_Escort:
|
case ESM::AiSequence::Ai_Escort:
|
||||||
|
|
|
@ -27,14 +27,26 @@ bool isWithinMaxRange(const osg::Vec3f& pos1, const osg::Vec3f& pos2)
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
AiTravel::AiTravel(float x, float y, float z, bool hidden)
|
AiTravel::AiTravel(float x, float y, float z, AiTravel*)
|
||||||
: mX(x),mY(y),mZ(z),mHidden(hidden)
|
: mX(x), mY(y), mZ(z), mHidden(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AiTravel::AiTravel(float x, float y, float z, AiInternalTravel* derived)
|
||||||
|
: TypedAiPackage<AiTravel>(derived), mX(x), mY(y), mZ(z), mHidden(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AiTravel::AiTravel(float x, float y, float z)
|
||||||
|
: AiTravel(x, y, z, this)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AiTravel::AiTravel(const ESM::AiSequence::AiTravel *travel)
|
AiTravel::AiTravel(const ESM::AiSequence::AiTravel *travel)
|
||||||
: mX(travel->mData.mX), mY(travel->mData.mY), mZ(travel->mData.mZ), mHidden(travel->mHidden)
|
: mX(travel->mData.mX), mY(travel->mData.mY), mZ(travel->mData.mZ), mHidden(false)
|
||||||
{
|
{
|
||||||
|
// Hidden ESM::AiSequence::AiTravel package should be converted into MWMechanics::AiInternalTravel type
|
||||||
|
assert(!travel->mHidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiTravel::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
bool AiTravel::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
||||||
|
@ -78,11 +90,6 @@ namespace MWMechanics
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiTravel::getTypeId() const
|
|
||||||
{
|
|
||||||
return mHidden ? TypeIdInternalTravel : TypeIdTravel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AiTravel::fastForward(const MWWorld::Ptr& actor, AiState& state)
|
void AiTravel::fastForward(const MWWorld::Ptr& actor, AiState& state)
|
||||||
{
|
{
|
||||||
if (!isWithinMaxRange(osg::Vec3f(mX, mY, mZ), actor.getRefData().getPosition().asVec3()))
|
if (!isWithinMaxRange(osg::Vec3f(mX, mY, mZ), actor.getRefData().getPosition().asVec3()))
|
||||||
|
@ -107,5 +114,20 @@ namespace MWMechanics
|
||||||
package.mPackage = travel.release();
|
package.mPackage = travel.release();
|
||||||
sequence.mPackages.push_back(package);
|
sequence.mPackages.push_back(package);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AiInternalTravel::AiInternalTravel(float x, float y, float z)
|
||||||
|
: AiTravel(x, y, z, this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AiInternalTravel::AiInternalTravel(const ESM::AiSequence::AiTravel* travel)
|
||||||
|
: AiTravel(travel->mData.mX, travel->mData.mY, travel->mData.mZ, this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<AiPackage> AiInternalTravel::clone() const
|
||||||
|
{
|
||||||
|
return std::make_unique<AiInternalTravel>(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,18 @@ namespace AiSequence
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
struct AiInternalTravel;
|
||||||
|
|
||||||
/// \brief Causes the AI to travel to the specified point
|
/// \brief Causes the AI to travel to the specified point
|
||||||
class AiTravel final : public TypedAiPackage<AiTravel>
|
class AiTravel : public TypedAiPackage<AiTravel>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Default constructor
|
AiTravel(float x, float y, float z, AiTravel* derived);
|
||||||
AiTravel(float x, float y, float z, bool hidden = false);
|
|
||||||
|
AiTravel(float x, float y, float z, AiInternalTravel* derived);
|
||||||
|
|
||||||
|
AiTravel(float x, float y, float z);
|
||||||
|
|
||||||
AiTravel(const ESM::AiSequence::AiTravel* travel);
|
AiTravel(const ESM::AiSequence::AiTravel* travel);
|
||||||
|
|
||||||
/// Simulates the passing of time
|
/// Simulates the passing of time
|
||||||
|
@ -28,11 +34,15 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdTravel; }
|
||||||
|
|
||||||
bool useVariableSpeed() const final { return true; }
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
bool alwaysActive() const final { return true; }
|
AiPackage::Options options;
|
||||||
|
options.mUseVariableSpeed = true;
|
||||||
|
options.mAlwaysActive = true;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
osg::Vec3f getDestination() const final { return osg::Vec3f(mX, mY, mZ); }
|
osg::Vec3f getDestination() const final { return osg::Vec3f(mX, mY, mZ); }
|
||||||
|
|
||||||
|
@ -43,6 +53,17 @@ namespace MWMechanics
|
||||||
|
|
||||||
const bool mHidden;
|
const bool mHidden;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AiInternalTravel final : public AiTravel
|
||||||
|
{
|
||||||
|
AiInternalTravel(float x, float y, float z);
|
||||||
|
|
||||||
|
explicit AiInternalTravel(const ESM::AiSequence::AiTravel* travel);
|
||||||
|
|
||||||
|
static constexpr TypeId getTypeId() { return TypeIdInternalTravel; }
|
||||||
|
|
||||||
|
std::unique_ptr<AiPackage> clone() const final;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -113,11 +113,12 @@ 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):
|
||||||
|
TypedAiPackage<AiWander>(makeDefaultOptions().withRepeat(repeat)),
|
||||||
mDistance(std::max(0, distance)),
|
mDistance(std::max(0, distance)),
|
||||||
mDuration(std::max(0, duration)),
|
mDuration(std::max(0, duration)),
|
||||||
mRemainingDuration(duration), mTimeOfDay(timeOfDay),
|
mRemainingDuration(duration), mTimeOfDay(timeOfDay),
|
||||||
mIdle(getInitialIdle(idle)),
|
mIdle(getInitialIdle(idle)),
|
||||||
mRepeat(repeat), mStoredInitialActorPosition(false), mInitialActorPosition(osg::Vec3f(0, 0, 0)),
|
mStoredInitialActorPosition(false), mInitialActorPosition(osg::Vec3f(0, 0, 0)),
|
||||||
mHasDestination(false), mDestination(osg::Vec3f(0, 0, 0)), mUsePathgrid(false)
|
mHasDestination(false), mDestination(osg::Vec3f(0, 0, 0)), mUsePathgrid(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -309,11 +310,6 @@ namespace MWMechanics
|
||||||
return false; // AiWander package not yet completed
|
return false; // AiWander package not yet completed
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiWander::getRepeat() const
|
|
||||||
{
|
|
||||||
return mRepeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec3f AiWander::getDestination(const MWWorld::Ptr& actor) const
|
osg::Vec3f AiWander::getDestination(const MWWorld::Ptr& actor) const
|
||||||
{
|
{
|
||||||
if (mHasDestination)
|
if (mHasDestination)
|
||||||
|
@ -599,11 +595,6 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiWander::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdWander;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AiWander::stopWalking(const MWWorld::Ptr& actor)
|
void AiWander::stopWalking(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
mPathFinder.clearPath();
|
mPathFinder.clearPath();
|
||||||
|
@ -873,7 +864,7 @@ namespace MWMechanics
|
||||||
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];
|
||||||
wander->mData.mShouldRepeat = mRepeat;
|
wander->mData.mShouldRepeat = mOptions.mRepeat;
|
||||||
wander->mStoredInitialActorPosition = mStoredInitialActorPosition;
|
wander->mStoredInitialActorPosition = mStoredInitialActorPosition;
|
||||||
if (mStoredInitialActorPosition)
|
if (mStoredInitialActorPosition)
|
||||||
wander->mInitialActorPosition = mInitialActorPosition;
|
wander->mInitialActorPosition = mInitialActorPosition;
|
||||||
|
@ -885,12 +876,12 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
AiWander::AiWander (const ESM::AiSequence::AiWander* wander)
|
AiWander::AiWander (const ESM::AiSequence::AiWander* wander)
|
||||||
: mDistance(std::max(static_cast<short>(0), wander->mData.mDistance))
|
: TypedAiPackage<AiWander>(makeDefaultOptions().withRepeat(wander->mData.mShouldRepeat != 0))
|
||||||
|
, mDistance(std::max(static_cast<short>(0), wander->mData.mDistance))
|
||||||
, mDuration(std::max(static_cast<short>(0), wander->mData.mDuration))
|
, mDuration(std::max(static_cast<short>(0), wander->mData.mDuration))
|
||||||
, mRemainingDuration(wander->mDurationData.mRemainingDuration)
|
, mRemainingDuration(wander->mDurationData.mRemainingDuration)
|
||||||
, mTimeOfDay(wander->mData.mTimeOfDay)
|
, mTimeOfDay(wander->mData.mTimeOfDay)
|
||||||
, mIdle(getInitialIdle(wander->mData.mIdle))
|
, mIdle(getInitialIdle(wander->mData.mIdle))
|
||||||
, mRepeat(wander->mData.mShouldRepeat != 0)
|
|
||||||
, mStoredInitialActorPosition(wander->mStoredInitialActorPosition)
|
, mStoredInitialActorPosition(wander->mStoredInitialActorPosition)
|
||||||
, mHasDestination(false)
|
, mHasDestination(false)
|
||||||
, mDestination(osg::Vec3f(0, 0, 0))
|
, mDestination(osg::Vec3f(0, 0, 0))
|
||||||
|
|
|
@ -93,16 +93,20 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
bool execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
int getTypeId() const final;
|
static constexpr TypeId getTypeId() { return TypeIdWander; }
|
||||||
|
|
||||||
bool useVariableSpeed() const final { return true; }
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
|
AiPackage::Options options;
|
||||||
|
options.mUseVariableSpeed = true;
|
||||||
|
options.mRepeat = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
||||||
|
|
||||||
void fastForward(const MWWorld::Ptr& actor, AiState& state) final;
|
void fastForward(const MWWorld::Ptr& actor, AiState& state) final;
|
||||||
|
|
||||||
bool getRepeat() const final;
|
|
||||||
|
|
||||||
osg::Vec3f getDestination(const MWWorld::Ptr& actor) const final;
|
osg::Vec3f getDestination(const MWWorld::Ptr& actor) const final;
|
||||||
|
|
||||||
osg::Vec3f getDestination() const final
|
osg::Vec3f getDestination() const final
|
||||||
|
@ -139,7 +143,6 @@ namespace MWMechanics
|
||||||
float mRemainingDuration;
|
float mRemainingDuration;
|
||||||
const int mTimeOfDay;
|
const int mTimeOfDay;
|
||||||
const std::vector<unsigned char> mIdle;
|
const std::vector<unsigned char> mIdle;
|
||||||
const bool mRepeat;
|
|
||||||
|
|
||||||
bool mStoredInitialActorPosition;
|
bool mStoredInitialActorPosition;
|
||||||
osg::Vec3f mInitialActorPosition; // Note: an original engine does not reset coordinates even when actor changes a cell
|
osg::Vec3f mInitialActorPosition; // Note: an original engine does not reset coordinates even when actor changes a cell
|
||||||
|
|
|
@ -8,6 +8,16 @@ namespace MWMechanics
|
||||||
template <class T>
|
template <class T>
|
||||||
struct TypedAiPackage : public AiPackage
|
struct TypedAiPackage : public AiPackage
|
||||||
{
|
{
|
||||||
|
TypedAiPackage() :
|
||||||
|
AiPackage(T::getTypeId(), T::makeDefaultOptions()) {}
|
||||||
|
|
||||||
|
TypedAiPackage(const Options& options) :
|
||||||
|
AiPackage(T::getTypeId(), options) {}
|
||||||
|
|
||||||
|
template <class Derived>
|
||||||
|
TypedAiPackage(Derived*) :
|
||||||
|
AiPackage(Derived::getTypeId(), Derived::makeDefaultOptions()) {}
|
||||||
|
|
||||||
virtual std::unique_ptr<AiPackage> clone() const override
|
virtual std::unique_ptr<AiPackage> clone() const override
|
||||||
{
|
{
|
||||||
return std::make_unique<T>(*static_cast<const T*>(this));
|
return std::make_unique<T>(*static_cast<const T*>(this));
|
||||||
|
|
Loading…
Reference in a new issue