2012-09-04 13:25:53 +02:00
|
|
|
#ifndef GAME_MWMECHANICS_AISEQUENCE_H
|
|
|
|
#define GAME_MWMECHANICS_AISEQUENCE_H
|
|
|
|
|
2022-02-12 23:50:41 +00:00
|
|
|
#include <algorithm>
|
2020-05-17 00:29:21 +02:00
|
|
|
#include <memory>
|
2022-02-12 23:50:41 +00:00
|
|
|
#include <vector>
|
2012-09-04 13:25:53 +02:00
|
|
|
|
2020-05-16 21:52:16 +02:00
|
|
|
#include "aipackagetypeid.hpp"
|
2018-06-27 12:48:34 +04:00
|
|
|
#include "aistate.hpp"
|
|
|
|
|
2022-01-22 15:58:41 +01:00
|
|
|
#include <components/esm3/loadnpc.hpp>
|
2013-07-31 00:55:08 +02:00
|
|
|
|
2012-09-04 13:25:53 +02:00
|
|
|
namespace MWWorld
|
|
|
|
{
|
|
|
|
class Ptr;
|
|
|
|
}
|
|
|
|
|
2014-06-12 23:27:04 +02:00
|
|
|
namespace ESM
|
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
|
|
|
class AiPackage;
|
2015-06-26 17:47:04 +02:00
|
|
|
class CharacterController;
|
2014-04-29 23:40:59 -04:00
|
|
|
|
2022-02-12 23:50:41 +00:00
|
|
|
using AiPackages = std::vector<std::shared_ptr<AiPackage>>;
|
|
|
|
|
2012-09-04 13:25:53 +02:00
|
|
|
/// \brief Sequence of AI-packages for a single actor
|
2014-05-13 14:21:59 -04:00
|
|
|
/** The top-most AI package is run each frame. When completed, it is removed from the stack. **/
|
2012-09-04 13:25:53 +02:00
|
|
|
class AiSequence
|
|
|
|
{
|
2014-04-29 23:40:59 -04:00
|
|
|
/// AiPackages to run though
|
2022-02-12 23:50:41 +00:00
|
|
|
AiPackages mPackages;
|
|
|
|
|
|
|
|
/// Finished with top AIPackage, set for one frame
|
|
|
|
bool mDone{};
|
2024-02-04 21:41:03 +01:00
|
|
|
bool mResetFriendlyHits{};
|
2012-09-04 13:25:53 +02:00
|
|
|
|
|
|
|
int mNumCombatPackages{};
|
2022-02-12 23:50:41 +00:00
|
|
|
int mNumPursuitPackages{};
|
2012-09-04 13:25:53 +02:00
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Copy AiSequence
|
2020-05-16 21:52:16 +02:00
|
|
|
void copy(const AiSequence& sequence);
|
2014-01-28 20:57:37 +01:00
|
|
|
|
2022-02-12 23:50:41 +00:00
|
|
|
/// The type of AI package that ran last
|
|
|
|
AiPackageTypeId mLastAiPackage;
|
2018-06-27 12:48:34 +04:00
|
|
|
AiState mAiState;
|
2022-02-12 23:50:41 +00:00
|
|
|
|
|
|
|
void onPackageAdded(const AiPackage& package);
|
|
|
|
void onPackageRemoved(const AiPackage& package);
|
|
|
|
|
2012-09-04 13:25:53 +02:00
|
|
|
AiPackages::iterator erase(AiPackages::iterator package);
|
2014-04-29 23:40:59 -04:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
public:
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Default constructor
|
2012-09-04 13:25:53 +02:00
|
|
|
AiSequence();
|
2014-04-29 23:40:59 -04:00
|
|
|
|
|
|
|
/// Copy Constructor
|
2012-09-04 13:25:53 +02:00
|
|
|
AiSequence(const AiSequence& sequence);
|
2014-04-29 23:40:59 -04:00
|
|
|
|
|
|
|
/// Assignment operator
|
2012-09-04 13:25:53 +02:00
|
|
|
AiSequence& operator=(const AiSequence& sequence);
|
|
|
|
|
2022-02-12 23:50:41 +00:00
|
|
|
virtual ~AiSequence();
|
|
|
|
|
|
|
|
/// Iterator may be invalidated by any function calls other than begin() or end().
|
|
|
|
AiPackages::const_iterator begin() const { return mPackages.begin(); }
|
|
|
|
AiPackages::const_iterator end() const { return mPackages.end(); }
|
|
|
|
|
|
|
|
/// Removes all packages controlled by the predicate.
|
|
|
|
template <typename F>
|
|
|
|
void erasePackagesIf(const F&& pred)
|
|
|
|
{
|
|
|
|
mPackages.erase(std::remove_if(mPackages.begin(), mPackages.end(),
|
|
|
|
[&](auto& entry) {
|
|
|
|
const bool doRemove = pred(entry);
|
|
|
|
if (doRemove)
|
|
|
|
onPackageRemoved(*entry);
|
|
|
|
return doRemove;
|
2022-09-22 21:26:05 +03:00
|
|
|
}),
|
2022-02-12 23:50:41 +00:00
|
|
|
mPackages.end());
|
|
|
|
}
|
2014-08-06 21:16:14 +02:00
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Removes a single package controlled by the predicate.
|
2020-05-16 21:52:16 +02:00
|
|
|
template <typename F>
|
|
|
|
void erasePackageIf(const F&& pred)
|
2022-09-22 21:26:05 +03:00
|
|
|
{
|
2020-05-16 21:52:16 +02:00
|
|
|
auto it = std::find_if(mPackages.begin(), mPackages.end(), pred);
|
|
|
|
if (it == mPackages.end())
|
|
|
|
return;
|
2022-02-12 23:50:41 +00:00
|
|
|
erase(it);
|
2022-09-22 21:26:05 +03:00
|
|
|
}
|
2014-01-07 04:12:37 +04:00
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Returns currently executing AiPackage type
|
2020-05-16 21:52:16 +02:00
|
|
|
/** \see enum class AiPackageTypeId **/
|
|
|
|
AiPackageTypeId getTypeId() const;
|
2014-01-28 20:57:37 +01:00
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Get the typeid of the Ai package that ran last
|
|
|
|
/** NOT the currently "active" Ai package that will be run in the next frame.
|
|
|
|
This difference is important when an Ai package has just finished and been removed.
|
|
|
|
\see enum class AiPackageTypeId **/
|
2014-05-18 20:13:46 +04:00
|
|
|
AiPackageTypeId getLastRunTypeId() const { return mLastAiPackage; }
|
2014-01-07 04:12:37 +04:00
|
|
|
|
2017-02-02 16:20:34 +09:00
|
|
|
/// Return true and assign target if combat package is currently active, return false otherwise
|
|
|
|
bool getCombatTarget(MWWorld::Ptr& targetActor) const;
|
|
|
|
|
2014-07-20 22:34:20 +02:00
|
|
|
/// Return true and assign targets for all combat packages, or return false if there are no combat packages
|
|
|
|
bool getCombatTargets(std::vector<MWWorld::Ptr>& targetActors) const;
|
|
|
|
|
2022-02-12 23:50:41 +00:00
|
|
|
/// Is there any combat package?
|
|
|
|
bool isInCombat() const;
|
|
|
|
|
|
|
|
/// Is there any pursuit package.
|
|
|
|
bool isInPursuit() const;
|
|
|
|
|
2023-10-21 13:56:13 +03:00
|
|
|
/// Is the actor fleeing?
|
|
|
|
bool isFleeing() const;
|
|
|
|
|
2018-08-16 00:26:02 +01:00
|
|
|
/// Removes all packages using the specified id.
|
|
|
|
void removePackagesById(AiPackageTypeId id);
|
|
|
|
|
2017-04-30 02:40:52 +09:00
|
|
|
/// Are we in combat with any other actor, who's also engaging us?
|
2020-05-16 21:52:16 +02:00
|
|
|
bool isEngagedWithActor() const;
|
2017-04-30 02:40:52 +09:00
|
|
|
|
2014-07-20 22:34:20 +02:00
|
|
|
/// Does this AI sequence have the given package type?
|
|
|
|
bool hasPackage(AiPackageTypeId typeId) const;
|
|
|
|
|
2014-05-16 00:03:48 +04:00
|
|
|
/// Are we in combat with this particular actor?
|
|
|
|
bool isInCombat(const MWWorld::Ptr& actor) const;
|
|
|
|
|
2021-11-25 22:00:52 +01:00
|
|
|
/// Removes all combat packages until first non-combat or stack empty.
|
|
|
|
void stopCombat();
|
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Removes all combat packages with the given targets
|
2012-09-04 13:25:53 +02:00
|
|
|
void stopCombat(const std::vector<MWWorld::Ptr>& targets);
|
2014-04-29 23:40:59 -04:00
|
|
|
|
2014-05-04 02:06:43 -04:00
|
|
|
/// Has a package been completed during the last update?
|
|
|
|
bool isPackageDone() const;
|
2014-05-12 14:49:08 -04:00
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Removes all pursue packages until first non-pursue or stack empty.
|
2020-01-06 15:09:32 +03:00
|
|
|
void stopPursuit();
|
2014-04-29 23:40:59 -04:00
|
|
|
|
2014-12-31 18:41:57 +01:00
|
|
|
/// Execute current package, switching if needed.
|
2018-06-27 12:48:34 +04:00
|
|
|
void execute(const MWWorld::Ptr& actor, CharacterController& characterController, float duration,
|
|
|
|
bool outOfRange = false);
|
2014-12-31 18:41:57 +01:00
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Simulate the passing of time using the currently active AI package
|
2012-09-04 13:25:53 +02:00
|
|
|
void fastForward(const MWWorld::Ptr& actor);
|
2013-11-18 12:33:09 +01:00
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Remove all packages.
|
2017-11-28 12:06:09 +04:00
|
|
|
void clear();
|
2014-04-29 23:40:59 -04:00
|
|
|
|
|
|
|
///< Add \a package to the front of the sequence
|
|
|
|
/** Suspends current package
|
|
|
|
@param actor The actor that owns this AiSequence **/
|
2022-03-28 16:17:42 +03:00
|
|
|
void stack(const AiPackage& package, const MWWorld::Ptr& actor, bool cancelOther = true);
|
2014-01-12 14:01:54 +01:00
|
|
|
|
2014-04-29 23:40:59 -04:00
|
|
|
/// Return the current active package.
|
|
|
|
/** If there is no active package, it will throw an exception **/
|
2013-07-31 00:55:08 +02:00
|
|
|
const AiPackage& getActivePackage() const;
|
2014-06-12 23:27:04 +02:00
|
|
|
|
2014-05-13 14:21:59 -04:00
|
|
|
/// Fills the AiSequence with packages
|
2014-04-29 23:40:59 -04:00
|
|
|
/** Typically used for loading from the ESM
|
|
|
|
\see ESM::AIPackageList **/
|
2013-07-31 00:55:08 +02:00
|
|
|
void fill(const ESM::AIPackageList& list);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2019-10-31 09:44:40 +04:00
|
|
|
bool isEmpty() const;
|
|
|
|
|
2014-06-12 23:27:04 +02:00
|
|
|
void writeState(ESM::AiSequence::AiSequence& sequence) const;
|
|
|
|
void readState(const ESM::AiSequence::AiSequence& sequence);
|
2012-09-04 13:25:53 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|