diff options
6 files changed, 57 insertions, 25 deletions
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index ae052640a86..7c25d871900 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -1135,13 +1135,13 @@ void MotionMaster::MovePath(WaypointPath const& path, bool repeatable, Optional< wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath), MOTION_SLOT_DEFAULT); } -void MotionMaster::MoveRotate(uint32 id, uint32 time, RotateDirection direction) +void MotionMaster::MoveRotate(uint32 id, RotateDirection direction, Optional<Milliseconds> time /*= {}*/, + Optional<float> turnSpeed /*= {}*/, Optional<float> totalTurnAngle /*= {}*/) { - if (!time) - return; + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRotate: '{}', starts rotate (time: {}ms, turnSpeed: {}, totalTurnAngle: {}, direction: {})", + _owner->GetGUID().ToString(), time.value_or(0ms).count(), turnSpeed, totalTurnAngle, direction); - TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRotate: '{}', starts rotate (time: {}, direction: {})", _owner->GetGUID().ToString(), time, direction); - Add(new RotateMovementGenerator(id, time, direction)); + Add(new RotateMovementGenerator(id, direction, time, turnSpeed, totalTurnAngle)); } void MotionMaster::MoveFormation(Unit* leader, float range, float angle, uint32 point1, uint32 point2) diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index dd9c322b706..840a8a08116 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -205,7 +205,17 @@ class TC_GAME_API MotionMaster MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd = {}, Optional<float> wanderDistanceAtPathEnds = {}, bool followPathBackwardsFromEndToStart = false, bool generatePath = true); - void MoveRotate(uint32 id, uint32 time, RotateDirection direction); + + /** + * \brief Makes the Unit turn in place + * \param id Movement identifier, later passed to script MovementInform hooks + * \param direction Rotation direction + * \param time How long should this movement last, infinite if not set + * \param turnSpeed How fast should the unit rotate, in radians per second. Uses unit's turn speed if not set + * \param totalTurnAngle Total angle of the entire movement, infinite if not set + */ + void MoveRotate(uint32 id, RotateDirection direction, Optional<Milliseconds> time = {}, + Optional<float> turnSpeed = {}, Optional<float> totalTurnAngle = {}); void MoveFormation(Unit* leader, float range, float angle, uint32 point1, uint32 point2); void LaunchMoveSpline(std::function<void(Movement::MoveSplineInit& init)>&& initializer, uint32 id = 0, MovementGeneratorPriority priority = MOTION_PRIORITY_NORMAL, MovementGeneratorType type = EFFECT_MOTION_TYPE); diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp index 08d32016438..7aa6a59178c 100644 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp @@ -62,7 +62,9 @@ MovementGeneratorType IdleMovementGenerator::GetMovementGeneratorType() const //----------------------------------------------------// -RotateMovementGenerator::RotateMovementGenerator(uint32 id, uint32 time, RotateDirection direction) : _id(id), _duration(time), _maxDuration(time), _direction(direction) +RotateMovementGenerator::RotateMovementGenerator(uint32 id, RotateDirection direction, Optional<Milliseconds> duration, + Optional<float> turnSpeed, Optional<float> totalTurnAngle) : _id(id), _duration(duration), _turnSpeed(turnSpeed), _totalTurnAngle(totalTurnAngle), + _direction(direction), _diffSinceLastUpdate(0) { Mode = MOTION_MODE_DEFAULT; Priority = MOTION_PRIORITY_NORMAL; @@ -95,23 +97,34 @@ void RotateMovementGenerator::Reset(Unit* owner) bool RotateMovementGenerator::Update(Unit* owner, uint32 diff) { - if (!owner) - return false; + _diffSinceLastUpdate += diff; - float angle = owner->GetOrientation(); - angle += (float(diff) * static_cast<float>(M_PI * 2) / _maxDuration) * (_direction == ROTATE_DIRECTION_LEFT ? 1.0f : -1.0f); - angle = std::clamp(angle, 0.0f, static_cast<float>(M_PI * 2)); + float currentAngle = owner->GetOrientation(); + float angleDelta = _turnSpeed.value_or(owner->GetSpeed(MOVE_TURN_RATE)) * (float(_diffSinceLastUpdate) / float(IN_MILLISECONDS)); - Movement::MoveSplineInit init(owner); - init.MoveTo(PositionToVector3(*owner), false); - if (!owner->GetTransGUID().IsEmpty()) - init.DisableTransportPathTransformations(); - init.SetFacing(angle); - init.Launch(); + if (_duration) + _duration->Update(diff); + + if (_totalTurnAngle) + _totalTurnAngle = *_totalTurnAngle - angleDelta; + + bool expired = (_duration && _duration->Passed()) || (_totalTurnAngle && _totalTurnAngle < 0.0f); + + if (angleDelta >= MIN_ANGLE_DELTA_FOR_FACING_UPDATE || expired) + { + float newAngle = Position::NormalizeOrientation(currentAngle + angleDelta * (_direction == ROTATE_DIRECTION_LEFT ? 1.0f : -1.0f)); + + Movement::MoveSplineInit init(owner); + init.MoveTo(PositionToVector3(owner->GetPosition()), false); + if (!owner->GetTransGUID().IsEmpty()) + init.DisableTransportPathTransformations(); + init.SetFacing(newAngle); + init.Launch(); + + _diffSinceLastUpdate = 0; + } - if (_duration > diff) - _duration -= diff; - else + if (expired) { AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); return false; diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h index a5c3939c96e..d525b9200f8 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -19,6 +19,8 @@ #define TRINITY_IDLEMOVEMENTGENERATOR_H #include "MovementGenerator.h" +#include "Optional.h" +#include "Timer.h" enum RotateDirection : uint8; @@ -38,7 +40,10 @@ class IdleMovementGenerator : public MovementGenerator class RotateMovementGenerator : public MovementGenerator { public: - explicit RotateMovementGenerator(uint32 id, uint32 time, RotateDirection direction); + static constexpr float MIN_ANGLE_DELTA_FOR_FACING_UPDATE = 0.05f; + + explicit RotateMovementGenerator(uint32 id, RotateDirection direction, Optional<Milliseconds> duration, + Optional<float> turnSpeed, Optional<float> totalTurnAngle); void Initialize(Unit*) override; void Reset(Unit*) override; @@ -48,8 +53,12 @@ class RotateMovementGenerator : public MovementGenerator MovementGeneratorType GetMovementGeneratorType() const override; private: - uint32 _id, _duration, _maxDuration; + uint32 _id; + Optional<TimeTracker> _duration; + Optional<float> _turnSpeed; ///< radians per sec + Optional<float> _totalTurnAngle; RotateDirection _direction; + uint32 _diffSinceLastUpdate; }; class DistractMovementGenerator : public MovementGenerator diff --git a/src/server/scripts/BrokenIsles/zone_mardum.cpp b/src/server/scripts/BrokenIsles/zone_mardum.cpp index fb88ff8bf2c..66a862bf8ee 100644 --- a/src/server/scripts/BrokenIsles/zone_mardum.cpp +++ b/src/server/scripts/BrokenIsles/zone_mardum.cpp @@ -1126,7 +1126,7 @@ struct npc_baleful_beaming_eye : public ScriptedAI me->SetDisplayId(DISPLAYID_BALEFUL_EYE, true); DoCastSelf(SPELL_BALEFUL_BEAMING_EYE_CREATE_AT); // ToDo: rotation isn't changing orientation, turnspeed should be random - me->GetMotionMaster()->MoveRotate(0, 10000, RAND(ROTATE_DIRECTION_LEFT, ROTATE_DIRECTION_RIGHT)); + me->GetMotionMaster()->MoveRotate(0, RAND(ROTATE_DIRECTION_LEFT, ROTATE_DIRECTION_RIGHT), 10s); } }; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp index a89ec5c1ec0..f645ab15b64 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp @@ -227,7 +227,7 @@ struct boss_the_lurker_below : public BossAI { Talk(EMOTE_SPOUT); me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveRotate(0, 20000, urand(0, 1) ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); + me->GetMotionMaster()->MoveRotate(0, urand(0, 1) ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT, 20s, float(M_PI) / 7.0f); SpoutTimer = 45000; WhirlTimer = 20000; // whirl directly after spout RotTimer = 20000; |
