diff options
26 files changed, 262 insertions, 95 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 6794ad6a21e..edd9206ff30 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2965,6 +2965,8 @@ SpellCastResult WorldObject::CastSpell(CastSpellTargetArg const& targets, uint32 } spell->m_customArg = args.CustomArg; + spell->m_scriptResult = args.ScriptResult; + spell->m_scriptWaitsForSpellHit = args.ScriptWaitsForSpellHit; return spell->prepare(*targets.Targets, args.TriggeringAura); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 90baf8de819..7c1e2d036bb 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -22072,7 +22072,7 @@ UF::PVPInfo const* Player::GetPvpInfoForBracket(int8 bracket) const } bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc /*= nullptr*/, uint32 spellid /*= 0*/, uint32 preferredMountDisplay /*= 0*/, - Optional<float> speed /*= {}*/) + Optional<float> speed /*= {}*/, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>> const& scriptResult /*= {}*/) { if (nodes.size() < 2) { @@ -22252,18 +22252,19 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc ModifyMoney(-int64(firstcost)); UpdateCriteria(CriteriaType::MoneySpentOnTaxis, firstcost); GetSession()->SendActivateTaxiReply(ERR_TAXIOK); - StartTaxiMovement(mount_display_id, sourcepath, 0, speed); + StartTaxiMovement(mount_display_id, sourcepath, 0, speed, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>(scriptResult)); } return true; } -bool Player::ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid /*= 0*/, Optional<float> speed /*= {}*/) +bool Player::ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid /*= 0*/, Optional<float> speed /*= {}*/, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>> const& scriptResult /*= {}*/) { TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(taxi_path_id); if (!entry) return false; - return ActivateTaxiPathTo({ { entry->FromTaxiNode, entry->ToTaxiNode } }, nullptr, spellid, 0, speed); + return ActivateTaxiPathTo({ { entry->FromTaxiNode, entry->ToTaxiNode } }, nullptr, spellid, 0, speed, scriptResult); } void Player::FinishTaxiFlight() @@ -22329,10 +22330,11 @@ void Player::ContinueTaxiFlight() } } - StartTaxiMovement(mountDisplayId, path, startNode, {}); + StartTaxiMovement(mountDisplayId, path, startNode, {}, {}); } -void Player::StartTaxiMovement(uint32 mountDisplayId, uint32 path, uint32 pathNode, Optional<float> speed) +void Player::StartTaxiMovement(uint32 mountDisplayId, uint32 path, uint32 pathNode, Optional<float> speed, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult) { // remove fake death RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting); @@ -22340,7 +22342,7 @@ void Player::StartTaxiMovement(uint32 mountDisplayId, uint32 path, uint32 pathNo if (mountDisplayId) Mount(mountDisplayId); - GetMotionMaster()->MoveTaxiFlight(path, pathNode, speed); + GetMotionMaster()->MoveTaxiFlight(path, pathNode, speed, std::move(scriptResult)); } void Player::InitDataForForm(bool reapplyMods) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1e8eab39d21..95e09d1ac73 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -102,6 +102,7 @@ enum InventoryType : uint8; enum ItemClass : uint8; enum LootError : uint8; enum LootType : uint8; +enum class MovementStopReason : uint8; enum PlayerRestState : uint8; enum class PlayerCreateMode : int8; enum RestTypes : uint8; @@ -1150,12 +1151,15 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player> PlayerTaxi m_taxi; void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(GetRace(), GetClass(), GetLevel()); } - bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc = nullptr, uint32 spellid = 0, uint32 preferredMountDisplay = 0, Optional<float> speed = {}); - bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0, Optional<float> speed = {}); + bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc = nullptr, uint32 spellid = 0, uint32 preferredMountDisplay = 0, Optional<float> speed = {}, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>> const& scriptResult = {}); + bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0, Optional<float> speed = {}, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>> const& scriptResult = {}); void FinishTaxiFlight(); void CleanupAfterTaxiFlight(); void ContinueTaxiFlight(); - void StartTaxiMovement(uint32 mountDisplayId, uint32 path, uint32 pathNode, Optional<float> speed); + void StartTaxiMovement(uint32 mountDisplayId, uint32 path, uint32 pathNode, Optional<float> speed, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult); bool IsDeveloper() const { return HasPlayerFlag(PLAYER_FLAGS_DEVELOPER); } void SetDeveloper(bool on) { if (on) SetPlayerFlag(PLAYER_FLAGS_DEVELOPER); else RemovePlayerFlag(PLAYER_FLAGS_DEVELOPER); } 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) diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 87cee0adf85..2f2d4d9d6da 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -156,16 +156,21 @@ class TC_GAME_API MotionMaster void MoveIdle(); void MoveTargetedHome(); - void MoveRandom(float wanderDistance = 0.0f, Optional<Milliseconds> duration = {}, MovementSlot slot = MOTION_SLOT_DEFAULT); - void MoveFollow(Unit* target, float dist, ChaseAngle angle, Optional<Milliseconds> duration = {}, MovementSlot slot = MOTION_SLOT_ACTIVE); + void MoveRandom(float wanderDistance = 0.0f, Optional<Milliseconds> duration = {}, MovementSlot slot = MOTION_SLOT_DEFAULT, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); + void MoveFollow(Unit* target, float dist, ChaseAngle angle, Optional<Milliseconds> duration = {}, MovementSlot slot = MOTION_SLOT_ACTIVE, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void MoveChase(Unit* target, Optional<ChaseRange> dist = {}, Optional<ChaseAngle> angle = {}); void MoveChase(Unit* target, float dist, float angle) { MoveChase(target, ChaseRange(dist), ChaseAngle(angle)); } void MoveConfused(); - void MoveFleeing(Unit* enemy, Milliseconds time = 0ms); + void MoveFleeing(Unit* enemy, Milliseconds time = 0ms, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void 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 = {}); void 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 = {}); /* * Makes the unit move toward the target until it is at a certain distance from it. The unit then stops. * Only works in 2D. @@ -174,37 +179,50 @@ class TC_GAME_API MotionMaster 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, Optional<int32> tierTransitionId = {}, Optional<float> velocity = {}, - MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default); + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void 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 = {}); 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 MoveJumpWithGravity(Position const& pos, float speedXY, float gravity, uint32 id = EVENT_JUMP, bool hasOrientation = false, JumpArrivalCastArgs const* arrivalCast = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); + 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, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); + 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, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); + void MoveJumpWithGravity(Position const& pos, float speedXY, float gravity, uint32 id = EVENT_JUMP, bool hasOrientation = false, + JumpArrivalCastArgs const* arrivalCast = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void 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 = {}); 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<SplineChainLink> const& chain, bool walk); void ResumeSplineChain(SplineChainResumeInfo const& info); - void MoveFall(uint32 id = 0); + void MoveFall(uint32 id = 0, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void MoveSeekAssistance(float x, float y, float z); void MoveSeekAssistanceDistract(uint32 timer); - void MoveTaxiFlight(uint32 path, uint32 pathnode, Optional<float> speed = {}); + void MoveTaxiFlight(uint32 path, uint32 pathnode, Optional<float> speed = {}, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void MoveDistract(uint32 time, float orientation); void 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<bool> followPathBackwardsFromEndToStart = {}, bool generatePath = true, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void 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<bool> followPathBackwardsFromEndToStart = {}, bool generatePath = true, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); /** * \brief Makes the Unit turn in place @@ -213,9 +231,11 @@ class TC_GAME_API MotionMaster * \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 + * \param scriptResult Awaitable script result (for internal use) */ void 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 = {}); 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/MovementGenerator.cpp b/src/server/game/Movement/MovementGenerator.cpp index 455f91795a5..38844c0d821 100644 --- a/src/server/game/Movement/MovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerator.cpp @@ -25,7 +25,10 @@ #include "WaypointMovementGenerator.h" #include <sstream> -MovementGenerator::~MovementGenerator() { } +MovementGenerator::~MovementGenerator() +{ + SetScriptResult(MovementStopReason::Interrupted); +} std::string MovementGenerator::GetDebugInfo() const { @@ -38,6 +41,15 @@ std::string MovementGenerator::GetDebugInfo() const return sstr.str(); } +void MovementGenerator::SetScriptResult(MovementStopReason reason) +{ + if (ScriptResult) + { + ScriptResult->SetResult(reason); + ScriptResult.reset(); + } +} + IdleMovementFactory::IdleMovementFactory() : MovementGeneratorCreator(IDLE_MOTION_TYPE) { } MovementGenerator* IdleMovementFactory::Create(Unit* /*object*/) const diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index a2c43528e49..79d3a5b9191 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -22,6 +22,8 @@ #include "FactoryHolder.h" #include "MovementDefines.h" #include "ObjectRegistry.h" +#include "Optional.h" +#include "ScriptActionResult.h" class Creature; class Unit; @@ -85,6 +87,10 @@ class TC_GAME_API MovementGenerator uint8 Priority; uint16 Flags; uint32 BaseUnitState; + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>> ScriptResult; + + protected: + void SetScriptResult(MovementStopReason reason); }; template<class T, class D> diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index bedeccbe350..3e03b58d28c 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -26,12 +26,14 @@ #define MIN_QUIET_DISTANCE 28.0f #define MAX_QUIET_DISTANCE 43.0f -FleeingMovementGenerator::FleeingMovementGenerator(ObjectGuid fleeTargetGUID) : _fleeTargetGUID(fleeTargetGUID), _timer(0) +FleeingMovementGenerator::FleeingMovementGenerator(ObjectGuid fleeTargetGUID, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) : _fleeTargetGUID(fleeTargetGUID), _timer(0) { Mode = MOTION_MODE_DEFAULT; Priority = MOTION_PRIORITY_HIGHEST; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_FLEEING; + ScriptResult = std::move(scriptResult); } MovementGeneratorType FleeingMovementGenerator::GetMovementGeneratorType() const @@ -89,7 +91,7 @@ void FleeingMovementGenerator::Deactivate(Unit* owner) owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); } -void FleeingMovementGenerator::Finalize(Unit* owner, bool active, bool /*movementInform*/) +void FleeingMovementGenerator::Finalize(Unit* owner, bool active, bool movementInform) { AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); @@ -105,6 +107,9 @@ void FleeingMovementGenerator::Finalize(Unit* owner, bool active, bool /*movemen else if (owner->IsPlayer()) owner->StopMoving(); } + + if (movementInform) + SetScriptResult(MovementStopReason::Finished); } void FleeingMovementGenerator::SetTargetLocation(Unit* owner) @@ -223,6 +228,8 @@ void TimedFleeingMovementGenerator::Finalize(Unit* owner, bool active, bool move if (movementInform) { + SetScriptResult(MovementStopReason::Finished); + Creature* ownerCreature = owner->ToCreature(); if (CreatureAI* AI = ownerCreature ? ownerCreature->AI() : nullptr) AI->MovementInform(TIMED_FLEEING_MOTION_TYPE, 0); diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h index 3e039265963..d8a28e9e54b 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h @@ -28,7 +28,8 @@ struct Position; class FleeingMovementGenerator : public MovementGenerator { public: - explicit FleeingMovementGenerator(ObjectGuid fleeTargetGUID); + explicit FleeingMovementGenerator(ObjectGuid fleeTargetGUID, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); MovementGeneratorType GetMovementGeneratorType() const override; @@ -52,7 +53,9 @@ class FleeingMovementGenerator : public MovementGenerator class TimedFleeingMovementGenerator : public FleeingMovementGenerator { public: - explicit TimedFleeingMovementGenerator(ObjectGuid fleeTargetGUID, Milliseconds time) : FleeingMovementGenerator(fleeTargetGUID), _totalFleeTime(time) { } + explicit TimedFleeingMovementGenerator(ObjectGuid fleeTargetGUID, Milliseconds time, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}) + : FleeingMovementGenerator(fleeTargetGUID, std::move(scriptResult)), _totalFleeTime(time) { } bool Update(Unit*, uint32) override; void Finalize(Unit*, bool, bool) override; diff --git a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp index 02184136e2c..0a95fad135e 100644 --- a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp @@ -32,7 +32,8 @@ #define SKIP_SPLINE_POINT_DISTANCE_SQ (40.f * 40.f) #define PLAYER_FLIGHT_SPEED 32.0f -FlightPathMovementGenerator::FlightPathMovementGenerator(Optional<float> speed) +FlightPathMovementGenerator::FlightPathMovementGenerator(Optional<float> speed, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult) { _speed = speed; _endGridX = 0.0f; @@ -44,6 +45,7 @@ FlightPathMovementGenerator::FlightPathMovementGenerator(Optional<float> speed) Priority = MOTION_PRIORITY_HIGHEST; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_IN_FLIGHT; + ScriptResult = std::move(scriptResult); } MovementGeneratorType FlightPathMovementGenerator::GetMovementGeneratorType() const @@ -152,7 +154,7 @@ void FlightPathMovementGenerator::DoDeactivate(Player* /*owner*/) AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); } -void FlightPathMovementGenerator::DoFinalize(Player* owner, bool active, bool/* movementInform*/) +void FlightPathMovementGenerator::DoFinalize(Player* owner, bool active, bool movementInform) { AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); if (!active) @@ -179,6 +181,9 @@ void FlightPathMovementGenerator::DoFinalize(Player* owner, bool active, bool/* } owner->RemovePlayerFlag(PLAYER_FLAGS_TAXI_BENCHMARK); + + if (movementInform) + SetScriptResult(MovementStopReason::Finished); } uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const diff --git a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h index 2abc4c275f4..ada9c742781 100644 --- a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h @@ -33,7 +33,8 @@ struct TaxiPathNodeEntry; class FlightPathMovementGenerator : public MovementGeneratorMedium<Player, FlightPathMovementGenerator>, public PathMovementBase<Player, std::vector<TaxiPathNodeEntry const*>> { public: - explicit FlightPathMovementGenerator(Optional<float> speed); + explicit FlightPathMovementGenerator(Optional<float> speed, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult); MovementGeneratorType GetMovementGeneratorType() const override; bool GetResetPosition(Unit* owner, float& x, float& y, float& z) override; diff --git a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp index a1ad2219d88..475a30481e5 100644 --- a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp @@ -35,13 +35,15 @@ static void DoMovementInform(Unit* owner, Unit* target) AI->MovementInform(FOLLOW_MOTION_TYPE, target->GetGUID().GetCounter()); } -FollowMovementGenerator::FollowMovementGenerator(Unit* target, float range, ChaseAngle angle, Optional<Milliseconds> duration) +FollowMovementGenerator::FollowMovementGenerator(Unit* target, float range, ChaseAngle angle, Optional<Milliseconds> duration, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle), _checkTimer(CHECK_INTERVAL) { Mode = MOTION_MODE_DEFAULT; Priority = MOTION_PRIORITY_NORMAL; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_FOLLOW; + ScriptResult = std::move(scriptResult); if (duration) _duration.emplace(*duration); } @@ -196,13 +198,15 @@ void FollowMovementGenerator::Deactivate(Unit* owner) owner->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); } -void FollowMovementGenerator::Finalize(Unit* owner, bool active, bool/* movementInform*/) +void FollowMovementGenerator::Finalize(Unit* owner, bool active, bool movementInform) { AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); if (active) { owner->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); UpdatePetSpeed(owner); + if (movementInform) + SetScriptResult(MovementStopReason::Finished); } } diff --git a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h index 27c3bd3bcf5..300ab9ce555 100644 --- a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h @@ -21,7 +21,6 @@ #include "AbstractFollower.h" #include "MovementDefines.h" #include "MovementGenerator.h" -#include "Optional.h" #include "Position.h" #include "Timer.h" @@ -33,7 +32,8 @@ class Unit; class FollowMovementGenerator : public MovementGenerator, public AbstractFollower { public: - explicit FollowMovementGenerator(Unit* target, float range, ChaseAngle angle, Optional<Milliseconds> duration); + explicit FollowMovementGenerator(Unit* target, float range, ChaseAngle angle, Optional<Milliseconds> duration, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); ~FollowMovementGenerator(); void Initialize(Unit*) override; diff --git a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp index 7bd9d084bc4..090f129cd8a 100644 --- a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp @@ -40,6 +40,7 @@ GenericMovementGenerator::GenericMovementGenerator(std::function<void(Movement:: _duration.emplace(*args.Duration); _durationTracksSpline = false; } + ScriptResult = std::move(args.ScriptResult); } void GenericMovementGenerator::Initialize(Unit* owner) @@ -101,6 +102,8 @@ void GenericMovementGenerator::MovementInform(Unit* owner) if (_arrivalSpellId) owner->CastSpell(ObjectAccessor::GetUnit(*owner, _arrivalSpellTargetGuid), _arrivalSpellId, true); + SetScriptResult(MovementStopReason::Finished); + if (Creature* creature = owner->ToCreature()) { if (creature->AI()) diff --git a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h index f9c46515e6b..f88b53c3fb0 100644 --- a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h @@ -32,6 +32,7 @@ struct GenericMovementGeneratorArgs Optional<uint32> ArrivalSpellId; Optional<ObjectGuid> ArrivalSpellTarget; Optional<Milliseconds> Duration; + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>> ScriptResult; }; class GenericMovementGenerator : public MovementGenerator diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp index 7aa6a59178c..1b524873841 100644 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp @@ -63,13 +63,16 @@ MovementGeneratorType IdleMovementGenerator::GetMovementGeneratorType() const //----------------------------------------------------// RotateMovementGenerator::RotateMovementGenerator(uint32 id, RotateDirection direction, Optional<Milliseconds> duration, - Optional<float> turnSpeed, Optional<float> totalTurnAngle) : _id(id), _duration(duration), _turnSpeed(turnSpeed), _totalTurnAngle(totalTurnAngle), + Optional<float> turnSpeed, Optional<float> totalTurnAngle, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult) : _id(id), _duration(duration), + _turnSpeed(turnSpeed), _totalTurnAngle(totalTurnAngle), _direction(direction), _diffSinceLastUpdate(0) { Mode = MOTION_MODE_DEFAULT; Priority = MOTION_PRIORITY_NORMAL; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_ROTATING; + ScriptResult = std::move(scriptResult); } void RotateMovementGenerator::Initialize(Unit* owner) @@ -142,8 +145,12 @@ void RotateMovementGenerator::Finalize(Unit* owner, bool/* active*/, bool moveme { AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); - if (movementInform && owner->GetTypeId() == TYPEID_UNIT) - owner->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, _id); + if (movementInform) + { + SetScriptResult(MovementStopReason::Finished); + if (owner->IsCreature()) + owner->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, _id); + } } MovementGeneratorType RotateMovementGenerator::GetMovementGeneratorType() const diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h index d525b9200f8..6e9fe57ba9f 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -43,7 +43,8 @@ class RotateMovementGenerator : public MovementGenerator 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); + Optional<float> turnSpeed, Optional<float> totalTurnAngle, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult); void Initialize(Unit*) override; void Reset(Unit*) override; diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index a626e6ece49..60c4b73a8e8 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -31,7 +31,7 @@ PointMovementGenerator::PointMovementGenerator(uint32 id, float x, float y, float z, bool generatePath, Optional<float> speed /*= {}*/, Optional<float> finalOrient /*= {}*/, Unit const* faceTarget /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/, MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/, - Optional<float> closeEnoughDistance /*= {}*/) + Optional<float> closeEnoughDistance /*= {}*/, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) : _movementId(id), _destination(x, y, z), _speed(speed), _generatePath(generatePath), _finalOrient(finalOrient), i_faceTarget(faceTarget), _speedSelectionMode(speedSelectionMode), _closeEnoughDistance(closeEnoughDistance) { @@ -39,6 +39,7 @@ PointMovementGenerator::PointMovementGenerator(uint32 id, float x, float y, floa this->Priority = MOTION_PRIORITY_NORMAL; this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; this->BaseUnitState = UNIT_STATE_ROAMING; + this->ScriptResult = std::move(scriptResult); if (spellEffectExtraData) this->i_spellEffectExtra = std::make_unique<Movement::SpellEffectExtraData>(*spellEffectExtraData); @@ -195,6 +196,8 @@ void PointMovementGenerator::Finalize(Unit* owner, bool active, bool movementInf void PointMovementGenerator::MovementInform(Unit* owner) { + SetScriptResult(MovementStopReason::Finished); + // deliver EVENT_CHARGE to scripts, EVENT_CHARGE_PREPATH is just internal implementation detail of this movement generator uint32 movementId = _movementId == EVENT_CHARGE_PREPATH ? uint32(EVENT_CHARGE) : _movementId; diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index 8666a2ccc57..ea5ffc8ada3 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -19,7 +19,6 @@ #define TRINITY_POINTMOVEMENTGENERATOR_H #include "MovementGenerator.h" -#include "Optional.h" #include "Position.h" class Creature; @@ -34,7 +33,8 @@ class PointMovementGenerator : public MovementGenerator explicit PointMovementGenerator(uint32 id, float x, float y, float z, bool generatePath, Optional<float> speed = {}, Optional<float> finalOrient = {}, Unit const* faceTarget = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr, MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, - Optional<float> closeEnoughDistance = {}); + Optional<float> closeEnoughDistance = {}, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); MovementGeneratorType GetMovementGeneratorType() const override; diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 1e2298ed088..e1ab9c3ad38 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -18,24 +18,28 @@ #include "RandomMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" -#include "MovementDefines.h" #include "MoveSpline.h" #include "MoveSplineInit.h" +#include "MovementDefines.h" #include "PathGenerator.h" #include "Random.h" template<class T> -RandomMovementGenerator<T>::RandomMovementGenerator(float distance, Optional<Milliseconds> duration) : _timer(0), _reference(), _wanderDistance(distance), _wanderSteps(0) +RandomMovementGenerator<T>::RandomMovementGenerator(float distance, Optional<Milliseconds> duration, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) : _timer(0), _reference(), _wanderDistance(distance), _wanderSteps(0) { this->Mode = MOTION_MODE_DEFAULT; this->Priority = MOTION_PRIORITY_NORMAL; this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; this->BaseUnitState = UNIT_STATE_ROAMING; + this->ScriptResult = std::move(scriptResult); if (duration) _duration.emplace(*duration); } -template RandomMovementGenerator<Creature>::RandomMovementGenerator(float distance, Optional<Milliseconds> duration); +template +RandomMovementGenerator<Creature>::RandomMovementGenerator(float distance, Optional<Milliseconds> duration, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult); template<class T> MovementGeneratorType RandomMovementGenerator<T>::GetMovementGeneratorType() const @@ -265,6 +269,9 @@ void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, } if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + { + SetScriptResult(MovementStopReason::Finished); if (owner->IsAIEnabled()) owner->AI()->MovementInform(RANDOM_MOTION_TYPE, 0); + } } diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h index 5d6ff652f2b..f67b4096e70 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h @@ -29,7 +29,8 @@ template<class T> class RandomMovementGenerator : public MovementGeneratorMedium<T, RandomMovementGenerator<T>> { public: - explicit RandomMovementGenerator(float distance = 0.0f, Optional<Milliseconds> duration = {}); + explicit RandomMovementGenerator(float distance = 0.0f, Optional<Milliseconds> duration = {}, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); MovementGeneratorType GetMovementGeneratorType() const override; diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index afbaae40562..55f462d3f41 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -30,7 +30,8 @@ WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bool repeating, Optional<Milliseconds> duration, Optional<float> speed, MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, - Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, bool generatePath) + Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, bool generatePath, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) : _nextMoveTime(0), _pathId(pathId), _repeating(repeating), _loadedFromDB(true), _speed(speed), _speedSelectionMode(speedSelectionMode), _waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)), _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds), _followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _isReturningToStart(false), @@ -40,13 +41,15 @@ WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bo Priority = MOTION_PRIORITY_NORMAL; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_ROAMING; + ScriptResult = std::move(scriptResult); if (duration) _duration.emplace(*duration); } WaypointMovementGenerator<Creature>::WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional<Milliseconds> duration, Optional<float> speed, MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, - Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, bool generatePath) + Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, bool generatePath, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) : _nextMoveTime(0), _pathId(0), _repeating(repeating), _loadedFromDB(false), _speed(speed), _speedSelectionMode(speedSelectionMode), _waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)), _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds), _followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _isReturningToStart(false), @@ -58,6 +61,7 @@ WaypointMovementGenerator<Creature>::WaypointMovementGenerator(WaypointPath cons Priority = MOTION_PRIORITY_NORMAL; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_ROAMING; + ScriptResult = std::move(scriptResult); if (duration) _duration.emplace(*duration); } @@ -166,6 +170,9 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff) { RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + owner->UpdateCurrentWaypointInfo(0, 0); + SetScriptResult(MovementStopReason::Finished); return false; } } @@ -248,7 +255,7 @@ void WaypointMovementGenerator<Creature>::DoDeactivate(Creature* owner) owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); } -void WaypointMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool/* movementInform*/) +void WaypointMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool movementInform) { AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); if (active) @@ -258,6 +265,9 @@ void WaypointMovementGenerator<Creature>::DoFinalize(Creature* owner, bool activ // TODO: Research if this modification is needed, which most likely isnt owner->SetWalk(false); } + + if (movementInform) + SetScriptResult(MovementStopReason::Finished); } void WaypointMovementGenerator<Creature>::MovementInform(Creature* owner) @@ -353,6 +363,8 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun // inform AI if (CreatureAI* AI = owner->AI()) AI->WaypointPathEnded(waypoint.Id, GetPath()->Id); + + SetScriptResult(MovementStopReason::Finished); return; } } @@ -391,7 +403,7 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun init.SetAnimation(AnimTier::Ground); break; case WaypointMoveType::TakeOff: - init.SetAnimation(AnimTier::Hover); + init.SetAnimation(AnimTier::Fly); break; case WaypointMoveType::Run: init.SetWalk(false); diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index 8de8f5de52b..23d5cc1c7c6 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -38,11 +38,13 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creat explicit WaypointMovementGenerator(uint32 pathId, bool repeating, 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<bool> followPathBackwardsFromEndToStart = {}, bool generatePath = true, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); explicit WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional<Milliseconds> duration, Optional<float> speed, MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, Optional<float> wanderDistanceAtPathEnds, - Optional<bool> followPathBackwardsFromEndToStart, bool generatePath); + Optional<bool> followPathBackwardsFromEndToStart, bool generatePath, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); ~WaypointMovementGenerator(); MovementGeneratorType GetMovementGeneratorType() const override; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index bb43a8be767..9927b4f7ec2 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3882,6 +3882,9 @@ void Spell::_cast(bool skipCheck) handle_immediate(); } + if (m_scriptResult && !m_scriptWaitsForSpellHit) + m_scriptResult->SetResult(SPELL_CAST_OK); + CallScriptAfterCastHandlers(); if (std::vector<int32> const* spell_triggered = sSpellMgr->GetSpellLinked(SPELL_LINK_CAST, m_spellInfo->Id)) @@ -4313,6 +4316,9 @@ void Spell::finish(SpellCastResult result) return; m_spellState = SPELL_STATE_FINISHED; + if (m_scriptResult && (m_scriptWaitsForSpellHit || result != SPELL_CAST_OK)) + m_scriptResult->SetResult(result); + if (!m_caster) return; diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 0c484b5ba56..e9ec910e322 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -603,6 +603,9 @@ class TC_GAME_API Spell UsedSpellMods m_appliedMods; + Optional<Scripting::v2::ActionResultSetter<SpellCastResult>> m_scriptResult; + bool m_scriptWaitsForSpellHit = false; + int32 GetCastTime() const { return m_casttime; } int32 GetRemainingCastTime() const { return m_timer; } bool IsAutoRepeat() const { return m_autoRepeat; } diff --git a/src/server/game/Spells/SpellDefines.h b/src/server/game/Spells/SpellDefines.h index 8e9b6d3ada5..7458c8925f5 100644 --- a/src/server/game/Spells/SpellDefines.h +++ b/src/server/game/Spells/SpellDefines.h @@ -24,6 +24,7 @@ #include "ObjectGuid.h" #include "Optional.h" #include "Position.h" +#include "ScriptActionResult.h" #include <any> #include <vector> @@ -38,6 +39,7 @@ class WorldObject; enum Difficulty : uint8; enum ProcFlags : uint32; enum ProcFlags2 : int32; +enum SpellCastResult : int32; namespace UF { @@ -474,6 +476,8 @@ struct TC_GAME_API CastSpellExtraArgs CastSpellExtraArgs& AddSpellMod(SpellValueMod mod, int32 val) { SpellValueOverrides.AddMod(mod, val); return *this; } CastSpellExtraArgs& AddSpellBP0(int32 val) { return AddSpellMod(SPELLVALUE_BASE_POINT0, val); } // because i don't want to type SPELLVALUE_BASE_POINT0 300 times CastSpellExtraArgs& SetCustomArg(std::any customArg) { CustomArg = std::move(customArg); return *this; } + CastSpellExtraArgs& SetScriptResult(Scripting::v2::ActionResultSetter<SpellCastResult> scriptResult) { ScriptResult.emplace(std::move(scriptResult)); return *this; } + CastSpellExtraArgs& SetScriptWaitsForSpellHit(bool scriptWaitsForSpellHit) { ScriptWaitsForSpellHit = scriptWaitsForSpellHit; return *this; } TriggerCastFlags TriggerFlags = TRIGGERED_NONE; Item* CastItem = nullptr; @@ -497,6 +501,9 @@ struct TC_GAME_API CastSpellExtraArgs std::vector<std::pair<SpellValueMod, int32>> data; } SpellValueOverrides; std::any CustomArg; + + Optional<Scripting::v2::ActionResultSetter<SpellCastResult>> ScriptResult; + bool ScriptWaitsForSpellHit = false; }; struct SpellCastVisual |