1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 16:49:55 +00:00
openmw-tes3mp/apps/openmw/mwmechanics/aiwander.hpp

183 lines
7.1 KiB
C++
Raw Normal View History

2012-11-15 21:15:20 +00:00
#ifndef GAME_MWMECHANICS_AIWANDER_H
#define GAME_MWMECHANICS_AIWANDER_H
2012-11-14 17:42:04 +00:00
#include "typedaipackage.hpp"
2012-11-14 17:42:04 +00:00
#include <vector>
2016-06-17 14:07:16 +00:00
#include "pathfinding.hpp"
#include "obstacle.hpp"
#include "aistate.hpp"
#include "aitimer.hpp"
2014-06-12 21:27:04 +00:00
namespace ESM
{
struct Cell;
2014-06-12 21:27:04 +00:00
namespace AiSequence
{
struct AiWander;
}
}
2012-11-14 17:42:04 +00:00
namespace MWMechanics
2018-06-27 08:48:34 +00:00
{
/// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive.
struct AiWanderStorage : AiTemporaryBase
{
AiReactionTimer mReaction;
2018-06-27 08:48:34 +00:00
// AiWander states
enum WanderState
{
Wander_ChooseAction,
Wander_IdleNow,
Wander_MoveNow,
Wander_Walking
};
WanderState mState;
bool mIsWanderingManually;
bool mCanWanderAlongPathGrid;
unsigned short mIdleAnimation;
std::vector<unsigned short> mBadIdles; // Idle animations that when called cause errors
// do we need to calculate allowed nodes based on mDistance
bool mPopulateAvailableNodes;
// allowed pathgrid nodes based on mDistance from the spawn point
// in local coordinates of mCell
std::vector<ESM::Pathgrid::Point> mAllowedNodes;
ESM::Pathgrid::Point mCurrentNode;
bool mTrimCurrentNode;
2020-08-30 23:12:52 +00:00
float mCheckIdlePositionTimer;
2018-06-27 08:48:34 +00:00
int mStuckCount;
AiWanderStorage():
mState(Wander_ChooseAction),
mIsWanderingManually(false),
mCanWanderAlongPathGrid(true),
mIdleAnimation(0),
mBadIdles(),
mPopulateAvailableNodes(true),
mAllowedNodes(),
mTrimCurrentNode(false),
2020-08-30 23:12:52 +00:00
mCheckIdlePositionTimer(0),
2018-06-27 08:48:34 +00:00
mStuckCount(0)
{};
void setState(const WanderState wanderState, const bool isManualWander = false)
{
mState = wanderState;
mIsWanderingManually = isManualWander;
}
};
/// \brief Causes the Actor to wander within a specified range
class AiWander final : public TypedAiPackage<AiWander>
2012-11-16 17:38:15 +00:00
{
public:
/// Constructor
/** \param distance Max distance the ACtor will wander
\param duration Time, in hours, that this package will be preformed
2016-06-11 19:25:40 +00:00
\param timeOfDay Currently unimplemented. Not functional in the original engine.
\param idle Chances of each idle to play (9 in total)
\param repeat Repeat wander or not **/
2014-06-12 21:27:04 +00:00
AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat);
explicit AiWander (const ESM::AiSequence::AiWander* wander);
2014-06-12 21:27:04 +00:00
bool execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override;
static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Wander; }
2012-11-14 17:42:04 +00:00
static constexpr Options makeDefaultOptions()
{
AiPackage::Options options;
options.mUseVariableSpeed = true;
return options;
}
2020-02-11 09:33:22 +00:00
void writeState(ESM::AiSequence::AiSequence &sequence) const override;
2014-06-12 21:27:04 +00:00
void fastForward(const MWWorld::Ptr& actor, AiState& state) override;
osg::Vec3f getDestination(const MWWorld::Ptr& actor) const override;
osg::Vec3f getDestination() const override
2020-02-11 09:33:22 +00:00
{
if (!mHasDestination)
return osg::Vec3f(0, 0, 0);
return mDestination;
}
2020-08-30 23:12:52 +00:00
bool isStationary() const { return mDistance == 0; }
private:
void stopWalking(const MWWorld::Ptr& actor);
/// Have the given actor play an idle animation
/// @return Success or error
bool playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
2015-07-19 06:04:42 +00:00
short unsigned getRandomIdle();
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
2020-05-16 15:07:42 +00:00
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
2018-08-18 15:48:34 +00:00
void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
2018-08-18 15:48:34 +00:00
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
inline bool isPackageCompleted() const;
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination);
void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage);
2020-08-30 23:12:52 +00:00
bool isNearAllowedNode(const MWWorld::Ptr &actor, const AiWanderStorage& storage, float distance) const;
const int mDistance; // how far the actor can wander from the spawn point
const int mDuration;
float mRemainingDuration;
const int mTimeOfDay;
const std::vector<unsigned char> mIdle;
bool mStoredInitialActorPosition;
osg::Vec3f mInitialActorPosition; // Note: an original engine does not reset coordinates even when actor changes a cell
bool mHasDestination;
osg::Vec3f mDestination;
2018-08-22 21:20:25 +00:00
bool mUsePathgrid;
void getNeighbouringNodes(ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points);
void getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage);
2016-06-15 18:43:09 +00:00
void trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes, const PathFinder& pathfinder);
2015-03-23 07:57:36 +00:00
// constants for converting idleSelect values into groupNames
enum GroupIndex
{
GroupIndex_MinIdle = 2,
GroupIndex_MaxIdle = 9
};
2016-12-14 21:11:22 +00:00
/// convert point from local (i.e. cell) to world coordinates
2015-07-05 06:07:14 +00:00
void ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell);
2017-04-20 11:36:14 +00:00
void SetCurrentNodeToClosestAllowedNode(const osg::Vec3f& npcPos, AiWanderStorage& storage);
2016-06-15 18:43:09 +00:00
void AddNonPathGridAllowedPoints(osg::Vec3f npcPos, const ESM::Pathgrid * pathGrid, int pointIndex, AiWanderStorage& storage);
2016-06-15 18:43:09 +00:00
void AddPointBetweenPathGridPoints(const ESM::Pathgrid::Point& start, const ESM::Pathgrid::Point& end, AiWanderStorage& storage);
2015-03-23 07:57:36 +00:00
/// lookup table for converting idleSelect value to groupName
static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1];
static int OffsetToPreventOvercrowding();
};
}
2012-11-14 17:42:04 +00:00
2012-11-16 19:28:20 +00:00
#endif