2012-09-04 13:25:53 +02:00
|
|
|
#ifndef GAME_MWMECHANICS_AIPACKAGE_H
|
|
|
|
#define GAME_MWMECHANICS_AIPACKAGE_H
|
|
|
|
|
2020-06-01 15:36:14 +02:00
|
|
|
#include <memory>
|
|
|
|
|
2020-06-13 01:56:04 +02:00
|
|
|
#include <components/detournavigator/areatype.hpp>
|
2022-07-16 12:49:01 +02:00
|
|
|
|
2020-05-16 21:52:16 +02:00
|
|
|
#include "aipackagetypeid.hpp"
|
2022-07-16 12:49:01 +02:00
|
|
|
#include "aistatefwd.hpp"
|
2021-03-19 23:23:26 +01:00
|
|
|
#include "aitimer.hpp"
|
2014-05-13 03:58:32 -04:00
|
|
|
#include "obstacle.hpp"
|
2016-06-17 23:07:16 +09:00
|
|
|
#include "pathfinding.hpp"
|
2022-07-16 12:49:01 +02:00
|
|
|
|
2022-04-17 17:15:00 +00:00
|
|
|
#include "../mwworld/ptr.hpp"
|
2012-09-04 13:25:53 +02:00
|
|
|
|
2014-06-12 23:27:04 +02:00
|
|
|
namespace ESM
|
|
|
|
{
|
2015-06-14 10:30:55 +12:00
|
|
|
struct Cell;
|
2014-06-12 23:27:04 +02:00
|
|
|
namespace AiSequence
|
|
|
|
{
|
2015-03-06 21:36:42 +13:00
|
|
|
struct AiSequence;
|
2014-06-12 23:27:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-04 13:25:53 +02:00
|
|
|
namespace MWMechanics
|
|
|
|
{
|
2015-06-26 17:47:04 +02:00
|
|
|
class CharacterController;
|
2017-11-27 18:30:31 +01:00
|
|
|
class PathgridGraph;
|
2015-06-26 17:47:04 +02:00
|
|
|
|
2012-09-04 13:25:53 +02:00
|
|
|
/// \brief Base class for AI packages
|
|
|
|
class AiPackage
|
|
|
|
{
|
|
|
|
public:
|
2020-05-16 21:08:39 +02:00
|
|
|
struct Options
|
2022-09-22 21:26:05 +03:00
|
|
|
{
|
2020-05-16 21:08:39 +02:00
|
|
|
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;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2020-05-16 21:08:39 +02:00
|
|
|
constexpr Options withRepeat(bool value)
|
|
|
|
{
|
|
|
|
mRepeat = value;
|
|
|
|
return *this;
|
|
|
|
}
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2020-05-16 21:08:39 +02:00
|
|
|
constexpr Options withShouldCancelPreviousAi(bool value)
|
|
|
|
{
|
|
|
|
mShouldCancelPreviousAi = value;
|
|
|
|
return *this;
|
|
|
|
}
|
2022-09-22 21:26:05 +03:00
|
|
|
};
|
|
|
|
|
2020-05-16 21:52:16 +02:00
|
|
|
AiPackage(AiPackageTypeId typeId, const Options& options);
|
2020-05-16 21:08:39 +02:00
|
|
|
|
2020-06-01 15:36:14 +02:00
|
|
|
virtual ~AiPackage() = default;
|
2014-04-29 23:40:59 -04:00
|
|
|
|
2015-06-26 17:47:04 +02:00
|
|
|
static constexpr Options makeDefaultOptions() { return Options{}; }
|
2014-04-29 23:40:59 -04:00
|
|
|
|
|
|
|
/// Clones the package
|
2020-05-16 21:52:16 +02:00
|
|
|
virtual std::unique_ptr<AiPackage> clone() const = 0;
|
2013-11-18 12:33:09 +01:00
|
|
|
|
2014-05-12 21:05:32 -04:00
|
|
|
/// Updates and runs the package (Should run every frame)
|
2020-05-16 21:08:39 +02:00
|
|
|
/// \return Package completed?
|
2015-06-26 17:47:04 +02:00
|
|
|
virtual bool execute(
|
2020-05-16 21:08:39 +02:00
|
|
|
const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
|
|
|
= 0;
|
2014-05-12 21:05:32 -04:00
|
|
|
|
2019-10-31 09:44:40 +04:00
|
|
|
/// Returns the TypeID of the AiPackage
|
|
|
|
/// \see enum TypeId
|
2020-05-16 21:08:39 +02:00
|
|
|
AiPackageTypeId getTypeId() const { return mTypeId; }
|
2019-10-31 09:44:40 +04:00
|
|
|
|
2014-06-12 23:27:04 +02:00
|
|
|
/// Higher number is higher priority (0 being the lowest)
|
|
|
|
unsigned int getPriority() const { return mOptions.mPriority; }
|
|
|
|
|
2014-12-31 18:41:57 +01:00
|
|
|
/// Check if package use movement with variable speed
|
|
|
|
bool useVariableSpeed() const { return mOptions.mUseVariableSpeed; }
|
|
|
|
|
2016-02-16 19:17:04 +01:00
|
|
|
virtual void writeState(ESM::AiSequence::AiSequence& sequence) const {}
|
2015-12-06 23:32:49 +01:00
|
|
|
|
2017-12-01 18:53:31 +04:00
|
|
|
/// Simulates the passing of time
|
|
|
|
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state) {}
|
|
|
|
|
2015-12-06 23:32:49 +01:00
|
|
|
/// Get the target actor the AI is targeted at (not applicable to all AI packages, default return empty Ptr)
|
2020-05-16 21:08:39 +02:00
|
|
|
virtual MWWorld::Ptr getTarget() const;
|
2015-12-06 23:32:49 +01:00
|
|
|
|
2015-12-19 15:11:07 +01:00
|
|
|
/// Get the destination point of the AI package (not applicable to all AI packages, default return (0, 0, 0))
|
2022-10-05 23:45:17 +02:00
|
|
|
virtual osg::Vec3f getDestination(const MWWorld::Ptr& actor) const { return osg::Vec3f(0, 0, 0); }
|
2015-12-19 15:11:07 +01:00
|
|
|
|
2016-01-19 14:51:42 +01:00
|
|
|
/// Return true if having this AiPackage makes the actor side with the target in fights (default false)
|
2020-05-16 21:08:39 +02:00
|
|
|
bool sideWithTarget() const { return mOptions.mSideWithTarget; }
|
2016-01-19 14:51:42 +01:00
|
|
|
|
|
|
|
/// Return true if the actor should follow the target through teleport doors (default false)
|
2020-05-16 21:08:39 +02:00
|
|
|
bool followTargetThroughDoors() const { return mOptions.mFollowTargetThroughDoors; }
|
2016-01-19 14:51:42 +01:00
|
|
|
|
2021-11-16 22:04:04 +01:00
|
|
|
/// Can this Ai package be canceled? (default true)
|
2020-05-16 21:08:39 +02:00
|
|
|
bool canCancel() const { return mOptions.mCanCancel; }
|
2016-05-29 01:02:22 +09:00
|
|
|
|
2020-02-11 12:33:22 +03:00
|
|
|
/// Upon adding this Ai package, should the Ai Sequence attempt to cancel previous Ai packages (default true)?
|
|
|
|
bool shouldCancelPreviousAi() const { return mOptions.mShouldCancelPreviousAi; }
|
2019-10-31 09:44:40 +04:00
|
|
|
|
2020-05-16 21:08:39 +02:00
|
|
|
/// Return true if this package should repeat.
|
|
|
|
bool getRepeat() const { return mOptions.mRepeat; }
|
2020-01-09 14:11:53 +03:00
|
|
|
|
2016-08-19 22:15:26 +03:00
|
|
|
virtual osg::Vec3f getDestination() const { return osg::Vec3f(0, 0, 0); }
|
|
|
|
|
2016-09-09 23:57:19 +03:00
|
|
|
/// Return true if any loaded actor with this AI package must be active.
|
2018-07-21 12:30:14 +03:00
|
|
|
bool alwaysActive() const { return mOptions.mAlwaysActive; }
|
2016-09-09 23:57:19 +03:00
|
|
|
|
2021-05-29 20:29:53 +00:00
|
|
|
/// Reset pathfinding state
|
|
|
|
void reset();
|
|
|
|
|
|
|
|
/// Return if actor's rotation speed is sufficient to rotate to the destination pathpoint on the run. Otherwise
|
|
|
|
/// actor should rotate while standing.
|
|
|
|
static bool isReachableRotatingOnTheRun(const MWWorld::Ptr& actor, const osg::Vec3f& dest);
|
|
|
|
|
2021-08-18 22:46:14 +02:00
|
|
|
osg::Vec3f getNextPathPoint(const osg::Vec3f& destination) const;
|
2016-08-19 22:15:26 +03:00
|
|
|
|
2018-07-21 12:30:14 +03:00
|
|
|
float getNextPathPointTolerance(float speed, float duration, const osg::Vec3f& halfExtents) const;
|
2016-08-19 22:15:26 +03:00
|
|
|
|
|
|
|
protected:
|
|
|
|
/// Handles path building and shortcutting with obstacles avoiding
|
|
|
|
/** \return If the actor has arrived at his destination **/
|
2018-07-21 12:30:14 +03:00
|
|
|
bool pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& dest, float duration, float destTolerance = 0.0f,
|
|
|
|
float endTolerance = 0.0f, PathType pathType = PathType::Full);
|
2014-05-12 21:05:32 -04:00
|
|
|
|
2019-10-07 20:19:12 +02:00
|
|
|
/// Check if there aren't any obstacles along the path to make shortcut possible
|
|
|
|
/// If a shortcut is possible then path will be cleared and filled with the destination point.
|
|
|
|
/// \param destInLOS If not nullptr function will return ray cast check result
|
2016-08-19 22:15:26 +03:00
|
|
|
/// \return If can shortcut the path
|
2019-10-07 20:19:12 +02:00
|
|
|
bool shortcutPath(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const MWWorld::Ptr& actor,
|
|
|
|
bool* destInLOS, bool isPathClear);
|
2015-06-11 18:28:31 +12:00
|
|
|
|
2018-08-18 18:41:48 +03:00
|
|
|
/// Check if the way to the destination is clear, taking into account actor speed
|
2018-07-21 12:30:14 +03:00
|
|
|
bool checkWayIsClearForActor(
|
2018-08-18 18:41:48 +03:00
|
|
|
const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const MWWorld::Ptr& actor);
|
2018-08-18 18:26:00 +03:00
|
|
|
|
2017-12-01 10:07:02 +04:00
|
|
|
bool doesPathNeedRecalc(const osg::Vec3f& newDest, const MWWorld::Ptr& actor) const;
|
2015-09-14 19:57:22 +12:00
|
|
|
|
2017-11-27 18:30:31 +01:00
|
|
|
void evadeObstacles(const MWWorld::Ptr& actor);
|
|
|
|
|
2018-07-21 14:16:19 +03:00
|
|
|
void openDoors(const MWWorld::Ptr& actor);
|
|
|
|
|
2023-04-10 15:45:58 +02:00
|
|
|
const PathgridGraph& getPathGridGraph(const ESM::Pathgrid* pathgrid) const;
|
2020-06-13 01:56:04 +02:00
|
|
|
|
2020-05-16 21:52:16 +02:00
|
|
|
DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const;
|
2020-05-16 21:08:39 +02:00
|
|
|
|
2014-12-01 13:34:42 +01:00
|
|
|
DetourNavigator::AreaCosts getAreaCosts(const MWWorld::Ptr& actor) const;
|
2014-05-12 21:05:32 -04:00
|
|
|
|
2021-03-19 23:23:26 +01:00
|
|
|
const AiPackageTypeId mTypeId;
|
|
|
|
const Options mOptions;
|
2014-06-12 23:27:04 +02:00
|
|
|
|
2017-11-21 20:00:51 +04:00
|
|
|
// TODO: all this does not belong here, move into temporary storage
|
|
|
|
PathFinder mPathFinder;
|
2022-04-17 17:15:00 +00:00
|
|
|
ObstacleCheck mObstacleCheck;
|
2017-11-21 20:00:51 +04:00
|
|
|
|
2016-09-09 23:57:19 +03:00
|
|
|
AiReactionTimer mReaction;
|
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
ESM::RefId mTargetActorRefId;
|
2016-08-19 22:15:26 +03:00
|
|
|
mutable int mTargetActorId;
|
|
|
|
mutable MWWorld::Ptr mCachedTarget;
|
2015-08-30 08:32:47 +12:00
|
|
|
|
2016-09-09 23:57:19 +03:00
|
|
|
short mRotateOnTheRunChecks; // attempts to check rotation to the pathpoint on the run possibility
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2016-08-19 22:15:26 +03:00
|
|
|
bool mIsShortcutting; // if shortcutting at the moment
|
|
|
|
bool mShortcutProhibited; // shortcutting may be prohibited after unsuccessful attempt
|
2018-07-21 12:30:14 +03:00
|
|
|
osg::Vec3f mShortcutFailPos; // position of last shortcut fail
|
2021-05-29 20:29:53 +00:00
|
|
|
float mLastDestinationTolerance = 0;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2015-08-30 08:32:47 +12:00
|
|
|
private:
|
2018-09-04 00:10:58 +03:00
|
|
|
bool isNearInactiveCell(osg::Vec3f position);
|
2012-09-04 13:25:53 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|