diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index db13329faa..ebcb5b9856 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -862,7 +862,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } case SMART_EVENT_MOVEMENTINFORM: { - if (e.event.movementInform.type >= MAX_MOTION_TYPE) + if (IsInvalidMovementGeneratorType(e.event.movementInform.type)) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Motion type %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.movementInform.type); return false; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index abb6037302..0e8ebce701 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -544,7 +544,7 @@ void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed, bool gen Movement::MoveSplineInit init(this); init.MoveTo(x, y, z, generatePath, forceDestination); init.SetVelocity(speed); - init.Launch(); + GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); } void Unit::UpdateSplineMovement(uint32 t_diff) @@ -11051,7 +11051,7 @@ void Unit::StopMoving() void Unit::PauseMovement(uint32 timer/* = 0*/, uint8 slot/* = 0*/, bool forced/* = true*/) { - if (slot >= MAX_MOTION_SLOT) + if (IsInvalidMovementSlot(slot)) return; if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MovementSlot(slot))) @@ -11063,7 +11063,7 @@ void Unit::PauseMovement(uint32 timer/* = 0*/, uint8 slot/* = 0*/, bool forced/* void Unit::ResumeMovement(uint32 timer/* = 0*/, uint8 slot/* = 0*/) { - if (slot >= MAX_MOTION_SLOT) + if (IsInvalidMovementSlot(slot)) return; if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MovementSlot(slot))) @@ -13547,7 +13547,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false); init.SetFacing(GetOrientation()); init.SetTransportExit(); - init.Launch(); + GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_EXIT, MOTION_SLOT_CONTROLLED); if (player) player->ResummonPetTemporaryUnSummonedIfAny(); diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 7ae7b92472..e716c666cf 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -23,6 +23,7 @@ #include "DBCStores.h" #include "EventProcessor.h" #include "Log.h" +#include "MotionMaster.h" #include "MoveSplineInit.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" @@ -913,7 +914,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32) init.MoveTo(x, y, z, false, true); init.SetFacing(o); init.SetTransportEnter(); - init.Launch(); + Passenger->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_SLOT_CONTROLLED); if (Creature* creature = Target->GetBase()->ToCreature()) { diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index a576f6b619..fe579ca891 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3762,7 +3762,11 @@ enum EventId /// Special charge event which is used for charge spells that have explicit targets /// and had a path already generated - using it in PointMovementGenerator will not /// create a new spline and launch it - EVENT_CHARGE_PREPATH = 1005 + EVENT_CHARGE_PREPATH = 1005, + + EVENT_FACE = 1006, + EVENT_VEHICLE_BOARD = 1007, + EVENT_VEHICLE_EXIT = 1008 }; enum ResponseCodes diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 5eb591e993..4b509df100 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -22,10 +22,12 @@ #include "Creature.h" #include "CreatureAISelector.h" #include "DBCStores.h" +#include "G3DPosition.hpp" #include "FleeingMovementGenerator.h" #include "FlightPathMovementGenerator.h" #include "FollowMovementGenerator.h" #include "FormationMovementGenerator.h" +#include "GenericMovementGenerator.h" #include "HomeMovementGenerator.h" #include "IdleMovementGenerator.h" #include "Log.h" @@ -126,7 +128,7 @@ void MotionMaster::Clear(bool reset /*= true*/) void MotionMaster::Clear(MovementSlot slot) { - if (empty() || slot >= MAX_MOTION_SLOT) + if (empty() || IsInvalidMovementSlot(slot)) return; if (_cleanFlag & MMCF_UPDATE) @@ -162,7 +164,7 @@ MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const MovementGeneratorType MotionMaster::GetMotionSlotType(MovementSlot slot) const { - if (empty() || slot >= MAX_MOTION_SLOT || !_slot[slot]) + if (empty() || IsInvalidMovementSlot(slot) || !_slot[slot]) return MAX_MOTION_TYPE; return _slot[slot]->GetMovementGeneratorType(); @@ -170,7 +172,7 @@ MovementGeneratorType MotionMaster::GetMotionSlotType(MovementSlot slot) const MovementGenerator* MotionMaster::GetMotionSlot(MovementSlot slot) const { - if (empty() || slot >= MAX_MOTION_SLOT || !_slot[slot]) + if (empty() || IsInvalidMovementSlot(slot) || !_slot[slot]) return nullptr; return _slot[slot]; @@ -209,26 +211,25 @@ void MotionMaster::MoveIdle() void MotionMaster::MoveTargetedHome() { + Creature* owner = _owner->ToCreature(); + if (!owner) + { + TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveTargetedHome: '%s', attempted to move towards target home.", _owner->GetGUID().ToString().c_str()); + return; + } + Clear(false); - if (_owner->GetTypeId() == TYPEID_UNIT && !_owner->ToCreature()->GetCharmerOrOwnerGUID()) + Unit* target = owner->GetCharmerOrOwner(); + if (!target) { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) targeted home.", _owner->GetEntry(), _owner->GetGUID().GetCounter()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveTargetedHome: '%s', targeted home.", _owner->GetGUID().ToString().c_str()); Mutate(new HomeMovementGenerator(), MOTION_SLOT_ACTIVE); } - else if (_owner->GetTypeId() == TYPEID_UNIT && _owner->ToCreature()->GetCharmerOrOwnerGUID()) - { - TC_LOG_DEBUG("misc", "Pet or controlled creature (Entry: %u GUID: %u) is targeting home.", _owner->GetEntry(), _owner->GetGUID().GetCounter()); - Unit* target = _owner->ToCreature()->GetCharmerOrOwner(); - if (target) - { - TC_LOG_DEBUG("misc", "Following %s (GUID: %u).", target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : ((Creature*)target)->GetSpawnId()); - Mutate(new FollowMovementGenerator(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE); - } - } else { - TC_LOG_ERROR("misc", "Player (GUID: %u) attempted to move towards target home.", _owner->GetGUID().GetCounter()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveTargetedHome: '%s', starts following '%s'", _owner->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str()); + Mutate(new FollowMovementGenerator(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE); } } @@ -236,7 +237,7 @@ void MotionMaster::MoveRandom(float spawndist) { if (_owner->GetTypeId() == TYPEID_UNIT) { - TC_LOG_DEBUG("misc", "Creature (GUID: %u) started random movement.", _owner->GetGUID().GetCounter()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRandom: '%s', started random movement (spawnDist: %f)", _owner->GetGUID().ToString().c_str(), spawndist); Mutate(new RandomMovementGenerator(spawndist), MOTION_SLOT_IDLE); } } @@ -247,12 +248,7 @@ void MotionMaster::MoveFollow(Unit* target, float dist, ChaseAngle angle, Moveme if (!target || target == _owner) return; - TC_LOG_DEBUG("misc", "%s (Entry: %u, GUID: %u) follows %s (Entry %u, GUID: %u).", - _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), - target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - target->GetEntry(), target->GetGUID().GetCounter()); - + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFollow: '%s', starts following '%s'", _owner->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str()); Mutate(new FollowMovementGenerator(target, dist, angle), slot); } @@ -262,11 +258,7 @@ void MotionMaster::MoveChase(Unit* target, Optional dist, OptionalGetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), - target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - target->GetEntry(), target->GetGUID().GetCounter()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveChase: '%s', starts chasing '%s'", _owner->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str()); Mutate(new ChaseMovementGenerator(target, dist, angle), MOTION_SLOT_ACTIVE); } @@ -274,13 +266,12 @@ void MotionMaster::MoveConfused() { if (_owner->GetTypeId() == TYPEID_PLAYER) { - TC_LOG_DEBUG("misc", "Player (GUID: %u) move confused", _owner->GetGUID().GetCounter()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveConfused: '%s', started confused movement.", _owner->GetGUID().ToString().c_str()); Mutate(new ConfusedMovementGenerator(), MOTION_SLOT_CONTROLLED); } else { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) move confused", - _owner->GetEntry(), _owner->GetGUID().GetCounter()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveConfused: '%s', started confused movement.", _owner->GetGUID().ToString().c_str()); Mutate(new ConfusedMovementGenerator(), MOTION_SLOT_CONTROLLED); } } @@ -290,39 +281,29 @@ void MotionMaster::MoveFleeing(Unit* enemy, uint32 time) if (!enemy) return; - if (_owner->GetTypeId() == TYPEID_PLAYER) + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFleeing: '%s', flees from '%s' (time: %u)", _owner->GetGUID().ToString().c_str(), enemy->GetGUID().ToString().c_str(), time); + if (_owner->GetTypeId() == TYPEID_UNIT) { - TC_LOG_DEBUG("misc", "Player (GUID: %u) flees from %s (GUID: %u).", _owner->GetGUID().GetCounter(), - enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId()); - Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); - } - else - { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) flees from %s (GUID: %u)%s.", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), - enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId(), - time ? " for a limited time" : ""); if (time) Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time), MOTION_SLOT_CONTROLLED); else Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); } + else + Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); } void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generatePath) { if (_owner->GetTypeId() == TYPEID_PLAYER) { - TC_LOG_DEBUG("misc", "Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f).", _owner->GetGUID().GetCounter(), id, x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z, generatePath), MOTION_SLOT_ACTIVE); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePoint: '%s', targeted point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, x, y, z); + Mutate(new PointMovementGenerator(id, x, y, z, generatePath, 0.0f), MOTION_SLOT_ACTIVE); } else { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f).", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), id, x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z, generatePath), MOTION_SLOT_ACTIVE); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePoint: '%s', targeted point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, x, y, z); + Mutate(new PointMovementGenerator(id, x, y, z, generatePath, 0.0f), MOTION_SLOT_ACTIVE); } } @@ -342,41 +323,32 @@ void MotionMaster::MoveCloserAndStop(uint32 id, Unit* target, float distance) Movement::MoveSplineInit init(_owner); init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); init.SetFacing(target); - init.Launch(); - Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_ACTIVE); } } void MotionMaster::MoveLand(uint32 id, Position const& pos) { - float x, y, z; - pos.GetPosition(x, y, z); - - TC_LOG_DEBUG("misc", "Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f).", _owner->GetEntry(), id, x, y, z); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveLand: '%s', landing point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); Movement::MoveSplineInit init(_owner); - init.MoveTo(x, y, z, false); + init.MoveTo(PositionToVector3(pos), false); init.SetSmooth(); init.SetFly(); init.SetAnimation(Movement::ToGround); - init.Launch(); - Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_ACTIVE); } void MotionMaster::MoveTakeoff(uint32 id, Position const& pos) { - float x, y, z; - pos.GetPosition(x, y, z); - - TC_LOG_DEBUG("misc", "Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f).", _owner->GetEntry(), id, x, y, z); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveTakeoff: '%s', landing point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); Movement::MoveSplineInit init(_owner); - init.MoveTo(x, y, z, false); + init.MoveTo(PositionToVector3(pos)); init.SetSmooth(); init.SetFly(); init.SetAnimation(Movement::ToFly); - init.Launch(); - Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_ACTIVE); } void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_CHARGE*/, uint32 id /*= EVENT_CHARGE*/, bool generatePath /*= false*/) @@ -386,13 +358,12 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_C if (_owner->GetTypeId() == TYPEID_PLAYER) { - TC_LOG_DEBUG("misc", "Player (GUID: %u) charged point (X: %f Y: %f Z: %f).", _owner->GetGUID().GetCounter(), x, y, z); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveCharge: '%s', charging point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, x, y, z); Mutate(new PointMovementGenerator(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); } else { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) charged point (X: %f Y: %f Z: %f).", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), x, y, z); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveCharge: '%s', charging point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, x, y, z); Mutate(new PointMovementGenerator(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); } } @@ -431,8 +402,7 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa init.SetParabolic(max_height, 0); init.SetOrientationFixed(true); init.SetVelocity(speedXY); - init.Launch(); - Mutate(new EffectMovementGenerator(0), MOTION_SLOT_CONTROLLED); + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, 0), MOTION_SLOT_CONTROLLED); } void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) @@ -441,19 +411,18 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) if (_owner->GetTypeId() == TYPEID_PLAYER) return; - float x, y, z; + float x, y, z = _owner->GetPositionZ(); float moveTimeHalf = speedZ / Movement::gravity; float dist = 2 * moveTimeHalf * speedXY; _owner->GetNearPoint2D(nullptr, x, y, dist, _owner->GetOrientation() + angle); - z = _owner->GetPositionZ(); _owner->UpdateAllowedPositionZ(x, y, z); MoveJump(x, y, z, 0.0f, speedXY, speedZ); } void MotionMaster::MoveJump(float x, float y, float z, float o, float speedXY, float speedZ, uint32 id, bool hasOrientation /* = false*/) { - TC_LOG_DEBUG("misc", "Unit (GUID: %u) jumps to point (X: %f Y: %f Z: %f).", _owner->GetGUID().GetCounter(), x, y, z); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveJump: '%s', jumps to point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, x, y, z); if (speedXY < 0.01f) return; @@ -466,8 +435,8 @@ void MotionMaster::MoveJump(float x, float y, float z, float o, float speedXY, f init.SetVelocity(speedXY); if (hasOrientation) init.SetFacing(o); - init.Launch(); - Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); + + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_CONTROLLED); } void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount) @@ -509,7 +478,7 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool } init.SetSmooth(); - init.Launch(); + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, 0), MOTION_SLOT_ACTIVE); } void MotionMaster::MoveCyclicPath(Position const* pathPoints, size_t pathSize, bool walk /*= false*/, bool fly /*= false*/, float velocity /*= 0.0f*/) @@ -535,7 +504,7 @@ void MotionMaster::MoveCyclicPath(Position const* pathPoints, size_t pathSize, b init.SetSmooth(); init.SetWalk(walk); init.SetCyclic(); - init.Launch(); + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, 0), MOTION_SLOT_ACTIVE); } void MotionMaster::MoveSmoothPath(uint32 pointId, Position const* pathPoints, size_t pathSize, bool walk /*= false*/, bool fly /*= false*/, float velocity /*= 0.0f*/) @@ -560,14 +529,11 @@ void MotionMaster::MoveSmoothPath(uint32 pointId, Position const* pathPoints, si init.MovebyPath(path); init.SetSmooth(); init.SetWalk(walk); - init.Launch(); // This code is not correct - // EffectMovementGenerator does not affect UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE + // GenericMovementGenerator does not affect UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE // need to call PointMovementGenerator with various pointIds - Mutate(new EffectMovementGenerator(pointId), MOTION_SLOT_ACTIVE); - //Position pos(pathPoints[pathSize - 1].x, pathPoints[pathSize - 1].y, pathPoints[pathSize - 1].z); - //MovePoint(EVENT_CHARGE_PREPATH, pos, false); + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, pointId), MOTION_SLOT_ACTIVE); } void MotionMaster::MoveAlongSplineChain(uint32 pointId, uint16 dbChainId, bool walk) @@ -575,13 +541,13 @@ void MotionMaster::MoveAlongSplineChain(uint32 pointId, uint16 dbChainId, bool w Creature* owner = _owner->ToCreature(); if (!owner) { - TC_LOG_ERROR("misc", "MotionMaster::MoveAlongSplineChain: non-creature %s tried to walk along DB spline chain. Ignoring.", _owner->GetGUID().ToString().c_str()); + TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveAlongSplineChain: '%s', tried to walk along DB spline chain. Ignoring.", _owner->GetGUID().ToString().c_str()); return; } std::vector const* chain = sScriptSystemMgr->GetSplineChain(owner, dbChainId); if (!chain) { - TC_LOG_ERROR("misc", "MotionMaster::MoveAlongSplineChain: creature with entry %u tried to walk along non-existing spline chain with DB id %u.", owner->GetEntry(), dbChainId); + TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveAlongSplineChain: '%s', tried to walk along non-existing spline chain with DB Id: %u.", _owner->GetGUID().ToString().c_str(), dbChainId); return; } MoveAlongSplineChain(pointId, *chain, walk); @@ -596,7 +562,7 @@ void MotionMaster::ResumeSplineChain(SplineChainResumeInfo const& info) { if (info.Empty()) { - TC_LOG_ERROR("misc", "MotionMaster::ResumeSplineChain: unit with entry %u tried to resume a spline chain from empty info.", _owner->GetEntry()); + TC_LOG_ERROR("movement.motionmaster", "MotionMaster::ResumeSplineChain: '%s', tried to resume a spline chain from empty info.", _owner->GetGUID().ToString().c_str()); return; } Mutate(new SplineChainMovementGenerator(info), MOTION_SLOT_ACTIVE); @@ -608,8 +574,8 @@ void MotionMaster::MoveFall(uint32 id /*=0*/) float tz = _owner->GetMapHeight(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ(), true, MAX_FALL_DISTANCE); if (tz <= INVALID_HEIGHT) { - TC_LOG_DEBUG("misc", "MotionMaster::MoveFall: unable to retrieve a proper height at map %u (x: %f, y: %f, z: %f).", - _owner->GetMap()->GetId(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ() + _owner->GetPositionZ()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFall: '%s', unable to retrieve a proper height at map Id: %u (X: %f, Y: %f, Z: %f)", + _owner->GetGUID().ToString().c_str(), _owner->GetMap()->GetId(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); return; } @@ -630,39 +596,32 @@ void MotionMaster::MoveFall(uint32 id /*=0*/) Movement::MoveSplineInit init(_owner); init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz + _owner->GetHoverOffset(), false); init.SetFall(); - init.Launch(); - Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); + Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_CONTROLLED); } void MotionMaster::MoveSeekAssistance(float x, float y, float z) { - if (_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_UNIT) { - TC_LOG_ERROR("misc", "Player (GUID: %u) attempted to seek assistance.", _owner->GetGUID().GetCounter()); - } - else - { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) seek assistance (X: %f Y: %f Z: %f)", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), x, y, z); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveSeekAssistance: '%s', seeks assistance (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), x, y, z); _owner->AttackStop(); _owner->CastStop(); _owner->ToCreature()->SetReactState(REACT_PASSIVE); Mutate(new AssistanceMovementGenerator(x, y, z), MOTION_SLOT_ACTIVE); } + else + TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveSeekAssistance: '%s', attempted to seek assistance.", _owner->GetGUID().ToString().c_str()); } void MotionMaster::MoveSeekAssistanceDistract(uint32 time) { - if (_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_UNIT) { - TC_LOG_ERROR("misc", "Player (GUID: %u) attempted to call distract assistance.", _owner->GetGUID().GetCounter()); - } - else - { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) is distracted after assistance call (Time: %u).", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), time); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveSeekAssistanceDistract: '%s', is distracted after assistance call (Time: %u)", _owner->GetGUID().ToString().c_str(), time); Mutate(new AssistanceDistractMovementGenerator(time), MOTION_SLOT_ACTIVE); } + else + TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveSeekAssistanceDistract: '%s', attempted to call distract assistance.", _owner->GetGUID().ToString().c_str()); } void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) @@ -671,22 +630,16 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) { if (path < sTaxiPathNodesByPath.size()) { - TC_LOG_DEBUG("misc", "%s taxi to (Path %u node %u).", _owner->GetName().c_str(), path, pathnode); - FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(pathnode); - mgen->LoadPath(_owner->ToPlayer()); - Mutate(mgen, MOTION_SLOT_CONTROLLED); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveTaxiFlight: '%s', taxi to path Id: %u (node %u)", _owner->GetGUID().ToString().c_str(), path, pathnode); + FlightPathMovementGenerator* movement = new FlightPathMovementGenerator(pathnode); + movement->LoadPath(_owner->ToPlayer()); + Mutate(movement, MOTION_SLOT_CONTROLLED); } else - { - TC_LOG_ERROR("misc", "%s attempted taxi to (non-existing Path %u node %u).", - _owner->GetName().c_str(), path, pathnode); - } + TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveTaxiFlight: '%s', attempted taxi to non-existing path Id: %u (node: %u)", _owner->GetGUID().ToString().c_str(), path, pathnode); } else - { - TC_LOG_ERROR("misc", "Creature (Entry: %u GUID: %u) attempted taxi to (Path %u node %u).", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), path, pathnode); - } + TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveTaxiFlight: '%s', attempted taxi to path Id: %u (node: %u)", _owner->GetGUID().ToString().c_str(), path, pathnode); } void MotionMaster::MoveDistract(uint32 timer) @@ -695,17 +648,11 @@ void MotionMaster::MoveDistract(uint32 timer) return; if (_owner->GetTypeId() == TYPEID_PLAYER) - { - TC_LOG_DEBUG("misc", "Player (GUID: %u) distracted (timer: %u).", _owner->GetGUID().GetCounter(), timer); - } + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveDistract: '%s', distracted (timer: %u)", _owner->GetGUID().ToString().c_str(), timer); else - { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) distracted (timer: %u)", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), timer); - } + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveDistract: '%s', distracted (timer: %u)", _owner->GetGUID().ToString().c_str(), timer); - DistractMovementGenerator* mgen = new DistractMovementGenerator(timer); - Mutate(mgen, MOTION_SLOT_CONTROLLED); + Mutate(new DistractMovementGenerator(timer), MOTION_SLOT_CONTROLLED); } void MotionMaster::MovePath(uint32 pathId, bool repeatable) @@ -713,16 +660,14 @@ void MotionMaster::MovePath(uint32 pathId, bool repeatable) if (!pathId) return; + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '%s', starts moving over path Id: %u (repeatable: %s)", _owner->GetGUID().ToString().c_str(), pathId, repeatable ? "YES" : "NO"); Mutate(new WaypointMovementGenerator(pathId, repeatable), MOTION_SLOT_IDLE); - - TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).", _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", _owner->GetGUID().GetCounter(), pathId, repeatable ? "YES" : "NO"); } void MotionMaster::MovePath(WaypointPath& path, bool repeatable) { + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '%s', starts moving over path Id: %u (repeatable: %s)", _owner->GetGUID().ToString().c_str(), path.id, repeatable ? "YES" : "NO"); Mutate(new WaypointMovementGenerator(path, repeatable), MOTION_SLOT_IDLE); - - TC_LOG_DEBUG("misc", "%s (GUID: %u) start moving over path(repeatable: %s)", _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", _owner->GetGUID().GetCounter(), repeatable ? "YES" : "NO"); } void MotionMaster::MoveRotate(uint32 time, RotateDirection direction) @@ -730,6 +675,7 @@ void MotionMaster::MoveRotate(uint32 time, RotateDirection direction) if (!time) return; + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRotate: '%s', starts rotate (time: %u, direction: %u)", _owner->GetGUID().ToString().c_str(), time, direction); Mutate(new RotateMovementGenerator(time, direction), MOTION_SLOT_ACTIVE); } @@ -737,11 +683,23 @@ void MotionMaster::MoveFormation(uint32 id, Position destination, uint32 moveTyp { if (_owner->GetTypeId() == TYPEID_UNIT) { - TC_LOG_DEBUG("misc", "MotionMaster::MoveFormation: creature (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f).", _owner->GetGUID().GetCounter(), id, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFormation: '%s', targeted point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); Mutate(new FormationMovementGenerator(id, destination, moveType, forceRun, forceOrientation), MOTION_SLOT_ACTIVE); } } +void MotionMaster::LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id/*= 0*/, MovementSlot slot/*= MOTION_SLOT_ACTIVE*/, MovementGeneratorType type/*= EFFECT_MOTION_TYPE*/) +{ + if (IsInvalidMovementGeneratorType(type)) + { + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::LaunchMoveSpline: '%s', tried to launch a spline with an invalid MovementGeneratorType: %u (Id: %u, Slot: %u)", _owner->GetGUID().ToString().c_str(), type, id, slot); + return; + } + + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::LaunchMoveSpline: '%s', initiates spline Id: %u (Type: %u, Slot: %u)", _owner->GetGUID().ToString().c_str(), id, type, slot); + Mutate(new GenericMovementGenerator(std::move(init), type, id), slot); +} + /******************** Private methods ********************/ void MotionMaster::pop() @@ -888,13 +846,14 @@ void MotionMaster::DirectDelete(MovementGenerator* curr) { if (IsStatic(curr)) return; + curr->Finalize(_owner); delete curr; } void MotionMaster::DelayedDelete(MovementGenerator* curr) { - TC_LOG_DEBUG("misc", "MotionMaster::DelayedDelete: unit (%u) delayed deleting movement generator (type %u)", _owner->GetEntry(), curr->GetMovementGeneratorType()); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::DelayedDelete: '%s', delayed deleting movement generator (type: %u)", _owner->GetGUID().ToString().c_str(), curr->GetMovementGeneratorType()); if (IsStatic(curr)) return; diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index d0c0f12017..0e9e0137b7 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -34,6 +34,11 @@ struct SplineChainLink; struct SplineChainResumeInfo; struct WaypointPath; +namespace Movement +{ + class MoveSplineInit; +} + // Creature Entry ID used for waypoints show, visible only for GMs #define VISUAL_WAYPOINT 1 // assume it is 25 yard per 0.6 second @@ -113,6 +118,8 @@ struct ChaseAngle } }; +inline bool IsInvalidMovementGeneratorType(uint8 const type) { return type == MAX_DB_MOTION_TYPE || type >= MAX_MOTION_TYPE; } +inline bool IsInvalidMovementSlot(uint8 const slot) { return slot >= MAX_MOTION_SLOT; } class TC_GAME_API MotionMaster { @@ -202,6 +209,8 @@ class TC_GAME_API MotionMaster void MoveRotate(uint32 time, RotateDirection direction); void MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun = false, bool forceOrientation = false); + + void LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id = 0, MovementSlot slot = MOTION_SLOT_ACTIVE, MovementGeneratorType type = EFFECT_MOTION_TYPE); private: typedef std::vector MovementList; diff --git a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp new file mode 100644 index 0000000000..64de380a34 --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008-2018 TrinityCore + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "GenericMovementGenerator.h" +#include "Creature.h" +#include "CreatureAI.h" +#include "MoveSpline.h" +#include "Unit.h" + +void GenericMovementGenerator::Initialize(Unit* /*owner*/) +{ + _duration.Reset(_splineInit.Launch()); +} + +bool GenericMovementGenerator::Update(Unit* owner, uint32 diff) +{ + _duration.Update(diff); + if (_duration.Passed()) + return false; + + return !owner->movespline->Finalized(); +} + +void GenericMovementGenerator::Finalize(Unit* owner) +{ + MovementInform(owner); +} + +void GenericMovementGenerator::MovementInform(Unit* owner) +{ + if (Creature* creature = owner->ToCreature()) + if (creature->AI()) + creature->AI()->MovementInform(_type, _pointId); +} diff --git a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h new file mode 100644 index 0000000000..db1198371a --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008-2019 TrinityCore + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef TRINITY_GENERICMOVEMENTGENERATOR_H +#define TRINITY_GENERICMOVEMENTGENERATOR_H + +#include "MovementGenerator.h" +#include "MoveSplineInit.h" +#include "Timer.h" + +class Unit; + +enum MovementGeneratorType : uint8; + +class GenericMovementGenerator : public MovementGenerator +{ + public: + explicit GenericMovementGenerator(Movement::MoveSplineInit&& splineInit, MovementGeneratorType type, uint32 id) : _splineInit(std::move(splineInit)), _type(type), _pointId(id), _duration(0) { } + + void Initialize(Unit*) override; + void Finalize(Unit*) override; + void Reset(Unit*) override { } + bool Update(Unit*, uint32) override; + MovementGeneratorType GetMovementGeneratorType() const override { return _type; } + + private: + void MovementInform(Unit*); + + Movement::MoveSplineInit _splineInit; + MovementGeneratorType _type; + uint32 _pointId; + TimeTrackerSmall _duration; +}; + +#endif diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index c7a89987d2..66fb053acb 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -37,7 +37,7 @@ void PointMovementGenerator::DoInitialize(T* owner) owner->AddUnitState(UNIT_STATE_ROAMING); - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || (owner->IsMovementPreventedByCasting() && _movementId != EVENT_CHARGE)) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { _interrupt = true; owner->StopMoving(); @@ -140,22 +140,3 @@ void AssistanceMovementGenerator::Finalize(Unit* owner) if (owner->IsAlive()) owner->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)); } - -//---- EffectMovementGenerator - -bool EffectMovementGenerator::Update(Unit* owner, uint32 /*diff*/) -{ - return !owner->movespline->Finalized(); -} - -void EffectMovementGenerator::Finalize(Unit* owner) -{ - MovementInform(owner); -} - -void EffectMovementGenerator::MovementInform(Unit* owner) -{ - if (Creature* creature = owner->ToCreature()) - if (creature->AI()) - creature->AI()->MovementInform(EFFECT_MOTION_TYPE, _pointId); -} diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index 59d8c741d7..e7b57ae513 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -57,21 +57,4 @@ class AssistanceMovementGenerator : public PointMovementGenerator void Finalize(Unit*) override; }; -class EffectMovementGenerator : public MovementGenerator -{ - public: - explicit EffectMovementGenerator(uint32 id) : _pointId(id) { } - - void Initialize(Unit*) override { } - void Finalize(Unit*) override; - void Reset(Unit*) override { } - bool Update(Unit*, uint32) override; - MovementGeneratorType GetMovementGeneratorType() const override { return EFFECT_MOTION_TYPE; } - - private: - void MovementInform(Unit*); - - uint32 _pointId; -}; - #endif diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index d1787bb769..75f6842daf 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -199,6 +199,8 @@ HasVelocity(false), TransformForTransport(true) path.reserve(path_capacity); } +MoveSplineInitArgs::MoveSplineInitArgs(MoveSplineInitArgs&& args) = default; + MoveSplineInitArgs::~MoveSplineInitArgs() = default; /// ============================================================================================ diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 52ce3353ab..b30bc43c35 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -53,6 +53,8 @@ namespace Movement public: explicit MoveSplineInit(Unit* m); + MoveSplineInit(MoveSplineInit&& init) = default; + ~MoveSplineInit(); MoveSplineInit(MoveSplineInit const&) = delete; MoveSplineInit& operator=(MoveSplineInit const&) = delete; diff --git a/src/server/game/Movement/Spline/MoveSplineInitArgs.h b/src/server/game/Movement/Spline/MoveSplineInitArgs.h index d6a188ec41..4509282374 100644 --- a/src/server/game/Movement/Spline/MoveSplineInitArgs.h +++ b/src/server/game/Movement/Spline/MoveSplineInitArgs.h @@ -44,6 +44,7 @@ namespace Movement struct MoveSplineInitArgs { explicit MoveSplineInitArgs(size_t path_capacity = 16); + MoveSplineInitArgs(MoveSplineInitArgs&& args); ~MoveSplineInitArgs(); PointsArray path; diff --git a/src/server/scripts/EasternKingdoms/Deadmines/boss_helix_gearbreaker.cpp b/src/server/scripts/EasternKingdoms/Deadmines/boss_helix_gearbreaker.cpp index 4eb5feb451..18fb46baef 100644 --- a/src/server/scripts/EasternKingdoms/Deadmines/boss_helix_gearbreaker.cpp +++ b/src/server/scripts/EasternKingdoms/Deadmines/boss_helix_gearbreaker.cpp @@ -75,44 +75,55 @@ enum Spells SPELL_ARMING_VISUAL_RED = 88317, SPELL_STICKY_BOMB_ARMED_STATE = 88319, SPELL_STICKY_BOMB_PERIODIC_TRIGGER = 88329, - SPELL_EXPLODE = 88974, + SPELL_EXPLODE = 88974 +}; + +uint32 const BombArmingVisualSpells[] = +{ + SPELL_ARMING_VISUAL_YELLOW, + SPELL_ARMING_VISUAL_ORANGE, + SPELL_ARMING_VISUAL_RED }; enum DisplayIds { - DISPLAY_ID_BOMB_INVISIBLE = 11686, + DISPLAY_ID_BOMB_INVISIBLE = 11686 }; enum Events { // Helix Gearbreaker - EVENT_STICKY_BOMB = 1, + EVENT_SUMMON_HELIX_CREW = 1, + EVENT_STICKY_BOMB, EVENT_OAF_SMASH, EVENT_THROW_HELIX, EVENT_RIDE_FACE, // Lumbering Oaf - EVENT_MOVE_TO_PREPARE_POSITION, - EVENT_CHARGE_DEST, + EVENT_PREPARE_OAF_SMASH, + EVENT_OAF_SMASH_CHARGE, // Sticky Bomb - EVENT_ARMING_VISUAL_YELLOW, - EVENT_ARMING_VISUAL_ORANGE, - EVENT_ARMING_VISUAL_RED, - EVENT_PREPARED_STATE, + EVENT_ARM_BOMB, EVENT_PERIODIC_TRIGGER, EVENT_EXPLOSION_COUNTDOWN, - EVENT_COUNTDOWN, // Helix' Crew - EVENT_TALK_READY, + EVENT_THROW_BOMB, + EVENT_TALK_READY }; enum Actions { + // Lumbering Oaf ACTION_OAF_SMASH = 1, ACTION_OAF_DEAD, + + // Helix' Crw ACTION_TALK_CREW, + + // Sticky Bomb + ACTION_BOMB_DETONATED, }; enum Points @@ -126,10 +137,12 @@ enum Phases PHASE_2 = 2 }; -Position const ChargePreparationPos = { -289.8343f, -526.2162f, 49.83808f }; -Position const ChargePos = { -289.5868f, -489.5746f, 49.91263f }; +Position const LumberingOafSummonPosition = { -302.3611f, -516.3455f, 52.03153f, 0.1745329f }; +Position const OafSmashStartigPosition = { -289.8343f, -526.2162f, 49.83808f }; +Position const ChargePos = { -289.5868f, -489.5746f, 49.91263f }; -Position const HelixCrewPositions[] = +static constexpr uint8 const HelixCrewPositionCount = 4; +Position const HelixFirstCrewPositions[HelixCrewPositionCount] = { { -283.8438f, -503.3698f, 60.512f, 1.902409f }, { -285.8681f, -503.8264f, 60.55348f, 5.009095f }, @@ -137,576 +150,459 @@ Position const HelixCrewPositions[] = { -289.8316f, -503.4063f, 60.36356f, 1.815142f } }; -class boss_helix_gearbreaker : public CreatureScript +struct boss_helix_gearbreaker : public BossAI { - public: - boss_helix_gearbreaker() : CreatureScript("boss_helix_gearbreaker") { } + boss_helix_gearbreaker(Creature* creature) : BossAI(creature, DATA_HELIX_GEARBREAKER) + { + me->SetReactState(REACT_PASSIVE); + } - struct boss_helix_gearbreakerAI : public BossAI + void JustEngagedWith(Unit* /*who*/) override + { + _JustEngagedWith(); + Talk(SAY_AGGRO); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 2); + + events.SetPhase(PHASE_1); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SUMMON_HELIX_CREW, 5s, 0, PHASE_1); + + events.ScheduleEvent(EVENT_STICKY_BOMB, 6s, 0, PHASE_1); + events.ScheduleEvent(EVENT_OAF_SMASH, 17s, 0, PHASE_1); + + /* + events.ScheduleEvent(EVENT_THROW_HELIX, Seconds(34), 0, PHASE_1); + */ + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + summons.DespawnAll(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + } + + void JustAppeared() override + { + DoCastSelf(SPELL_OAFGUARD); + DoSummon(NPC_LUMBERING_OAF, LumberingOafSummonPosition, 2 * IN_MILLISECONDS, TEMPSUMMON_CORPSE_TIMED_DESPAWN); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + if (Creature* lumberingOaf = instance->GetCreature(DATA_LUMBERING_OAF)) + if (lumberingOaf->IsAlive()) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, lumberingOaf); + + summons.DespawnAll(); + _DespawnAtEvade(); + } + + void DoAction(int32 action) override + { + switch (action) { - boss_helix_gearbreakerAI(Creature* creature) : BossAI(creature, DATA_HELIX_GEARBREAKER) + case ACTION_OAF_DEAD: + Talk(SAY_OAF_DEAD); + DoCastSelf(SPELL_EMOTE_TALK); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveAurasDueToSpell(SPELL_OAFGUARD); + events.SetPhase(PHASE_2); + if (!me->GetVehicleBase()) + events.ScheduleEvent(EVENT_RIDE_FACE, Seconds(2) + Milliseconds(500), 0, PHASE_2); + break; + default: + break; + } + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + // Helix cannot die while he is protected by his Lumbering Oaf + if (damage >= me->GetHealth() && me->HasAura(SPELL_OAFGUARD)) + damage = me->GetHealth() - 1; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - Initialize(); - } - void Initialize() - { - _crewSummoned = false; - } - - void Reset() override - { - _Reset(); - Initialize(); - } - - void JustEngagedWith(Unit* /*who*/) override - { - _JustEngagedWith(); - Talk(SAY_AGGRO); - me->AttackStop(); - me->SetReactState(REACT_PASSIVE); - - if (Creature* lumberingOaf = instance->GetCreature(DATA_LUMBERING_OAF)) - instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, lumberingOaf); - - events.SetPhase(PHASE_1); - events.ScheduleEvent(EVENT_STICKY_BOMB, Seconds(5), 0, PHASE_1); - events.ScheduleEvent(EVENT_OAF_SMASH, Seconds(16), 0, PHASE_1); - events.ScheduleEvent(EVENT_THROW_HELIX, Seconds(34), 0, PHASE_1); - } - - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - Talk(SAY_DEATH); - summons.DespawnAll(); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - } - - void KilledUnit(Unit* who) override - { - if (who->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - - void EnterEvadeMode(EvadeReason /*why*/) override - { - _EnterEvadeMode(); - summons.DespawnAll(); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - if (Creature* lumberingOaf = instance->GetCreature(DATA_LUMBERING_OAF)) - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, lumberingOaf); - lumberingOaf->DespawnOrUnsummon(0, Seconds(30)); - } - me->DespawnOrUnsummon(); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - } - - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_OAF_DEAD: - Talk(SAY_OAF_DEAD); - DoCastSelf(SPELL_EMOTE_TALK); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveAurasDueToSpell(SPELL_OAFGUARD); - events.SetPhase(PHASE_2); - if (!me->GetVehicleBase()) - events.ScheduleEvent(EVENT_RIDE_FACE, Seconds(2) + Milliseconds(500), 0, PHASE_2); - break; - default: - break; - } - } - - void DamageTaken(Unit* /*attacker*/, uint32& damage) override - { - if (damage >= me->GetHealth() && me->HasAura(SPELL_OAFGUARD)) - damage = me->GetHealth() - 1; - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + case EVENT_SUMMON_HELIX_CREW: + for (uint8 i = 0; i < HelixCrewPositionCount; i++) { - case EVENT_STICKY_BOMB: - if (!_crewSummoned && IsHeroic()) - { - for (uint8 i = 0; i < 4; i++) - { - if (Creature* crew = DoSummon(NPC_HELIX_CREW, HelixCrewPositions[i], 0, TEMPSUMMON_MANUAL_DESPAWN)) - if (i == 1) - crew->AI()->DoAction(ACTION_TALK_CREW); - } - _crewSummoned = true; - } - - DoCastAOE(SPELL_THROW_BOMB_TARGETING, true); - events.Repeat(Seconds(3) + Milliseconds(500)); - break; - case EVENT_OAF_SMASH: - if (Creature* lumberingOaf = me->GetVehicleCreatureBase()) - { - lumberingOaf->AI()->DoAction(ACTION_OAF_SMASH); - events.RescheduleEvent(EVENT_STICKY_BOMB, Seconds(10), 0, PHASE_1); - events.Repeat(Seconds(52)); - } - break; - case EVENT_THROW_HELIX: - Talk(SAY_THROW_HELIX); - events.ScheduleEvent(EVENT_RIDE_FACE, Seconds(2)); - events.Repeat(Seconds(52)); - break; - case EVENT_RIDE_FACE: - DoCastAOE(SPELL_RIDE_FACE_TARGETING, true); - events.RescheduleEvent(EVENT_STICKY_BOMB, Seconds(20), 0, PHASE_1); - break; - default: - break; + if (Creature* crew = DoSummon(NPC_HELIX_CREW, HelixFirstCrewPositions[i], 0, TEMPSUMMON_MANUAL_DESPAWN)) + if (!i && crew->IsAIEnabled) + crew->AI()->DoAction(ACTION_TALK_CREW); } - } + break; + case EVENT_STICKY_BOMB: + DoCastAOE(SPELL_THROW_BOMB_TARGETING); + events.Repeat(3s + 500ms); + break; + case EVENT_OAF_SMASH: + if (Creature* oaf = instance->GetCreature(DATA_LUMBERING_OAF)) + if (oaf->IsAIEnabled) + oaf->AI()->DoAction(ACTION_OAF_SMASH); - DoMeleeAttackIfReady(); + events.RescheduleEvent(EVENT_STICKY_BOMB, 11s, 0, PHASE_1); + events.Repeat(52s); + break; + + case EVENT_THROW_HELIX: + Talk(SAY_THROW_HELIX); + events.ScheduleEvent(EVENT_RIDE_FACE, Seconds(2)); + events.Repeat(Seconds(52)); + break; + case EVENT_RIDE_FACE: + DoCastAOE(SPELL_RIDE_FACE_TARGETING, true); + events.RescheduleEvent(EVENT_STICKY_BOMB, Seconds(20), 0, PHASE_1); + break; + default: + break; } - private: - bool _crewSummoned; - }; - - CreatureAI* GetAI(Creature *creature) const override - { - return GetDeadminesAI(creature); } + + DoMeleeAttackIfReady(); + } }; -class npc_helix_lumbering_oaf : public CreatureScript +struct npc_helix_lumbering_oaf : public ScriptedAI { - public: - npc_helix_lumbering_oaf() : CreatureScript("npc_helix_lumbering_oaf") { } + npc_helix_lumbering_oaf(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - struct npc_helix_lumbering_oafAI : public ScriptedAI + void JustEngagedWith(Unit* /*who*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + + if (Creature* helix = _instance->GetCreature(DATA_HELIX_GEARBREAKER)) + if (helix->IsAIEnabled) + helix->AI()->DoZoneInCombat(); + } + + void JustAppeared() override + { + if (Creature* helix = _instance->GetCreature(DATA_HELIX_GEARBREAKER)) + helix->EnterVehicle(me); + } + + void DoAction(int32 action) override + { + switch (action) { - npc_helix_lumbering_oafAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + case ACTION_OAF_SMASH: + DoCastAOE(SPELL_OAF_GRAB_TARGETING); + break; + default: + break; + } + } - void JustEngagedWith(Unit* who) override + void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override + { + if (!passenger) + return; + + if (apply && passenger->GetTypeId() == TYPEID_PLAYER) + { + Talk(SAY_OAF_SMASH_1); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + _events.ScheduleEvent(EVENT_PREPARE_OAF_SMASH, 1s); + } + + /* + if (!apply && passenger->GetEntry() == BOSS_HELIX_GEARBREAKER && me->IsInCombat()) + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, passenger); + else if (apply && passenger->GetEntry() == BOSS_HELIX_GEARBREAKER && me->IsInCombat()) + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, passenger); + */ + } + + void MovementInform(uint32 type, uint32 point) override + { + if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) + return; + + switch (point) + { + case POINT_CHARGE_PREP: + me->SetFacingTo(1.570796f); + _events.ScheduleEvent(EVENT_OAF_SMASH_CHARGE, 1s); + break; + default: + break; + } + } + + void JustDied(Unit* /*killer*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + if (Creature* helix = _instance->GetCreature(DATA_HELIX_GEARBREAKER)) + helix->AI()->DoAction(ACTION_OAF_DEAD); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - if (Creature* helix = _instance->GetCreature(DATA_HELIX_GEARBREAKER)) - if (!helix->IsInCombat()) - helix->AI()->AttackStart(who); + case EVENT_PREPARE_OAF_SMASH: + Talk(SAY_OAF_SMASH_2); + me->GetMotionMaster()->MovePoint(POINT_CHARGE_PREP, OafSmashStartigPosition, true); + break; + case EVENT_OAF_SMASH_CHARGE: + DoCastAOE(SPELL_CHARGE); + break; + default: + break; } + } + DoMeleeAttackIfReady(); + } +private: + EventMap _events; + InstanceScript* _instance; +}; - void DoAction(int32 action) override +struct npc_helix_sticky_bomb : public NullCreatureAI +{ + npc_helix_sticky_bomb(Creature* creature) : NullCreatureAI(creature), _countdown(0) { } + + void Reset() override + { + _events.ScheduleEvent(EVENT_ARM_BOMB, 2s); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_BOMB_DETONATED: + me->SetDisplayId(DISPLAY_ID_BOMB_INVISIBLE); + me->RemoveAllAuras(); + me->DespawnOrUnsummon(2s + 500ms); + _events.Reset(); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - switch (action) - { - case ACTION_OAF_SMASH: - Talk(SAY_OAF_SMASH_1); - DoCastAOE(SPELL_OAF_GRAB_TARGETING, true); - break; - default: - break; - } - } - - void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override - { - if (!passenger) - return; - - if (apply && passenger->GetTypeId() == TYPEID_PLAYER) - { - me->AttackStop(); - me->SetReactState(REACT_PASSIVE); - _events.ScheduleEvent(EVENT_MOVE_TO_PREPARE_POSITION, Milliseconds(500)); - } - - if (!apply && passenger->GetEntry() == BOSS_HELIX_GEARBREAKER && me->IsInCombat()) - _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, passenger); - else if (apply && passenger->GetEntry() == BOSS_HELIX_GEARBREAKER && me->IsInCombat()) - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, passenger); - } - - void MovementInform(uint32 type, uint32 point) override - { - if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) - return; - - switch (point) - { - case POINT_CHARGE_PREP: - me->SetFacingTo(1.570796f); - _events.ScheduleEvent(EVENT_CHARGE_DEST, Seconds(1)); - break; - default: - break; - } - } - - void JustDied(Unit* /*killer*/) override - { - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - if (Creature* helix = _instance->GetCreature(DATA_HELIX_GEARBREAKER)) - helix->AI()->DoAction(ACTION_OAF_DEAD); - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) + case EVENT_ARM_BOMB: + if (_countdown < 3) { - case EVENT_MOVE_TO_PREPARE_POSITION: - Talk(SAY_OAF_SMASH_2); - me->GetMotionMaster()->MovePoint(POINT_CHARGE_PREP, ChargePreparationPos, true); - break; - case EVENT_CHARGE_DEST: - DoCastAOE(SPELL_CHARGE); - break; - default: - break; + DoCastSelf(BombArmingVisualSpells[_countdown]); + _events.Repeat(1s); + _countdown++; } - } - DoMeleeAttackIfReady(); - } - private: - EventMap _events; - InstanceScript* _instance; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetDeadminesAI(creature); - } -}; - -class npc_helix_sticky_bomb : public CreatureScript -{ - public: - npc_helix_sticky_bomb() : CreatureScript("npc_helix_sticky_bomb") { } - - struct npc_helix_sticky_bombAI : public PassiveAI - { - npc_helix_sticky_bombAI(Creature* creature) : PassiveAI(creature) - { - Initialize(); - } - - void Initialize() - { - _countdown = 0; - } - - void IsSummonedBy(Unit* /*summoner*/) override - { - _events.ScheduleEvent(EVENT_ARMING_VISUAL_YELLOW, Seconds(2) + Milliseconds(500)); - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) + else { - case EVENT_ARMING_VISUAL_YELLOW: - DoCastSelf(SPELL_ARMING_VISUAL_YELLOW); - _events.ScheduleEvent(EVENT_ARMING_VISUAL_ORANGE, Seconds(1)); - break; - case EVENT_ARMING_VISUAL_ORANGE: - DoCastSelf(SPELL_ARMING_VISUAL_ORANGE); - _events.ScheduleEvent(EVENT_ARMING_VISUAL_RED, Seconds(2)); - break; - case EVENT_ARMING_VISUAL_RED: - DoCastSelf(SPELL_ARMING_VISUAL_RED); - _events.ScheduleEvent(EVENT_PREPARED_STATE, Seconds(1)); - break; - case EVENT_PREPARED_STATE: - DoCastSelf(SPELL_STICKY_BOMB_ARMED_STATE); - _events.ScheduleEvent(EVENT_PERIODIC_TRIGGER, Seconds(1)); - break; - case EVENT_PERIODIC_TRIGGER: - DoCastSelf(SPELL_STICKY_BOMB_PERIODIC_TRIGGER); - _events.ScheduleEvent(EVENT_EXPLOSION_COUNTDOWN, Seconds(15) + Milliseconds(500)); - break; - case EVENT_EXPLOSION_COUNTDOWN: - DoCastSelf(SPELL_ARMING_VISUAL_RED); - _events.ScheduleEvent(EVENT_COUNTDOWN, Seconds(1)); - break; - case EVENT_COUNTDOWN: - if (_countdown != 3) - { - DoCastSelf(SPELL_ARMING_VISUAL_RED); - _countdown++; - _events.Repeat(Seconds(1)); - } - else - { - me->RemoveAllAuras(); - DoCastSelf(SPELL_EXPLODE, true); - } - break; - default: - break; + DoCastSelf(SPELL_STICKY_BOMB_ARMED_STATE); + _events.ScheduleEvent(EVENT_PERIODIC_TRIGGER, 1s); } - } - } - private: - EventMap _events; - uint8 _countdown; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetDeadminesAI(creature); - } -}; - -class npc_helix_crew : public CreatureScript -{ - public: - npc_helix_crew() : CreatureScript("npc_helix_crew") { } - - struct npc_helix_crewAI : public PassiveAI - { - npc_helix_crewAI(Creature* creature) : PassiveAI(creature) { } - - void IsSummonedBy(Unit* /*summoner*/) override - { - _events.ScheduleEvent(EVENT_STICKY_BOMB, Seconds(1)); - } - - void DoAction(int32 action) override - { - switch (action) + break; + case EVENT_PERIODIC_TRIGGER: + DoCastSelf(SPELL_STICKY_BOMB_PERIODIC_TRIGGER); + _events.ScheduleEvent(EVENT_EXPLOSION_COUNTDOWN, 15s + 500ms); + break; + case EVENT_EXPLOSION_COUNTDOWN: + if (_countdown) { - case ACTION_TALK_CREW: - _events.ScheduleEvent(EVENT_TALK_READY, Seconds(1)); - break; - default: - break; + DoCastSelf(SPELL_ARMING_VISUAL_RED); + _events.Repeat(1s); + _countdown--; } - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) + else { - switch (eventId) - { - case EVENT_STICKY_BOMB: - DoCastAOE(SPELL_THROW_BOMB_TARGETING, true); - _events.Repeat(Seconds(5)); - break; - case EVENT_TALK_READY: - Talk(SAY_CREW_JOIN_FIGHT); - break; - default: - break; - } + DoCastSelf(SPELL_EXPLODE); + DoAction(ACTION_BOMB_DETONATED); } + break; + default: + break; } - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetDeadminesAI(creature); } + } +private: + EventMap _events; + uint8 _countdown; }; -class spell_helix_throw_bomb_targeting : public SpellScriptLoader +struct npc_helix_crew : public PassiveAI { - public: - spell_helix_throw_bomb_targeting() : SpellScriptLoader("spell_helix_throw_bomb_targeting") { } + npc_helix_crew(Creature* creature) : PassiveAI(creature) { } - class spell_helix_throw_bomb_targeting_SpellScript : public SpellScript + void IsSummonedBy(Unit* /*summoner*/) override + { + _events.ScheduleEvent(EVENT_THROW_BOMB, 1s); + } + + void DoAction(int32 action) override + { + switch (action) { - PrepareSpellScript(spell_helix_throw_bomb_targeting_SpellScript); - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; - - Trinity::Containers::RandomResize(targets, 1); - } - - void HandleHit(SpellEffIndex effIndex) - { - GetCaster()->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_helix_throw_bomb_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_helix_throw_bomb_targeting_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_helix_throw_bomb_targeting_SpellScript(); + case ACTION_TALK_CREW: + _events.ScheduleEvent(EVENT_TALK_READY, 1s); + break; + default: + break; } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_THROW_BOMB: + DoCastAOE(SPELL_THROW_BOMB_TARGETING); + _events.Repeat(5s); + break; + case EVENT_TALK_READY: + Talk(SAY_CREW_JOIN_FIGHT); + break; + default: + break; + } + } + } +private: + EventMap _events; }; -class spell_helix_sticky_bomb_periodic_trigger : public SpellScriptLoader +class spell_helix_throw_bomb_targeting : public SpellScript { - public: - spell_helix_sticky_bomb_periodic_trigger() : SpellScriptLoader("spell_helix_sticky_bomb_periodic_trigger") { } + PrepareSpellScript(spell_helix_throw_bomb_targeting); - class spell_helix_sticky_bomb_periodic_trigger_AuraScript : public AuraScript - { - PrepareAuraScript(spell_helix_sticky_bomb_periodic_trigger_AuraScript); + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; - void HandleTick(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - if (Unit* caster = GetCaster()) - if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell)) - if (Player* player = caster->SelectNearestPlayer(spell->Effects[EFFECT_0].CalcRadius())) - if (!player->GetVehicleBase()) - caster->CastSpell(GetCaster()->GetVictim(), GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true); - } + Trinity::Containers::RandomResize(targets, 1); + } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_helix_sticky_bomb_periodic_trigger_AuraScript::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); + } - AuraScript* GetAuraScript() const - { - return new spell_helix_sticky_bomb_periodic_trigger_AuraScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_helix_throw_bomb_targeting::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_helix_throw_bomb_targeting::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } }; -class spell_helix_explode : public SpellScriptLoader +class spell_helix_sticky_bomb_periodic_trigger : public AuraScript { - public: - spell_helix_explode() : SpellScriptLoader("spell_helix_explode") { } + PrepareAuraScript(spell_helix_sticky_bomb_periodic_trigger); - class spell_helix_explode_SpellScript : public SpellScript + void HandleTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + Creature* target = GetTarget()->ToCreature(); + if (!target || !target->IsAIEnabled) + return; + + SpellInfo const* spell = sSpellMgr->GetSpellInfo(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell); + if (!spell) + return; + + if (Player* player = target->SelectNearestPlayer(spell->Effects[EFFECT_0].CalcRadius())) { - PrepareSpellScript(spell_helix_explode_SpellScript); - - void HandleLaunch(SpellEffIndex /*effIndex*/) + if (!player->GetVehicleBase() && player->GetExactDist(target) <= 1.0f) { - if (Unit* caster = GetCaster()) - { - if (caster->GetTypeId() == TYPEID_UNIT) - { - caster->RemoveAllAuras(); - caster->SetDisplayId(DISPLAY_ID_BOMB_INVISIBLE); - caster->ToCreature()->DespawnOrUnsummon(Seconds(2) + Milliseconds(400)); - } - } + target->CastSpell(target, spell->Id, true); + target->AI()->DoAction(ACTION_BOMB_DETONATED); } - - void Register() override - { - OnEffectLaunch += SpellEffectFn(spell_helix_explode_SpellScript::HandleLaunch, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } - private: - uint8 _targetsCounter; - }; - - SpellScript* GetSpellScript() const override - { - return new spell_helix_explode_SpellScript(); } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_helix_sticky_bomb_periodic_trigger::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } }; -class spell_helix_oaf_grab_targeting : public SpellScriptLoader +class spell_helix_oaf_grab_targeting : public SpellScript { - public: - spell_helix_oaf_grab_targeting() : SpellScriptLoader("spell_helix_oaf_grab_targeting") { } + PrepareSpellScript(spell_helix_oaf_grab_targeting); - class spell_helix_oaf_grab_targeting_SpellScript : public SpellScript - { - PrepareSpellScript(spell_helix_oaf_grab_targeting_SpellScript); + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; + Trinity::Containers::RandomResize(targets, 1); + } - Trinity::Containers::RandomResize(targets, 1); - } + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); + } - void HandleHit(SpellEffIndex effIndex) - { - if (Unit* caster = GetCaster()) - caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_helix_oaf_grab_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_helix_oaf_grab_targeting_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_helix_oaf_grab_targeting_SpellScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_helix_oaf_grab_targeting::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_helix_oaf_grab_targeting::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } }; -class spell_helix_force_player_to_ride_oaf : public SpellScriptLoader +class spell_helix_force_player_to_ride_oaf : public SpellScript { - public: - spell_helix_force_player_to_ride_oaf() : SpellScriptLoader("spell_helix_force_player_to_ride_oaf") { } + PrepareSpellScript(spell_helix_force_player_to_ride_oaf); - class spell_helix_force_player_to_ride_oaf_SpellScript : public SpellScript - { - PrepareSpellScript(spell_helix_force_player_to_ride_oaf_SpellScript); + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + GetHitUnit()->CastSpell(caster, GetSpellInfo()->Effects[effIndex].BasePoints, false); + } - void HandleHit(SpellEffIndex effIndex) - { - if (Unit* caster = GetCaster()) - if (Unit* target = GetHitUnit()) - if (caster->GetVehicleKit()) - { - target->CastStop(); - target->CastSpell(caster, GetSpellInfo()->Effects[effIndex].BasePoints, false); - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_helix_force_player_to_ride_oaf_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_helix_force_player_to_ride_oaf_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_helix_force_player_to_ride_oaf::HandleHit, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; class spell_helix_oaf_smash : public SpellScriptLoader @@ -1009,15 +905,14 @@ class spell_helix_chest_bomb : public SpellScriptLoader void AddSC_boss_helix_gearbreaker() { - new boss_helix_gearbreaker(); - new npc_helix_lumbering_oaf(); - new npc_helix_sticky_bomb(); - new npc_helix_crew(); - new spell_helix_throw_bomb_targeting(); - new spell_helix_sticky_bomb_periodic_trigger(); - new spell_helix_explode(); - new spell_helix_oaf_grab_targeting(); - new spell_helix_force_player_to_ride_oaf(); + RegisterDeadminesCreatureAI(boss_helix_gearbreaker); + RegisterDeadminesCreatureAI(npc_helix_lumbering_oaf); + RegisterDeadminesCreatureAI(npc_helix_sticky_bomb); + RegisterDeadminesCreatureAI(npc_helix_crew); + RegisterSpellScript(spell_helix_throw_bomb_targeting); + RegisterAuraScript(spell_helix_sticky_bomb_periodic_trigger); + RegisterSpellScript(spell_helix_oaf_grab_targeting); + RegisterSpellScript(spell_helix_force_player_to_ride_oaf); new spell_helix_oaf_smash(); new spell_helix_ride_face_targeting(); new spell_helix_ride_vehicle(); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index 50f9e0f1a3..3fc38e060e 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -383,12 +383,10 @@ class npc_eye_of_acherus : public CreatureScript me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MovePoint(POINT_EYE_FALL, EyeOFAcherusFallPoint, false); - Movement::MoveSplineInit init(me); init.MoveTo(EyeOFAcherusFallPoint.GetPositionX(), EyeOFAcherusFallPoint.GetPositionY(), EyeOFAcherusFallPoint.GetPositionZ(), false); init.SetFall(); - init.Launch(); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), POINT_EYE_FALL, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); } void OnCharmed(bool /*apply*/) override { } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index b931df98af..bb2c193d05 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -472,12 +472,10 @@ public: if (!_owner->IsAlive()) return true; - _owner->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, *_owner, false); - Movement::MoveSplineInit init(_owner); init.DisableTransportPathTransformations(); init.MoveTo(_dest.GetPositionX(), _dest.GetPositionY(), _dest.GetPositionZ(), false); - init.Launch(); + _owner->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_CHARGE_PREPATH, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); return true; } @@ -568,12 +566,10 @@ struct gunship_npc_AI : public ScriptedAI me->GetTransport()->CalculatePassengerPosition(hx, hy, hz, &ho); me->SetHomePosition(hx, hy, hz, ho); - me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, Slot->TargetPosition, false); - Movement::MoveSplineInit init(me); init.DisableTransportPathTransformations(); init.MoveTo(x, y, z, false); - init.Launch(); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_CHARGE_PREPATH, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); } } @@ -942,16 +938,11 @@ class npc_high_overlord_saurfang_igb : public CreatureScript } else if (action == ACTION_EXIT_SHIP) { - Position pos; - pos.Relocate(SaurfangExitPath[SaurfangExitPathSize - 1].x, SaurfangExitPath[SaurfangExitPathSize - 1].y, SaurfangExitPath[SaurfangExitPathSize - 1].z); - me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, pos, false); - Movement::PointsArray path(SaurfangExitPath, SaurfangExitPath + SaurfangExitPathSize); - Movement::MoveSplineInit init(me); init.DisableTransportPathTransformations(); init.MovebyPath(path, 0); - init.Launch(); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); me->DespawnOrUnsummon(18000); } @@ -1211,16 +1202,11 @@ class npc_muradin_bronzebeard_igb : public CreatureScript } else if (action == ACTION_EXIT_SHIP) { - Position pos; - pos.Relocate(MuradinExitPath[MuradinExitPathSize - 1].x, MuradinExitPath[MuradinExitPathSize - 1].y, MuradinExitPath[MuradinExitPathSize - 1].z); - me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, pos, false); - Movement::PointsArray path(MuradinExitPath, MuradinExitPath + MuradinExitPathSize); - Movement::MoveSplineInit init(me); init.DisableTransportPathTransformations(); init.MovebyPath(path, 0); - init.Launch(); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); me->DespawnOrUnsummon(18000); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 0c61719efc..d6b17ae322 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -473,7 +473,7 @@ class npc_bone_spike : public CreatureScript Movement::MoveSplineInit init(passenger); init.DisableTransportPathTransformations(); init.MoveTo(-0.02206125f, -0.02132235f, 5.514783f, false); - init.Launch(); + passenger->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_SLOT_CONTROLLED); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index e9074eddb6..389741c2c5 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -351,12 +351,12 @@ class boss_algalon_the_observer : public CreatureScript me->SetDisableGravity(true); DoCast(me, SPELL_ARRIVAL, true); DoCast(me, SPELL_RIDE_THE_LIGHTNING, true); - me->GetMotionMaster()->MovePoint(POINT_ALGALON_LAND, AlgalonLandPos); me->SetHomePosition(AlgalonLandPos); Movement::MoveSplineInit init(me); init.MoveTo(AlgalonLandPos.GetPositionX(), AlgalonLandPos.GetPositionY(), AlgalonLandPos.GetPositionZ(), false); init.SetOrientationFixed(true); - init.Launch(); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), POINT_ALGALON_LAND, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + events.Reset(); events.SetPhase(PHASE_ROLE_PLAY); events.ScheduleEvent(EVENT_INTRO_1, 5000, 0, PHASE_ROLE_PLAY); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index 97601242e7..cd964c91f7 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -651,8 +651,6 @@ class boss_thorim : public CreatureScript summon->SetReactState(REACT_PASSIVE); summon->CastSpell(summon, SPELL_LIGHTNING_DESTRUCTION, true); - summon->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, LightningOrbPath[LightningOrbPathSize - 1], false); - Movement::PointsArray path; path.reserve(LightningOrbPathSize); std::transform(std::begin(LightningOrbPath), std::end(LightningOrbPath), std::back_inserter(path), [](Position const& pos) @@ -662,7 +660,7 @@ class boss_thorim : public CreatureScript Movement::MoveSplineInit init(summon); init.MovebyPath(path); - init.Launch(); + summon->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); break; } case NPC_DARK_RUNE_CHAMPION: diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index 50c33ba78b..fb53c131d1 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -361,7 +361,7 @@ public: Movement::MoveSplineInit init(who); init.DisableTransportPathTransformations(); init.MoveTo(0.3320355f, 0.05355075f, 5.196949f, false); - init.Launch(); + who->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_SLOT_CONTROLLED); me->setActive(true); me->SetFarVisible(true); diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 840ad6bcd9..34cc6b5a09 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -2943,7 +2943,7 @@ public: init.DisableTransportPathTransformations(); init.MoveTo(x, y, z, false); init.SetFacing(o); - init.Launch(); + who->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_SLOT_CONTROLLED); who->m_Events.AddEvent(new CastFoodSpell(who, _chairSpells.at(who->GetEntry())), who->m_Events.CalculateTime(1000)); if (who->GetTypeId() == TYPEID_UNIT) who->SetDisplayId(who->ToCreature()->GetCreatureTemplate()->Modelid1);