diff options
Diffstat (limited to 'src/server/game/Movement/MotionMaster.cpp')
-rw-r--r-- | src/server/game/Movement/MotionMaster.cpp | 128 |
1 files changed, 88 insertions, 40 deletions
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 5fadcff5f58..7b43eea41ae 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -46,6 +46,7 @@ #include "GenericMovementGenerator.h" #include "HomeMovementGenerator.h" #include "IdleMovementGenerator.h" +#include "Memory.h" #include "PointMovementGenerator.h" #include "RandomMovementGenerator.h" #include "SplineChainMovementGenerator.h" @@ -596,23 +597,31 @@ void MotionMaster::MoveTargetedHome() } } -void MotionMaster::MoveRandom(float wanderDistance, Optional<Milliseconds> duration, MovementSlot slot /*= MOTION_SLOT_DEFAULT*/) +void MotionMaster::MoveRandom(float wanderDistance /*= 0.0f*/, Optional<Milliseconds> duration /*= {}*/, MovementSlot slot /*= MOTION_SLOT_DEFAULT*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { if (_owner->GetTypeId() == TYPEID_UNIT) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRandom: '{}', started random movement (spawnDist: {})", _owner->GetGUID(), wanderDistance); - Add(new RandomMovementGenerator<Creature>(wanderDistance, duration), slot); + Add(new RandomMovementGenerator<Creature>(wanderDistance, duration, std::move(scriptResult)), slot); } + else if (scriptResult) + scriptResult->SetResult(MovementStopReason::Interrupted); } -void MotionMaster::MoveFollow(Unit* target, float dist, ChaseAngle angle, Optional<Milliseconds> duration /*= {}*/, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/) +void MotionMaster::MoveFollow(Unit* target, float dist, ChaseAngle angle, Optional<Milliseconds> duration /*= {}*/, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { // Ignore movement request if target not exist if (!target || target == _owner) + { + if (scriptResult) + scriptResult->SetResult(MovementStopReason::Interrupted); return; + } TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFollow: '{}', starts following '{}'", _owner->GetGUID(), target->GetGUID()); - Add(new FollowMovementGenerator(target, dist, angle, duration), slot); + Add(new FollowMovementGenerator(target, dist, angle, duration, std::move(scriptResult)), slot); } void MotionMaster::MoveChase(Unit* target, Optional<ChaseRange> dist, Optional<ChaseAngle> angle) @@ -639,29 +648,36 @@ void MotionMaster::MoveConfused() } } -void MotionMaster::MoveFleeing(Unit* enemy, Milliseconds time /*= 0ms*/) +void MotionMaster::MoveFleeing(Unit* enemy, Milliseconds time /*= 0ms*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { if (!enemy) + { + if (scriptResult) + scriptResult->SetResult(MovementStopReason::Interrupted); return; + } TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFleeing: '{}', flees from '{}' (time: {}ms)", _owner->GetGUID(), enemy->GetGUID(), time.count()); if (_owner->GetTypeId() == TYPEID_UNIT && time > 0ms) - Add(new TimedFleeingMovementGenerator(enemy->GetGUID(), time)); + Add(new TimedFleeingMovementGenerator(enemy->GetGUID(), time, std::move(scriptResult))); else - Add(new FleeingMovementGenerator(enemy->GetGUID())); + Add(new FleeingMovementGenerator(enemy->GetGUID(), std::move(scriptResult))); } void MotionMaster::MovePoint(uint32 id, Position const& pos, bool generatePath/* = true*/, Optional<float> finalOrient/* = {}*/, Optional<float> speed /*= {}*/, - MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, Optional<float> closeEnoughDistance /*= {}*/) + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, Optional<float> closeEnoughDistance /*= {}*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { - MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath, finalOrient, speed, speedSelectionMode, closeEnoughDistance); + MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath, finalOrient, speed, speedSelectionMode, closeEnoughDistance, std::move(scriptResult)); } void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generatePath /*= true*/, Optional<float> finalOrient /*= {}*/, Optional<float> speed /*= {}*/, - MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, Optional<float> closeEnoughDistance /*= {}*/) + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, Optional<float> closeEnoughDistance /*= {}*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePoint: '{}', targeted point Id: {} (X: {}, Y: {}, Z: {})", _owner->GetGUID(), id, x, y, z); - Add(new PointMovementGenerator(id, x, y, z, generatePath, speed, finalOrient, nullptr, nullptr, speedSelectionMode, closeEnoughDistance)); + Add(new PointMovementGenerator(id, x, y, z, generatePath, speed, finalOrient, nullptr, nullptr, speedSelectionMode, closeEnoughDistance, std::move(scriptResult))); } void MotionMaster::MoveCloserAndStop(uint32 id, Unit* target, float distance) @@ -688,14 +704,15 @@ void MotionMaster::MoveCloserAndStop(uint32 id, Unit* target, float distance) } void MotionMaster::MoveLand(uint32 id, Position const& pos, Optional<int32> tierTransitionId /*= {}*/, Optional<float> velocity /*= {}*/, - MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/) + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveLand: '{}', landing point Id: {} (X: {}, Y: {}, Z: {})", _owner->GetGUID(), id, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); std::function<void(Movement::MoveSplineInit&)> initializer = [=](Movement::MoveSplineInit& init) { init.MoveTo(PositionToVector3(pos), false); - init.SetAnimation(AnimTier::Ground, tierTransitionId.value_or(0)); + init.SetAnimation(AnimTier::Ground, tierTransitionId.value_or(1)); switch (speedSelectionMode) { case MovementWalkRunSpeedSelectionMode::ForceRun: @@ -711,18 +728,19 @@ void MotionMaster::MoveLand(uint32 id, Position const& pos, Optional<int32> tier if (velocity) init.SetVelocity(*velocity); }; - Add(new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, id)); + Add(new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, id, { .ScriptResult = std::move(scriptResult) })); } void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, Optional<int32> tierTransitionId /*= {}*/, Optional<float> velocity /*= {}*/, - MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/) + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveTakeoff: '{}', landing point Id: {} (X: {}, Y: {}, Z: {})", _owner->GetGUID(), id, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); std::function<void(Movement::MoveSplineInit&)> initializer = [=](Movement::MoveSplineInit& init) { init.MoveTo(PositionToVector3(pos), false); - init.SetAnimation(AnimTier::Hover, tierTransitionId.value_or(0)); + init.SetAnimation(AnimTier::Hover, tierTransitionId.value_or(15)); switch (speedSelectionMode) { case MovementWalkRunSpeedSelectionMode::ForceRun: @@ -738,7 +756,7 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, Optional<int32> t if (velocity) init.SetVelocity(*velocity); }; - Add(new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, id)); + Add(new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, id, { .ScriptResult = std::move(scriptResult) })); } void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_CHARGE*/, uint32 id /*= EVENT_CHARGE*/, bool generatePath /*= false*/, @@ -826,17 +844,24 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) } void MotionMaster::MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id/* = EVENT_JUMP*/, bool hasOrientation/* = false*/, - JumpArrivalCastArgs const* arrivalCast /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/) + JumpArrivalCastArgs const* arrivalCast /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { - MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), speedXY, speedZ, id, hasOrientation, arrivalCast, spellEffectExtraData); + MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), speedXY, speedZ, id, hasOrientation, + arrivalCast, spellEffectExtraData, std::move(scriptResult)); } void MotionMaster::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*/) + JumpArrivalCastArgs const* arrivalCast /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveJump: '{}', jumps to point Id: {} (X: {}, Y: {}, Z: {})", _owner->GetGUID(), id, x, y, z); if (speedXY < 0.01f) + { + if (scriptResult) + scriptResult->SetResult(MovementStopReason::Interrupted); return; + } float moveTimeHalf = speedZ / Movement::gravity; float max_height = -Movement::computeFallElevation(moveTimeHalf, false, -speedZ); @@ -861,18 +886,23 @@ void MotionMaster::MoveJump(float x, float y, float z, float o, float speedXY, f } GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, id, - { .ArrivalSpellId = arrivalSpellId, .ArrivalSpellTarget = arrivalSpellTargetGuid }); + { .ArrivalSpellId = arrivalSpellId, .ArrivalSpellTarget = arrivalSpellTargetGuid, .ScriptResult = std::move(scriptResult) }); movement->Priority = MOTION_PRIORITY_HIGHEST; movement->BaseUnitState = UNIT_STATE_JUMPING; Add(movement); } void MotionMaster::MoveJumpWithGravity(Position const& pos, float speedXY, float gravity, uint32 id/* = EVENT_JUMP*/, bool hasOrientation/* = false*/, - JumpArrivalCastArgs const* arrivalCast /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/) + JumpArrivalCastArgs const* arrivalCast /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveJumpWithGravity: '{}', jumps to point Id: {} ({})", _owner->GetGUID(), id, pos.ToString()); if (speedXY < 0.01f) + { + if (scriptResult) + scriptResult->SetResult(MovementStopReason::Interrupted); return; + } std::function<void(Movement::MoveSplineInit&)> initializer = [=, effect = (spellEffectExtraData ? Optional<Movement::SpellEffectExtraData>(*spellEffectExtraData) : Optional<Movement::SpellEffectExtraData>())](Movement::MoveSplineInit& init) { @@ -896,7 +926,7 @@ void MotionMaster::MoveJumpWithGravity(Position const& pos, float speedXY, float } GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, id, - { .ArrivalSpellId = arrivalSpellId, .ArrivalSpellTarget = arrivalSpellTargetGuid }); + { .ArrivalSpellId = arrivalSpellId, .ArrivalSpellTarget = arrivalSpellTargetGuid, .ScriptResult = std::move(scriptResult) }); movement->Priority = MOTION_PRIORITY_HIGHEST; movement->BaseUnitState = UNIT_STATE_JUMPING; movement->AddFlag(MOVEMENTGENERATOR_FLAG_PERSIST_ON_DEATH); @@ -905,7 +935,8 @@ void MotionMaster::MoveJumpWithGravity(Position const& pos, float speedXY, float void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount, Optional<Milliseconds> duration /*= {}*/, Optional<float> speed /*= {}*/, - MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/) + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { std::function<void(Movement::MoveSplineInit&)> initializer = [=, this](Movement::MoveSplineInit& init) { @@ -953,7 +984,7 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool init.SetVelocity(*speed); }; - Add(new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, 0, { .Duration = duration })); + Add(new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, 0, { .Duration = duration, .ScriptResult = std::move(scriptResult) })); } void MotionMaster::MoveSmoothPath(uint32 pointId, Position const* pathPoints, size_t pathSize, bool walk, bool fly) @@ -1014,8 +1045,15 @@ void MotionMaster::ResumeSplineChain(SplineChainResumeInfo const& info) Add(new SplineChainMovementGenerator(info)); } -void MotionMaster::MoveFall(uint32 id/* = 0*/) +void MotionMaster::MoveFall(uint32 id /*= 0*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { + auto setterScopeExit = Trinity::make_unique_ptr_with_deleter(&scriptResult, [](Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>* opt) + { + if (opt->has_value()) + (*opt)->SetResult(MovementStopReason::Interrupted); + }); + // Use larger distance for vmap height search than in most other cases float tz = _owner->GetMapHeight(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ(), true, MAX_FALL_DISTANCE); if (tz <= INVALID_HEIGHT) @@ -1042,13 +1080,13 @@ void MotionMaster::MoveFall(uint32 id/* = 0*/) return; } - std::function<void(Movement::MoveSplineInit&)> initializer = [=, this](Movement::MoveSplineInit& init) + std::function<void(Movement::MoveSplineInit&)> initializer = [this, tz](Movement::MoveSplineInit& init) { init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz + _owner->GetHoverOffset(), false); init.SetFall(); }; - GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, id); + GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(initializer), EFFECT_MOTION_TYPE, id, { .ScriptResult = std::move(*setterScopeExit.release()) }); movement->Priority = MOTION_PRIORITY_HIGHEST; Add(movement); } @@ -1079,7 +1117,8 @@ void MotionMaster::MoveSeekAssistanceDistract(uint32 time) TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveSeekAssistanceDistract: '{}', attempted to call distract assistance.", _owner->GetGUID()); } -void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode, Optional<float> speed /*= {}*/) +void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode, Optional<float> speed /*= {}*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { if (_owner->GetTypeId() == TYPEID_PLAYER) { @@ -1091,7 +1130,7 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode, Optional<float> bool hasExisting = HasMovementGenerator([](MovementGenerator const* gen) { return gen->GetMovementGeneratorType() == FLIGHT_MOTION_TYPE; }); ASSERT(!hasExisting, "Duplicate flight path movement generator"); - FlightPathMovementGenerator* movement = new FlightPathMovementGenerator(speed); + FlightPathMovementGenerator* movement = new FlightPathMovementGenerator(speed, std::move(scriptResult)); movement->LoadPath(_owner->ToPlayer(), pathnode); Add(movement); } @@ -1112,36 +1151,45 @@ void MotionMaster::MoveDistract(uint32 timer, float orientation) Add(new DistractMovementGenerator(timer, orientation)); } -void MotionMaster::MovePath(uint32 pathId, bool repeatable, Optional<Milliseconds> duration, Optional<float> speed, - MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, - Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, bool generatePath) +void MotionMaster::MovePath(uint32 pathId, bool repeatable, Optional<Milliseconds> duration /*= {}*/, Optional<float> speed /*= {}*/, + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, + Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd /*= {}*/, + Optional<float> wanderDistanceAtPathEnds /*= {}*/, Optional<bool> followPathBackwardsFromEndToStart /*= {}*/, bool generatePath /*= true*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { if (!pathId) + { + if (scriptResult) + scriptResult->SetResult(MovementStopReason::Interrupted); return; + } TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})", _owner->GetGUID(), pathId, repeatable ? "YES" : "NO"); Add(new WaypointMovementGenerator<Creature>(pathId, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, - wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath), MOTION_SLOT_DEFAULT); + wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT); } -void MotionMaster::MovePath(WaypointPath const& path, bool repeatable, Optional<Milliseconds> duration, Optional<float> speed, - MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, - Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, bool generatePath) +void MotionMaster::MovePath(WaypointPath const& path, bool repeatable, Optional<Milliseconds> duration /*= {}*/, Optional<float> speed /*= {}*/, + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, + Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd /*= {}*/, + Optional<float> wanderDistanceAtPathEnds /*= {}*/, Optional<bool> followPathBackwardsFromEndToStart /*= {}*/, bool generatePath /*= true*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})", _owner->GetGUID(), path.Id, repeatable ? "YES" : "NO"); Add(new WaypointMovementGenerator<Creature>(path, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, - wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath), MOTION_SLOT_DEFAULT); + wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT); } void MotionMaster::MoveRotate(uint32 id, RotateDirection direction, Optional<Milliseconds> time /*= {}*/, - Optional<float> turnSpeed /*= {}*/, Optional<float> totalTurnAngle /*= {}*/) + Optional<float> turnSpeed /*= {}*/, Optional<float> totalTurnAngle /*= {}*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRotate: '{}', starts rotate (time: {}ms, turnSpeed: {}, totalTurnAngle: {}, direction: {})", _owner->GetGUID(), time.value_or(0ms).count(), turnSpeed, totalTurnAngle, direction); - Add(new RotateMovementGenerator(id, direction, time, turnSpeed, totalTurnAngle)); + Add(new RotateMovementGenerator(id, direction, time, turnSpeed, totalTurnAngle, std::move(scriptResult))); } void MotionMaster::MoveFormation(Unit* leader, float range, float angle, uint32 point1, uint32 point2) |