/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef MOTIONMASTER_H #define MOTIONMASTER_H #include "Common.h" #include "ObjectGuid.h" #include "Optional.h" #include "MovementDefines.h" #include "MovementGenerator.h" #include "SharedDefines.h" #include #include #include #include #include class PathGenerator; class Unit; struct Position; struct SplineChainLink; struct SplineChainResumeInfo; struct WaypointPath; namespace Movement { class MoveSplineInit; struct SpellEffectExtraData; } enum MotionMasterFlags : uint8 { MOTIONMASTER_FLAG_NONE = 0x0, MOTIONMASTER_FLAG_UPDATE = 0x1, // Update in progress MOTIONMASTER_FLAG_STATIC_INITIALIZATION_PENDING = 0x2 }; enum MotionMasterDelayedActionType : uint8 { MOTIONMASTER_DELAYED_CLEAR = 0, MOTIONMASTER_DELAYED_CLEAR_SLOT, MOTIONMASTER_DELAYED_CLEAR_MODE, MOTIONMASTER_DELAYED_CLEAR_PRIORITY, MOTIONMASTER_DELAYED_ADD, MOTIONMASTER_DELAYED_REMOVE, MOTIONMASTER_DELAYED_REMOVE_TYPE, MOTIONMASTER_DELAYED_INITIALIZE }; struct MovementGeneratorDeleter { void operator()(MovementGenerator* a); }; struct MovementGeneratorComparator { public: bool operator()(MovementGenerator const* a, MovementGenerator const* b) const; }; struct MovementGeneratorInformation { MovementGeneratorInformation(MovementGeneratorType type, ObjectGuid targetGUID, std::string const& targetName); MovementGeneratorType Type; ObjectGuid TargetGUID; std::string TargetName; }; class MotionMasterDelayedAction { public: explicit MotionMasterDelayedAction(std::function&& action, MotionMasterDelayedActionType type) : Action(std::move(action)), Type(type) { } ~MotionMasterDelayedAction() { } void Resolve() { Action(); } std::function Action; uint8 Type; }; class TC_GAME_API MotionMaster { public: explicit MotionMaster(Unit* unit); ~MotionMaster(); void Initialize(); void InitializeDefault(); bool Empty() const; uint32 Size() const; std::vector const GetMovementGeneratorsInformation() const; MovementSlot GetCurrentSlot() const; MovementGenerator* GetCurrentMovementGenerator() const; MovementGeneratorType GetCurrentMovementGeneratorType() const; MovementGeneratorType GetCurrentMovementGeneratorType(MovementSlot slot) const; MovementGenerator* GetCurrentMovementGenerator(MovementSlot slot) const; // Returns first found MovementGenerator that matches the given criteria MovementGenerator* GetMovementGenerator(std::function const& filter, MovementSlot slot = MOTION_SLOT_ACTIVE) const; bool HasMovementGenerator(std::function const& filter, MovementSlot slot = MOTION_SLOT_ACTIVE) const; void Update(uint32 diff); void Add(MovementGenerator* movement, MovementSlot slot = MOTION_SLOT_ACTIVE); // NOTE: MOTION_SLOT_DEFAULT will be autofilled with IDLE_MOTION_TYPE void Remove(MovementGenerator* movement, MovementSlot slot = MOTION_SLOT_ACTIVE); // Removes first found movement // NOTE: MOTION_SLOT_DEFAULT will be autofilled with IDLE_MOTION_TYPE void Remove(MovementGeneratorType type, MovementSlot slot = MOTION_SLOT_ACTIVE); // NOTE: NOTE: MOTION_SLOT_DEFAULT wont be affected void Clear(); // Removes all movements for the given MovementSlot // NOTE: MOTION_SLOT_DEFAULT will be autofilled with IDLE_MOTION_TYPE void Clear(MovementSlot slot); // Removes all movements with the given MovementGeneratorMode // NOTE: MOTION_SLOT_DEFAULT wont be affected void Clear(MovementGeneratorMode mode); // Removes all movements with the given MovementGeneratorPriority // NOTE: MOTION_SLOT_DEFAULT wont be affected void Clear(MovementGeneratorPriority priority); void PropagateSpeedChange(); bool GetDestination(float &x, float &y, float &z); void MoveIdle(); void MoveTargetedHome(); void MoveRandom(float spawndist = 0.0f); void MoveFollow(Unit* target, float dist, ChaseAngle angle, MovementSlot slot = MOTION_SLOT_ACTIVE); void MoveChase(Unit* target, Optional dist = {}, Optional angle = {}); void MoveChase(Unit* target, float dist, float angle) { MoveChase(target, ChaseRange(dist), ChaseAngle(angle)); } void MoveChase(Unit* target, float dist) { MoveChase(target, ChaseRange(dist)); } void MoveConfused(); void MoveFleeing(Unit* enemy, uint32 time = 0); void MovePoint(uint32 id, Position const& pos, bool generatePath = true, Optional finalOrient = {}); void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true, Optional finalOrient = {}); /* * Makes the unit move toward the target until it is at a certain distance from it. The unit then stops. * Only works in 2D. * This method doesn't account for any movement done by the target. in other words, it only works if the target is stationary. */ void MoveCloserAndStop(uint32 id, Unit* target, float distance); // These two movement types should only be used with creatures having landing/takeoff animations void MoveLand(uint32 id, Position const& pos); void MoveTakeoff(uint32 id, Position const& pos); void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = false, Unit const* target = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); void MoveCharge(PathGenerator const& path, float speed = SPEED_CHARGE, Unit const* target = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); void MoveKnockbackFrom(Position const& origin, float speedXY, float speedZ, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); void MoveJumpTo(float angle, float speedXY, float speedZ); void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = EVENT_JUMP, bool hasOrientation = false, JumpArrivalCastArgs const* arrivalCast = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); void MoveJump(float x, float y, float z, float o, float speedXY, float speedZ, uint32 id = EVENT_JUMP, bool hasOrientation = false, JumpArrivalCastArgs const* arrivalCast = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount); void MoveSmoothPath(uint32 pointId, Position const* pathPoints, size_t pathSize, bool walk = false, bool fly = false); // Walk along spline chain stored in DB (script_spline_chain_meta and script_spline_chain_waypoints) void MoveAlongSplineChain(uint32 pointId, uint16 dbChainId, bool walk); void MoveAlongSplineChain(uint32 pointId, std::vector const& chain, bool walk); void ResumeSplineChain(SplineChainResumeInfo const& info); void MoveFall(uint32 id = 0); void MoveSeekAssistance(float x, float y, float z); void MoveSeekAssistanceDistract(uint32 timer); void MoveTaxiFlight(uint32 path, uint32 pathnode); void MoveDistract(uint32 time, float orientation); void MovePath(uint32 pathId, bool repeatable); void MovePath(WaypointPath& path, bool repeatable); void MoveRotate(uint32 id, uint32 time, RotateDirection direction); void MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun = false, bool forceOrientation = false); void LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id = 0, MovementGeneratorPriority priority = MOTION_PRIORITY_NORMAL, MovementGeneratorType type = EFFECT_MOTION_TYPE); private: typedef std::unique_ptr MovementGeneratorPointer; typedef std::multiset MotionMasterContainer; typedef std::unordered_multimap MotionMasterUnitStatesContainer; void AddFlag(uint8 const flag) { _flags |= flag; } bool HasFlag(uint8 const flag) const { return (_flags & flag) != 0; } void RemoveFlag(uint8 const flag) { _flags &= ~flag; } void Pop(bool active, bool movementInform); void DirectInitialize(); void DirectClear(); void DirectClearDefault(); void DirectClear(std::function const& filter); void DirectAdd(MovementGenerator* movement, MovementSlot slot); void Delete(MovementGenerator* movement, bool active, bool movementInform); void DeleteDefault(bool active, bool movementInform); void AddBaseUnitState(MovementGenerator const* movement); void ClearBaseUnitState(MovementGenerator const* movement); void ClearBaseUnitStates(); Unit* _owner; MovementGeneratorPointer _defaultGenerator; MotionMasterContainer _generators; MotionMasterUnitStatesContainer _baseUnitStatesMap; std::deque _delayedActions; uint8 _flags; }; #endif // MOTIONMASTER_H