diff options
Diffstat (limited to 'src')
96 files changed, 2351 insertions, 1420 deletions
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 0686ad20c6e..1dd66d76996 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -157,9 +157,7 @@ void CreatureAI::TriggerAlert(Unit const* who) const me->SendAIReaction(AI_REACTION_ALERT); // Face the unit (stealthed player) and set distracted state for 5 seconds - me->GetMotionMaster()->MoveDistract(5 * IN_MILLISECONDS); - me->StopMoving(); - me->SetFacingTo(me->GetAbsoluteAngle(who)); + me->GetMotionMaster()->MoveDistract(5 * IN_MILLISECONDS, me->GetAbsoluteAngle(who)); } void CreatureAI::EnterEvadeMode(EvadeReason why) @@ -173,8 +171,8 @@ void CreatureAI::EnterEvadeMode(EvadeReason why) { if (Unit* owner = me->GetCharmerOrOwner()) { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); } else { diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index 1a61a9dc6a9..091d7a42e47 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -207,7 +207,7 @@ void EscortAI::UpdateAI(uint32 diff) else if (_resume) { _resume = false; - if (MovementGenerator* movementGenerator = me->GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE)) + if (MovementGenerator* movementGenerator = me->GetMotionMaster()->GetCurrentMovementGenerator(MOTION_SLOT_DEFAULT)) movementGenerator->Resume(0); } } @@ -331,7 +331,7 @@ void EscortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */, TC_LOG_DEBUG("scripts", "EscortAI::Start: (script: %s, creature entry: %u) is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.", me->GetScriptName().c_str(), me->GetEntry()); me->GetMotionMaster()->MoveIdle(); - me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE); + me->GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL); // disable npcflags me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); @@ -368,7 +368,7 @@ void EscortAI::SetEscortPaused(bool on) if (on) { AddEscortState(STATE_ESCORT_PAUSED); - if (MovementGenerator* movementGenerator = me->GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE)) + if (MovementGenerator* movementGenerator = me->GetMotionMaster()->GetCurrentMovementGenerator(MOTION_SLOT_DEFAULT)) movementGenerator->Pause(0); } else diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index ccbfdfd0ed6..0fb99e63d9c 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -112,7 +112,7 @@ void SmartAI::PausePath(uint32 delay, bool forced) { if (!HasEscortState(SMART_ESCORT_ESCORTING)) { - me->PauseMovement(delay, MOTION_SLOT_IDLE, forced); + me->PauseMovement(delay, MOTION_SLOT_DEFAULT, forced); if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) { std::pair<uint32, uint32> waypointInfo = me->GetCurrentWaypointInfo(); @@ -544,8 +544,11 @@ void SmartAI::JustReachedHome() CreatureGroup* formation = me->GetFormation(); if (!formation || formation->GetLeader() == me || !formation->IsFormed()) { - if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != WAYPOINT_MOTION_TYPE && me->GetWaypointPath()) - me->GetMotionMaster()->MovePath(me->GetWaypointPath(), true); + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType(MOTION_SLOT_DEFAULT) != WAYPOINT_MOTION_TYPE) + { + if (me->GetWaypointPath()) + me->GetMotionMaster()->MovePath(me->GetWaypointPath(), true); + } else me->ResumeMovement(); } @@ -591,7 +594,8 @@ void SmartAI::AttackStart(Unit* who) if (who && me->Attack(who, mCanAutoAttack)) { - me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE); + me->GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL); + me->PauseMovement(); if (mCanCombatMove) { @@ -770,13 +774,22 @@ void SmartAI::SetCombatMove(bool on) if (me->IsEngaged()) { - if (on && !me->HasReactState(REACT_PASSIVE) && me->GetVictim() && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == MAX_MOTION_TYPE) + if (on) { - SetRun(mRun); - me->GetMotionMaster()->MoveChase(me->GetVictim()); + if (!me->HasReactState(REACT_PASSIVE) && me->GetVictim() && !me->GetMotionMaster()->HasMovementGenerator([](MovementGenerator const* movement) -> bool + { + return movement->Mode == MOTION_MODE_DEFAULT && movement->Priority == MOTION_PRIORITY_NORMAL; + })) + { + SetRun(mRun); + me->GetMotionMaster()->MoveChase(me->GetVictim()); + } } - else if (!on && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == CHASE_MOTION_TYPE) - me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE); + else if (MovementGenerator* movement = me->GetMotionMaster()->GetMovementGenerator([](MovementGenerator const* a) -> bool + { + return a->GetMovementGeneratorType() == CHASE_MOTION_TYPE && a->Mode == MOTION_MODE_DEFAULT && a->Priority == MOTION_PRIORITY_NORMAL; + })) + me->GetMotionMaster()->Remove(movement); } } diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 2a524ae8c5e..2e8d2f72563 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -1594,10 +1594,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u float attackAngle = float(e.action.setRangedMovement.angle) / 180.0f * float(M_PI); for (WorldObject* target : targets) + { if (Creature* creature = target->ToCreature()) if (IsSmart(creature) && creature->GetVictim()) if (ENSURE_AI(SmartAI, creature->AI())->CanCombatMove()) creature->GetMotionMaster()->MoveChase(creature->GetVictim(), attackDistance, attackAngle); + } break; } @@ -2230,16 +2232,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u target->ToUnit()->RemoveAllGameObjects(); break; } - case SMART_ACTION_STOP_MOTION: + case SMART_ACTION_REMOVE_MOVEMENT: { for (WorldObject* const target : targets) { if (IsUnit(target)) { - if (e.action.stopMotion.stopMovement) + if (e.action.removeMovement.movementType && e.action.removeMovement.movementType < MAX_MOTION_TYPE) + target->ToUnit()->GetMotionMaster()->Remove(MovementGeneratorType(e.action.removeMovement.movementType)); + if (e.action.removeMovement.forced) target->ToUnit()->StopMoving(); - if (e.action.stopMotion.movementExpired) - target->ToUnit()->GetMotionMaster()->MovementExpired(); } } break; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 538df1630ed..8baeca1857b 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -22,7 +22,7 @@ #include "GameEventMgr.h" #include "InstanceScript.h" #include "Log.h" -#include "MotionMaster.h" +#include "MovementDefines.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "SpellInfo.h" @@ -1570,7 +1570,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_REMOVE_ALL_GAMEOBJECTS: case SMART_ACTION_SPAWN_SPAWNGROUP: case SMART_ACTION_DESPAWN_SPAWNGROUP: - case SMART_ACTION_STOP_MOTION: + case SMART_ACTION_REMOVE_MOVEMENT: break; default: TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 2159ed2a8ba..fa2e59f8941 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -574,7 +574,7 @@ enum SMART_ACTION SMART_ACTION_LOAD_EQUIPMENT = 124, // id SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT = 125, // id min range, id max range SMART_ACTION_REMOVE_ALL_GAMEOBJECTS = 126, - SMART_ACTION_STOP_MOTION = 127, // stopMoving, movementExpired + SMART_ACTION_REMOVE_MOVEMENT = 127, // movementType, forced SMART_ACTION_PLAY_ANIMKIT = 128, // don't use on 3.3.5a SMART_ACTION_SCENE_PLAY = 129, // don't use on 3.3.5a SMART_ACTION_SCENE_CANCEL = 130, // don't use on 3.3.5a @@ -1122,9 +1122,9 @@ struct SmartAction struct { - uint32 stopMovement; - uint32 movementExpired; - } stopMotion; + uint32 movementType; + uint32 forced; + } removeMovement; struct { diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 598bd8b320c..17aa90a1f46 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -31,7 +31,6 @@ #include "LFGQueue.h" #include "Log.h" #include "Map.h" -#include "MotionMaster.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" @@ -1340,11 +1339,7 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* if (!player->GetMap()->IsDungeon()) player->SetBattlegroundEntryPoint(); - if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } + player->FinishTaxiFlight(); if (!player->TeleportTo(mapid, x, y, z, orientation)) error = LFG_TELEPORTERROR_INVALID_LOCATION; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 2cb7fc998a0..85c72c17e9f 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -329,7 +329,7 @@ void Creature::DisappearAndDie() bool Creature::IsReturningHome() const { - if (GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == HOME_MOTION_TYPE) + if (GetMotionMaster()->GetCurrentMovementGeneratorType() == HOME_MOTION_TYPE) return true; return false; @@ -762,8 +762,7 @@ void Creature::Update(uint32 diff) IsAIEnabled = true; if (!IsInEvadeMode() && LastCharmerGUID) if (Unit* charmer = ObjectAccessor::GetUnit(*this, LastCharmerGUID)) - if (CanStartAttack(charmer, true)) - i_AI->AttackStart(charmer); + EngageWithTarget(charmer); LastCharmerGUID.Clear(); } @@ -973,7 +972,6 @@ void Creature::DoFleeToGetAssistance() UpdateSpeed(MOVE_RUN); if (!creature) - //SetFeared(true, EnsureVictim()->GetGUID(), 0, sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_FLEE_DELAY)); /// @todo use 31365 SetControlled(true, UNIT_STATE_FLEEING); else @@ -1042,7 +1040,7 @@ void Creature::Motion_Initialize() m_formation->FormationReset(false); else if (m_formation->IsFormed()) { - GetMotionMaster()->MoveIdle(); //wait the order of leader + GetMotionMaster()->MoveIdle(); // wait the order of leader return; } } @@ -2075,8 +2073,9 @@ void Creature::Respawn(bool force) SetNativeDisplayId(displayID); } - GetMotionMaster()->InitDefault(); - //Re-initialize reactstate that could be altered by movementgenerators + GetMotionMaster()->InitializeDefault(); + + // Re-initialize reactstate that could be altered by movementgenerators InitializeReactState(); if (IsAIEnabled) // reset the AI to be sure no dirty or uninitialized values will be used till next tick diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 768db3fde03..cebf1d37ecb 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -269,7 +269,7 @@ void CreatureGroup::FormationReset(bool dismiss) pair.first->GetMotionMaster()->Initialize(); else pair.first->GetMotionMaster()->MoveIdle(); - TC_LOG_DEBUG("entities.unit", "Set %s movement for member GUID: %u", dismiss ? "default" : "idle", pair.first->GetGUID().GetCounter()); + TC_LOG_DEBUG("entities.unit", "CreatureGroup::FormationReset: Set %s movement for member GUID: %u", dismiss ? "default" : "idle", pair.first->GetGUID().GetCounter()); } } @@ -317,16 +317,16 @@ void CreatureGroup::LeaderMoveTo(Position const& destination, uint32 id /*= 0*/, if (!member->IsFlying()) member->UpdateGroundPositionZ(dx, dy, dz); - Position point(dx, dy, dz, destination.GetOrientation()); + member->SetHomePosition(dx, dy, dz, pathangle); + Position point(dx, dy, dz, destination.GetOrientation()); member->GetMotionMaster()->MoveFormation(id, point, moveType, !member->IsWithinDist(_leader, dist + MAX_DESYNC), orientation); - member->SetHomePosition(dx, dy, dz, pathangle); } } bool CreatureGroup::CanLeaderStartMoving() const { - for (auto const& pair : _members) + for (std::unordered_map<Creature*, FormationInfo*>::value_type const& pair : _members) { if (pair.first != _leader && pair.first->IsAlive()) { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c8702e15b85..7db69390677 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -21248,9 +21248,18 @@ bool Player::ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid /*= 0*/) return ActivateTaxiPathTo(nodes, nullptr, spellid); } +void Player::FinishTaxiFlight() +{ + if (!IsInFlight()) + return; + + GetMotionMaster()->Remove(FLIGHT_MOTION_TYPE); + m_taxi.ClearTaxiDestinations(); // not destinations, clear source node +} + void Player::CleanupAfterTaxiFlight() { - m_taxi.ClearTaxiDestinations(); // not destinations, clear source node + m_taxi.ClearTaxiDestinations(); // not destinations, clear source node Dismount(); RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT); } @@ -23325,11 +23334,7 @@ void Player::SummonIfPossible(bool agree) return; // stop taxi flight at summon - if (IsInFlight()) - { - GetMotionMaster()->MovementExpired(); - CleanupAfterTaxiFlight(); - } + FinishTaxiFlight(); // drop flag at summon // this code can be reached only when GM is summoning player who carries flag, because player should be immune to summoning spells when he carries flag @@ -23742,13 +23747,9 @@ void Player::SetClientControl(Unit* target, bool allowMove) void Player::SetMovedUnit(Unit* target) { m_unitMovedByMe->m_playerMovingMe = nullptr; - if (m_unitMovedByMe->GetTypeId() == TYPEID_UNIT) - m_unitMovedByMe->GetMotionMaster()->Initialize(); m_unitMovedByMe = target; m_unitMovedByMe->m_playerMovingMe = this; - if (m_unitMovedByMe->GetTypeId() == TYPEID_UNIT) - m_unitMovedByMe->GetMotionMaster()->Initialize(); } void Player::UpdateZoneDependentAuras(uint32 newZone) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index bb5573af0f8..64756dfb287 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -945,10 +945,11 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); } bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc = nullptr, uint32 spellid = 0); bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0); + void FinishTaxiFlight(); void CleanupAfterTaxiFlight(); void ContinueTaxiFlight() const; void SendTaxiNodeStatusMultiple(); - // mount_id can be used in scripting calls + bool isAcceptWhispers() const { return (m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS) != 0; } void SetAcceptWhispers(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; } bool IsGameMaster() const { return (m_ExtraFlags & PLAYER_EXTRA_GM_ON) != 0; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 7c78ca3f649..4817ef51515 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -452,7 +452,7 @@ void Unit::Update(uint32 p_time) } UpdateSplineMovement(p_time); - i_motionMaster->UpdateMotion(p_time); + i_motionMaster->Update(p_time); } bool Unit::haveOffhandWeapon() const @@ -468,7 +468,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); - GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE); } void Unit::UpdateSplineMovement(uint32 t_diff) @@ -8543,7 +8543,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype) { if (GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE) { - Unit* followed = ASSERT_NOTNULL(dynamic_cast<AbstractFollower*>(GetMotionMaster()->top()))->GetTarget(); + Unit* followed = ASSERT_NOTNULL(dynamic_cast<AbstractFollower*>(GetMotionMaster()->GetCurrentMovementGenerator()))->GetTarget(); if (followed && followed->GetGUID() == GetOwnerGUID() && !followed->IsInCombat()) { float ownerSpeed = followed->GetSpeedRate(mtype); @@ -8698,7 +8698,7 @@ void Unit::setDeathState(DeathState s) // * Using 'call pet' on dead pets // * Using 'call stabled pet' // * Logging in with dead pets - GetMotionMaster()->Clear(false); + GetMotionMaster()->Clear(); GetMotionMaster()->MoveIdle(); } StopMoving(); @@ -10186,10 +10186,10 @@ void Unit::PauseMovement(uint32 timer/* = 0*/, uint8 slot/* = 0*/, bool forced/* if (IsInvalidMovementSlot(slot)) return; - if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MovementSlot(slot))) + if (MovementGenerator* movementGenerator = GetMotionMaster()->GetCurrentMovementGenerator(MovementSlot(slot))) movementGenerator->Pause(timer); - if (forced) + if (forced && GetMotionMaster()->GetCurrentSlot() == MovementSlot(slot)) StopMoving(); } @@ -10198,7 +10198,7 @@ void Unit::ResumeMovement(uint32 timer/* = 0*/, uint8 slot/* = 0*/) if (IsInvalidMovementSlot(slot)) return; - if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MovementSlot(slot))) + if (MovementGenerator* movementGenerator = GetMotionMaster()->GetCurrentMovementGenerator(MovementSlot(slot))) movementGenerator->Resume(timer); } @@ -11274,8 +11274,7 @@ void Unit::SetFeared(bool apply) { if (IsAlive()) { - if (GetMotionMaster()->GetCurrentMovementGeneratorType() == FLEEING_MOTION_TYPE) - GetMotionMaster()->MovementExpired(); + GetMotionMaster()->Remove(FLEEING_MOTION_TYPE); if (GetVictim()) SetTarget(EnsureVictim()->GetGUID()); } @@ -11300,8 +11299,7 @@ void Unit::SetConfused(bool apply) { if (IsAlive()) { - if (GetMotionMaster()->GetCurrentMovementGeneratorType() == CONFUSED_MOTION_TYPE) - GetMotionMaster()->MovementExpired(); + GetMotionMaster()->Remove(CONFUSED_MOTION_TYPE); if (GetVictim()) SetTarget(EnsureVictim()->GetGUID()); } @@ -11393,10 +11391,8 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au if (GetTypeId() == TYPEID_UNIT) { - if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE)) - movementGenerator->Pause(0); - - GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE); + PauseMovement(0, 0, false); + GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL); StopMoving(); @@ -11515,7 +11511,7 @@ void Unit::RemoveCharmedBy(Unit* charmer) RestoreFaction(); ///@todo Handle SLOT_IDLE motion resume - GetMotionMaster()->InitDefault(); + GetMotionMaster()->InitializeDefault(); if (Creature* creature = ToCreature()) { @@ -11584,8 +11580,6 @@ void Unit::RemoveCharmedBy(Unit* charmer) player->SetClientControl(this, true); } - EngageWithTarget(charmer); - // a guardian should always have charminfo if (playerCharmer && this != charmer->GetFirstControlled()) playerCharmer->SendRemoveControlBar(); @@ -12619,7 +12613,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false); init.SetFacing(GetOrientation()); init.SetTransportExit(); - GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_EXIT, MOTION_SLOT_CONTROLLED); + GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_EXIT, MOTION_PRIORITY_HIGHEST); if (player) player->ResummonPetTemporaryUnSummonedIfAny(); @@ -13041,7 +13035,7 @@ void Unit::SetFacingTo(float ori, bool force) init.DisableTransportPathTransformations(); // It makes no sense to target global orientation init.SetFacing(ori); - //GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_FACE, MOTION_SLOT_CONTROLLED); + //GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_FACE, MOTION_PRIORITY_HIGHEST); init.Launch(); } @@ -13056,7 +13050,7 @@ void Unit::SetFacingToObject(WorldObject const* object, bool force) init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false); init.SetFacing(GetAbsoluteAngle(object)); // when on transport, GetAbsoluteAngle will still return global coordinates (and angle) that needs transforming - //GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_FACE, MOTION_SLOT_CONTROLLED); + //GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_FACE, MOTION_PRIORITY_HIGHEST); init.Launch(); } diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index f317f98e450..528b521f59d 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -850,7 +850,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32) init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ, false, true); init.SetFacing(0.0f); init.SetTransportEnter(); - Passenger->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_SLOT_CONTROLLED); + Passenger->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_PRIORITY_HIGHEST); if (Creature* creature = Target->GetBase()->ToCreature()) { diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index 6707931b603..145c3062e0f 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -31,7 +31,6 @@ #include "Group.h" #include "Language.h" #include "Log.h" -#include "MotionMaster.h" #include "Object.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" @@ -458,11 +457,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) _player->SpawnCorpseBones(); } // stop taxi flight at port - if (_player->IsInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } + _player->FinishTaxiFlight(); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), ginfo.Team); _player->SendDirectMessage(&data); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 720733249e3..dd8f9bd94c7 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -127,29 +127,29 @@ void WorldSession::HandleMoveWorldportAck() GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case - if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) + if (GetPlayer()->IsInFlight()) { if (!_player->InBattleground()) { // short preparations to continue flight - MovementGenerator* movementGenerator = GetPlayer()->GetMotionMaster()->top(); + MovementGenerator* movementGenerator = GetPlayer()->GetMotionMaster()->GetCurrentMovementGenerator(); movementGenerator->Initialize(GetPlayer()); return; } // battleground state prepare, stop flight - GetPlayer()->GetMotionMaster()->MovementExpired(); - GetPlayer()->CleanupAfterTaxiFlight(); + GetPlayer()->FinishTaxiFlight(); } // resurrect character at enter into instance where his corpse exist after add to map - if (mEntry->IsDungeon() && !GetPlayer()->IsAlive()) + { if (GetPlayer()->GetCorpseLocation().GetMapId() == mEntry->MapID) { GetPlayer()->ResurrectPlayer(0.5f, false); GetPlayer()->SpawnCorpseBones(); } + } bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena(); if (mInstance) diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 4ed71333ccf..d266fef5a42 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -160,7 +160,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe { case COMMAND_STAY: //flat=1792 //STAY pet->StopMoving(); - pet->GetMotionMaster()->Clear(false); + pet->GetMotionMaster()->Clear(); pet->GetMotionMaster()->MoveIdle(); charmInfo->SetCommandState(COMMAND_STAY); diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp index 3b0c2a1785f..2845e723724 100644 --- a/src/server/game/Handlers/TaxiHandler.cpp +++ b/src/server/game/Handlers/TaxiHandler.cpp @@ -119,7 +119,7 @@ void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathN if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - GetPlayer()->GetMotionMaster()->Clear(MOTION_SLOT_CONTROLLED); + GetPlayer()->GetMotionMaster()->Remove(FLIGHT_MOTION_TYPE); if (mountDisplayId) GetPlayer()->Mount(mountDisplayId); @@ -224,13 +224,11 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData) TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case - if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId()) + if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId() && GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { - if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) + if (FlightPathMovementGenerator* flight = dynamic_cast<FlightPathMovementGenerator*>(GetPlayer()->GetMotionMaster()->GetCurrentMovementGenerator())) { // short preparations to continue flight - FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); - flight->SetCurrentNodeAfterTeleport(); TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 6233a2bf7f4..3aec174c854 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -1554,7 +1554,7 @@ bool Map::CreatureRespawnRelocation(Creature* c, bool diffGridOnly) if (CreatureCellRelocation(c, resp_cell)) { c->Relocate(resp_x, resp_y, resp_z, resp_o); - c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators + c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators //CreatureRelocationNotify(c, resp_cell, resp_cell.GetCellCoord()); c->UpdatePositionData(); c->UpdateObjectVisibility(false); diff --git a/src/server/game/Maps/MapScripts.cpp b/src/server/game/Maps/MapScripts.cpp index a949d0a099a..dda0263fe4f 100644 --- a/src/server/game/Maps/MapScripts.cpp +++ b/src/server/game/Maps/MapScripts.cpp @@ -880,7 +880,6 @@ void Map::ScriptsProcess() if (!cSource->IsAlive()) return; - cSource->GetMotionMaster()->MovementExpired(); cSource->GetMotionMaster()->MoveIdle(); switch (step.script->Movement.MovementType) diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 7a1e629fc36..24afda84de6 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3239,7 +3239,8 @@ enum EventId EVENT_FACE = 1006, EVENT_VEHICLE_BOARD = 1007, - EVENT_VEHICLE_EXIT = 1008 + EVENT_VEHICLE_EXIT = 1008, + EVENT_ASSIST_MOVE = 1009, }; enum ResponseCodes diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 37969f51483..ebccc6fa481 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -17,13 +17,15 @@ */ #include "MotionMaster.h" +#include "AbstractFollower.h" #include "Creature.h" #include "CreatureAISelector.h" +#include "Containers.h" #include "DBCStores.h" +#include "Errors.h" #include "G3DPosition.hpp" #include "Log.h" #include "Map.h" -#include "MovementGenerator.h" #include "MoveSpline.h" #include "MoveSplineInit.h" #include "PathGenerator.h" @@ -31,6 +33,8 @@ #include "ScriptSystem.h" #include "Unit.h" #include "WaypointDefines.h" +#include <algorithm> +#include <iterator> #include "ChaseMovementGenerator.h" #include "ConfusedMovementGenerator.h" @@ -56,144 +60,465 @@ inline bool IsStatic(MovementGenerator* movement) return (movement == GetIdleMovementGenerator()); } +inline void MovementGeneratorPointerDeleter(MovementGenerator* a) +{ + if (a != nullptr && !IsStatic(a)) + delete a; +} + +void MovementGeneratorDeleter::operator()(MovementGenerator * a) +{ + MovementGeneratorPointerDeleter(a); +} + +bool MovementGeneratorComparator::operator()(MovementGenerator const* a, MovementGenerator const* b) const +{ + if (a->Mode > b->Mode) + return true; + else if (a->Mode == b->Mode) + return a->Priority > b->Priority; + + return false; +} + +MovementGeneratorInformation::MovementGeneratorInformation(MovementGeneratorType type, ObjectGuid targetGUID, std::string const& targetName) : Type(type), TargetGUID(targetGUID), TargetName(targetName) { } + +MotionMaster::MotionMaster(Unit* unit) : _owner(unit), _defaultGenerator(nullptr), _flags(MOTIONMASTER_FLAG_NONE) { } + MotionMaster::~MotionMaster() { - // clear ALL movement generators (including default) - while (!empty()) + _delayedActions.clear(); + + for (auto itr = _generators.begin(); itr != _generators.end(); itr = _generators.erase(itr)) + MovementGeneratorPointerDeleter(*itr); +} + +void MotionMaster::Initialize() +{ + if (HasFlag(MOTIONMASTER_FLAG_UPDATE)) { - MovementGenerator* movement = top(); - pop(); - if (movement && !IsStatic(movement)) - delete movement; + std::function<void()> action = [this]() + { + Initialize(); + }; + _delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_INITIALIZE); + return; } - while (!_expireList.empty()) + DirectInitialize(); +} + +void MotionMaster::InitializeDefault() +{ + Add(FactorySelector::SelectMovementGenerator(_owner), MOTION_SLOT_DEFAULT); +} + +bool MotionMaster::Empty() const +{ + return !_defaultGenerator && _generators.empty(); +} + +uint32 MotionMaster::Size() const +{ + return _defaultGenerator ? 1 : 0 + uint32(_generators.size()); +} + +std::vector<MovementGeneratorInformation> MotionMaster::GetMovementGeneratorsInformation() const +{ + std::vector<MovementGeneratorInformation> list; + + if (_defaultGenerator) + list.emplace_back(_defaultGenerator->GetMovementGeneratorType(), ObjectGuid::Empty, std::string()); + + for (auto itr = _generators.begin(); itr != _generators.end(); ++itr) { - delete _expireList.back(); - _expireList.pop_back(); + MovementGenerator* movement = *itr; + MovementGeneratorType const type = movement->GetMovementGeneratorType(); + switch (type) + { + case CHASE_MOTION_TYPE: + case FOLLOW_MOTION_TYPE: + if (AbstractFollower* followInformation = dynamic_cast<AbstractFollower*>(movement)) + { + if (Unit* target = followInformation->GetTarget()) + list.emplace_back(type, target->GetGUID(), target->GetName()); + else + list.emplace_back(type, ObjectGuid::Empty, std::string()); + } + else + list.emplace_back(type, ObjectGuid::Empty, std::string()); + break; + default: + list.emplace_back(type, ObjectGuid::Empty, std::string()); + break; + } } + + return list; } -MovementGenerator* MotionMaster::top() const +MovementSlot MotionMaster::GetCurrentSlot() const { - ASSERT(!empty()); + if (!_generators.empty()) + return MOTION_SLOT_ACTIVE; - return _slot[_top]; + if (_defaultGenerator) + return MOTION_SLOT_DEFAULT; + + return MAX_MOTION_SLOT; } -void MotionMaster::Initialize() +MovementGenerator* MotionMaster::GetCurrentMovementGenerator() const +{ + if (!_generators.empty()) + return *_generators.begin(); + + if (_defaultGenerator) + return _defaultGenerator.get(); + + return nullptr; +} + +MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const +{ + if (Empty()) + return MAX_MOTION_TYPE; + + MovementGenerator const* movement = GetCurrentMovementGenerator(); + if (!movement) + return MAX_MOTION_TYPE; + + return movement->GetMovementGeneratorType(); +} + +MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType(MovementSlot slot) const +{ + if (Empty() || IsInvalidMovementSlot(slot)) + return MAX_MOTION_TYPE; + + if (slot == MOTION_SLOT_ACTIVE && !_generators.empty()) + return (*_generators.begin())->GetMovementGeneratorType(); + + if (slot == MOTION_SLOT_DEFAULT && _defaultGenerator) + return _defaultGenerator->GetMovementGeneratorType(); + + return MAX_MOTION_TYPE; +} + +MovementGenerator* MotionMaster::GetCurrentMovementGenerator(MovementSlot slot) const +{ + if (Empty() || IsInvalidMovementSlot(slot)) + return nullptr; + + if (slot == MOTION_SLOT_ACTIVE && !_generators.empty()) + return *_generators.begin(); + + if (slot == MOTION_SLOT_DEFAULT && _defaultGenerator) + return _defaultGenerator.get(); + + return nullptr; +} + +MovementGenerator* MotionMaster::GetMovementGenerator(std::function<bool(MovementGenerator const*)> const& filter, MovementSlot slot) const { - // clear ALL movement generators (including default) - while (!empty()) + if (Empty() || IsInvalidMovementSlot(slot)) + return nullptr; + + MovementGenerator* movement = nullptr; + switch (slot) { - MovementGenerator* curr = top(); - pop(); - if (curr) - DirectDelete(curr); + case MOTION_SLOT_DEFAULT: + if (_defaultGenerator && filter(_defaultGenerator.get())) + movement = _defaultGenerator.get(); + break; + case MOTION_SLOT_ACTIVE: + if (!_generators.empty()) + { + auto itr = std::find_if(_generators.begin(), _generators.end(), std::ref(filter)); + if (itr != _generators.end()) + movement = *itr; + } + break; + default: + break; } - InitDefault(); + return movement; } -// set new default movement generator -void MotionMaster::InitDefault() +bool MotionMaster::HasMovementGenerator(std::function<bool(MovementGenerator const*)> const& filter, MovementSlot slot) const { - Mutate(FactorySelector::SelectMovementGenerator(_owner), MOTION_SLOT_IDLE); + if (Empty() || IsInvalidMovementSlot(slot)) + return false; + + bool value = false; + switch (slot) + { + case MOTION_SLOT_DEFAULT: + if (_defaultGenerator && filter(_defaultGenerator.get())) + value = true; + break; + case MOTION_SLOT_ACTIVE: + if (!_generators.empty()) + { + auto itr = std::find_if(_generators.begin(), _generators.end(), std::ref(filter)); + value = itr != _generators.end(); + } + break; + default: + break; + } + + return value; } -void MotionMaster::UpdateMotion(uint32 diff) +void MotionMaster::Update(uint32 diff) { if (!_owner) return; - ASSERT(!empty()); + ASSERT(!Empty(), "MotionMaster:Update: update called without Initializing! (%s)", _owner->GetGUID().ToString().c_str()); - _cleanFlag |= MOTIONMMASTER_CLEANFLAG_UPDATE; - if (!top()->Update(_owner, diff)) + AddFlag(MOTIONMASTER_FLAG_UPDATE); + + MovementGenerator* top = GetCurrentMovementGenerator(); + if (HasFlag(MOTIONMASTER_FLAG_STATIC_INITIALIZATION_PENDING) && IsStatic(top)) { - _cleanFlag &= ~MOTIONMMASTER_CLEANFLAG_UPDATE; - MovementExpired(); + RemoveFlag(MOTIONMASTER_FLAG_STATIC_INITIALIZATION_PENDING); + top->Initialize(_owner); } - else - _cleanFlag &= ~MOTIONMMASTER_CLEANFLAG_UPDATE; + if (top->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING)) + top->Initialize(_owner); + if (top->HasFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED)) + top->Reset(_owner); + + ASSERT(!top->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING | MOVEMENTGENERATOR_FLAG_DEACTIVATED), "MotionMaster:Update: update called on an uninitialized top! (%s) (type: %u, flags: %u)", _owner->GetGUID().ToString().c_str(), top->GetMovementGeneratorType(), top->Flags); + + if (!top->Update(_owner, diff)) + { + ASSERT(top == GetCurrentMovementGenerator(), "MotionMaster::Update: top was modified while updating! (%s)", _owner->GetGUID().ToString().c_str()); + + // Since all the actions that modify any slot are delayed, this movement is guaranteed to be top + Pop(true, true); // Natural, and only, call to MovementInform + } + + RemoveFlag(MOTIONMASTER_FLAG_UPDATE); - if (!_expireList.empty()) - ClearExpireList(); + while (!_delayedActions.empty()) + { + _delayedActions.front().Resolve(); + _delayedActions.pop_front(); + } } -void MotionMaster::Clear(bool reset /*= true*/) +void MotionMaster::Add(MovementGenerator* movement, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/) { - if (_cleanFlag & MOTIONMMASTER_CLEANFLAG_UPDATE) + if (!movement) + return; + + if (IsInvalidMovementSlot(slot)) { - if (reset) - _cleanFlag |= MOTIONMMASTER_CLEANFLAG_RESET; - else - _cleanFlag &= ~MOTIONMMASTER_CLEANFLAG_RESET; - DelayedClean(); + delete movement; + return; + } + + if (HasFlag(MOTIONMASTER_FLAG_UPDATE)) + { + std::function<void()> action = [this, movement, slot]() + { + Add(movement, slot); + }; + _delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_ADD); } else - DirectClean(reset); + DirectAdd(movement, slot); } -void MotionMaster::Clear(MovementSlot slot) +void MotionMaster::Remove(MovementGenerator* movement, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/) { - if (empty() || IsInvalidMovementSlot(slot)) + if (!movement || IsInvalidMovementSlot(slot)) return; - if (_cleanFlag & MOTIONMMASTER_CLEANFLAG_UPDATE) - DelayedClean(slot); - else - DirectClean(slot); + if (HasFlag(MOTIONMASTER_FLAG_UPDATE)) + { + std::function<void()> action = [this, movement, slot]() + { + Remove(movement, slot); + }; + _delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_REMOVE); + return; + } + + if (Empty()) + return; + + switch (slot) + { + case MOTION_SLOT_DEFAULT: + if (_defaultGenerator && _defaultGenerator.get() == movement) + DirectClearDefault(); + break; + case MOTION_SLOT_ACTIVE: + if (!_generators.empty()) + { + auto itr = _generators.find(movement); + if (itr != _generators.end()) + { + MovementGenerator* pointer = *itr; + bool const top = GetCurrentMovementGenerator() == pointer; + _generators.erase(pointer); + Delete(pointer, top, false); + } + } + break; + default: + break; + } } -void MotionMaster::MovementExpired(bool reset /*= true*/) +void MotionMaster::Remove(MovementGeneratorType type, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/) { - if (_cleanFlag & MOTIONMMASTER_CLEANFLAG_UPDATE) + if (IsInvalidMovementGeneratorType(type) || IsInvalidMovementSlot(slot)) + return; + + if (HasFlag(MOTIONMASTER_FLAG_UPDATE)) { - if (reset) - _cleanFlag |= MOTIONMMASTER_CLEANFLAG_RESET; - else - _cleanFlag &= ~MOTIONMMASTER_CLEANFLAG_RESET; - DelayedExpire(); + std::function<void()> action = [this, type, slot]() + { + Remove(type, slot); + }; + _delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_REMOVE_TYPE); + return; + } + + if (Empty()) + return; + + switch (slot) + { + case MOTION_SLOT_DEFAULT: + if (_defaultGenerator && _defaultGenerator->GetMovementGeneratorType() == type) + DirectClearDefault(); + break; + case MOTION_SLOT_ACTIVE: + if (!_generators.empty()) + { + auto itr = std::find_if(_generators.begin(), _generators.end(), [type](MovementGenerator const* a) -> bool + { + return a->GetMovementGeneratorType() == type; + }); + + if (itr != _generators.end()) + { + MovementGenerator* pointer = *itr; + bool const top = GetCurrentMovementGenerator() == pointer; + _generators.erase(pointer); + Delete(pointer, top, false); + } + } + break; + default: + break; } - else - DirectExpire(reset); } -MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const +void MotionMaster::Clear() { - if (empty()) - return MAX_MOTION_TYPE; + if (HasFlag(MOTIONMASTER_FLAG_UPDATE)) + { + std::function<void()> action = [this]() + { + Clear(); + }; + _delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_CLEAR); + return; + } - MovementGenerator* movement = top(); - if (!movement) - return MAX_MOTION_TYPE; + if (!Empty()) + DirectClear(); +} - return movement->GetMovementGeneratorType(); +void MotionMaster::Clear(MovementSlot slot) +{ + if (IsInvalidMovementSlot(slot)) + return; + + if (HasFlag(MOTIONMASTER_FLAG_UPDATE)) + { + std::function<void()> action = [this, slot]() + { + Clear(slot); + }; + _delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_CLEAR_SLOT); + return; + } + + if (Empty()) + return; + + switch (slot) + { + case MOTION_SLOT_DEFAULT: + DirectClearDefault(); + break; + case MOTION_SLOT_ACTIVE: + DirectClear(); + break; + default: + break; + } } -MovementGeneratorType MotionMaster::GetMotionSlotType(MovementSlot slot) const +void MotionMaster::Clear(MovementGeneratorMode mode) { - if (empty() || IsInvalidMovementSlot(slot) || !_slot[slot]) - return MAX_MOTION_TYPE; + if (HasFlag(MOTIONMASTER_FLAG_UPDATE)) + { + std::function<void()> action = [this, mode]() + { + Clear(mode); + }; + _delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_CLEAR_MODE); + return; + } + + if (Empty()) + return; - return _slot[slot]->GetMovementGeneratorType(); + std::function<bool(MovementGenerator*)> criteria = [mode](MovementGenerator* a) -> bool + { + return a->Mode == mode; + }; + DirectClear(criteria); } -MovementGenerator* MotionMaster::GetMotionSlot(MovementSlot slot) const +void MotionMaster::Clear(MovementGeneratorPriority priority) { - if (empty() || IsInvalidMovementSlot(slot) || !_slot[slot]) - return nullptr; + if (HasFlag(MOTIONMASTER_FLAG_UPDATE)) + { + std::function<void()> action = [this, priority]() + { + Clear(priority); + }; + _delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_CLEAR_PRIORITY); + return; + } - return _slot[slot]; + if (Empty()) + return; + + std::function<bool(MovementGenerator*)> criteria = [priority](MovementGenerator* a) -> bool + { + return a->Priority == priority; + }; + DirectClear(criteria); } void MotionMaster::PropagateSpeedChange() { - if (empty()) + if (Empty()) return; - MovementGenerator* movement = top(); + MovementGenerator* movement = GetCurrentMovementGenerator(); if (!movement) return; @@ -214,9 +539,7 @@ bool MotionMaster::GetDestination(float &x, float &y, float &z) void MotionMaster::MoveIdle() { - //! Should be preceded by MovementExpired or Clear if there's an overlying movementgenerator active - if (empty() || !IsStatic(top())) - Mutate(GetIdleMovementGenerator(), MOTION_SLOT_IDLE); + Add(GetIdleMovementGenerator(), MOTION_SLOT_DEFAULT); } void MotionMaster::MoveTargetedHome() @@ -228,18 +551,18 @@ void MotionMaster::MoveTargetedHome() return; } - Clear(false); + Clear(); Unit* target = owner->GetCharmerOrOwner(); if (!target) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveTargetedHome: '%s', targeted home.", _owner->GetGUID().ToString().c_str()); - Mutate(new HomeMovementGenerator<Creature>(), MOTION_SLOT_ACTIVE); + Add(new HomeMovementGenerator<Creature>()); } else { 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); + Add(new FollowMovementGenerator(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE)); } } @@ -248,28 +571,28 @@ void MotionMaster::MoveRandom(float spawndist) if (_owner->GetTypeId() == TYPEID_UNIT) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRandom: '%s', started random movement (spawnDist: %f)", _owner->GetGUID().ToString().c_str(), spawndist); - Mutate(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_IDLE); + Add(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_DEFAULT); } } -void MotionMaster::MoveFollow(Unit* target, float dist, ChaseAngle angle, MovementSlot slot) +void MotionMaster::MoveFollow(Unit* target, float dist, ChaseAngle angle, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/) { - // ignore movement request if target not exist + // Ignore movement request if target not exist if (!target || target == _owner) return; 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); + Add(new FollowMovementGenerator(target, dist, angle), slot); } void MotionMaster::MoveChase(Unit* target, Optional<ChaseRange> dist, Optional<ChaseAngle> angle) { - // ignore movement request if target not exist + // Ignore movement request if target not exist if (!target || target == _owner) return; 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); + Add(new ChaseMovementGenerator(target, dist, angle)); } void MotionMaster::MoveConfused() @@ -277,12 +600,12 @@ void MotionMaster::MoveConfused() if (_owner->GetTypeId() == TYPEID_PLAYER) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveConfused: '%s', started confused movement.", _owner->GetGUID().ToString().c_str()); - Mutate(new ConfusedMovementGenerator<Player>(), MOTION_SLOT_CONTROLLED); + Add(new ConfusedMovementGenerator<Player>()); } else { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveConfused: '%s', started confused movement.", _owner->GetGUID().ToString().c_str()); - Mutate(new ConfusedMovementGenerator<Creature>(), MOTION_SLOT_CONTROLLED); + Add(new ConfusedMovementGenerator<Creature>()); } } @@ -295,12 +618,12 @@ void MotionMaster::MoveFleeing(Unit* enemy, uint32 time) if (_owner->GetTypeId() == TYPEID_UNIT) { if (time) - Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time), MOTION_SLOT_CONTROLLED); + Add(new TimedFleeingMovementGenerator(enemy->GetGUID(), time)); else - Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); + Add(new FleeingMovementGenerator<Creature>(enemy->GetGUID())); } else - Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); + Add(new FleeingMovementGenerator<Player>(enemy->GetGUID())); } void MotionMaster::MovePoint(uint32 id, Position const& pos, bool generatePath/* = true*/, Optional<float> finalOrient/* = {}*/) @@ -313,12 +636,12 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generate if (_owner->GetTypeId() == TYPEID_PLAYER) { 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<Player>(id, x, y, z, generatePath, 0.0f, finalOrient), MOTION_SLOT_ACTIVE); + Add(new PointMovementGenerator<Player>(id, x, y, z, generatePath, 0.0f, finalOrient)); } else { 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<Creature>(id, x, y, z, generatePath, 0.0f, finalOrient), MOTION_SLOT_ACTIVE); + Add(new PointMovementGenerator<Creature>(id, x, y, z, generatePath, 0.0f, finalOrient)); } } @@ -334,11 +657,11 @@ void MotionMaster::MoveCloserAndStop(uint32 id, Unit* target, float distance) } else { - // we are already close enough. We just need to turn toward the target without changing position. + // We are already close enough. We just need to turn toward the target without changing position. Movement::MoveSplineInit init(_owner); init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); init.SetFacing(target); - Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_ACTIVE); + Add(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id)); } } @@ -349,7 +672,7 @@ void MotionMaster::MoveLand(uint32 id, Position const& pos) Movement::MoveSplineInit init(_owner); init.MoveTo(PositionToVector3(pos)); init.SetAnimation(Movement::ToGround); - Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_ACTIVE); + Add(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id)); } void MotionMaster::MoveTakeoff(uint32 id, Position const& pos) @@ -359,23 +682,30 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos) Movement::MoveSplineInit init(_owner); init.MoveTo(PositionToVector3(pos)); init.SetAnimation(Movement::ToFly); - Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_ACTIVE); + Add(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id)); } void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_CHARGE*/, uint32 id /*= EVENT_CHARGE*/, bool generatePath /*= false*/) { +/* if (_slot[MOTION_SLOT_CONTROLLED] && _slot[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE) return; - +*/ if (_owner->GetTypeId() == TYPEID_PLAYER) { 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<Player>(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); + PointMovementGenerator<Player>* movement = new PointMovementGenerator<Player>(id, x, y, z, generatePath, speed); + movement->Priority = MOTION_PRIORITY_HIGHEST; + movement->BaseUnitState = UNIT_STATE_CHARGING; + Add(movement); } else { 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<Creature>(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); + PointMovementGenerator<Creature>* movement = new PointMovementGenerator<Creature>(id, x, y, z, generatePath, speed); + movement->Priority = MOTION_PRIORITY_HIGHEST; + movement->BaseUnitState = UNIT_STATE_CHARGING; + Add(movement); } } @@ -394,7 +724,7 @@ void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_C void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ) { - // this function may make players fall below map + // This function may make players fall below map if (_owner->GetTypeId() == TYPEID_PLAYER) return; @@ -414,12 +744,14 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa init.SetOrientationFixed(true); init.SetVelocity(speedXY); - Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, 0), MOTION_SLOT_CONTROLLED); + GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, 0); + movement->Priority = MOTION_PRIORITY_HIGHEST; + Add(movement); } void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) { - // this function may make players fall below map + // This function may make players fall below map if (_owner->GetTypeId() == TYPEID_PLAYER) return; @@ -455,7 +787,10 @@ void MotionMaster::MoveJump(float x, float y, float z, float o, float speedXY, f if (hasOrientation) init.SetFacing(o); - Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_CONTROLLED); + GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id); + movement->Priority = MOTION_PRIORITY_HIGHEST; + movement->BaseUnitState = UNIT_STATE_JUMPING; + Add(movement); } void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount) @@ -492,7 +827,7 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool init.SetCyclic(); } - Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, 0), MOTION_SLOT_ACTIVE); + Add(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, 0)); } void MotionMaster::MoveSmoothPath(uint32 pointId, Position const* pathPoints, size_t pathSize, bool walk) @@ -510,9 +845,9 @@ void MotionMaster::MoveSmoothPath(uint32 pointId, Position const* pathPoints, si init.SetWalk(walk); // This code is not correct - // GenericMovementGenerator does not affect UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE + // GenericMovementGenerator does not affect UNIT_STATE_ROAMING_MOVE // need to call PointMovementGenerator with various pointIds - Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, pointId), MOTION_SLOT_ACTIVE); + Add(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, pointId)); } void MotionMaster::MoveAlongSplineChain(uint32 pointId, uint16 dbChainId, bool walk) @@ -534,7 +869,7 @@ void MotionMaster::MoveAlongSplineChain(uint32 pointId, uint16 dbChainId, bool w void MotionMaster::MoveAlongSplineChain(uint32 pointId, std::vector<SplineChainLink> const& chain, bool walk) { - Mutate(new SplineChainMovementGenerator(pointId, chain, walk), MOTION_SLOT_ACTIVE); + Add(new SplineChainMovementGenerator(pointId, chain, walk)); } void MotionMaster::ResumeSplineChain(SplineChainResumeInfo const& info) @@ -544,12 +879,12 @@ void MotionMaster::ResumeSplineChain(SplineChainResumeInfo const& info) 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); + Add(new SplineChainMovementGenerator(info)); } void MotionMaster::MoveFall(uint32 id/* = 0*/) { - // use larger distance for vmap height search than in most other cases + // 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) { @@ -565,7 +900,7 @@ void MotionMaster::MoveFall(uint32 id/* = 0*/) _owner->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); _owner->m_movementInfo.SetFallTime(0); - // don't run spline movement for players + // Don't run spline movement for players if (_owner->GetTypeId() == TYPEID_PLAYER) { _owner->ToPlayer()->SetFallInformation(0, _owner->GetPositionZ()); @@ -575,7 +910,10 @@ void MotionMaster::MoveFall(uint32 id/* = 0*/) Movement::MoveSplineInit init(_owner); init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz + _owner->GetHoverOffset(), false); init.SetFall(); - Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id), MOTION_SLOT_CONTROLLED); + + GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id); + movement->Priority = MOTION_PRIORITY_HIGHEST; + Add(movement); } void MotionMaster::MoveSeekAssistance(float x, float y, float z) @@ -586,7 +924,7 @@ void MotionMaster::MoveSeekAssistance(float x, float y, float z) _owner->AttackStop(); _owner->CastStop(); _owner->ToCreature()->SetReactState(REACT_PASSIVE); - Mutate(new AssistanceMovementGenerator(x, y, z), MOTION_SLOT_ACTIVE); + Add(new AssistanceMovementGenerator(EVENT_ASSIST_MOVE, x, y, z)); } else TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveSeekAssistance: '%s', attempted to seek assistance.", _owner->GetGUID().ToString().c_str()); @@ -597,7 +935,7 @@ void MotionMaster::MoveSeekAssistanceDistract(uint32 time) if (_owner->GetTypeId() == TYPEID_UNIT) { 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); + Add(new AssistanceDistractMovementGenerator(time, _owner->GetOrientation())); } else TC_LOG_ERROR("movement.motionmaster", "MotionMaster::MoveSeekAssistanceDistract: '%s', attempted to call distract assistance.", _owner->GetGUID().ToString().c_str()); @@ -610,9 +948,13 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) if (path < sTaxiPathNodesByPath.size()) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveTaxiFlight: '%s', taxi to path Id: %u (node %u)", _owner->GetGUID().ToString().c_str(), path, pathnode); + + // Only one FLIGHT_MOTION_TYPE is allowed + Remove(FLIGHT_MOTION_TYPE); + FlightPathMovementGenerator* movement = new FlightPathMovementGenerator(pathnode); movement->LoadPath(_owner->ToPlayer()); - Mutate(movement, MOTION_SLOT_CONTROLLED); + Add(movement); } else 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); @@ -621,17 +963,14 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 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) +void MotionMaster::MoveDistract(uint32 timer, float orientation) { +/* if (_slot[MOTION_SLOT_CONTROLLED]) return; - - if (_owner->GetTypeId() == TYPEID_PLAYER) - TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveDistract: '%s', distracted (timer: %u)", _owner->GetGUID().ToString().c_str(), timer); - else - TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveDistract: '%s', distracted (timer: %u)", _owner->GetGUID().ToString().c_str(), timer); - - Mutate(new DistractMovementGenerator(timer), MOTION_SLOT_CONTROLLED); +*/ + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveDistract: '%s', distracted (timer: %u, orientation: %f)", _owner->GetGUID().ToString().c_str(), timer, orientation); + Add(new DistractMovementGenerator(timer, orientation)); } void MotionMaster::MovePath(uint32 pathId, bool repeatable) @@ -640,22 +979,22 @@ void MotionMaster::MovePath(uint32 pathId, bool repeatable) 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<Creature>(pathId, repeatable), MOTION_SLOT_IDLE); + Add(new WaypointMovementGenerator<Creature>(pathId, repeatable), MOTION_SLOT_DEFAULT); } 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<Creature>(path, repeatable), MOTION_SLOT_IDLE); + Add(new WaypointMovementGenerator<Creature>(path, repeatable), MOTION_SLOT_DEFAULT); } -void MotionMaster::MoveRotate(uint32 time, RotateDirection direction) +void MotionMaster::MoveRotate(uint32 id, 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); + Add(new RotateMovementGenerator(id, time, direction)); } void MotionMaster::MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun /*= false*/, bool forceOrientation /*= false*/) @@ -663,49 +1002,85 @@ void MotionMaster::MoveFormation(uint32 id, Position destination, uint32 moveTyp if (_owner->GetTypeId() == TYPEID_UNIT) { 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); + Add(new FormationMovementGenerator(id, destination, moveType, forceRun, forceOrientation)); } } -void MotionMaster::LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id/*= 0*/, MovementSlot slot/*= MOTION_SLOT_ACTIVE*/, MovementGeneratorType type/*= EFFECT_MOTION_TYPE*/) +void MotionMaster::LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id/*= 0*/, MovementGeneratorPriority priority/* = MOTION_PRIORITY_NORMAL*/, 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); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::LaunchMoveSpline: '%s', tried to launch a spline with an invalid MovementGeneratorType: %u (Id: %u, Priority: %u)", _owner->GetGUID().ToString().c_str(), type, id, priority); 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); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::LaunchMoveSpline: '%s', initiates spline Id: %u (Type: %u, Priority: %u)", _owner->GetGUID().ToString().c_str(), id, type, priority); + + GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(init), type, id); + movement->Priority = priority; + Add(movement); } /******************** Private methods ********************/ -void MotionMaster::pop() +void MotionMaster::Pop(bool active, bool movementInform) { - if (empty()) - return; + MovementGenerator* pointer = *_generators.begin(); + _generators.erase(pointer); + Delete(pointer, active, movementInform); +} + +void MotionMaster::DirectInitialize() +{ + // Clear ALL movement generators (including default) + DirectClearDefault(); + DirectClear(); - _slot[_top] = nullptr; - while (!empty() && !top()) - --_top; + InitializeDefault(); } -bool MotionMaster::NeedInitTop() const +void MotionMaster::DirectClear() { - if (empty()) - return false; - return _initialize[_top]; + // First delete Top + if (!_generators.empty()) + Pop(true, false); + + // Then the rest + while (!_generators.empty()) + Pop(false, false); + + // Make sure the storage is empty + ClearBaseUnitStates(); } -void MotionMaster::InitTop() +void MotionMaster::DirectClearDefault() { - top()->Initialize(_owner); - _initialize[_top] = false; + if (_defaultGenerator) + DeleteDefault(_generators.empty(), false); } -void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) +void MotionMaster::DirectClear(std::function<bool(MovementGenerator*)> const& filter) { + if (_generators.empty()) + return; + + MovementGenerator const* top = GetCurrentMovementGenerator(); + for (auto itr = _generators.begin(); itr != _generators.end();) + { + if (filter(*itr)) + { + MovementGenerator* movement = *itr; + itr = _generators.erase(itr); + Delete(movement, movement == top, false); + } + else + ++itr; + } +} + +void MotionMaster::DirectAdd(MovementGenerator* movement, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/) +{ +/* if (MovementGenerator* curr = _slot[slot]) { _slot[slot] = nullptr; // in case a new one is generated in this slot during directdelete @@ -727,131 +1102,108 @@ void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) _initialize[slot] = false; m->Initialize(_owner); } -} +*/ -void MotionMaster::DirectClean(bool reset) -{ - while (size() > 1) - { - MovementGenerator* curr = top(); - pop(); - if (curr) - DirectDelete(curr); - } + /* + * NOTE: This mimics old behaviour: only one MOTION_SLOT_IDLE, MOTION_SLOT_ACTIVE, MOTION_SLOT_CONTROLLED + * On future changes support for multiple will be added + */ - if (empty()) - return; - - if (NeedInitTop()) - InitTop(); - else if (reset) - top()->Reset(_owner); -} - -void MotionMaster::DelayedClean() -{ - while (size() > 1) - { - MovementGenerator* curr = top(); - pop(); - if (curr) - DelayedDelete(curr); - } -} - -void MotionMaster::DirectClean(MovementSlot slot) -{ - if (MovementGenerator* motion = GetMotionSlot(slot)) - { - _slot[slot] = nullptr; - DirectDelete(motion); - } - - while (!empty() && !top()) - --_top; - - if (empty()) - Initialize(); - else if (NeedInitTop()) - InitTop(); -} - -void MotionMaster::DelayedClean(MovementSlot slot) -{ - if (MovementGenerator* motion = GetMotionSlot(slot)) + switch (slot) { - _slot[slot] = nullptr; - DelayedDelete(motion); + case MOTION_SLOT_DEFAULT: + if (_defaultGenerator) + _defaultGenerator->Finalize(_owner, _generators.empty(), false); + + _defaultGenerator = MovementGeneratorPointer(movement); + if (IsStatic(movement)) + AddFlag(MOTIONMASTER_FLAG_STATIC_INITIALIZATION_PENDING); + break; + case MOTION_SLOT_ACTIVE: + if (!_generators.empty()) + { + if (movement->Priority >= (*_generators.begin())->Priority) + { + MovementGenerator* pointer = *_generators.begin(); + if (movement->Priority == pointer->Priority) + { + _generators.erase(pointer); + Delete(pointer, true, false); + } + else + pointer->Deactivate(_owner); + } + else + { + auto itr = std::find_if(_generators.begin(), _generators.end(), [movement](MovementGenerator const* a) -> bool + { + return a->Priority == movement->Priority; + }); + + if (itr != _generators.end()) + { + MovementGenerator* pointer = *itr; + _generators.erase(pointer); + Delete(pointer, false, false); + } + } + } + else + _defaultGenerator->Deactivate(_owner); + + _generators.emplace(movement); + AddBaseUnitState(movement); + break; + default: + break; } - - while (!empty() && !top()) - --_top; } -void MotionMaster::DirectExpire(bool reset) +void MotionMaster::Delete(MovementGenerator* movement, bool active, bool movementInform) { - if (size() > 1) - { - MovementGenerator* curr = top(); - pop(); - DirectDelete(curr); - } - - while (!empty() && !top()) - --_top; + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::Delete: deleting generator (Priority: %u, Flags: %u, BaseUnitState: %u, Type: %u), owner: '%s'", + movement->Priority, movement->Flags, movement->BaseUnitState, movement->GetMovementGeneratorType(), _owner->GetGUID().ToString().c_str()); - if (empty()) - Initialize(); - else if (NeedInitTop()) - InitTop(); - else if (reset) - top()->Reset(_owner); + movement->Finalize(_owner, active, movementInform); + ClearBaseUnitState(movement); + MovementGeneratorPointerDeleter(movement); } -void MotionMaster::DelayedExpire() +void MotionMaster::DeleteDefault(bool active, bool movementInform) { - if (size() > 1) - { - MovementGenerator* curr = top(); - pop(); - DelayedDelete(curr); - } + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::DeleteDefault: deleting generator (Priority: %u, Flags: %u, BaseUnitState: %u, Type: %u), owner: '%s'", + _defaultGenerator->Priority, _defaultGenerator->Flags, _defaultGenerator->BaseUnitState, _defaultGenerator->GetMovementGeneratorType(), _owner->GetGUID().ToString().c_str()); - while (!empty() && !top()) - --_top; + _defaultGenerator->Finalize(_owner, active, movementInform); + _defaultGenerator = MovementGeneratorPointer(GetIdleMovementGenerator()); + AddFlag(MOTIONMASTER_FLAG_STATIC_INITIALIZATION_PENDING); } -void MotionMaster::DirectDelete(MovementGenerator* curr) +void MotionMaster::AddBaseUnitState(MovementGenerator const* movement) { - if (IsStatic(curr)) + if (!movement || !movement->BaseUnitState) return; - curr->Finalize(_owner); - delete curr; + _baseUnitStatesMap.emplace(movement->BaseUnitState, movement); + _owner->AddUnitState(movement->BaseUnitState); } -void MotionMaster::DelayedDelete(MovementGenerator* curr) +void MotionMaster::ClearBaseUnitState(MovementGenerator const* movement) { - TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::DelayedDelete: '%s', delayed deleting movement generator (type: %u)", _owner->GetGUID().ToString().c_str(), curr->GetMovementGeneratorType()); - if (IsStatic(curr)) + if (!movement || !movement->BaseUnitState) return; - _expireList.push_back(curr); + Trinity::Containers::MultimapErasePair(_baseUnitStatesMap, movement->BaseUnitState, movement); + if (_baseUnitStatesMap.count(movement->BaseUnitState) == 0) + _owner->ClearUnitState(movement->BaseUnitState); } -void MotionMaster::ClearExpireList() +void MotionMaster::ClearBaseUnitStates() { - for (auto itr : _expireList) - DirectDelete(itr); - - _expireList.clear(); - - if (empty()) - Initialize(); - else if (NeedInitTop()) - InitTop(); - else if (_cleanFlag & MOTIONMMASTER_CLEANFLAG_RESET) - top()->Reset(_owner); + uint32 unitState = 0; + for (auto itr = _baseUnitStatesMap.begin(); itr != _baseUnitStatesMap.end(); ++itr) + unitState |= itr->first; - _cleanFlag &= ~MOTIONMMASTER_CLEANFLAG_RESET; + _owner->ClearUnitState(unitState); + _baseUnitStatesMap.clear(); } diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index fbf49a4d8e8..3be8d735a20 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -20,14 +20,19 @@ #define MOTIONMASTER_H #include "Common.h" +#include "ObjectGuid.h" #include "Optional.h" #include "MovementDefines.h" +#include "MovementGenerator.h" #include "SharedDefines.h" +#include <deque> +#include <functional> +#include <set> +#include <unordered_map> #include <vector> -class MovementGenerator; -class Unit; class PathGenerator; +class Unit; struct Position; struct SplineChainLink; struct SplineChainResumeInfo; @@ -38,38 +43,97 @@ namespace Movement class MoveSplineInit; } -class TC_GAME_API MotionMaster +enum MotionMasterFlags : uint8 +{ + MOTIONMASTER_FLAG_NONE = 0x0, + MOTIONMASTER_FLAG_UPDATE = 0x1, // Update in progress + MOTIONMASTER_FLAG_STATIC_INITIALIZATION_PENDING = 0x2 +}; + +enum MotionMasterDelayedActionType : uint8 +{ + MOTIONMASTER_DELAYED_CLEAR = 0, + MOTIONMASTER_DELAYED_CLEAR_SLOT, + MOTIONMASTER_DELAYED_CLEAR_MODE, + MOTIONMASTER_DELAYED_CLEAR_PRIORITY, + MOTIONMASTER_DELAYED_ADD, + MOTIONMASTER_DELAYED_REMOVE, + MOTIONMASTER_DELAYED_REMOVE_TYPE, + MOTIONMASTER_DELAYED_INITIALIZE +}; + +struct MovementGeneratorDeleter +{ + void operator()(MovementGenerator* a); +}; + +struct MovementGeneratorComparator { public: - explicit MotionMaster(Unit* unit) : _owner(unit), _top(-1), _cleanFlag(MOTIONMMASTER_CLEANFLAG_NONE) - { - for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) - { - _slot[i] = nullptr; - _initialize[i] = true; - } - } - ~MotionMaster(); + bool operator()(MovementGenerator const* a, MovementGenerator const* b) const; +}; - bool empty() const { return (_top < 0); } - int size() const { return _top + 1; } - MovementGenerator* top() const; +struct MovementGeneratorInformation +{ + MovementGeneratorInformation(MovementGeneratorType type, ObjectGuid targetGUID, std::string const& targetName); - void Initialize(); - void InitDefault(); + MovementGeneratorType Type; + ObjectGuid TargetGUID; + std::string TargetName; +}; + +class MotionMasterDelayedAction +{ + public: + explicit MotionMasterDelayedAction(std::function<void()>&& action, MotionMasterDelayedActionType type) : Action(std::move(action)), Type(type) { } + ~MotionMasterDelayedAction() { } - void UpdateMotion(uint32 diff); + void Resolve() { Action(); } - void Clear(bool reset = true); - void Clear(MovementSlot slot); - void MovementExpired(bool reset = true); + std::function<void()> Action; + uint8 Type; +}; - MovementGeneratorType GetCurrentMovementGeneratorType() const; - MovementGeneratorType GetMotionSlotType(MovementSlot slot) const; - MovementGenerator* GetMotionSlot(MovementSlot slot) const; +class TC_GAME_API MotionMaster +{ + public: + explicit MotionMaster(Unit* unit); + ~MotionMaster(); - void PropagateSpeedChange(); + void Initialize(); + void InitializeDefault(); + bool Empty() const; + uint32 Size() const; + std::vector<MovementGeneratorInformation> GetMovementGeneratorsInformation() const; + MovementSlot GetCurrentSlot() const; + MovementGenerator* GetCurrentMovementGenerator() const; + MovementGeneratorType GetCurrentMovementGeneratorType() const; + MovementGeneratorType GetCurrentMovementGeneratorType(MovementSlot slot) const; + MovementGenerator* GetCurrentMovementGenerator(MovementSlot slot) const; + // Returns first found MovementGenerator that matches the given criteria + MovementGenerator* GetMovementGenerator(std::function<bool(MovementGenerator const*)> const& filter, MovementSlot slot = MOTION_SLOT_ACTIVE) const; + bool HasMovementGenerator(std::function<bool(MovementGenerator const*)> const& filter, MovementSlot slot = MOTION_SLOT_ACTIVE) const; + + void Update(uint32 diff); + void Add(MovementGenerator* movement, MovementSlot slot = MOTION_SLOT_ACTIVE); + // NOTE: MOTION_SLOT_DEFAULT will be autofilled with IDLE_MOTION_TYPE + void Remove(MovementGenerator* movement, MovementSlot slot = MOTION_SLOT_ACTIVE); + // Removes first found movement + // NOTE: MOTION_SLOT_DEFAULT will be autofilled with IDLE_MOTION_TYPE + void Remove(MovementGeneratorType type, MovementSlot slot = MOTION_SLOT_ACTIVE); + // NOTE: NOTE: MOTION_SLOT_DEFAULT wont be affected + void Clear(); + // Removes all movements for the given MovementSlot + // NOTE: MOTION_SLOT_DEFAULT will be autofilled with IDLE_MOTION_TYPE + void Clear(MovementSlot slot); + // Removes all movements with the given MovementGeneratorMode + // NOTE: MOTION_SLOT_DEFAULT wont be affected + void Clear(MovementGeneratorMode mode); + // Removes all movements with the given MovementGeneratorPriority + // NOTE: MOTION_SLOT_DEFAULT wont be affected + void Clear(MovementGeneratorPriority priority); + void PropagateSpeedChange(); bool GetDestination(float &x, float &y, float &z); void MoveIdle(); @@ -82,10 +146,11 @@ class TC_GAME_API MotionMaster void MoveFleeing(Unit* enemy, uint32 time = 0); void MovePoint(uint32 id, Position const& pos, bool generatePath = true, Optional<float> finalOrient = {}); void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true, Optional<float> finalOrient = {}); - /* Makes the unit move toward the target until it is at a certain distance from it. The unit then stops. - Only works in 2D. - This method doesn't account for any movement done by the target. in other words, it only works if the target is stationary. - */ + /* + * Makes the unit move toward the target until it is at a certain distance from it. The unit then stops. + * Only works in 2D. + * This method doesn't account for any movement done by the target. in other words, it only works if the target is stationary. + */ void MoveCloserAndStop(uint32 id, Unit* target, float distance); // These two movement types should only be used with creatures having landing/takeoff animations void MoveLand(uint32 id, Position const& pos); @@ -106,39 +171,41 @@ class TC_GAME_API MotionMaster void MoveSeekAssistance(float x, float y, float z); void MoveSeekAssistanceDistract(uint32 timer); void MoveTaxiFlight(uint32 path, uint32 pathnode); - void MoveDistract(uint32 time); + void MoveDistract(uint32 time, float orientation); void MovePath(uint32 pathId, bool repeatable); void MovePath(WaypointPath& path, bool repeatable); - void MoveRotate(uint32 time, RotateDirection direction); + void MoveRotate(uint32 id, uint32 time, RotateDirection direction); void MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun = false, bool forceOrientation = false); - void LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id = 0, MovementSlot slot = MOTION_SLOT_ACTIVE, MovementGeneratorType type = EFFECT_MOTION_TYPE); + void LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id = 0, MovementGeneratorPriority priority = MOTION_PRIORITY_NORMAL, MovementGeneratorType type = EFFECT_MOTION_TYPE); private: - typedef std::vector<MovementGenerator*> MovementList; - - void pop(); - - bool NeedInitTop() const; - void InitTop(); - - void Mutate(MovementGenerator* m, MovementSlot slot); - - void DirectClean(bool reset); - void DelayedClean(); - void DirectClean(MovementSlot slot); - void DelayedClean(MovementSlot slot); - void DirectExpire(bool reset); - void DelayedExpire(); - void DirectDelete(MovementGenerator* curr); - void DelayedDelete(MovementGenerator* curr); - void ClearExpireList(); + typedef std::unique_ptr<MovementGenerator, MovementGeneratorDeleter> MovementGeneratorPointer; + typedef std::multiset<MovementGenerator*, MovementGeneratorComparator> MotionMasterContainer; + typedef std::unordered_multimap<uint32, MovementGenerator const*> MotionMasterUnitStatesContainer; + + void AddFlag(uint8 const flag) { _flags |= flag; } + bool HasFlag(uint8 const flag) const { return (_flags & flag) != 0; } + void RemoveFlag(uint8 const flag) { _flags &= ~flag; } + + void Pop(bool active, bool movementInform); + void DirectInitialize(); + void DirectClear(); + void DirectClearDefault(); + void DirectClear(std::function<bool(MovementGenerator*)> const& filter); + void DirectAdd(MovementGenerator* movement, MovementSlot slot); + + void Delete(MovementGenerator* movement, bool active, bool movementInform); + void DeleteDefault(bool active, bool movementInform); + void AddBaseUnitState(MovementGenerator const* movement); + void ClearBaseUnitState(MovementGenerator const* movement); + void ClearBaseUnitStates(); - MovementGenerator* _slot[MAX_MOTION_SLOT]; - bool _initialize[MAX_MOTION_SLOT]; - MovementList _expireList; Unit* _owner; - int _top; - uint8 _cleanFlag; + MovementGeneratorPointer _defaultGenerator; + MotionMasterContainer _generators; + MotionMasterUnitStatesContainer _baseUnitStatesMap; + std::deque<MotionMasterDelayedAction> _delayedActions; + uint8 _flags; }; #endif // MOTIONMASTER_H diff --git a/src/server/game/Movement/MovementDefines.h b/src/server/game/Movement/MovementDefines.h index 041158a5016..b75835f8b44 100644 --- a/src/server/game/Movement/MovementDefines.h +++ b/src/server/game/Movement/MovementDefines.h @@ -29,36 +29,41 @@ enum MovementGeneratorType : uint8 WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h MAX_DB_MOTION_TYPE = 3, // Below motion types can't be set in DB. CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h - CHASE_MOTION_TYPE = 5, // TargetedMovementGenerator.h + CHASE_MOTION_TYPE = 5, // ChaseMovementGenerator.h HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h - FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h + FLIGHT_MOTION_TYPE = 7, // FlightPathMovementGenerator.h POINT_MOTION_TYPE = 8, // PointMovementGenerator.h FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h ASSISTANCE_MOTION_TYPE = 11, // PointMovementGenerator.h ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h - FOLLOW_MOTION_TYPE = 14, - ROTATE_MOTION_TYPE = 15, + FOLLOW_MOTION_TYPE = 14, // FollowMovementGenerator.h + ROTATE_MOTION_TYPE = 15, // IdleMovementGenerator.h EFFECT_MOTION_TYPE = 16, SPLINE_CHAIN_MOTION_TYPE = 17, // SplineChainMovementGenerator.h FORMATION_MOTION_TYPE = 18, // FormationMovementGenerator.h MAX_MOTION_TYPE // limit }; -enum MovementSlot : uint8 +enum MovementGeneratorMode : uint8 { - MOTION_SLOT_IDLE = 0, - MOTION_SLOT_ACTIVE, - MOTION_SLOT_CONTROLLED, - MAX_MOTION_SLOT + MOTION_MODE_DEFAULT = 0, + MOTION_MODE_OVERRIDE }; -enum MotionMasterCleanFlags +enum MovementGeneratorPriority : uint8 { - MOTIONMMASTER_CLEANFLAG_NONE = 0, - MOTIONMMASTER_CLEANFLAG_UPDATE = 1, // Clear or Expire called from update - MOTIONMMASTER_CLEANFLAG_RESET = 2 // Flag if need top()->Reset() + MOTION_PRIORITY_NONE = 0, + MOTION_PRIORITY_NORMAL, + MOTION_PRIORITY_HIGHEST +}; + +enum MovementSlot : uint8 +{ + MOTION_SLOT_DEFAULT = 0, + MOTION_SLOT_ACTIVE, + MAX_MOTION_SLOT }; enum RotateDirection : uint8 diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index befff195f38..c551d943f58 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -28,22 +28,56 @@ class Unit; enum MovementGeneratorType : uint8; +enum MovementGeneratorFlags : uint16 +{ + MOVEMENTGENERATOR_FLAG_NONE = 0x000, + MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING = 0x001, + MOVEMENTGENERATOR_FLAG_INITIALIZED = 0x002, + MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING = 0x004, + MOVEMENTGENERATOR_FLAG_INTERRUPTED = 0x008, + MOVEMENTGENERATOR_FLAG_PAUSED = 0x010, + MOVEMENTGENERATOR_FLAG_TIMED_PAUSED = 0x020, + MOVEMENTGENERATOR_FLAG_DEACTIVATED = 0x040, + MOVEMENTGENERATOR_FLAG_INFORM_ENABLED = 0x080, + MOVEMENTGENERATOR_FLAG_FINALIZED = 0x100, + + MOVEMENTGENERATOR_FLAG_TRANSITORY = MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING | MOVEMENTGENERATOR_FLAG_INTERRUPTED +}; + class TC_GAME_API MovementGenerator { public: + MovementGenerator() : Mode(0), Priority(0), Flags(MOVEMENTGENERATOR_FLAG_NONE), BaseUnitState(0) { } virtual ~MovementGenerator(); + // on top first update virtual void Initialize(Unit*) = 0; - virtual void Finalize(Unit*) = 0; + // on top reassign virtual void Reset(Unit*) = 0; + // on top on MotionMaster::Update virtual bool Update(Unit*, uint32 diff) = 0; + // on current top if another movement replaces + virtual void Deactivate(Unit*) = 0; + // on movement delete + virtual void Finalize(Unit*, bool, bool) = 0; virtual MovementGeneratorType GetMovementGeneratorType() const = 0; virtual void UnitSpeedChanged() { } - virtual void Pause(uint32/* timer = 0*/) { } // timer in ms - virtual void Resume(uint32/* overrideTimer = 0*/) { } // timer in ms - - virtual bool GetResetPosition(Unit*, float&/* x*/, float&/* y*/, float&/* z*/) { return false; } // used by Evade code for select point to evade with expected restart default movement + // timer in ms + virtual void Pause(uint32/* timer = 0*/) { } + // timer in ms + virtual void Resume(uint32/* overrideTimer = 0*/) { } + // used by Evade code for select point to evade with expected restart default movement + virtual bool GetResetPosition(Unit*, float&/* x*/, float&/* y*/, float&/* z*/) { return false; } + + void AddFlag(uint16 const flag) { Flags |= flag; } + bool HasFlag(uint16 const flag) const { return (Flags & flag) != 0; } + void RemoveFlag(uint16 const flag) { Flags &= ~flag; } + + uint8 Mode; + uint8 Priority; + uint16 Flags; + uint32 BaseUnitState; }; template<class T, class D> @@ -55,11 +89,6 @@ class MovementGeneratorMedium : public MovementGenerator (static_cast<D*>(this))->DoInitialize(static_cast<T*>(owner)); } - void Finalize(Unit* owner) override - { - (static_cast<D*>(this))->DoFinalize(static_cast<T*>(owner)); - } - void Reset(Unit* owner) override { (static_cast<D*>(this))->DoReset(static_cast<T*>(owner)); @@ -69,6 +98,16 @@ class MovementGeneratorMedium : public MovementGenerator { return (static_cast<D*>(this))->DoUpdate(static_cast<T*>(owner), diff); } + + void Deactivate(Unit* owner) override + { + (static_cast<D*>(this))->DoDeactivate(static_cast<T*>(owner)); + } + + void Finalize(Unit* owner, bool active, bool movementInform) override + { + (static_cast<D*>(this))->DoFinalize(static_cast<T*>(owner), active, movementInform); + } }; typedef FactoryHolder<MovementGenerator, Unit, MovementGeneratorType> MovementGeneratorCreator; diff --git a/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp index 791e5ccc1dd..ee01a5974b9 100644 --- a/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp @@ -31,14 +31,7 @@ static bool IsMutualChase(Unit* owner, Unit* target) if (target->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) return false; - return (static_cast<ChaseMovementGenerator const*>(target->GetMotionMaster()->top())->GetTarget() == owner); -} - -static void DoMovementInform(Unit* owner, Unit* target) -{ - if (Creature* cOwner = owner->ToCreature()) - if (CreatureAI* ai = cOwner->AI()) - ai->MovementInform(CHASE_MOTION_TYPE, target->GetGUID().GetCounter()); + return (dynamic_cast<ChaseMovementGenerator const*>(target->GetMotionMaster()->GetCurrentMovementGenerator())->GetTarget() == owner); } static bool PositionOkay(Unit* owner, Unit* target, Optional<float> minDistance, Optional<float> maxDistance, Optional<ChaseAngle> angle) @@ -51,14 +44,40 @@ static bool PositionOkay(Unit* owner, Unit* target, Optional<float> minDistance, return !angle || angle->IsAngleOkay(target->GetRelativeAngle(owner)); } -ChaseMovementGenerator::ChaseMovementGenerator(Unit* target, Optional<ChaseRange> range, Optional<ChaseAngle> angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle) {} +static void DoMovementInform(Unit* owner, Unit* target) +{ + if (owner->GetTypeId() != TYPEID_UNIT) + return; + + Creature* creatureOwner = owner->ToCreature(); + if (creatureOwner->IsAIEnabled && creatureOwner->AI()) + creatureOwner->AI()->MovementInform(CHASE_MOTION_TYPE, target->GetGUID().GetCounter()); +} + +ChaseMovementGenerator::ChaseMovementGenerator(Unit* target, Optional<ChaseRange> range, Optional<ChaseAngle> angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle) +{ + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_CHASE; +} ChaseMovementGenerator::~ChaseMovementGenerator() = default; void ChaseMovementGenerator::Initialize(Unit* owner) { - owner->AddUnitState(UNIT_STATE_CHASE); + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + owner->SetWalk(false); _path = nullptr; + _lastTargetPosition.Relocate(0.0f, 0.0f, 0.0f); +} + +void ChaseMovementGenerator::Reset(Unit* owner) +{ + RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + + Initialize(owner); } bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff) @@ -83,13 +102,13 @@ bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff) return true; } - bool const mutualChase = IsMutualChase(owner, target); - float const hitboxSum = owner->GetCombatReach() + target->GetCombatReach(); - float const minRange = _range ? _range->MinRange + hitboxSum : CONTACT_DISTANCE; - float const minTarget = (_range ? _range->MinTolerance : 0.0f) + hitboxSum; - float const maxRange = _range ? _range->MaxRange + hitboxSum : owner->GetMeleeRange(target); // melee range already includes hitboxes - float const maxTarget = _range ? _range->MaxTolerance + hitboxSum : CONTACT_DISTANCE + hitboxSum; - Optional<ChaseAngle> angle = mutualChase ? Optional<ChaseAngle>() : _angle; + bool const mutualChase = IsMutualChase(owner, target); + float const hitboxSum = owner->GetCombatReach() + target->GetCombatReach(); + float const minRange = _range ? _range->MinRange + hitboxSum : CONTACT_DISTANCE; + float const minTarget = (_range ? _range->MinTolerance : 0.0f) + hitboxSum; + float const maxRange = _range ? _range->MaxRange + hitboxSum : owner->GetMeleeRange(target); // melee range already includes hitboxes + float const maxTarget = _range ? _range->MaxTolerance + hitboxSum : CONTACT_DISTANCE + hitboxSum; + Optional<ChaseAngle> angle = mutualChase ? Optional<ChaseAngle>() : _angle; // if we're already moving, periodically check if we're already in the expected range... if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE)) @@ -176,6 +195,7 @@ bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff) if (cOwner) cOwner->SetCannotReachTarget(false); + owner->AddUnitState(UNIT_STATE_CHASE_MOVE); Movement::MoveSplineInit init(owner); @@ -191,9 +211,19 @@ bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff) return true; } -void ChaseMovementGenerator::Finalize(Unit* owner) +void ChaseMovementGenerator::Deactivate(Unit* owner) { - owner->ClearUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); - if (Creature* cOwner = owner->ToCreature()) - cOwner->SetCannotReachTarget(false); + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); +} + +void ChaseMovementGenerator::Finalize(Unit* owner, bool active, bool/* movementInform*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (active) + { + owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); + if (Creature* cOwner = owner->ToCreature()) + cOwner->SetCannotReachTarget(false); + } } diff --git a/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h index c1d967d6eed..48d828b7602 100644 --- a/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h @@ -33,10 +33,11 @@ class ChaseMovementGenerator : public MovementGenerator, public AbstractFollower explicit ChaseMovementGenerator(Unit* target, Optional<ChaseRange> range = {}, Optional<ChaseAngle> angle = {}); ~ChaseMovementGenerator(); - void Initialize(Unit* owner) override; - void Reset(Unit* owner) override { Initialize(owner); } - bool Update(Unit* owner, uint32 diff) override; - void Finalize(Unit* owner) override; + void Initialize(Unit*) override; + void Reset(Unit*) override; + bool Update(Unit*, uint32) override; + void Deactivate(Unit*) override; + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override { return CHASE_MOTION_TYPE; } void UnitSpeedChanged() override { _lastTargetPosition.Relocate(0.0f, 0.0f, 0.0f); } diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 01b5de37f26..94e786749c3 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -26,8 +26,12 @@ #include "Random.h" template<class T> -ConfusedMovementGenerator<T>::~ConfusedMovementGenerator() +ConfusedMovementGenerator<T>::ConfusedMovementGenerator() : _timer(0), _x(0.f), _y(0.f), _z(0.f) { + this->Mode = MOTION_MODE_DEFAULT; + this->Priority = MOTION_PRIORITY_HIGHEST; + this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + this->BaseUnitState = UNIT_STATE_CONFUSED; } template<class T> @@ -39,10 +43,13 @@ MovementGeneratorType ConfusedMovementGenerator<T>::GetMovementGeneratorType() c template<class T> void ConfusedMovementGenerator<T>::DoInitialize(T* owner) { + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + if (!owner || !owner->IsAlive()) return; - owner->AddUnitState(UNIT_STATE_CONFUSED); + // TODO: UNIT_FIELD_FLAGS should not be handled by generators owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); owner->StopMoving(); @@ -54,6 +61,8 @@ void ConfusedMovementGenerator<T>::DoInitialize(T* owner) template<class T> void ConfusedMovementGenerator<T>::DoReset(T* owner) { + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + DoInitialize(owner); } @@ -65,20 +74,19 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* owner, uint32 diff) if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); _path = nullptr; return true; } else - _interrupt = false; + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); // waiting for next move _timer.Update(diff); - if (!_interrupt && _timer.Passed() && owner->movespline->Finalized()) + if ((MovementGenerator::HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized()) || (_timer.Passed() && owner->movespline->Finalized())) { - // start moving - owner->AddUnitState(UNIT_STATE_CONFUSED_MOVE); + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); Position destination(_x, _y, _z); float distance = 4.0f * frand(0.0f, 1.0f) - 2.0f; @@ -98,6 +106,8 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* owner, uint32 diff) return true; } + owner->AddUnitState(UNIT_STATE_CONFUSED_MOVE); + Movement::MoveSplineInit init(owner); init.MovebyPath(_path->GetPath()); init.SetWalk(true); @@ -109,32 +119,50 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* owner, uint32 diff) } template<class T> -void ConfusedMovementGenerator<T>::DoFinalize(T*) { } +void ConfusedMovementGenerator<T>::DoDeactivate(T* owner) +{ + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_CONFUSED_MOVE); +} + +template<class T> +void ConfusedMovementGenerator<T>::DoFinalize(T*, bool, bool) { } template<> -void ConfusedMovementGenerator<Player>::DoFinalize(Player* unit) +void ConfusedMovementGenerator<Player>::DoFinalize(Player* owner, bool active, bool/* movementInform*/) { - unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit->ClearUnitState(UNIT_STATE_CONFUSED); - unit->StopMoving(); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + if (active) + { + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + owner->StopMoving(); + } } template<> -void ConfusedMovementGenerator<Creature>::DoFinalize(Creature* unit) +void ConfusedMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool/* movementInform*/) { - unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); - if (unit->GetVictim()) - unit->SetTarget(unit->EnsureVictim()->GetGUID()); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + if (active) + { + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + owner->ClearUnitState(UNIT_STATE_CONFUSED_MOVE); + if (owner->GetVictim()) + owner->SetTarget(owner->EnsureVictim()->GetGUID()); + } } -template ConfusedMovementGenerator<Player>::~ConfusedMovementGenerator(); -template ConfusedMovementGenerator<Creature>::~ConfusedMovementGenerator(); +template ConfusedMovementGenerator<Player>::ConfusedMovementGenerator(); +template ConfusedMovementGenerator<Creature>::ConfusedMovementGenerator(); template MovementGeneratorType ConfusedMovementGenerator<Player>::GetMovementGeneratorType() const; template MovementGeneratorType ConfusedMovementGenerator<Creature>::GetMovementGeneratorType() const; template void ConfusedMovementGenerator<Player>::DoInitialize(Player*); template void ConfusedMovementGenerator<Creature>::DoInitialize(Creature*); template void ConfusedMovementGenerator<Player>::DoReset(Player*); template void ConfusedMovementGenerator<Creature>::DoReset(Creature*); -template bool ConfusedMovementGenerator<Player>::DoUpdate(Player*, uint32 diff); -template bool ConfusedMovementGenerator<Creature>::DoUpdate(Creature*, uint32 diff); +template bool ConfusedMovementGenerator<Player>::DoUpdate(Player*, uint32); +template bool ConfusedMovementGenerator<Creature>::DoUpdate(Creature*, uint32); +template void ConfusedMovementGenerator<Player>::DoDeactivate(Player*); +template void ConfusedMovementGenerator<Creature>::DoDeactivate(Creature*); diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h index 1286295d5fa..965c81bd8e6 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h @@ -25,25 +25,25 @@ class PathGenerator; template<class T> -class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator<T> > +class ConfusedMovementGenerator : public MovementGeneratorMedium<T, ConfusedMovementGenerator<T>> { public: - explicit ConfusedMovementGenerator() : _timer(0), _x(0.f), _y(0.f), _z(0.f), _interrupt(false) { } - ~ConfusedMovementGenerator(); + explicit ConfusedMovementGenerator(); MovementGeneratorType GetMovementGeneratorType() const override; - void UnitSpeedChanged() override { } //TODO void DoInitialize(T*); - void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); + void DoDeactivate(T*); + void DoFinalize(T*, bool, bool); + + void UnitSpeedChanged() override { ConfusedMovementGenerator<T>::AddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); } private: std::unique_ptr<PathGenerator> _path; TimeTracker _timer; float _x, _y, _z; - bool _interrupt; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index f91452cff0d..40836186ee3 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -20,8 +20,8 @@ #include "Creature.h" #include "CreatureAI.h" #include "MovementDefines.h" -#include "MoveSplineInit.h" #include "MoveSpline.h" +#include "MoveSplineInit.h" #include "ObjectAccessor.h" #include "PathGenerator.h" #include "Player.h" @@ -31,8 +31,12 @@ #define MAX_QUIET_DISTANCE 43.0f template<class T> -FleeingMovementGenerator<T>::~FleeingMovementGenerator() +FleeingMovementGenerator<T>::FleeingMovementGenerator(ObjectGuid fleeTargetGUID) : _fleeTargetGUID(fleeTargetGUID), _timer(0) { + this->Mode = MOTION_MODE_DEFAULT; + this->Priority = MOTION_PRIORITY_HIGHEST; + this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + this->BaseUnitState = UNIT_STATE_FLEEING; } template<class T> @@ -44,40 +48,24 @@ MovementGeneratorType FleeingMovementGenerator<T>::GetMovementGeneratorType() co template<class T> void FleeingMovementGenerator<T>::DoInitialize(T* owner) { - if (!owner) + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + + if (!owner || !owner->IsAlive()) return; + // TODO: UNIT_FIELD_FLAGS should not be handled by generators owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->AddUnitState(UNIT_STATE_FLEEING); - SetTargetLocation(owner); - _path = nullptr; -} - -template<class T> -void FleeingMovementGenerator<T>::DoFinalize(T *) -{ -} - -template<> -void FleeingMovementGenerator<Player>::DoFinalize(Player* owner) -{ - owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->ClearUnitState(UNIT_STATE_FLEEING); - owner->StopMoving(); -} -template<> -void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner) -{ - owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); - if (owner->GetVictim()) - owner->SetTarget(owner->EnsureVictim()->GetGUID()); + _path = nullptr; + SetTargetLocation(owner); } template<class T> void FleeingMovementGenerator<T>::DoReset(T* owner) { + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + DoInitialize(owner); } @@ -89,37 +77,77 @@ bool FleeingMovementGenerator<T>::DoUpdate(T* owner, uint32 diff) if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); _path = nullptr; return true; } else - _interrupt = false; + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); _timer.Update(diff); - if (!_interrupt && _timer.Passed() && owner->movespline->Finalized()) + if ((MovementGenerator::HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized()) || (_timer.Passed() && owner->movespline->Finalized())) + { + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); SetTargetLocation(owner); + } return true; } template<class T> +void FleeingMovementGenerator<T>::DoDeactivate(T* owner) +{ + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); +} + +template<class T> +void FleeingMovementGenerator<T>::DoFinalize(T*, bool, bool) +{ +} + +template<> +void FleeingMovementGenerator<Player>::DoFinalize(Player* owner, bool active, bool/* movementInform*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + if (active) + { + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); + owner->StopMoving(); + } +} + +template<> +void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool/* movementInform*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + if (active) + { + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); + if (owner->GetVictim()) + owner->SetTarget(owner->EnsureVictim()->GetGUID()); + } +} + +template<class T> void FleeingMovementGenerator<T>::SetTargetLocation(T* owner) { - if (!owner) + if (!owner || !owner->IsAlive()) return; if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); _path = nullptr; return; } - owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); - Position destination = owner->GetPosition(); GetPoint(owner, destination); @@ -143,6 +171,8 @@ void FleeingMovementGenerator<T>::SetTargetLocation(T* owner) return; } + owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); + Movement::MoveSplineInit init(owner); init.MovebyPath(_path->GetPath()); init.SetWalk(false); @@ -188,8 +218,8 @@ void FleeingMovementGenerator<T>::GetPoint(T* owner, Position &position) owner->MovePositionToFirstCollision(position, distance, angle); } -template FleeingMovementGenerator<Player>::~FleeingMovementGenerator(); -template FleeingMovementGenerator<Creature>::~FleeingMovementGenerator(); +template FleeingMovementGenerator<Player>::FleeingMovementGenerator(ObjectGuid); +template FleeingMovementGenerator<Creature>::FleeingMovementGenerator(ObjectGuid); template MovementGeneratorType FleeingMovementGenerator<Player>::GetMovementGeneratorType() const; template MovementGeneratorType FleeingMovementGenerator<Creature>::GetMovementGeneratorType() const; template void FleeingMovementGenerator<Player>::DoInitialize(Player*); @@ -198,6 +228,8 @@ template void FleeingMovementGenerator<Player>::DoReset(Player*); template void FleeingMovementGenerator<Creature>::DoReset(Creature*); template bool FleeingMovementGenerator<Player>::DoUpdate(Player*, uint32); template bool FleeingMovementGenerator<Creature>::DoUpdate(Creature*, uint32); +template void FleeingMovementGenerator<Player>::DoDeactivate(Player*); +template void FleeingMovementGenerator<Creature>::DoDeactivate(Creature*); template void FleeingMovementGenerator<Player>::SetTargetLocation(Player*); template void FleeingMovementGenerator<Creature>::SetTargetLocation(Creature*); template void FleeingMovementGenerator<Player>::GetPoint(Player*, Position &); @@ -205,29 +237,25 @@ template void FleeingMovementGenerator<Creature>::GetPoint(Creature*, Position & //---- TimedFleeingMovementGenerator -MovementGeneratorType TimedFleeingMovementGenerator::GetMovementGeneratorType() const -{ - return TIMED_FLEEING_MOTION_TYPE; -} - -bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_diff) +bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 diff) { - if (!owner->IsAlive()) + if (!owner || !owner->IsAlive()) return false; - _totalFleeTime.Update(time_diff); + _totalFleeTime.Update(diff); if (_totalFleeTime.Passed()) return false; - // This calls grant-parent Update method hiden by FleeingMovementGenerator::Update(Creature &, uint32) version - // This is done instead of casting Unit& to Creature& and call parent method, then we can use Unit directly - return MovementGeneratorMedium< Creature, FleeingMovementGenerator<Creature> >::Update(owner, time_diff); + return FleeingMovementGenerator<Creature>::DoUpdate(owner->ToCreature(), diff); } -void TimedFleeingMovementGenerator::Finalize(Unit* owner) +void TimedFleeingMovementGenerator::Finalize(Unit* owner, bool active, bool/* movementInform*/) { + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (!active) + return; + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->ClearUnitState(UNIT_STATE_FLEEING); owner->StopMoving(); if (Unit* victim = owner->GetVictim()) { @@ -238,3 +266,8 @@ void TimedFleeingMovementGenerator::Finalize(Unit* owner) } } } + +MovementGeneratorType TimedFleeingMovementGenerator::GetMovementGeneratorType() const +{ + return TIMED_FLEEING_MOTION_TYPE; +} diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h index af95f87c96c..0b17bb0cd32 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h @@ -28,28 +28,28 @@ class PathGenerator; struct Position; template<class T> -class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator<T> > +class FleeingMovementGenerator : public MovementGeneratorMedium<T, FleeingMovementGenerator<T>> { public: - explicit FleeingMovementGenerator(ObjectGuid fleeTargetGUID) : _fleeTargetGUID(fleeTargetGUID), _timer(0), _interrupt(false) { } - ~FleeingMovementGenerator(); + explicit FleeingMovementGenerator(ObjectGuid fleeTargetGUID); MovementGeneratorType GetMovementGeneratorType() const override; - void UnitSpeedChanged() override { } //TODO void DoInitialize(T*); - void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); + void DoDeactivate(T*); + void DoFinalize(T*, bool, bool); + + void UnitSpeedChanged() override { FleeingMovementGenerator<T>::AddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); } private: void SetTargetLocation(T*); - void GetPoint(T*, Position &position); + void GetPoint(T*, Position& position); std::unique_ptr<PathGenerator> _path; ObjectGuid _fleeTargetGUID; TimeTracker _timer; - bool _interrupt; }; class TimedFleeingMovementGenerator : public FleeingMovementGenerator<Creature> @@ -57,9 +57,9 @@ class TimedFleeingMovementGenerator : public FleeingMovementGenerator<Creature> public: explicit TimedFleeingMovementGenerator(ObjectGuid fleeTargetGUID, uint32 time) : FleeingMovementGenerator<Creature>(fleeTargetGUID), _totalFleeTime(time) { } - MovementGeneratorType GetMovementGeneratorType() const override; bool Update(Unit*, uint32) override; - void Finalize(Unit*) override; + void Finalize(Unit*, bool, bool) override; + MovementGeneratorType GetMovementGeneratorType() const override; private: TimeTracker _totalFleeTime; diff --git a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp index 2d0ca8c282e..4c4da89de17 100644 --- a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp @@ -25,8 +25,6 @@ #include "ObjectMgr.h" #include "Player.h" - //----------------------------------------------------// - #define FLIGHT_TRAVEL_UPDATE 100 #define TIMEDIFF_NEXT_WP 250 #define SKIP_SPLINE_POINT_DISTANCE_SQ (40.f * 40.f) @@ -39,6 +37,122 @@ FlightPathMovementGenerator::FlightPathMovementGenerator(uint32 startNode) _endGridY = 0.0f; _endMapId = 0; _preloadTargetNode = 0; + + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_HIGHEST; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_IN_FLIGHT; +} + +MovementGeneratorType FlightPathMovementGenerator::GetMovementGeneratorType() const +{ + return FLIGHT_MOTION_TYPE; +} + +bool FlightPathMovementGenerator::GetResetPosition(Unit* /*owner*/, float& x, float& y, float& z) +{ + TaxiPathNodeEntry const* node = _path[_currentNode]; + x = node->LocX; + y = node->LocY; + z = node->LocZ; + return true; +} + +void FlightPathMovementGenerator::DoInitialize(Player* owner) +{ + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + + DoReset(owner); + InitEndGridInfo(); +} + +void FlightPathMovementGenerator::DoReset(Player* owner) +{ + RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + + owner->CombatStopWithPets(); + owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT); + + Movement::MoveSplineInit init(owner); + uint32 end = GetPathAtMapEnd(); + for (uint32 i = GetCurrentNode(); i != end; ++i) + { + G3D::Vector3 vertice(_path[i]->LocX, _path[i]->LocY, _path[i]->LocZ); + init.Path().push_back(vertice); + } + init.SetFirstPointId(GetCurrentNode()); + init.SetFly(); + init.SetVelocity(PLAYER_FLIGHT_SPEED); + init.Launch(); +} + +bool FlightPathMovementGenerator::DoUpdate(Player* owner, uint32 /*diff*/) +{ + if (!owner) + return false; + + uint32 pointId = owner->movespline->currentPathIdx() < 0 ? 0 : owner->movespline->currentPathIdx(); + if (pointId > _currentNode) + { + bool departureEvent = true; + do + { + DoEventIfAny(owner, _path[_currentNode], departureEvent); + while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode) + { + _pointsForPathSwitch.pop_front(); + owner->m_taxi.NextTaxiDestination(); + if (!_pointsForPathSwitch.empty()) + { + owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, _pointsForPathSwitch.front().Cost); + owner->ModifyMoney(-_pointsForPathSwitch.front().Cost); + } + } + + if (pointId == _currentNode) + break; + + if (_currentNode == _preloadTargetNode) + PreloadEndGrid(); + + _currentNode += departureEvent ? 1 : 0; + departureEvent = !departureEvent; + } while (true); + } + + if (_currentNode >= (_path.size() - 1)) + { + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + return false; + } + return true; +} + +void FlightPathMovementGenerator::DoDeactivate(Player* /*owner*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); +} + +void FlightPathMovementGenerator::DoFinalize(Player* owner, bool active, bool/* movementInform*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (!active) + return; + + owner->Dismount(); + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT); + + if (owner->m_taxi.empty()) + { + // update z position to ground and orientation for landing point + // this prevent cheating with landing point at lags + // when client side flight end early in comparison server side + owner->StopMoving(); + owner->SetFallInformation(0, owner->GetPositionZ()); + } + + owner->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK); } uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const @@ -48,8 +162,10 @@ uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const uint32 curMapId = _path[_currentNode]->MapID; for (uint32 itr = _currentNode; itr < _path.size(); ++itr) + { if (_path[itr]->MapID != curMapId) return itr; + } return _path.size(); } @@ -59,11 +175,11 @@ bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntr return p1->MapID != p2->MapID || std::pow(p1->LocX - p2->LocX, 2) + std::pow(p1->LocY - p2->LocY, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ; } -void FlightPathMovementGenerator::LoadPath(Player* player) +void FlightPathMovementGenerator::LoadPath(Player* owner) { _pointsForPathSwitch.clear(); - std::deque<uint32> const& taxi = player->m_taxi.GetPath(); - float discount = player->GetReputationPriceDiscount(player->m_taxi.GetFlightMasterFactionTemplate()); + std::deque<uint32> const& taxi = owner->m_taxi.GetPath(); + float discount = owner->GetReputationPriceDiscount(owner->m_taxi.GetFlightMasterFactionTemplate()); for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++) { uint32 path, cost; @@ -100,89 +216,6 @@ void FlightPathMovementGenerator::LoadPath(Player* player) } } -void FlightPathMovementGenerator::DoInitialize(Player* player) -{ - Reset(player); - InitEndGridInfo(); -} - -void FlightPathMovementGenerator::DoFinalize(Player* player) -{ - // remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack) - player->ClearUnitState(UNIT_STATE_IN_FLIGHT); - - player->Dismount(); - player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT); - - if (player->m_taxi.empty()) - { - // update z position to ground and orientation for landing point - // this prevent cheating with landing point at lags - // when client side flight end early in comparison server side - player->StopMoving(); - player->SetFallInformation(0, player->GetPositionZ()); - } - - player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK); -} - -void FlightPathMovementGenerator::DoReset(Player* player) -{ - player->AddUnitState(UNIT_STATE_IN_FLIGHT); - player->CombatStopWithPets(); - player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT); - - Movement::MoveSplineInit init(player); - uint32 end = GetPathAtMapEnd(); - for (uint32 i = GetCurrentNode(); i != end; ++i) - { - G3D::Vector3 vertice(_path[i]->LocX, _path[i]->LocY, _path[i]->LocZ); - init.Path().push_back(vertice); - } - init.SetFirstPointId(GetCurrentNode()); - init.SetFly(); - init.SetVelocity(PLAYER_FLIGHT_SPEED); - init.Launch(); -} - -bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/) -{ - uint32 pointId = (uint32)player->movespline->currentPathIdx(); - if (pointId > _currentNode) - { - bool departureEvent = true; - do - { - DoEventIfAny(player, _path[_currentNode], departureEvent); - while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode) - { - _pointsForPathSwitch.pop_front(); - player->m_taxi.NextTaxiDestination(); - if (!_pointsForPathSwitch.empty()) - { - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, _pointsForPathSwitch.front().Cost); - player->ModifyMoney(-_pointsForPathSwitch.front().Cost); - } - } - - if (pointId == _currentNode) - break; - - if (_currentNode == _preloadTargetNode) - PreloadEndGrid(); - _currentNode += departureEvent ? 1 : 0; - departureEvent = !departureEvent; - } while (true); - } - - return _currentNode < (_path.size() - 1); -} - -MovementGeneratorType FlightPathMovementGenerator::GetMovementGeneratorType() const -{ - return FLIGHT_MOTION_TYPE; -} - void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() { if (_path.empty() || _currentNode >= _path.size()) @@ -199,29 +232,22 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() } } -void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure) +void FlightPathMovementGenerator::DoEventIfAny(Player* owner, TaxiPathNodeEntry const* node, bool departure) { if (uint32 eventid = departure ? node->DepartureEventID : node->ArrivalEventID) { - TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node->NodeIndex, node->PathID, player->GetName().c_str()); - player->GetMap()->ScriptsStart(sEventScripts, eventid, player, player); + TC_LOG_DEBUG("maps.script", "FlightPathMovementGenerator::DoEventIfAny: taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node->NodeIndex, node->PathID, owner->GetName().c_str()); + owner->GetMap()->ScriptsStart(sEventScripts, eventid, owner, owner); } } -bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z) -{ - TaxiPathNodeEntry const* node = _path[_currentNode]; - x = node->LocX; - y = node->LocY; - z = node->LocZ; - return true; -} - void FlightPathMovementGenerator::InitEndGridInfo() { - /*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will - be reinitialized for each flightmaster at the end of each spline (or stop) in the flight. */ - uint32 nodeCount = _path.size(); //! Number of nodes in path. + /*! + * Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will + * be reinitialized for each flightmaster at the end of each spline (or stop) in the flight. + */ + uint32 nodeCount = _path.size(); //! Number of nodes in path. _endMapId = _path[nodeCount - 1]->MapID; //! MapId of last node _preloadTargetNode = nodeCount - 3; _endGridX = _path[nodeCount - 1]->LocX; @@ -230,15 +256,15 @@ void FlightPathMovementGenerator::InitEndGridInfo() void FlightPathMovementGenerator::PreloadEndGrid() { - // used to preload the final grid where the flightmaster is + // Used to preload the final grid where the flightmaster is Map* endMap = sMapMgr->FindBaseNonInstanceMap(_endMapId); // Load the grid if (endMap) { - TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(_path.size() - 1)); + TC_LOG_DEBUG("movement.flightpath", "FlightPathMovementGenerator::PreloadEndGrid: preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, uint32(_path.size() - 1)); endMap->LoadGrid(_endGridX, _endGridY); } else - TC_LOG_DEBUG("misc", "Unable to determine map to preload flightmaster grid"); + TC_LOG_DEBUG("movement.flightpath", "FlightPathMovementGenerator::PreloadEndGrid: unable to determine map to preload flightmaster grid"); } diff --git a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h index 9d63b60394b..2815073b17f 100644 --- a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h @@ -15,8 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef FlightPathMovementGenerator_h__ -#define FlightPathMovementGenerator_h__ +#ifndef TRINITY_FLIGHTPATHMOVEMENTGENERATOR_H +#define TRINITY_FLIGHTPATHMOVEMENTGENERATOR_H #include "DBCStructure.h" #include "MovementGenerator.h" @@ -26,46 +26,46 @@ class Player; /** -* FlightPathMovementGenerator generates movement of the player for the paths -* and hence generates ground and activities for the player. -*/ + * FlightPathMovementGenerator generates movement of the player for the paths + * and hence generates ground and activities for the player. + */ class FlightPathMovementGenerator : public MovementGeneratorMedium<Player, FlightPathMovementGenerator>, public PathMovementBase<Player, TaxiPathNodeList> { -public: - explicit FlightPathMovementGenerator(uint32 startNode = 0); - - void LoadPath(Player* player); - void DoInitialize(Player*); - void DoReset(Player*); - void DoFinalize(Player*); - bool DoUpdate(Player*, uint32); - MovementGeneratorType GetMovementGeneratorType() const override; + public: + explicit FlightPathMovementGenerator(uint32 startNode = 0); - TaxiPathNodeList const& GetPath() { return _path; } - uint32 GetPathAtMapEnd() const; - bool HasArrived() const { return (_currentNode >= _path.size()); } - void SetCurrentNodeAfterTeleport(); - void SkipCurrentNode() { ++_currentNode; } - void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure); + MovementGeneratorType GetMovementGeneratorType() const override; + bool GetResetPosition(Unit* owner, float& x, float& y, float& z) override; - bool GetResetPos(Player*, float& x, float& y, float& z); - void InitEndGridInfo(); - void PreloadEndGrid(); + void DoInitialize(Player*); + void DoReset(Player*); + bool DoUpdate(Player*, uint32); + void DoDeactivate(Player*); + void DoFinalize(Player*, bool, bool); -private: + TaxiPathNodeList const& GetPath() { return _path; } + uint32 GetPathAtMapEnd() const; + bool HasArrived() const { return _currentNode >= _path.size(); } - float _endGridX; //! X coord of last node location - float _endGridY; //! Y coord of last node location - uint32 _endMapId; //! map Id of last node location - uint32 _preloadTargetNode; //! node index where preloading starts + void LoadPath(Player* owner); + void SetCurrentNodeAfterTeleport(); + void SkipCurrentNode() { ++_currentNode; } + void DoEventIfAny(Player* owner, TaxiPathNodeEntry const* node, bool departure); + void InitEndGridInfo(); + void PreloadEndGrid(); - struct TaxiNodeChangeInfo - { - uint32 PathIndex; - int32 Cost; - }; + private: + float _endGridX; //! X coord of last node location + float _endGridY; //! Y coord of last node location + uint32 _endMapId; //! map Id of last node location + uint32 _preloadTargetNode; //! node index where preloading starts - std::deque<TaxiNodeChangeInfo> _pointsForPathSwitch; //! node indexes and costs where TaxiPath changes + struct TaxiNodeChangeInfo + { + uint32 PathIndex; + int32 Cost; + }; + std::deque<TaxiNodeChangeInfo> _pointsForPathSwitch; //! node indexes and costs where TaxiPath changes }; -#endif // FlightPathMovementGenerator_h__ +#endif // TRINITY_FLIGHTPATHMOVEMENTGENERATOR_H diff --git a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp index 45bfa376ae3..a9552d5bd6a 100644 --- a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp @@ -16,6 +16,7 @@ */ #include "FollowMovementGenerator.h" +#include "Creature.h" #include "CreatureAI.h" #include "MoveSpline.h" #include "MoveSplineInit.h" @@ -25,17 +26,25 @@ #include "Unit.h" #include "Util.h" -FollowMovementGenerator::FollowMovementGenerator(Unit* target, float range, ChaseAngle angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle) {} -FollowMovementGenerator::~FollowMovementGenerator() = default; - static void DoMovementInform(Unit* owner, Unit* target) { if (owner->GetTypeId() != TYPEID_UNIT) return; - if (UnitAI* ai = owner->GetAI()) - static_cast<CreatureAI*>(ai)->MovementInform(FOLLOW_MOTION_TYPE, target->GetGUID().GetCounter()); + + Creature* creatureOwner = owner->ToCreature(); + if (creatureOwner->IsAIEnabled && creatureOwner->AI()) + creatureOwner->AI()->MovementInform(FOLLOW_MOTION_TYPE, target->GetGUID().GetCounter()); } +FollowMovementGenerator::FollowMovementGenerator(Unit* target, float range, ChaseAngle angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle) +{ + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_FOLLOW; +} +FollowMovementGenerator::~FollowMovementGenerator() = default; + static bool PositionOkay(Unit* owner, Unit* target, float range, Optional<ChaseAngle> angle = {}) { if (owner->GetExactDistSq(target) > square(owner->GetCombatReach() + target->GetCombatReach() + range)) @@ -46,15 +55,26 @@ static bool PositionOkay(Unit* owner, Unit* target, float range, Optional<ChaseA void FollowMovementGenerator::Initialize(Unit* owner) { - owner->AddUnitState(UNIT_STATE_FOLLOW); + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + + owner->StopMoving(); UpdatePetSpeed(owner); _path = nullptr; + _lastTargetPosition.Relocate(0.0f, 0.0f, 0.0f); +} + +void FollowMovementGenerator::Reset(Unit* owner) +{ + RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + + Initialize(owner); } bool FollowMovementGenerator::Update(Unit* owner, uint32 diff) { // owner might be dead or gone - if (!owner->IsAlive()) + if (!owner || !owner->IsAlive()) return false; // our target might have gone away @@ -125,8 +145,10 @@ bool FollowMovementGenerator::Update(Unit* owner, uint32 diff) // pets are allowed to "cheat" on pathfinding when following their master bool allowShortcut = false; if (Pet* oPet = owner->ToPet()) + { if (target->GetGUID() == oPet->GetOwnerGUID()) allowShortcut = true; + } bool success = _path->CalculatePath(x, y, z, allowShortcut); if (!success || (_path->GetPathType() & PATHFIND_NOPATH)) @@ -147,10 +169,20 @@ bool FollowMovementGenerator::Update(Unit* owner, uint32 diff) return true; } -void FollowMovementGenerator::Finalize(Unit* owner) +void FollowMovementGenerator::Deactivate(Unit* owner) { - owner->ClearUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); - UpdatePetSpeed(owner); + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); +} + +void FollowMovementGenerator::Finalize(Unit* owner, bool active, bool/* movementInform*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (active) + { + owner->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); + UpdatePetSpeed(owner); + } } void FollowMovementGenerator::UpdatePetSpeed(Unit* owner) diff --git a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h index 2725656f2ef..91d99bb8fb5 100644 --- a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h @@ -34,10 +34,11 @@ class FollowMovementGenerator : public MovementGenerator, public AbstractFollowe explicit FollowMovementGenerator(Unit* target, float range, ChaseAngle angle); ~FollowMovementGenerator(); - void Initialize(Unit* owner) override; - void Reset(Unit* owner) override { Initialize(owner); } - bool Update(Unit* owner, uint32 diff) override; - void Finalize(Unit* owner) override; + void Initialize(Unit*) override; + void Reset(Unit*) override; + bool Update(Unit*, uint32) override; + void Deactivate(Unit*) override; + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override { return FOLLOW_MOTION_TYPE; } void UnitSpeedChanged() override { _lastTargetPosition.Relocate(0.0f, 0.0f, 0.0f); } diff --git a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp index 55b1907bb9e..2953fe336c9 100644 --- a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp @@ -19,8 +19,16 @@ #include "Creature.h" #include "CreatureAI.h" #include "MovementDefines.h" -#include "MoveSplineInit.h" #include "MoveSpline.h" +#include "MoveSplineInit.h" + +FormationMovementGenerator::FormationMovementGenerator(uint32 id, Position destination, uint32 moveType, bool run, bool orientation) : _movementId(id), _destination(destination), _moveType(moveType), _run(run), _orientation(orientation) +{ + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_ROAMING; +} MovementGeneratorType FormationMovementGenerator::GetMovementGeneratorType() const { @@ -29,11 +37,12 @@ MovementGeneratorType FormationMovementGenerator::GetMovementGeneratorType() con void FormationMovementGenerator::DoInitialize(Creature* owner) { - owner->AddUnitState(UNIT_STATE_ROAMING); + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); return; } @@ -67,6 +76,14 @@ void FormationMovementGenerator::DoInitialize(Creature* owner) init.Launch(); } +void FormationMovementGenerator::DoReset(Creature* owner) +{ + RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + + owner->StopMoving(); + DoInitialize(owner); +} + bool FormationMovementGenerator::DoUpdate(Creature* owner, uint32 /*diff*/) { if (!owner) @@ -74,15 +91,14 @@ bool FormationMovementGenerator::DoUpdate(Creature* owner, uint32 /*diff*/) if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); return true; } - if ((_interrupt && owner->movespline->Finalized()) || (_recalculateSpeed && !owner->movespline->Finalized())) + if ((HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED) && owner->movespline->Finalized()) || (HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized())) { - _recalculateSpeed = false; - _interrupt = false; + RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED | MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); @@ -112,21 +128,29 @@ bool FormationMovementGenerator::DoUpdate(Creature* owner, uint32 /*diff*/) init.Launch(); } - return !owner->movespline->Finalized(); + if (owner->movespline->Finalized()) + { + RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + return false; + } + return true; } -void FormationMovementGenerator::DoFinalize(Creature* owner) +void FormationMovementGenerator::DoDeactivate(Creature* owner) { - owner->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - - if (owner->movespline->Finalized()) - MovementInform(owner); + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); } -void FormationMovementGenerator::DoReset(Creature* owner) +void FormationMovementGenerator::DoFinalize(Creature* owner, bool active, bool movementInform) { - owner->StopMoving(); - DoInitialize(owner); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (active) + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + + if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + MovementInform(owner); } void FormationMovementGenerator::MovementInform(Creature* owner) diff --git a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h index 8b5f91042ee..bf9def8a049 100644 --- a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h @@ -23,19 +23,20 @@ class Creature; -class FormationMovementGenerator : public MovementGeneratorMedium< Creature, FormationMovementGenerator > +class FormationMovementGenerator : public MovementGeneratorMedium<Creature, FormationMovementGenerator> { public: - explicit FormationMovementGenerator(uint32 id, Position destination, uint32 moveType, bool run, bool orientation) : _movementId(id), _destination(destination), _moveType(moveType), _run(run), _orientation(orientation), _recalculateSpeed(false), _interrupt(false) { } + explicit FormationMovementGenerator(uint32 id, Position destination, uint32 moveType, bool run, bool orientation); MovementGeneratorType GetMovementGeneratorType() const override; void DoInitialize(Creature*); - void DoFinalize(Creature*); void DoReset(Creature*); bool DoUpdate(Creature*, uint32); + void DoDeactivate(Creature*); + void DoFinalize(Creature*, bool, bool); - void UnitSpeedChanged() override { _recalculateSpeed = true; } + void UnitSpeedChanged() override { AddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); } private: void MovementInform(Creature*); @@ -45,8 +46,6 @@ class FormationMovementGenerator : public MovementGeneratorMedium< Creature, For uint32 _moveType; bool _run; bool _orientation; - bool _recalculateSpeed; - bool _interrupt; }; #endif // TRINITY_FORMATIONMOVEMENTGENERATOR_H diff --git a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp index 64de380a345..4fc40d5bb0c 100644 --- a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp @@ -18,31 +18,70 @@ #include "GenericMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" +#include "MovementDefines.h" #include "MoveSpline.h" #include "Unit.h" +GenericMovementGenerator::GenericMovementGenerator(Movement::MoveSplineInit&& splineInit, MovementGeneratorType type, uint32 id) : _splineInit(std::move(splineInit)), _type(type), _pointId(id), _duration(0) +{ + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_ROAMING; +} + void GenericMovementGenerator::Initialize(Unit* /*owner*/) { + if (HasFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED)) // Resume spline is not supported + { + RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + return; + } + + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + _duration.Reset(_splineInit.Launch()); } +void GenericMovementGenerator::Reset(Unit* owner) +{ + Initialize(owner); +} + bool GenericMovementGenerator::Update(Unit* owner, uint32 diff) { + if (!owner || HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED)) + return false; + _duration.Update(diff); - if (_duration.Passed()) + if (_duration.Passed() || owner->movespline->Finalized()) + { + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); return false; + } + return true; +} - return !owner->movespline->Finalized(); +void GenericMovementGenerator::Deactivate(Unit*) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); } -void GenericMovementGenerator::Finalize(Unit* owner) +void GenericMovementGenerator::Finalize(Unit* owner, bool/* active*/, bool movementInform) { - MovementInform(owner); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + 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 index 66e166a6f92..564cbbff17e 100644 --- a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h @@ -29,12 +29,13 @@ 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) { } + explicit GenericMovementGenerator(Movement::MoveSplineInit&& splineInit, MovementGeneratorType type, uint32 id); void Initialize(Unit*) override; - void Finalize(Unit*) override; - void Reset(Unit*) override { } + void Reset(Unit*) override; bool Update(Unit*, uint32) override; + void Deactivate(Unit*) override; + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override { return _type; } private: diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 40a58007d49..dd5e4aff60d 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -19,11 +19,22 @@ #include "HomeMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" +#include "G3DPosition.hpp" #include "MotionMaster.h" #include "MovementDefines.h" #include "MoveSpline.h" #include "MoveSplineInit.h" -#include "PathGenerator.h" + +template<class T> +HomeMovementGenerator<T>::HomeMovementGenerator() +{ + this->Mode = MOTION_MODE_DEFAULT; + this->Priority = MOTION_PRIORITY_NORMAL; + this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + this->BaseUnitState = UNIT_STATE_ROAMING; +} + +template HomeMovementGenerator<Creature>::HomeMovementGenerator(); template<class T> MovementGeneratorType HomeMovementGenerator<T>::GetMovementGeneratorType() const @@ -39,29 +50,34 @@ void HomeMovementGenerator<T>::SetTargetLocation(T*) { } template<> void HomeMovementGenerator<Creature>::SetTargetLocation(Creature* owner) { + // if we are ROOT/STUNNED/DISTRACTED even after aura clear, finalize on next update - otherwise we would get stuck in evade if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) - { // if we are ROOT/STUNNED/DISTRACTED even after aura clear, finalize on next update - otherwise we would get stuck in evade - _skipToHome = true; + { + AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); return; } + owner->ClearUnitState(UNIT_STATE_ALL_ERASABLE & ~UNIT_STATE_EVADE); + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); + + Position destination = owner->GetHomePosition(); Movement::MoveSplineInit init(owner); - float x, y, z, o; - // at apply we can select more nice return points base at current movegen - if (owner->GetMotionMaster()->empty() || !owner->GetMotionMaster()->top()->GetResetPosition(owner, x, y, z)) - { - owner->GetHomePosition(x, y, z, o); - init.SetFacing(o); - } - owner->UpdateAllowedPositionZ(x, y, z); - init.MoveTo(x, y, z); + + /* + * TODO: maybe this never worked, who knows, top is always this generator, so this code calls GetResetPosition on itself + * + * if (owner->GetMotionMaster()->empty() || !owner->GetMotionMaster()->top()->GetResetPosition(owner, x, y, z)) + * { + * owner->GetHomePosition(x, y, z, o); + * init.SetFacing(o); + * } + */ + + owner->UpdateAllowedPositionZ(destination.m_positionX, destination.m_positionY, destination.m_positionZ); + init.MoveTo(PositionToVector3(destination)); + init.SetFacing(destination.GetOrientation()); init.SetWalk(false); init.Launch(); - - _skipToHome = false; - _arrived = false; - - owner->ClearUnitState(UNIT_STATE_ALL_ERASABLE & ~UNIT_STATE_EVADE); } template<class T> @@ -70,23 +86,10 @@ void HomeMovementGenerator<T>::DoInitialize(T*) { } template<> void HomeMovementGenerator<Creature>::DoInitialize(Creature* owner) { - SetTargetLocation(owner); -} + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); -template<class T> -void HomeMovementGenerator<T>::DoFinalize(T*) { } - -template<> -void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner) -{ - if (_arrived) - { - owner->ClearUnitState(UNIT_STATE_EVADE); - owner->SetWalk(true); - owner->LoadCreaturesAddon(); - owner->AI()->JustReachedHome(); - owner->SetSpawnHealth(); - } + SetTargetLocation(owner); } template<class T> @@ -95,6 +98,8 @@ void HomeMovementGenerator<T>::DoReset(T*) { } template<> void HomeMovementGenerator<Creature>::DoReset(Creature* owner) { + RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + DoInitialize(owner); } @@ -107,6 +112,39 @@ bool HomeMovementGenerator<T>::DoUpdate(T*, uint32) template<> bool HomeMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 /*diff*/) { - _arrived = _skipToHome || owner->movespline->Finalized(); - return !_arrived; + if (HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED) || owner->movespline->Finalized()) + { + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + return false; + } + return true; +} + +template<class T> +void HomeMovementGenerator<T>::DoDeactivate(T*) { } + +template<> +void HomeMovementGenerator<Creature>::DoDeactivate(Creature* owner) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); +} + +template<class T> +void HomeMovementGenerator<T>::DoFinalize(T*, bool, bool) { } + +template<> +void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool movementInform) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (active) + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE | UNIT_STATE_EVADE); + + if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + { + owner->SetWalk(true); + owner->SetSpawnHealth(); + owner->LoadCreaturesAddon(); + owner->AI()->JustReachedHome(); + } } diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h index 9e9c9c277c9..5d7c1dbf619 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h @@ -25,20 +25,18 @@ template <class T> class HomeMovementGenerator : public MovementGeneratorMedium< T, HomeMovementGenerator<T> > { public: - explicit HomeMovementGenerator() : _arrived(false), _skipToHome(false) { } + explicit HomeMovementGenerator(); MovementGeneratorType GetMovementGeneratorType() const override; void DoInitialize(T*); - void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); + void DoDeactivate(T*); + void DoFinalize(T*, bool, bool); private: void SetTargetLocation(T*); - - bool _arrived; - bool _skipToHome; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp index 69a89cede20..2d3909c34e1 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp @@ -19,19 +19,41 @@ #include "IdleMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" +#include "G3DPosition.hpp" #include "MovementDefines.h" +#include "MoveSpline.h" +#include "MoveSplineInit.h" +#include "Unit.h" -// StopMoving is needed to make unit stop if its last movement generator expires -// But it should not be sent otherwise there are many redundent packets +IdleMovementGenerator::IdleMovementGenerator() +{ + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZED; + BaseUnitState = 0; +} + +/* + * TODO: "if (!owner->IsStopped())" is useless, each generator cleans their own STATE_MOVE, the result is that StopMoving is almost never called + * Old comment: "StopMoving is needed to make unit stop if its last movement generator expires but it should not be sent otherwise there are many redundent packets" + */ void IdleMovementGenerator::Initialize(Unit* owner) { - Reset(owner); + owner->StopMoving(); } void IdleMovementGenerator::Reset(Unit* owner) { - if (!owner->IsStopped()) - owner->StopMoving(); + owner->StopMoving(); +} + +void IdleMovementGenerator::Deactivate(Unit* /*owner*/) +{ +} + +void IdleMovementGenerator::Finalize(Unit* /*owner*/, bool/* active*/, bool/* movementInform*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); } MovementGeneratorType IdleMovementGenerator::GetMovementGeneratorType() const @@ -41,21 +63,43 @@ MovementGeneratorType IdleMovementGenerator::GetMovementGeneratorType() const //----------------------------------------------------// -void RotateMovementGenerator::Initialize(Unit* owner) +RotateMovementGenerator::RotateMovementGenerator(uint32 id, uint32 time, RotateDirection direction) : _id(id), _duration(time), _maxDuration(time), _direction(direction) { - if (!owner->IsStopped()) - owner->StopMoving(); + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_ROTATING; +} - if (owner->GetVictim()) - owner->SetInFront(owner->GetVictim()); +void RotateMovementGenerator::Initialize(Unit* owner) +{ + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + + owner->StopMoving(); + + /* + * TODO: This code should be handled somewhere else, like MovementInform + * + * if (owner->GetVictim()) + * owner->SetInFront(owner->GetVictim()); + * + * owner->AttackStop(); + */ +} - owner->AddUnitState(UNIT_STATE_ROTATING); +void RotateMovementGenerator::Reset(Unit* owner) +{ + RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); - owner->AttackStop(); + Initialize(owner); } bool RotateMovementGenerator::Update(Unit* owner, uint32 diff) { + if (!owner) + return false; + float angle = owner->GetOrientation(); if (_direction == ROTATE_DIRECTION_LEFT) { @@ -70,60 +114,109 @@ bool RotateMovementGenerator::Update(Unit* owner, uint32 diff) angle += float(M_PI) * 2.f; } - owner->SetFacingTo(angle); + Movement::MoveSplineInit init(owner); + init.MoveTo(PositionToVector3(*owner), false); + if (owner->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && owner->GetTransGUID()) + init.DisableTransportPathTransformations(); + init.SetFacing(angle); + init.Launch(); if (_duration > diff) _duration -= diff; else + { + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); return false; + } return true; } -MovementGeneratorType RotateMovementGenerator::GetMovementGeneratorType() const +void RotateMovementGenerator::Deactivate(Unit*) { - return ROTATE_MOTION_TYPE; + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); } -void RotateMovementGenerator::Finalize(Unit* owner) +void RotateMovementGenerator::Finalize(Unit* owner, bool/* active*/, bool movementInform) { - owner->ClearUnitState(UNIT_STATE_ROTATING); - if (owner->GetTypeId() == TYPEID_UNIT) - owner->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + if (movementInform && owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, _id); +} + +MovementGeneratorType RotateMovementGenerator::GetMovementGeneratorType() const +{ + return ROTATE_MOTION_TYPE; } //----------------------------------------------------// +DistractMovementGenerator::DistractMovementGenerator(uint32 timer, float orientation) : _timer(timer), _orientation(orientation) +{ + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_HIGHEST; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_DISTRACTED; +} + void DistractMovementGenerator::Initialize(Unit* owner) { + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + // Distracted creatures stand up if not standing if (!owner->IsStandState()) owner->SetStandState(UNIT_STAND_STATE_STAND); - owner->AddUnitState(UNIT_STATE_DISTRACTED); + Movement::MoveSplineInit init(owner); + init.MoveTo(PositionToVector3(*owner), false); + if (owner->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && owner->GetTransGUID()) + init.DisableTransportPathTransformations(); + init.SetFacing(_orientation); + init.Launch(); } -void DistractMovementGenerator::Finalize(Unit* owner) +void DistractMovementGenerator::Reset(Unit* owner) { - owner->ClearUnitState(UNIT_STATE_DISTRACTED); + RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); - // If this is a creature, then return orientation to original position (for idle movement creatures) - if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()) - { - float angle = owner->ToCreature()->GetHomePosition().GetOrientation(); - owner->SetFacingTo(angle); - } + Initialize(owner); } -bool DistractMovementGenerator::Update(Unit* /*owner*/, uint32 diff) +bool DistractMovementGenerator::Update(Unit* owner, uint32 diff) { + if (!owner) + return false; + if (diff > _timer) + { + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); return false; + } _timer -= diff; return true; } +void DistractMovementGenerator::Deactivate(Unit*) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); +} + +void DistractMovementGenerator::Finalize(Unit* owner, bool/* active*/, bool movementInform) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + // TODO: This code should be handled somewhere else + // If this is a creature, then return orientation to original position (for idle movement creatures) + if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) && owner->GetTypeId() == TYPEID_UNIT) + { + float angle = owner->ToCreature()->GetHomePosition().GetOrientation(); + owner->SetFacingTo(angle); + } +} + MovementGeneratorType DistractMovementGenerator::GetMovementGeneratorType() const { return DISTRACT_MOTION_TYPE; @@ -131,13 +224,20 @@ MovementGeneratorType DistractMovementGenerator::GetMovementGeneratorType() cons //----------------------------------------------------// -MovementGeneratorType AssistanceDistractMovementGenerator::GetMovementGeneratorType() const +AssistanceDistractMovementGenerator::AssistanceDistractMovementGenerator(uint32 timer, float orientation) : DistractMovementGenerator(timer, orientation) { - return ASSISTANCE_DISTRACT_MOTION_TYPE; + Priority = MOTION_PRIORITY_NORMAL; } -void AssistanceDistractMovementGenerator::Finalize(Unit* owner) +void AssistanceDistractMovementGenerator::Finalize(Unit* owner, bool/* active*/, bool movementInform) { - owner->ClearUnitState(UNIT_STATE_DISTRACTED); - owner->ToCreature()->SetReactState(REACT_AGGRESSIVE); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) && owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->SetReactState(REACT_AGGRESSIVE); +} + +MovementGeneratorType AssistanceDistractMovementGenerator::GetMovementGeneratorType() const +{ + return ASSISTANCE_DISTRACT_MOTION_TYPE; } diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h index c9f45005316..d83e6723185 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -27,51 +27,57 @@ enum RotateDirection : uint8; class IdleMovementGenerator : public MovementGenerator { public: + explicit IdleMovementGenerator(); + void Initialize(Unit*) override; - void Finalize(Unit*) override { } void Reset(Unit*) override; bool Update(Unit*, uint32) override { return true; } + void Deactivate(Unit*) override; + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override; }; class RotateMovementGenerator : public MovementGenerator { public: - explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : _duration(time), _maxDuration(time), _direction(direction) { } + explicit RotateMovementGenerator(uint32 id, uint32 time, RotateDirection direction); void Initialize(Unit*) override; - void Finalize(Unit*) override; - void Reset(Unit* owner) override { Initialize(owner); } + void Reset(Unit*) override; bool Update(Unit*, uint32) override; + void Deactivate(Unit*) override; + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override; private: - uint32 _duration, _maxDuration; + uint32 _id, _duration, _maxDuration; RotateDirection _direction; }; class DistractMovementGenerator : public MovementGenerator { public: - explicit DistractMovementGenerator(uint32 timer) : _timer(timer) { } + explicit DistractMovementGenerator(uint32 timer, float orientation); void Initialize(Unit*) override; - void Finalize(Unit*) override; - void Reset(Unit* owner) override { Initialize(owner); } + void Reset(Unit*) override; bool Update(Unit*, uint32) override; + void Deactivate(Unit*) override; + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override; private: uint32 _timer; + float _orientation; }; class AssistanceDistractMovementGenerator : public DistractMovementGenerator { public: - explicit AssistanceDistractMovementGenerator(uint32 timer) : DistractMovementGenerator(timer) { } + explicit AssistanceDistractMovementGenerator(uint32 timer, float orientation); + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override; - void Finalize(Unit*) override; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/PathMovementBase.h b/src/server/game/Movement/MovementGenerators/PathMovementBase.h index d20f330ef5a..00c438ab406 100644 --- a/src/server/game/Movement/MovementGenerators/PathMovementBase.h +++ b/src/server/game/Movement/MovementGenerators/PathMovementBase.h @@ -23,15 +23,15 @@ template<class Entity, class BasePath> class PathMovementBase { -public: - PathMovementBase() : _path(), _currentNode(0) { } - virtual ~PathMovementBase() { }; + public: + PathMovementBase() : _path(), _currentNode(0) { } + virtual ~PathMovementBase() { }; - uint32 GetCurrentNode() const { return _currentNode; } + uint32 GetCurrentNode() const { return _currentNode; } -protected: - BasePath _path; - uint32 _currentNode; + protected: + BasePath _path; + uint32 _currentNode; }; #endif // PathMovementBase_h__ diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index a6a67ade8d1..07142515325 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -29,6 +29,15 @@ //----- Point Movement Generator template<class T> +PointMovementGenerator<T>::PointMovementGenerator(uint32 id, float x, float y, float z, bool generatePath, float speed, Optional<float> finalOrient) : _movementId(id), _x(x), _y(y), _z(z), _speed(speed), _generatePath(generatePath), _finalOrient(finalOrient) +{ + this->Mode = MOTION_MODE_DEFAULT; + this->Priority = MOTION_PRIORITY_NORMAL; + this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + this->BaseUnitState = UNIT_STATE_ROAMING; +} + +template<class T> MovementGeneratorType PointMovementGenerator<T>::GetMovementGeneratorType() const { return POINT_MOTION_TYPE; @@ -37,17 +46,18 @@ MovementGeneratorType PointMovementGenerator<T>::GetMovementGeneratorType() cons template<class T> void PointMovementGenerator<T>::DoInitialize(T* owner) { + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + if (_movementId == EVENT_CHARGE_PREPATH) { - owner->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); return; } - owner->AddUnitState(UNIT_STATE_ROAMING); - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); return; } @@ -70,25 +80,40 @@ void PointMovementGenerator<T>::DoInitialize(T* owner) } template<class T> +void PointMovementGenerator<T>::DoReset(T* owner) +{ + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + + owner->StopMoving(); + DoInitialize(owner); +} + +template<class T> bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/) { if (!owner) return false; if (_movementId == EVENT_CHARGE_PREPATH) - return !owner->movespline->Finalized(); + { + if (owner->movespline->Finalized()) + { + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + return false; + } + return true; + } if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); return true; } - if ((_interrupt && owner->movespline->Finalized()) || (_recalculateSpeed && !owner->movespline->Finalized())) + if ((MovementGenerator::HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED) && owner->movespline->Finalized()) || (MovementGenerator::HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized())) { - _recalculateSpeed = false; - _interrupt = false; + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED | MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); @@ -103,23 +128,31 @@ bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/) creature->SignalFormationMovement(Position(_x, _y, _z), _movementId); } - return !owner->movespline->Finalized(); + if (owner->movespline->Finalized()) + { + MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + return false; + } + return true; } template<class T> -void PointMovementGenerator<T>::DoFinalize(T* owner) +void PointMovementGenerator<T>::DoDeactivate(T* owner) { - owner->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - - if (owner->movespline->Finalized()) - MovementInform(owner); + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); } template<class T> -void PointMovementGenerator<T>::DoReset(T* owner) +void PointMovementGenerator<T>::DoFinalize(T* owner, bool active, bool movementInform) { - owner->StopMoving(); - DoInitialize(owner); + MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (active) + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + + if (movementInform && MovementGenerator::HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + MovementInform(owner); } template<class T> @@ -132,30 +165,40 @@ void PointMovementGenerator<Creature>::MovementInform(Creature* owner) owner->AI()->MovementInform(POINT_MOTION_TYPE, _movementId); } +template PointMovementGenerator<Player>::PointMovementGenerator(uint32, float, float, float, bool, float, Optional<float>); +template PointMovementGenerator<Creature>::PointMovementGenerator(uint32, float, float, float, bool, float, Optional<float>); template MovementGeneratorType PointMovementGenerator<Player>::GetMovementGeneratorType() const; template MovementGeneratorType PointMovementGenerator<Creature>::GetMovementGeneratorType() const; template void PointMovementGenerator<Player>::DoInitialize(Player*); template void PointMovementGenerator<Creature>::DoInitialize(Creature*); -template void PointMovementGenerator<Player>::DoFinalize(Player*); -template void PointMovementGenerator<Creature>::DoFinalize(Creature*); template void PointMovementGenerator<Player>::DoReset(Player*); template void PointMovementGenerator<Creature>::DoReset(Creature*); template bool PointMovementGenerator<Player>::DoUpdate(Player*, uint32); template bool PointMovementGenerator<Creature>::DoUpdate(Creature*, uint32); +template void PointMovementGenerator<Player>::DoDeactivate(Player*); +template void PointMovementGenerator<Creature>::DoDeactivate(Creature*); +template void PointMovementGenerator<Player>::DoFinalize(Player*, bool, bool); +template void PointMovementGenerator<Creature>::DoFinalize(Creature*, bool, bool); //---- AssistanceMovementGenerator -MovementGeneratorType AssistanceMovementGenerator::GetMovementGeneratorType() const +void AssistanceMovementGenerator::Finalize(Unit* owner, bool active, bool movementInform) { - return ASSISTANCE_MOTION_TYPE; + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (active) + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + + if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + { + Creature* ownerCreature = owner->ToCreature(); + ownerCreature->SetNoCallAssistance(false); + ownerCreature->CallAssistance(); + if (ownerCreature->IsAlive()) + ownerCreature->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)); + } } -void AssistanceMovementGenerator::Finalize(Unit* owner) +MovementGeneratorType AssistanceMovementGenerator::GetMovementGeneratorType() const { - owner->ClearUnitState(UNIT_STATE_ROAMING); - owner->StopMoving(); - owner->ToCreature()->SetNoCallAssistance(false); - owner->ToCreature()->CallAssistance(); - if (owner->IsAlive()) - owner->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)); + return ASSISTANCE_MOTION_TYPE; } diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index c9f7c18a70d..072f8663ff5 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -25,19 +25,22 @@ class Creature; template<class T> -class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator<T> > +class PointMovementGenerator : public MovementGeneratorMedium<T, PointMovementGenerator<T>> { public: - explicit PointMovementGenerator(uint32 id, float x, float y, float z, bool generatePath, float speed = 0.0f, Optional<float> finalOrient = {}) : _movementId(id), _x(x), _y(y), _z(z), _speed(speed), _generatePath(generatePath), _recalculateSpeed(false), _interrupt(false), _finalOrient(finalOrient) { } + explicit PointMovementGenerator(uint32 id, float x, float y, float z, bool generatePath, float speed = 0.0f, Optional<float> finalOrient = {}); MovementGeneratorType GetMovementGeneratorType() const override; void DoInitialize(T*); - void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); + void DoDeactivate(T*); + void DoFinalize(T*, bool, bool); - void UnitSpeedChanged() override { _recalculateSpeed = true; } + void UnitSpeedChanged() override { PointMovementGenerator<T>::AddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); } + + uint32 GetId() const { return _movementId; } private: void MovementInform(T*); @@ -46,8 +49,6 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG float _x, _y, _z; float _speed; bool _generatePath; - bool _recalculateSpeed; - bool _interrupt; //! if set then unit will turn to specified _orient in provided _pos Optional<float> _finalOrient; }; @@ -55,10 +56,10 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG class AssistanceMovementGenerator : public PointMovementGenerator<Creature> { public: - explicit AssistanceMovementGenerator(float x, float y, float z) : PointMovementGenerator<Creature>(0, x, y, z, true) { } + explicit AssistanceMovementGenerator(uint32 id, float x, float y, float z) : PointMovementGenerator<Creature>(id, x, y, z, true) { } + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override; - void Finalize(Unit*) override; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 106636fe26e..180b830bc7e 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -20,17 +20,21 @@ #include "Creature.h" #include "Map.h" #include "MovementDefines.h" -#include "MoveSplineInit.h" #include "MoveSpline.h" +#include "MoveSplineInit.h" #include "PathGenerator.h" #include "Random.h" template<class T> -RandomMovementGenerator<T>::~RandomMovementGenerator() +RandomMovementGenerator<T>::RandomMovementGenerator(float distance) : _timer(0), _reference(), _wanderDistance(distance) { + this->Mode = MOTION_MODE_DEFAULT; + this->Priority = MOTION_PRIORITY_NORMAL; + this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + this->BaseUnitState = UNIT_STATE_ROAMING; } -template RandomMovementGenerator<Creature>::~RandomMovementGenerator(); +template RandomMovementGenerator<Creature>::RandomMovementGenerator(float/* distance*/); template<class T> MovementGeneratorType RandomMovementGenerator<T>::GetMovementGeneratorType() const @@ -46,10 +50,12 @@ void RandomMovementGenerator<T>::DoInitialize(T*) { } template<> void RandomMovementGenerator<Creature>::DoInitialize(Creature* owner) { + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + if (!owner || !owner->IsAlive()) return; - owner->AddUnitState(UNIT_STATE_ROAMING); _reference = owner->GetPosition(); owner->StopMoving(); @@ -61,22 +67,13 @@ void RandomMovementGenerator<Creature>::DoInitialize(Creature* owner) } template<class T> -void RandomMovementGenerator<T>::DoFinalize(T*) { } - -template<> -void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner) -{ - owner->ClearUnitState(UNIT_STATE_ROAMING); - owner->StopMoving(); - owner->SetWalk(false); -} - -template<class T> void RandomMovementGenerator<T>::DoReset(T*) { } template<> void RandomMovementGenerator<Creature>::DoReset(Creature* owner) { + RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + DoInitialize(owner); } @@ -91,14 +88,12 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner) if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); _path = nullptr; return; } - owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); - Position position(_reference); float distance = frand(0.f, 1.f) * _wanderDistance; float angle = frand(0.f, 1.f) * float(M_PI) * 2.f; @@ -119,6 +114,8 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner) return; } + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); + Movement::MoveSplineInit init(owner); init.MovebyPath(_path->GetPath()); init.SetWalk(true); @@ -139,21 +136,51 @@ template<> bool RandomMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff) { if (!owner || !owner->IsAlive()) - return false; + return true; if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - _interrupt = true; + AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); _path = nullptr; return true; } else - _interrupt = false; + RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); _timer.Update(diff); - if (!_interrupt && _timer.Passed() && owner->movespline->Finalized()) + if ((HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized()) || (_timer.Passed() && owner->movespline->Finalized())) + { + RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); SetRandomLocation(owner); + } return true; } + +template<class T> +void RandomMovementGenerator<T>::DoDeactivate(T*) { } + +template<> +void RandomMovementGenerator<Creature>::DoDeactivate(Creature* owner) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); +} + +template<class T> +void RandomMovementGenerator<T>::DoFinalize(T*, bool, bool) { } + +template<> +void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool/* movementInform*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (active) + { + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + owner->StopMoving(); + + // TODO: Research if this modification is needed, which most likely isnt + owner->SetWalk(false); + } +} diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h index 9ef2af3aabc..a268692f658 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h @@ -26,19 +26,20 @@ class PathGenerator; template<class T> -class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator<T> > +class RandomMovementGenerator : public MovementGeneratorMedium<T, RandomMovementGenerator<T>> { public: - explicit RandomMovementGenerator(float distance = 0.0f) : _timer(0), _reference(), _wanderDistance(distance), _interrupt(false) { } - ~RandomMovementGenerator(); + explicit RandomMovementGenerator(float distance = 0.0f); MovementGeneratorType GetMovementGeneratorType() const override; - void UnitSpeedChanged() override { } //TODO void DoInitialize(T*); - void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); + void DoDeactivate(T*); + void DoFinalize(T*, bool, bool); + + void UnitSpeedChanged() override { RandomMovementGenerator<T>::AddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); } private: void SetRandomLocation(T*); @@ -47,7 +48,6 @@ class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovemen TimeTracker _timer; Position _reference; float _wanderDistance; - bool _interrupt; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp index 72862f2f5ce..b3e3aa0fc2b 100644 --- a/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp @@ -18,109 +18,143 @@ #include "SplineChainMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" +#include "Errors.h" #include "MotionMaster.h" #include "MovementDefines.h" -#include "MoveSplineInit.h" #include "MoveSpline.h" +#include "MoveSplineInit.h" #include "Log.h" +#include "Unit.h" + +SplineChainMovementGenerator::SplineChainMovementGenerator(uint32 id, std::vector<SplineChainLink> const& chain, bool walk) : _id(id), _chain(chain), _chainSize(chain.size()), _walk(walk), _nextIndex(0), _nextFirstWP(0), _msToNext(0) +{ + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_ROAMING; +} + +SplineChainMovementGenerator::SplineChainMovementGenerator(SplineChainResumeInfo const& info) : _id(info.PointID), _chain(*info.Chain), _chainSize(info.Chain->size()), _walk(info.IsWalkMode), _nextIndex(info.SplineIndex), _nextFirstWP(info.PointIndex), _msToNext(info.TimeToNext) +{ + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; -uint32 SplineChainMovementGenerator::SendPathSpline(Unit* me, Movement::PointsArray const& wp) const + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + if (info.SplineIndex >= info.Chain->size()) + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + BaseUnitState = UNIT_STATE_ROAMING; +} + +uint32 SplineChainMovementGenerator::SendPathSpline(Unit* owner, Movement::PointsArray const& path) const { - uint32 numWp = wp.size(); - ASSERT(numWp > 1 && "Every path must have source & destination"); - Movement::MoveSplineInit init(me); - if (numWp > 2) - init.MovebyPath(wp); + uint32 nodeCount = path.size(); + ASSERT(nodeCount > 1, "SplineChainMovementGenerator::SendPathSpline: Every path must have source & destination (size > 1)! (%s)", owner->GetGUID().ToString().c_str()); + + Movement::MoveSplineInit init(owner); + if (nodeCount > 2) + init.MovebyPath(path); else - init.MoveTo(wp[1], false, true); + init.MoveTo(path[1], false, true); init.SetWalk(_walk); return init.Launch(); } -void SplineChainMovementGenerator::SendSplineFor(Unit* me, uint32 index, uint32& toNext) +void SplineChainMovementGenerator::SendSplineFor(Unit* owner, uint32 index, uint32& duration) { - ASSERT(index < _chainSize); - TC_LOG_DEBUG("movement.splinechain", "%s: Sending spline for %u.", me->GetGUID().ToString().c_str(), index); + ASSERT(index < _chainSize, "SplineChainMovementGenerator::SendSplineFor: referenced index (%u) higher than path size (%u)!", index, _chainSize); + TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::SendSplineFor: sending spline on index: %u. (%s)", index, owner->GetGUID().ToString().c_str()); SplineChainLink const& thisLink = _chain[index]; - uint32 actualDuration = SendPathSpline(me, thisLink.Points); + uint32 actualDuration = SendPathSpline(owner, thisLink.Points); if (actualDuration != thisLink.ExpectedDuration) { - TC_LOG_DEBUG("movement.splinechain", "%s: Sent spline for %u, duration is %u ms. Expected was %u ms (delta %d ms). Adjusting.", me->GetGUID().ToString().c_str(), index, actualDuration, thisLink.ExpectedDuration, int32(actualDuration) - int32(thisLink.ExpectedDuration)); - toNext = uint32(double(actualDuration)/double(thisLink.ExpectedDuration) * toNext); + TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::SendSplineFor: sent spline on index: %u, duration: %u ms. Expected duration: %u ms (delta %d ms). Adjusting. (%s)", index, actualDuration, thisLink.ExpectedDuration, int32(actualDuration) - int32(thisLink.ExpectedDuration), owner->GetGUID().ToString().c_str()); + duration = uint32(double(actualDuration) / double(thisLink.ExpectedDuration) * duration); } else { - TC_LOG_DEBUG("movement.splinechain", "%s: Sent spline for %u, duration is %u ms.", me->GetGUID().ToString().c_str(), index, actualDuration); + TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::SendSplineFor: sent spline on index %u, duration: %u ms. (%s)", index, actualDuration, owner->GetGUID().ToString().c_str()); } } -void SplineChainMovementGenerator::Initialize(Unit* me) +void SplineChainMovementGenerator::Initialize(Unit* owner) { - if (_chainSize) + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + + if (!_chainSize) { - if (_nextFirstWP) // this is a resumed movegen that has to start with a partial spline - { - if (finished) - return; - SplineChainLink const& thisLink = _chain[_nextIndex]; - if (_nextFirstWP >= thisLink.Points.size()) - { - TC_LOG_ERROR("movement.splinechain", "%s: Attempted to resume spline chain from invalid resume state (%u, %u).", me->GetGUID().ToString().c_str(), _nextIndex, _nextFirstWP); - _nextFirstWP = thisLink.Points.size()-1; - } - Movement::PointsArray partial(thisLink.Points.begin() + (_nextFirstWP-1), thisLink.Points.end()); - SendPathSpline(me, partial); - TC_LOG_DEBUG("movement.splinechain", "%s: Resumed spline chain generator from resume state.", me->GetGUID().ToString().c_str()); - ++_nextIndex; - if (_nextIndex >= _chainSize) - _msToNext = 0; - else if (!_msToNext) - _msToNext = 1; - _nextFirstWP = 0; - } - else + TC_LOG_ERROR("movement", "SplineChainMovementGenerator::Initialize: couldn't initialize generator, referenced spline is empty! (%s)", owner->GetGUID().ToString().c_str()); + return; + } + + if (_nextFirstWP) // this is a resumed movegen that has to start with a partial spline + { + if (HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED)) + return; + + SplineChainLink const& thisLink = _chain[_nextIndex]; + if (_nextFirstWP >= thisLink.Points.size()) { - _msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u); - SendSplineFor(me, _nextIndex, _msToNext); - ++_nextIndex; - if (_nextIndex >= _chainSize) - _msToNext = 0; + TC_LOG_ERROR("movement.splinechain", "SplineChainMovementGenerator::Initialize: attempted to resume spline chain from invalid resume state, _nextFirstWP >= path size (_nextIndex: %u, _nextFirstWP: %u). (%s)", _nextIndex, _nextFirstWP, owner->GetGUID().ToString().c_str()); + _nextFirstWP = thisLink.Points.size() - 1; } + + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); + Movement::PointsArray partial(thisLink.Points.begin() + (_nextFirstWP-1), thisLink.Points.end()); + SendPathSpline(owner, partial); + + TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::Initialize: resumed spline chain generator from resume state. (%s)", owner->GetGUID().ToString().c_str()); + + ++_nextIndex; + if (_nextIndex >= _chainSize) + _msToNext = 0; + else if (!_msToNext) + _msToNext = 1; + _nextFirstWP = 0; } else { - TC_LOG_ERROR("movement", "SplineChainMovementGenerator::Initialize - empty spline chain passed for %s.", me->GetGUID().ToString().c_str()); + _msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u); + SendSplineFor(owner, _nextIndex, _msToNext); + + ++_nextIndex; + if (_nextIndex >= _chainSize) + _msToNext = 0; } } -void SplineChainMovementGenerator::Finalize(Unit* me) +void SplineChainMovementGenerator::Reset(Unit* owner) { - if (!finished) - return; - Creature* cMe = me->ToCreature(); - if (cMe && cMe->IsAIEnabled) - cMe->AI()->MovementInform(SPLINE_CHAIN_MOTION_TYPE, _id); + RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + + owner->StopMoving(); + Initialize(owner); } -bool SplineChainMovementGenerator::Update(Unit* me, uint32 diff) +bool SplineChainMovementGenerator::Update(Unit* owner, uint32 diff) { - if (finished) + if (!owner || HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED)) return false; // _msToNext being zero here means we're on the final spline if (!_msToNext) { - finished = me->movespline->Finalized(); - return !finished; + if (owner->movespline->Finalized()) + { + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + return false; + } + return true; } if (_msToNext <= diff) { // Send next spline - TC_LOG_DEBUG("movement.splinechain", "%s: Should send spline %u (%u ms late).", me->GetGUID().ToString().c_str(), _nextIndex, diff - _msToNext); + TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::Update: sending spline on index %u (%u ms late). (%s)", _nextIndex, diff - _msToNext, owner->GetGUID().ToString().c_str()); _msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u); - SendSplineFor(me, _nextIndex, _msToNext); + SendSplineFor(owner, _nextIndex, _msToNext); ++_nextIndex; if (_nextIndex >= _chainSize) { @@ -131,37 +165,69 @@ bool SplineChainMovementGenerator::Update(Unit* me, uint32 diff) } else _msToNext -= diff; + return true; } +void SplineChainMovementGenerator::Deactivate(Unit* owner) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); +} + +void SplineChainMovementGenerator::Finalize(Unit* owner, bool active, bool movementInform) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + + if (active) + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + + if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + { + Creature* ownerCreature = owner->ToCreature(); + if (ownerCreature && ownerCreature->IsAIEnabled) + ownerCreature->AI()->MovementInform(SPLINE_CHAIN_MOTION_TYPE, _id); + } +} + MovementGeneratorType SplineChainMovementGenerator::GetMovementGeneratorType() const { return SPLINE_CHAIN_MOTION_TYPE; } -SplineChainResumeInfo SplineChainMovementGenerator::GetResumeInfo(Unit const* me) const +SplineChainResumeInfo SplineChainMovementGenerator::GetResumeInfo(Unit const* owner) const { if (!_nextIndex) return SplineChainResumeInfo(_id, &_chain, _walk, 0, 0, _msToNext); - if (me->movespline->Finalized()) + + if (owner->movespline->Finalized()) { if (_nextIndex < _chainSize) return SplineChainResumeInfo(_id, &_chain, _walk, _nextIndex, 0, 1u); else return SplineChainResumeInfo(); } - return SplineChainResumeInfo(_id, &_chain, _walk, uint8(_nextIndex - 1), uint8(me->movespline->_currentSplineIdx()), _msToNext); + + return SplineChainResumeInfo(_id, &_chain, _walk, uint8(_nextIndex - 1), uint8(owner->movespline->_currentSplineIdx()), _msToNext); } -/* static */ void SplineChainMovementGenerator::GetResumeInfo(Unit const* me, SplineChainResumeInfo& info) +/* static */ void SplineChainMovementGenerator::GetResumeInfo(Unit const* owner, uint32 id, SplineChainResumeInfo& info) { - if (MovementGenerator const* activeGenerator = me->GetMotionMaster()->GetMotionSlot(MOTION_SLOT_ACTIVE)) + std::function<bool(MovementGenerator const*)> criteria = [id](MovementGenerator const* movement) -> bool { - if (activeGenerator->GetMovementGeneratorType() == SPLINE_CHAIN_MOTION_TYPE) + if (movement->GetMovementGeneratorType() == SPLINE_CHAIN_MOTION_TYPE) { - info = reinterpret_cast<SplineChainMovementGenerator const*>(activeGenerator)->GetResumeInfo(me); - return; + SplineChainMovementGenerator const* splineChainMovement = dynamic_cast<SplineChainMovementGenerator const*>(movement); + return splineChainMovement && splineChainMovement->GetId() == id; } + return false; + }; + + if (MovementGenerator const* activeGenerator = owner->GetMotionMaster()->GetMovementGenerator(criteria)) + { + if (activeGenerator->GetMovementGeneratorType() == SPLINE_CHAIN_MOTION_TYPE) + info = reinterpret_cast<SplineChainMovementGenerator const*>(activeGenerator)->GetResumeInfo(owner); } - info.Chain = nullptr; + else + info.Chain = nullptr; } diff --git a/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h index 583fe3a9fc7..8d94dcf503c 100644 --- a/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h @@ -27,29 +27,31 @@ class Unit; class TC_GAME_API SplineChainMovementGenerator : public MovementGenerator { public: - explicit SplineChainMovementGenerator(uint32 id, std::vector<SplineChainLink> const& chain, bool walk = false) : _id(id), _chain(chain), _chainSize(chain.size()), _walk(walk), finished(false), _nextIndex(0), _nextFirstWP(0), _msToNext(0) { } - explicit SplineChainMovementGenerator(SplineChainResumeInfo const& info) : _id(info.PointID), _chain(*info.Chain), _chainSize(info.Chain->size()), _walk(info.IsWalkMode), finished(info.SplineIndex >= info.Chain->size()), _nextIndex(info.SplineIndex), _nextFirstWP(info.PointIndex), _msToNext(info.TimeToNext) { } - - void Initialize(Unit* me) override; - void Finalize(Unit* me) override; - void Reset(Unit* /*me*/) override { }; - bool Update(Unit* me, uint32 diff) override; + explicit SplineChainMovementGenerator(uint32 id, std::vector<SplineChainLink> const& chain, bool walk = false); + explicit SplineChainMovementGenerator(SplineChainResumeInfo const& info); + + void Initialize(Unit*) override; + void Reset(Unit*) override; + bool Update(Unit*, uint32) override; + void Deactivate(Unit*) override; + void Finalize(Unit*, bool, bool) override; MovementGeneratorType GetMovementGeneratorType() const override; // Builds info that can later be used to resume this spline chain movement at the current position - static void GetResumeInfo(Unit const* me, SplineChainResumeInfo& info); + static void GetResumeInfo(Unit const* owner, uint32 id, SplineChainResumeInfo& info); // Leaving the object method public for people that know what they're doing to use // But really, 99% of the time you should be using the static one instead - SplineChainResumeInfo GetResumeInfo(Unit const* me) const; + SplineChainResumeInfo GetResumeInfo(Unit const* owner) const; + uint32 GetId() const { return _id; } private: - void SendSplineFor(Unit* me, uint32 index, uint32& toNext); - uint32 SendPathSpline(Unit* me, Movement::PointsArray const& wp) const; + void SendSplineFor(Unit* owner, uint32 index, uint32& duration); + uint32 SendPathSpline(Unit* owner, Movement::PointsArray const& path) const; + uint32 const _id; std::vector<SplineChainLink> const& _chain; uint8 const _chainSize; bool const _walk; - bool finished; uint8 _nextIndex; uint8 _nextFirstWP; // only used for resuming uint32 _msToNext; diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index b282aa0b880..b62c8678658 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -19,6 +19,7 @@ #include "WaypointMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" +#include "Errors.h" #include "Log.h" #include "Map.h" #include "MovementDefines.h" @@ -28,15 +29,22 @@ #include "Transport.h" #include "WaypointManager.h" -WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bool repeating) : _nextMoveTime(0), _recalculateSpeed(false), _isArrivalDone(false), _pathId(pathId), - _repeating(repeating), _loadedFromDB(true), _stalled(false), _done(false) +WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bool repeating) : _nextMoveTime(0), _pathId(pathId), _repeating(repeating), _loadedFromDB(true) { + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_ROAMING; } -WaypointMovementGenerator<Creature>::WaypointMovementGenerator(WaypointPath& path, bool repeating) : _nextMoveTime(0), _recalculateSpeed(false), _isArrivalDone(false), _pathId(0), - _repeating(repeating), _loadedFromDB(false), _stalled(false), _done(false) +WaypointMovementGenerator<Creature>::WaypointMovementGenerator(WaypointPath& path, bool repeating) : _nextMoveTime(0), _pathId(0), _repeating(repeating), _loadedFromDB(false) { _path = &path; + + Mode = MOTION_MODE_DEFAULT; + Priority = MOTION_PRIORITY_NORMAL; + Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + BaseUnitState = UNIT_STATE_ROAMING; } MovementGeneratorType WaypointMovementGenerator<Creature>::GetMovementGeneratorType() const @@ -44,51 +52,190 @@ MovementGeneratorType WaypointMovementGenerator<Creature>::GetMovementGeneratorT return WAYPOINT_MOTION_TYPE; } -void WaypointMovementGenerator<Creature>::DoInitialize(Creature* creature) +void WaypointMovementGenerator<Creature>::Pause(uint32 timer/* = 0*/) +{ + if (timer) + { + AddFlag(MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); + _nextMoveTime.Reset(timer); + RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED); + } + else + { + AddFlag(MOVEMENTGENERATOR_FLAG_PAUSED); + _nextMoveTime.Reset(1); // Needed so that Update does not behave as if node was reached + RemoveFlag(MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); + } +} + +void WaypointMovementGenerator<Creature>::Resume(uint32 overrideTimer/* = 0*/) +{ + if (overrideTimer) + _nextMoveTime.Reset(overrideTimer); + + if (_nextMoveTime.Passed()) + _nextMoveTime.Reset(1); // Needed so that Update does not behave as if node was reached + + RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED); +} + +bool WaypointMovementGenerator<Creature>::GetResetPosition(Unit* /*owner*/, float& x, float& y, float& z) { - _done = false; + // prevent a crash at empty waypoint path. + if (!_path || _path->nodes.empty()) + return false; + + ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::GetResetPosition: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id); + WaypointNode const &waypoint = _path->nodes.at(_currentNode); + + x = waypoint.x; + y = waypoint.y; + z = waypoint.z; + return true; +} + +void WaypointMovementGenerator<Creature>::DoInitialize(Creature* owner) +{ + RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING); if (_loadedFromDB) { if (!_pathId) - _pathId = creature->GetWaypointPath(); + _pathId = owner->GetWaypointPath(); _path = sWaypointMgr->GetPath(_pathId); } if (!_path) { - // No path id found for entry - TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::DoInitialize: creature %s (Entry: %u GUID: %u DB GUID: %u) doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUID().GetCounter(), creature->GetSpawnId(), _pathId); + TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::DoInitialize: couldn't load path for creature (%s) (_pathId: %u)", owner->GetGUID().ToString().c_str(), _pathId); return; } + owner->StopMoving(); + _nextMoveTime.Reset(1000); // inform AI - if (creature->IsAIEnabled) - creature->AI()->WaypointPathStarted(_path->id); + if (owner->IsAIEnabled) + owner->AI()->WaypointPathStarted(_path->id); } -void WaypointMovementGenerator<Creature>::DoFinalize(Creature* creature) +void WaypointMovementGenerator<Creature>::DoReset(Creature* owner) { - creature->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - creature->SetWalk(false); + RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + + owner->StopMoving(); + + if (!HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED) && _nextMoveTime.Passed()) + _nextMoveTime.Reset(1); // Needed so that Update does not behave as if node was reached } -void WaypointMovementGenerator<Creature>::DoReset(Creature* creature) +bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff) { - if (!_done && _nextMoveTime.Passed() && CanMove(creature)) - StartMove(creature); - else if (_done) + if (!owner || !owner->IsAlive()) + return true; + + if (HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED | MOVEMENTGENERATOR_FLAG_PAUSED) || !_path || _path->nodes.empty()) + return true; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) + { + AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); + owner->StopMoving(); + return true; + } + + if (HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED)) + { + /* + * relaunch only if + * - has a tiner? -> was it interrupted while not waiting aka moving? need to check both: + * -> has a timer - is it because its waiting to start next node? + * -> has a timer - is it because something set it while moving (like timed pause)? + * + * - doesnt have a timer? -> is movement valid? + * + * TODO: ((_nextMoveTime.Passed() && VALID_MOVEMENT) || (!_nextMoveTime.Passed() && !HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))) + */ + if (HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED) && (_nextMoveTime.Passed() || !HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))) + { + StartMove(owner, true); + return true; + } + + RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); + } + + // if it's moving + if (!owner->movespline->Finalized()) { - // mimic IdleMovementGenerator - if (!creature->IsStopped()) - creature->StopMoving(); + // set home position at place (every MotionMaster::UpdateMotion) + if (!owner->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) || owner->GetTransGUID().IsEmpty()) + owner->SetHomePosition(owner->GetPosition()); + + // relaunch movement if its speed has changed + if (HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING)) + StartMove(owner, true); } + else if (!_nextMoveTime.Passed()) // it's not moving, is there a timer? + { + if (UpdateTimer(diff)) + { + if (!HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) // initial movement call + { + StartMove(owner); + return true; + } + else if (!HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) // timer set before node was reached, resume now + { + StartMove(owner, true); + return true; + } + } + else + return true; // keep waiting + } + else // not moving, no timer + { + if (HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED) && !HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + { + OnArrived(owner); // hooks and wait timer reset (if necessary) + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); // signals to future StartMove that it reached a node + } + + if (_nextMoveTime.Passed()) // OnArrived might have set a timer + StartMove(owner); // check path status, get next point and move if necessary & can + } + + return true; } -void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature) +void WaypointMovementGenerator<Creature>::DoDeactivate(Creature* owner) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); +} + +void WaypointMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool/* movementInform*/) +{ + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + if (active) + { + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + + // TODO: Research if this modification is needed, which most likely isnt + owner->SetWalk(false); + } +} + +void WaypointMovementGenerator<Creature>::MovementInform(Creature* owner) +{ + if (owner->AI()) + owner->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode); +} + +void WaypointMovementGenerator<Creature>::OnArrived(Creature* owner) { if (!_path || _path->nodes.empty()) return; @@ -97,103 +244,105 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature) WaypointNode const &waypoint = _path->nodes.at(_currentNode); if (waypoint.delay) { - creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); _nextMoveTime.Reset(waypoint.delay); } if (waypoint.eventId && urand(0, 99) < waypoint.eventChance) { - TC_LOG_DEBUG("maps.script", "Creature movement start script %u at point %u for %s.", waypoint.eventId, _currentNode, creature->GetGUID().ToString().c_str()); - creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); - creature->GetMap()->ScriptsStart(sWaypointScripts, waypoint.eventId, creature, nullptr); + TC_LOG_DEBUG("maps.script", "Creature movement start script %u at point %u for %s.", waypoint.eventId, _currentNode, owner->GetGUID().ToString().c_str()); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + owner->GetMap()->ScriptsStart(sWaypointScripts, waypoint.eventId, owner, nullptr); } // inform AI - if (creature->IsAIEnabled) + if (owner->IsAIEnabled) { - creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode); - creature->AI()->WaypointReached(waypoint.id, _path->id); + owner->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode); + owner->AI()->WaypointReached(waypoint.id, _path->id); } - creature->UpdateCurrentWaypointInfo(waypoint.id, _path->id); + owner->UpdateCurrentWaypointInfo(waypoint.id, _path->id); } -void WaypointMovementGenerator<Creature>::StartMove(Creature* creature, bool relaunch/* = false*/) +void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaunch/* = false*/) { // sanity checks - if (!creature || !creature->IsAlive() || _done || !_path || _path->nodes.empty() || (relaunch && _isArrivalDone)) + if (!owner || !owner->IsAlive() || HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED) || !_path || _path->nodes.empty() || (relaunch && (HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) || !HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)))) return; - if (!relaunch) // on relaunch, can avoid this since its only called on valid movement + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || (owner->IsFormationLeader() && !owner->IsFormationLeaderMoveAllowed())) // if cannot move OR cannot move because of formation { - if (!CanMove(creature) || (creature->IsFormationLeader() && !creature->IsFormationLeaderMoveAllowed())) // if cannot move OR cannot move because of formation - { - _nextMoveTime.Reset(1000); // delay 1s - return; - } + _nextMoveTime.Reset(1000); // delay 1s + return; } - bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && !creature->GetTransGUID().IsEmpty(); + bool const transportPath = owner->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && !owner->GetTransGUID().IsEmpty(); - if (_isArrivalDone) + if (HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) && HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) { - ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id); - WaypointNode const &waypoint = _path->nodes.at(_currentNode); + if (ComputeNextNode()) + { + ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id); - if ((_currentNode == _path->nodes.size() - 1) && !_repeating) // If that's our last waypoint + // inform AI + if (owner->IsAIEnabled) + owner->AI()->WaypointStarted(_path->nodes[_currentNode].id, _path->id); + } + else { + WaypointNode const &waypoint = _path->nodes[_currentNode]; float x = waypoint.x; float y = waypoint.y; float z = waypoint.z; - float o = creature->GetOrientation(); + float o = owner->GetOrientation(); if (!transportPath) - creature->SetHomePosition(x, y, z, o); + owner->SetHomePosition(x, y, z, o); else { - if (Transport* trans = creature->GetTransport()) + if (Transport* trans = owner->GetTransport()) { o -= trans->GetOrientation(); - creature->SetTransportHomePosition(x, y, z, o); + owner->SetTransportHomePosition(x, y, z, o); trans->CalculatePassengerPosition(x, y, z, &o); - creature->SetHomePosition(x, y, z, o); + owner->SetHomePosition(x, y, z, o); } - else - transportPath = false; // else if (vehicle) - this should never happen, vehicle offsets are const } - _done = true; - creature->UpdateCurrentWaypointInfo(0, 0); + AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + owner->UpdateCurrentWaypointInfo(0, 0); // inform AI - if (creature->IsAIEnabled) - creature->AI()->WaypointPathEnded(waypoint.id, _path->id); + if (owner->IsAIEnabled) + owner->AI()->WaypointPathEnded(waypoint.id, _path->id); return; } - - _currentNode = (_currentNode + 1) % _path->nodes.size(); + } + else if (!HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) + { + AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); // inform AI - if (creature->IsAIEnabled) - creature->AI()->WaypointStarted(waypoint.id, _path->id); + if (owner->IsAIEnabled) + owner->AI()->WaypointStarted(_path->nodes[_currentNode].id, _path->id); } ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id); WaypointNode const &waypoint = _path->nodes[_currentNode]; Position formationDest(waypoint.x, waypoint.y, waypoint.z, (waypoint.orientation && waypoint.delay) ? waypoint.orientation : 0.0f); - _isArrivalDone = false; - _recalculateSpeed = false; + RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_INFORM_ENABLED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); - creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); - Movement::MoveSplineInit init(creature); + Movement::MoveSplineInit init(owner); //! If creature is on transport, we assume waypoints set in DB are already transport offsets if (transportPath) { init.DisableTransportPathTransformations(); - if (TransportBase* trans = creature->GetDirectTransport()) + if (TransportBase* trans = owner->GetDirectTransport()) { float orientation = formationDest.GetOrientation(); trans->CalculatePassengerPosition(formationDest.m_positionX, formationDest.m_positionY, formationDest.m_positionZ, &orientation); @@ -230,95 +379,14 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* creature, bool rel init.Launch(); // inform formation - creature->SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation && waypoint.delay) ? true : false); -} - -bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 diff) -{ - if (!creature || !creature->IsAlive()) - return true; - - if (_done || !_path || _path->nodes.empty()) - return true; - - if (_stalled || creature->HasUnitState(UNIT_STATE_NOT_MOVE) || creature->IsMovementPreventedByCasting()) - { - creature->StopMoving(); - return true; - } - - // if it's moving - if (!creature->movespline->Finalized()) - { - // set home position at place (every MotionMaster::UpdateMotion) - if (!creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) || creature->GetTransGUID().IsEmpty()) - creature->SetHomePosition(creature->GetPosition()); - - // relaunch movement if its speed has changed - if (_recalculateSpeed) - StartMove(creature, true); - } - else - { - // check if there is a wait time for the next movement - if (!_nextMoveTime.Passed()) - { - // update timer since it's not moving - _nextMoveTime.Update(diff); - if (_nextMoveTime.Passed()) - { - _nextMoveTime.Reset(0); - StartMove(creature); // check path status, get next point and move if necessary & can - } - } - else // if it's not moving and there is no timer, assume node is reached - { - OnArrived(creature); // hooks and wait timer reset (if necessary) - _isArrivalDone = true; // signals to future StartMove that it reached a node - - if (_nextMoveTime.Passed()) - StartMove(creature); // check path status, get next point and move if necessary & can - } - } - - return true; + owner->SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation && waypoint.delay) ? true : false); } -void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature) +bool WaypointMovementGenerator<Creature>::ComputeNextNode() { - if (creature->AI()) - creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode); -} - -bool WaypointMovementGenerator<Creature>::GetResetPos(Creature*, float& x, float& y, float& z) -{ - // prevent a crash at empty waypoint path. - if (!_path || _path->nodes.empty()) + if ((_currentNode == _path->nodes.size() - 1) && !_repeating) return false; - ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::GetResetPos: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id); - WaypointNode const &waypoint = _path->nodes.at(_currentNode); - - x = waypoint.x; - y = waypoint.y; - z = waypoint.z; + _currentNode = (_currentNode + 1) % _path->nodes.size(); return true; } - -void WaypointMovementGenerator<Creature>::Pause(uint32 timer/* = 0*/) -{ - _stalled = timer ? false : true; - _nextMoveTime.Reset(timer ? timer : 1); -} - -void WaypointMovementGenerator<Creature>::Resume(uint32 overrideTimer/* = 0*/) -{ - _stalled = false; - if (overrideTimer) - _nextMoveTime.Reset(overrideTimer); -} - -/*static*/ bool WaypointMovementGenerator<Creature>::CanMove(Creature* creature) -{ - return !creature->HasUnitState(UNIT_STATE_NOT_MOVE) && !creature->IsMovementPreventedByCasting(); -} diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index 34aee0578f2..31269e7ec97 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -19,18 +19,12 @@ #ifndef TRINITY_WAYPOINTMOVEMENTGENERATOR_H #define TRINITY_WAYPOINTMOVEMENTGENERATOR_H -/** - * @page PathMovementGenerator is used to generate movements - * of waypoints and flight paths. Each serves the purpose - * of generate activities so that it generates updated - * packets for the players. - */ - #include "MovementGenerator.h" #include "PathMovementBase.h" #include "Timer.h" class Creature; +class Unit; struct WaypointPath; template<class T> @@ -42,36 +36,42 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creat public: explicit WaypointMovementGenerator(uint32 pathId = 0, bool repeating = true); explicit WaypointMovementGenerator(WaypointPath& path, bool repeating = true); - ~WaypointMovementGenerator() { _path = nullptr; } - void DoInitialize(Creature*); - void DoFinalize(Creature*); - void DoReset(Creature*); - bool DoUpdate(Creature*, uint32 diff); - MovementGeneratorType GetMovementGeneratorType() const override; - void UnitSpeedChanged() override { _recalculateSpeed = true; } + + void UnitSpeedChanged() override { AddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); } void Pause(uint32 timer = 0) override; void Resume(uint32 overrideTimer = 0) override; + bool GetResetPosition(Unit*, float& x, float& y, float& z) override; - void MovementInform(Creature*); - - bool GetResetPos(Creature*, float& x, float& y, float& z); + void DoInitialize(Creature*); + void DoReset(Creature*); + bool DoUpdate(Creature*, uint32); + void DoDeactivate(Creature*); + void DoFinalize(Creature*, bool, bool); private: + void MovementInform(Creature*); void OnArrived(Creature*); void StartMove(Creature*, bool relaunch = false); + bool ComputeNextNode(); + bool UpdateTimer(uint32 diff) + { + _nextMoveTime.Update(diff); + if (_nextMoveTime.Passed()) + { + _nextMoveTime.Reset(0); + return true; + } + return false; + } static bool CanMove(Creature*); TimeTrackerSmall _nextMoveTime; - bool _recalculateSpeed; - bool _isArrivalDone; uint32 _pathId; bool _repeating; bool _loadedFromDB; - bool _stalled; - bool _done; }; #endif diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index d6dc7a1c2bf..4f27edc6334 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2629,8 +2629,10 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode } if (target->SetCanFly(apply)) + { if (!apply && !target->IsLevitating()) target->GetMotionMaster()->MoveFall(); + } } void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -2863,8 +2865,6 @@ void AuraEffect::HandleModPossess(AuraApplication const* aurApp, uint8 mode, boo void AuraEffect::HandleModPossessPet(AuraApplication const* aurApp, uint8 mode, bool apply) const { - // Used by spell "Eyes of the Beast" - if (!(mode & AURA_EFFECT_HANDLE_REAL)) return; @@ -2872,7 +2872,7 @@ void AuraEffect::HandleModPossessPet(AuraApplication const* aurApp, uint8 mode, if (!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - //seems it may happen that when removing it is no longer owner's pet + // seems it may happen that when removing it is no longer owner's pet //if (caster->ToPlayer()->GetPet() != target) // return; @@ -2881,15 +2881,11 @@ void AuraEffect::HandleModPossessPet(AuraApplication const* aurApp, uint8 mode, return; Pet* pet = target->ToPet(); - if (apply) { if (caster->ToPlayer()->GetPet() != pet) return; - // Must clear current motion or pet leashes back to owner after a few yards - // when under spell 'Eyes of the Beast' - pet->GetMotionMaster()->Clear(); pet->SetCharmedBy(caster, CHARM_TYPE_POSSESS, aurApp); } else @@ -2903,13 +2899,9 @@ void AuraEffect::HandleModPossessPet(AuraApplication const* aurApp, uint8 mode, // Reinitialize the pet bar or it will appear greyed out caster->ToPlayer()->PetSpellInitialize(); - // Follow owner only if not fighting or owner didn't click "stay" at new location - // This may be confusing because pet bar shows "stay" when under the spell but it retains - // the "follow" flag. Player MUST click "stay" while under the spell. + // TODO: remove this if (!pet->GetVictim() && !pet->GetCharmInfo()->HasCommandState(COMMAND_STAY)) - { pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, pet->GetFollowAngle()); - } } } } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 24e33258d58..cfa211c579d 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2529,11 +2529,7 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/) if (unitTarget->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING)) return; - if (unitTarget->GetTypeId() == TYPEID_UNIT) - unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS); - - unitTarget->StopMoving(); - unitTarget->SetFacingTo(unitTarget->GetAbsoluteAngle(destTarget)); + unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS, unitTarget->GetAbsoluteAngle(destTarget)); } void Spell::EffectPickPocket(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index a9771331b8c..a3d4c6f13c9 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -27,7 +27,6 @@ EndScriptData */ #include "DatabaseEnv.h" #include "Language.h" #include "MapManager.h" -#include "MotionMaster.h" #include "ObjectMgr.h" #include "Player.h" #include "RBAC.h" @@ -147,13 +146,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case player->TeleportTo(mapId, x, y, z, o); return true; @@ -192,13 +187,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, player->GetOrientation()); return true; @@ -234,13 +225,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case Map const* map = sMapMgr->CreateBaseMap(mapId); float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); @@ -284,13 +271,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case player->TeleportTo(goData->spawnPoint); return true; @@ -329,13 +312,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case player->TeleportTo(node->map_id, node->x, node->y, node->z, player->GetOrientation()); return true; @@ -374,13 +353,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case player->TeleportTo(at->mapid, at->x, at->y, at->z, player->GetOrientation()); return true; @@ -445,13 +420,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); @@ -506,13 +477,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case player->TeleportTo(mapId, x, y, z, ort); return true; @@ -539,13 +506,12 @@ public: } Player* player = handler->GetSession()->GetPlayer(); + + // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case ticket->TeleportTo(player); return true; @@ -583,13 +549,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case player->TeleportTo(player->GetMapId(), x, y, z, o); return true; diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index 75f3e222497..b6ed2a60a7b 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -24,7 +24,6 @@ #include "Language.h" #include "LFG.h" #include "Map.h" -#include "MotionMaster.h" #include "ObjectAccessor.h" #include "Player.h" #include "RBAC.h" @@ -142,13 +141,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case // before GM float x, y, z; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 5565c89e630..36a7a00c2da 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -20,11 +20,9 @@ #include "ArenaTeamMgr.h" #include "CellImpl.h" #include "CharacterCache.h" -#include "ChaseMovementGenerator.h" #include "Chat.h" #include "DatabaseEnv.h" #include "DisableMgr.h" -#include "FollowMovementGenerator.h" #include "GridNotifiers.h" #include "Group.h" #include "GroupMgr.h" @@ -37,7 +35,6 @@ #include "MMapFactory.h" #include "MotionMaster.h" #include "MovementDefines.h" -#include "MovementGenerator.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Opcodes.h" @@ -449,13 +446,9 @@ public: // stop flight if need if (_player->IsInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + _player->FinishTaxiFlight(); else - _player->SaveRecallPosition(); + _player->SaveRecallPosition(); // save only in non-flight case // to point to see at target with same orientation float x, y, z; @@ -483,13 +476,9 @@ public: // stop flight if need if (_player->IsInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + _player->FinishTaxiFlight(); else - _player->SaveRecallPosition(); + _player->SaveRecallPosition(); // save only in non-flight case _player->TeleportTo(map, x, y, z, _player->GetOrientation()); } @@ -579,14 +568,10 @@ public: ChatHandler(target->GetSession()).PSendSysMessage(LANG_SUMMONED_BY, handler->playerLink(_player->GetName()).c_str()); // stop flight if need - if (target->IsInFlight()) - { - target->GetMotionMaster()->MovementExpired(); - target->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + if (_player->IsInFlight()) + _player->FinishTaxiFlight(); else - target->SaveRecallPosition(); + _player->SaveRecallPosition(); // save only in non-flight case // before GM float x, y, z; @@ -885,12 +870,7 @@ public: return false; } - // stop flight if need - if (target->IsInFlight()) - { - target->GetMotionMaster()->MovementExpired(); - target->CleanupAfterTaxiFlight(); - } + target->FinishTaxiFlight(); target->Recall(); return true; @@ -2138,20 +2118,19 @@ public: handler->PSendSysMessage(LANG_MOVEGENS_LIST, (unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), unit->GetGUID().GetCounter()); - MotionMaster* motionMaster = unit->GetMotionMaster(); + if (unit->GetMotionMaster()->Empty()) + { + handler->SendSysMessage("Empty"); + return true; + } + float x, y, z; - motionMaster->GetDestination(x, y, z); + unit->GetMotionMaster()->GetDestination(x, y, z); - for (uint8 itr = 0; itr < MAX_MOTION_SLOT; ++itr) + std::vector<MovementGeneratorInformation> list = unit->GetMotionMaster()->GetMovementGeneratorsInformation(); + for (MovementGeneratorInformation info : list) { - MovementGenerator* movementGenerator = motionMaster->GetMotionSlot(MovementSlot(itr)); - if (!movementGenerator) - { - handler->SendSysMessage("Empty"); - continue; - } - - switch (movementGenerator->GetMovementGeneratorType()) + switch (info.Type) { case IDLE_MOTION_TYPE: handler->SendSysMessage(LANG_MOVEGENS_IDLE); @@ -2166,45 +2145,33 @@ public: handler->SendSysMessage(LANG_MOVEGENS_CONFUSED); break; case CHASE_MOTION_TYPE: - { - Unit* target = static_cast<ChaseMovementGenerator const*>(movementGenerator)->GetTarget(); - - if (!target) + if (info.TargetGUID.IsEmpty()) handler->SendSysMessage(LANG_MOVEGENS_CHASE_NULL); - else if (target->GetTypeId() == TYPEID_PLAYER) - handler->PSendSysMessage(LANG_MOVEGENS_CHASE_PLAYER, target->GetName().c_str(), target->GetGUID().GetCounter()); + else if (info.TargetGUID.IsPlayer()) + handler->PSendSysMessage(LANG_MOVEGENS_CHASE_PLAYER, info.TargetName.c_str(), info.TargetGUID.GetCounter()); else - handler->PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, target->GetName().c_str(), target->GetGUID().GetCounter()); + handler->PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, info.TargetName.c_str(), info.TargetGUID.GetCounter()); break; - } case FOLLOW_MOTION_TYPE: - { - Unit* target = static_cast<FollowMovementGenerator const*>(movementGenerator)->GetTarget(); - - if (!target) + if (info.TargetGUID.IsEmpty()) handler->SendSysMessage(LANG_MOVEGENS_FOLLOW_NULL); - else if (target->GetTypeId() == TYPEID_PLAYER) - handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_PLAYER, target->GetName().c_str(), target->GetGUID().GetCounter()); + else if (info.TargetGUID.IsPlayer()) + handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_PLAYER, info.TargetName.c_str(), info.TargetGUID.GetCounter()); else - handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, target->GetName().c_str(), target->GetGUID().GetCounter()); + handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, info.TargetName.c_str(), info.TargetGUID.GetCounter()); break; - } case HOME_MOTION_TYPE: - { if (unit->GetTypeId() == TYPEID_UNIT) handler->PSendSysMessage(LANG_MOVEGENS_HOME_CREATURE, x, y, z); else handler->SendSysMessage(LANG_MOVEGENS_HOME_PLAYER); break; - } case FLIGHT_MOTION_TYPE: handler->SendSysMessage(LANG_MOVEGENS_FLIGHT); break; case POINT_MOTION_TYPE: - { handler->PSendSysMessage(LANG_MOVEGENS_POINT, x, y, z); break; - } case FLEEING_MOTION_TYPE: handler->SendSysMessage(LANG_MOVEGENS_FEAR); break; @@ -2215,7 +2182,7 @@ public: handler->SendSysMessage(LANG_MOVEGENS_EFFECT); break; default: - handler->PSendSysMessage(LANG_MOVEGENS_UNKNOWN, movementGenerator->GetMovementGeneratorType()); + handler->PSendSysMessage(LANG_MOVEGENS_UNKNOWN, info.Type); break; } } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index ee4d0024450..50fe639eb3f 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -1289,7 +1289,7 @@ public: return true; } - //npc unfollow handling + // npc unfollow handling static bool HandleNpcUnFollowCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); @@ -1302,26 +1302,24 @@ public: return false; } - if (/*creature->GetMotionMaster()->empty() ||*/ - creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != FOLLOW_MOTION_TYPE) + MovementGenerator* movement = creature->GetMotionMaster()->GetMovementGenerator([player](MovementGenerator const* a) -> bool { - handler->PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName().c_str()); - handler->SetSentErrorMessage(true); + if (a->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE) + { + FollowMovementGenerator const* followMovement = dynamic_cast<FollowMovementGenerator const*>(a); + return followMovement && followMovement->GetTarget() == player; + } return false; - } - - FollowMovementGenerator const* mgen = static_cast<FollowMovementGenerator const*>((creature->GetMotionMaster()->top())); + }); - if (mgen->GetTarget() != player) + if (!movement) { handler->PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName().c_str()); handler->SetSentErrorMessage(true); return false; } - // reset movement - creature->GetMotionMaster()->MovementExpired(true); - + creature->GetMotionMaster()->Remove(movement); handler->PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName().c_str()); return true; } diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index 3a9c0331cb2..7afeff82163 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -29,7 +29,6 @@ EndScriptData */ #include "Group.h" #include "Language.h" #include "MapManager.h" -#include "MotionMaster.h" #include "ObjectMgr.h" #include "Player.h" #include "RBAC.h" @@ -185,13 +184,9 @@ public: // stop flight if need if (target->IsInFlight()) - { - target->GetMotionMaster()->MovementExpired(); - target->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + target->FinishTaxiFlight(); else - target->SaveRecallPosition(); + target->SaveRecallPosition(); // save only in non-flight case target->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); } @@ -283,13 +278,9 @@ public: // stop flight if need if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + player->FinishTaxiFlight(); else - player->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case player->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); } @@ -302,7 +293,7 @@ public: if (!*args) return false; - Player* me = handler->GetSession()->GetPlayer(); + Player* player = handler->GetSession()->GetPlayer(); // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r GameTele const* tele = handler->extractGameTeleFromLink((char*)args); @@ -313,7 +304,7 @@ public: return false; } - if (me->IsInCombat() && !handler->GetSession()->HasPermission(rbac::RBAC_PERM_COMMAND_TELE_NAME)) + if (player->IsInCombat() && !handler->GetSession()->HasPermission(rbac::RBAC_PERM_COMMAND_TELE_NAME)) { handler->SendSysMessage(LANG_YOU_IN_COMBAT); handler->SetSentErrorMessage(true); @@ -321,7 +312,7 @@ public: } MapEntry const* map = sMapStore.LookupEntry(tele->mapId); - if (!map || (map->IsBattlegroundOrArena() && (me->GetMapId() != tele->mapId || !me->IsGameMaster()))) + if (!map || (map->IsBattlegroundOrArena() && (player->GetMapId() != tele->mapId || !player->IsGameMaster()))) { handler->SendSysMessage(LANG_CANNOT_TELE_TO_BG); handler->SetSentErrorMessage(true); @@ -329,16 +320,12 @@ public: } // stop flight if need - if (me->IsInFlight()) - { - me->GetMotionMaster()->MovementExpired(); - me->CleanupAfterTaxiFlight(); - } - // save only in non-flight case + if (player->IsInFlight()) + player->FinishTaxiFlight(); else - me->SaveRecallPosition(); + player->SaveRecallPosition(); // save only in non-flight case - me->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); + player->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); return true; } }; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp index ffaff3ba47c..81a547ea16f 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp @@ -1022,7 +1022,7 @@ void PretendToDie(Creature* creature) creature->RemoveAllAuras(); creature->SetHealth(0); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - creature->GetMotionMaster()->MovementExpired(false); + creature->GetMotionMaster()->Clear(); creature->GetMotionMaster()->MoveIdle(); creature->SetStandState(UNIT_STAND_STATE_DEAD); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index edbfe09a76d..f4facc19d0e 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -385,7 +385,7 @@ class npc_eye_of_acherus : public CreatureScript Movement::MoveSplineInit init(me); init.MoveTo(EyeOFAcherusFallPoint.GetPositionX(), EyeOFAcherusFallPoint.GetPositionY(), EyeOFAcherusFallPoint.GetPositionZ(), false); init.SetFall(); - me->GetMotionMaster()->LaunchMoveSpline(std::move(init), POINT_EYE_FALL, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), POINT_EYE_FALL, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE); } void OnCharmed(bool /*apply*/) override { } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp index 1f70792779c..023782021ae 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp @@ -78,7 +78,7 @@ public: z += 4.0f; x -= 3.5f; y -= 5.0f; - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->UpdatePosition(x, y, z, 0.0f); } diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp index 780dd473288..ebbc56e3bee 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp @@ -324,7 +324,7 @@ public: DoCast(me, SPELL_HEAD_LANDS, true); DoCast(me, SPELL_HEAD, false); SaySound(SAY_LOST_HEAD); - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveFleeing(caster->GetVictim()); } } @@ -339,7 +339,7 @@ public: wait = 1000; if (!me->GetVictim()) return; - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveFleeing(me->GetVictim()); } else wait -= diff; @@ -604,7 +604,7 @@ public: me->SetFullHealth(); SaySound(SAY_REJOINED); DoCast(me, SPELL_HEAD); - caster->GetMotionMaster()->Clear(false); + caster->GetMotionMaster()->Clear(); caster->GetMotionMaster()->MoveFollow(me, 6, float(urand(0, 5))); } } @@ -679,7 +679,7 @@ public: if (wp_reached) { wp_reached = false; - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(id, FlightPoint[id]); } } diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp index 11bc1401431..d1bfe7c220d 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp @@ -129,19 +129,19 @@ public: Talk(SAY_MO_KILL); } - void DamageTaken(Unit* /*doneBy*/, uint32 &damage) override + void DamageTaken(Unit* /*doneBy*/, uint32& damage) override { - if (damage < me->GetHealth() || _bHasDied || _bFakeDeath) + if (damage <= me->GetHealth() || _bHasDied || _bFakeDeath) return; - //On first death, fake death and open door, as well as initiate whitemane if exist + // On first death, fake death and open door, as well as initiate whitemane if exist if (Unit* Whitemane = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_WHITEMANE))) { instance->SetBossState(DATA_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS); Whitemane->GetMotionMaster()->MovePoint(1, 1163.113370f, 1398.856812f, 32.527786f); - me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); me->SetHealth(0); diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp index 7a2e7cf09ca..135bb109f51 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp @@ -277,7 +277,7 @@ public: { case 0: //me->AttackStop(); - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); me->StopMoving(); Talk(YELL_TAKEOFF); diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index 3c225099ca6..039ad2525cf 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -311,7 +311,7 @@ class boss_nalorakk : public CreatureScript { if (waitTimer <= diff) { - me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL); me->GetMotionMaster()->MovePoint(MovePhase, NalorakkWay[MovePhase][0], NalorakkWay[MovePhase][1], NalorakkWay[MovePhase][2]); waitTimer = 0; } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index a4ccef587d9..54cac735a1e 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -377,7 +377,7 @@ class npc_zulian_prowler : public CreatureScript void JustEngagedWith(Unit* /*who*/) override { - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->RemoveAura(SPELL_SNEAK_RANK_1_1); me->RemoveAura(SPELL_SNEAK_RANK_1_2); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 1fe47520fee..6efe482eac9 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -409,7 +409,7 @@ public: if (!HasProtected) { - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); // All members of raid must get this buff @@ -496,7 +496,7 @@ public: switch (actionId) { case ACTION_ENRAGE: - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); Enraged = true; Talk(SAY_ENRAGE); diff --git a/src/server/scripts/Kalimdor/zone_azshara.cpp b/src/server/scripts/Kalimdor/zone_azshara.cpp index cb607486e74..5cfcb2355f5 100644 --- a/src/server/scripts/Kalimdor/zone_azshara.cpp +++ b/src/server/scripts/Kalimdor/zone_azshara.cpp @@ -195,7 +195,9 @@ public: { me->DespawnOrUnsummon(); return; - } else MustDieTimer -= diff; + } + else + MustDieTimer -= diff; } if (!Escape) @@ -207,7 +209,9 @@ public: { DoCast(me, SPELL_RIZZLE_ESCAPE, false); SpellEscapeTimer = 10000; - } else SpellEscapeTimer -= diff; + } + else + SpellEscapeTimer -= diff; if (TeleportTimer <= diff) { @@ -224,10 +228,12 @@ public: me->SetHover(true); me->SetSwim(true); me->SetSpeedRate(MOVE_RUN, 0.85f); - me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL); me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP]); Escape = true; - } else TeleportTimer -= diff; + } + else + TeleportTimer -= diff; return; } @@ -246,7 +252,9 @@ public: DoCast(player, SPELL_RIZZLE_FROST_GRENADE, true); } GrenadeTimer = 30000; - } else GrenadeTimer -= diff; + } + else + GrenadeTimer -= diff; if (CheckTimer <= diff) { @@ -268,7 +276,9 @@ public: } CheckTimer = 1000; - } else CheckTimer -= diff; + } + else + CheckTimer -= diff; } bool GossipHello(Player* player) override diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index 6ee613636ed..da6c486ab48 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -826,7 +826,7 @@ class npc_anubarak_spike : public CreatureScript me->GetThreatManager().ResetAllThreat(); DoZoneInCombat(); AddThreat(who, 1000000.0f); - me->GetMotionMaster()->Clear(true); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveChase(who); } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 0f0047ef819..3a5c2764551 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -15,20 +15,24 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptMgr.h" #include "halls_of_reflection.h" +#include "Creature.h" +#include "EventProcessor.h" #include "InstanceScript.h" #include "MotionMaster.h" #include "MoveSplineInit.h" #include "ObjectAccessor.h" +#include "ObjectGuid.h" #include "Player.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" +#include "ScriptMgr.h" #include "Spell.h" #include "SpellInfo.h" #include "SpellScript.h" #include "TemporarySummon.h" #include "Transport.h" +#include "Unit.h" enum Text { @@ -344,12 +348,6 @@ Position const IceWallTargetPosition[] = { 5318.289f, 1749.184f, 771.9423f, 0.8726646f } // 4th Icewall }; -void GameObjectDeleteDelayEvent::DeleteGameObject() -{ - if (GameObject* go = ObjectAccessor::GetGameObject(*_owner, _gameObjectGUID)) - go->Delete(); -} - class npc_jaina_or_sylvanas_intro_hor : public CreatureScript { public: @@ -797,6 +795,33 @@ class npc_jaina_or_sylvanas_intro_hor : public CreatureScript } }; +class HoRGameObjectDeleteDelayEvent : public BasicEvent +{ + public: + explicit HoRGameObjectDeleteDelayEvent(Unit* owner, ObjectGuid gameObjectGUID) : _owner(owner), _gameObjectGUID(gameObjectGUID) { } + + void DeleteGameObject() + { + if (GameObject* go = ObjectAccessor::GetGameObject(*_owner, _gameObjectGUID)) + go->Delete(); + } + + bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override + { + DeleteGameObject(); + return true; + } + + void Abort(uint64 /*execTime*/) override + { + DeleteGameObject(); + } + + private: + Unit* _owner; + ObjectGuid _gameObjectGUID; +}; + class npc_jaina_or_sylvanas_escape_hor : public CreatureScript { public: @@ -894,7 +919,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript me->RemoveAurasDueToSpell(SPELL_SYLVANAS_DESTROY_ICE_WALL); _instance->HandleGameObject(_instance->GetGuidData(DATA_ICEWALL), true); - me->m_Events.AddEvent(new GameObjectDeleteDelayEvent(me, _instance->GetGuidData(DATA_ICEWALL)), me->m_Events.CalculateTime(5000)); + me->m_Events.AddEvent(new HoRGameObjectDeleteDelayEvent(me, _instance->GetGuidData(DATA_ICEWALL)), me->m_Events.CalculateTime(5000)); if (Creature* wallTarget = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_ICEWALL_TARGET))) wallTarget->DespawnOrUnsummon(); @@ -2123,13 +2148,10 @@ enum EscapeEvents EVENT_LUMBERING_ABOMINATION_CLEAVE }; -namespace hor -{ - -class StartMovementEvent : public BasicEvent +class HoRStartMovementEvent : public BasicEvent { public: - StartMovementEvent(Creature* owner) : _owner(owner) { } + explicit HoRStartMovementEvent(Creature* owner) : _owner(owner) { } bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override { @@ -2143,8 +2165,6 @@ class StartMovementEvent : public BasicEvent Creature* _owner; }; -} // namespace hor - struct npc_escape_event_trash : public ScriptedAI { npc_escape_event_trash(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } @@ -2197,7 +2217,7 @@ class npc_raging_ghoul : public CreatureScript me->CastSpell(me, SPELL_RAGING_GHOUL_SPAWN, true); me->SetReactState(REACT_PASSIVE); me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); - me->m_Events.AddEvent(new hor::StartMovementEvent(me), me->m_Events.CalculateTime(5000)); + me->m_Events.AddEvent(new HoRStartMovementEvent(me), me->m_Events.CalculateTime(5000)); npc_escape_event_trash::IsSummonedBy(summoner); } @@ -2263,7 +2283,7 @@ class npc_risen_witch_doctor : public CreatureScript me->CastSpell(me, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true); me->SetReactState(REACT_PASSIVE); me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); - me->m_Events.AddEvent(new hor::StartMovementEvent(me), me->m_Events.CalculateTime(5000)); + me->m_Events.AddEvent(new HoRStartMovementEvent(me), me->m_Events.CalculateTime(5000)); npc_escape_event_trash::IsSummonedBy(summoner); } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h index 4303bc5fa5d..1104c92fcb6 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h @@ -19,19 +19,18 @@ #define HALLS_OF_REFLECTION_H_ #include "CreatureAIImpl.h" -#include "EventProcessor.h" -#include "ObjectGuid.h" #define HoRScriptName "instance_halls_of_reflection" -#define DataHeader "HOR" +#define DataHeader "HOR" uint32 const EncounterCount = 3; -/* Halls of Reflection encounters: - 0 - Falric - 1 - Marwyn - 2 - The Lich King -*/ +/* + * Halls of Reflection encounters: + * 0 - Falric + * 1 - Marwyn + * 2 - The Lich King + */ enum HORDataTypes { @@ -196,29 +195,6 @@ enum HORInstanceYells SAY_CAPTAIN_FINAL = 1 }; -class GameObjectDeleteDelayEvent : public BasicEvent -{ - public: - GameObjectDeleteDelayEvent(Unit* owner, ObjectGuid gameObjectGUID) : _owner(owner), _gameObjectGUID(gameObjectGUID) { } - - void DeleteGameObject(); - - bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override - { - DeleteGameObject(); - return true; - } - - void Abort(uint64 /*execTime*/) override - { - DeleteGameObject(); - } - - private: - Unit* _owner; - ObjectGuid _gameObjectGUID; -}; - template <class AI, class T> inline AI* GetHallsOfReflectionAI(T* obj) { 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 60b3c43a970..e80d238d7c9 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -476,7 +476,7 @@ public: Movement::MoveSplineInit init(_owner); init.DisableTransportPathTransformations(); init.MoveTo(_dest.GetPositionX(), _dest.GetPositionY(), _dest.GetPositionZ(), false); - _owner->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_CHARGE_PREPATH, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + _owner->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_CHARGE_PREPATH, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE); return true; } @@ -570,7 +570,7 @@ struct gunship_npc_AI : public ScriptedAI Movement::MoveSplineInit init(me); init.DisableTransportPathTransformations(); init.MoveTo(x, y, z, false); - me->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_CHARGE_PREPATH, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_CHARGE_PREPATH, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE); } } @@ -943,7 +943,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript Movement::MoveSplineInit init(me); init.DisableTransportPathTransformations(); init.MovebyPath(path, 0); - me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE); me->DespawnOrUnsummon(18000); } @@ -1207,7 +1207,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript Movement::MoveSplineInit init(me); init.DisableTransportPathTransformations(); init.MovebyPath(path, 0); - me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_PRIORITY_NORMAL, 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 d974533d9ef..1d107a720fc 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -23,6 +23,7 @@ #include "MoveSplineInit.h" #include "ObjectAccessor.h" #include "Player.h" +#include "PointMovementGenerator.h" #include "ScriptedCreature.h" #include "SpellAuras.h" #include "SpellScript.h" @@ -242,8 +243,16 @@ class boss_lord_marrowgar : public CreatureScript break; } case EVENT_BONE_STORM_END: - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); + if (MovementGenerator* movement = me->GetMotionMaster()->GetMovementGenerator([](MovementGenerator const* a) -> bool + { + if (a->GetMovementGeneratorType() == POINT_MOTION_TYPE) + { + PointMovementGenerator<Creature> const* pointMovement = dynamic_cast<PointMovementGenerator<Creature> const*>(a); + return pointMovement && pointMovement->GetId() == POINT_TARGET_BONESTORM_PLAYER; + } + return false; + })) + me->GetMotionMaster()->Remove(movement); me->GetMotionMaster()->MoveChase(me->GetVictim()); me->SetSpeedRate(MOVE_RUN, _baseSpeed); events.CancelEvent(EVENT_BONE_STORM_MOVE); @@ -473,7 +482,7 @@ class npc_bone_spike : public CreatureScript Movement::MoveSplineInit init(passenger); init.DisableTransportPathTransformations(); init.MoveTo(-0.02206125f, -0.02132235f, 5.514783f, false); - passenger->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_SLOT_CONTROLLED); + passenger->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_PRIORITY_HIGHEST); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index ff0dd695971..6a3c459916a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -245,8 +245,6 @@ class boss_professor_putricide : public CreatureScript _experimentState = EXPERIMENT_STATE_OOZE; me->SetReactState(REACT_DEFENSIVE); me->SetWalk(false); - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); if (instance->GetBossState(DATA_ROTFACE) == DONE && instance->GetBossState(DATA_FESTERGUT) == DONE) { diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index bf9035604a3..2d190659d1d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -393,8 +393,7 @@ class boss_sindragosa : public CreatureScript me->SetDisableGravity(false); me->RemoveByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->SetReactState(REACT_DEFENSIVE); - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); + _isInAirPhase = false; // trigger Asphyxiation EntryCheckPredicate pred(NPC_ICE_TOMB); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 7353486e186..0878b5645f5 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -441,10 +441,10 @@ class FrozenThroneResetWorker } }; -class StartMovementEvent : public BasicEvent +class LichKingStartMovementEvent : public BasicEvent { public: - StartMovementEvent(Creature* summoner, Creature* owner) + LichKingStartMovementEvent(Creature* summoner, Creature* owner) : _summonerGuid(summoner->GetGUID()), _owner(owner) { } @@ -737,7 +737,7 @@ class boss_the_lich_king : public CreatureScript summon->CastSpell(summon, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true); summon->SetReactState(REACT_PASSIVE); summon->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); - summon->m_Events.AddEvent(new StartMovementEvent(me, summon), summon->m_Events.CalculateTime(5000)); + summon->m_Events.AddEvent(new LichKingStartMovementEvent(me, summon), summon->m_Events.CalculateTime(5000)); break; case NPC_ICE_SPHERE: { @@ -1690,7 +1690,7 @@ class npc_strangulate_vehicle : public CreatureScript switch (eventId) { case EVENT_TELEPORT: - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); if (TempSummon* summ = me->ToTempSummon()) { diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index d9c1c8e1128..21d6dfa30ee 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -1292,7 +1292,7 @@ struct npc_argent_captainAI : public ScriptedAI me->SetReactState(REACT_DEFENSIVE); FollowAngle = me->GetAbsoluteAngle(crok) + me->GetOrientation(); FollowDist = me->GetDistance2d(crok); - me->GetMotionMaster()->MoveFollow(crok, FollowDist, FollowAngle, MOTION_SLOT_IDLE); + me->GetMotionMaster()->MoveFollow(crok, FollowDist, FollowAngle, MOTION_SLOT_DEFAULT); } me->setActive(true); @@ -1320,7 +1320,7 @@ struct npc_argent_captainAI : public ScriptedAI void EnterEvadeMode(EvadeReason why) override { // not yet following - if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != CHASE_MOTION_TYPE || IsUndead) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType(MOTION_SLOT_DEFAULT) != FOLLOW_MOTION_TYPE || IsUndead) { ScriptedAI::EnterEvadeMode(why); return; @@ -1331,9 +1331,9 @@ struct npc_argent_captainAI : public ScriptedAI if (!me->GetVehicle()) { - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); if (Creature* crok = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_CROK_SCOURGEBANE))) - me->GetMotionMaster()->MoveFollow(crok, FollowDist, FollowAngle, MOTION_SLOT_IDLE); + me->GetMotionMaster()->MoveFollow(crok, FollowDist, FollowAngle, MOTION_SLOT_DEFAULT); } Reset(); diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 61faa846a85..2c5456229e5 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -502,7 +502,7 @@ public: DummyEntryCheckPredicate pred; summons.DoAction(ACTION_DELAYED_DESPAWN, pred); Talk(SAY_END_P_TWO); - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->StopMoving(); if (me->GetPositionZ() > 300.0f) events.ScheduleEvent(EVENT_DELAY_MOVE_TO_DESTROY_P, 5*IN_MILLISECONDS, 0, PHASE_TWO); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 997ff31527e..c916d93fefc 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -419,21 +419,21 @@ public: } } - void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) override + void DamageTaken(Unit* /*attacker*/, uint32& damage) override { - if (uiDamage > me->GetHealth()) + if (damage >= me->GetHealth()) { me->UpdateEntry(NPC_BRITTLE_GOLEM); me->SetHealth(1); - uiDamage = 0; + damage = 0; me->RemoveAllAuras(); me->AttackStop(); - // me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); //Set in DB - // me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //Set in DB + // me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); // Set in DB + // me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); // Set in DB if (me->IsNonMeleeSpellCast(false)) me->InterruptNonMeleeSpells(false); - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); + + me->GetMotionMaster()->Clear(); m_bIsFrozen = true; } } 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 671b781f86b..0da39233faa 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 @@ -357,7 +357,7 @@ class boss_algalon_the_observer : public CreatureScript Movement::MoveSplineInit init(me); init.MoveTo(AlgalonLandPos.GetPositionX(), AlgalonLandPos.GetPositionY(), AlgalonLandPos.GetPositionZ(), false); init.SetOrientationFixed(true); - me->GetMotionMaster()->LaunchMoveSpline(std::move(init), POINT_ALGALON_LAND, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), POINT_ALGALON_LAND, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE); events.Reset(); events.SetPhase(PHASE_ROLE_PLAY); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index f26ddedd8f3..303cdd85a0e 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -1133,7 +1133,7 @@ class boss_aerial_command_unit : public CreatureScript if (events.IsInPhase(PHASE_AERIAL_COMMAND_UNIT)) { - me->GetMotionMaster()->Clear(true); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(WP_AERIAL_P4_POS, VehicleRelocation[WP_AERIAL_P4_POS]); } else if (events.IsInPhase(PHASE_VOL7RON)) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp index ae3d1b6eb01..fd96955add0 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp @@ -337,7 +337,7 @@ struct boss_razorscale : public BossAI init.MovebyPath(path, 0); init.SetCyclic(); init.SetFly(); - me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE); } bool CanAIAttack(Unit const* target) const override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index 0f47cd67419..141c005e5d6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -660,7 +660,7 @@ class boss_thorim : public CreatureScript Movement::MoveSplineInit init(summon); init.MovebyPath(path); - summon->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_SLOT_ACTIVE, POINT_MOTION_TYPE); + summon->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE); break; } case NPC_DARK_RUNE_CHAMPION: diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp index c1f8dae9145..2a392030b0f 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp @@ -256,7 +256,7 @@ class npc_vrykul_skeleton : public CreatureScript events.ScheduleEvent(EVENT_DECREPIFY, urand(4, 6) * IN_MILLISECONDS); } - void DamageTaken(Unit* /*doneBy*/, uint32& damage) override + void DamageTaken(Unit* /*attacker*/, uint32& damage) override { if (damage >= me->GetHealth()) { @@ -273,7 +273,7 @@ class npc_vrykul_skeleton : public CreatureScript events.Reset(); events.ScheduleEvent(EVENT_RESURRECT, urand(18, 22) * IN_MILLISECONDS); - me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); } } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index 0bb6b26baff..a90cdbd42c5 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -362,7 +362,7 @@ public: Movement::MoveSplineInit init(who); init.DisableTransportPathTransformations(); init.MoveTo(0.3320355f, 0.05355075f, 5.196949f, false); - who->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_SLOT_CONTROLLED); + who->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_PRIORITY_HIGHEST); me->setActive(true); me->SetFarVisible(true); diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 6af5ea78700..e7aa7ab9fde 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -721,7 +721,7 @@ public: owner->RemoveAllAurasExceptType(SPELL_AURA_DUMMY); owner->CombatStop(true); owner->GetThreatManager().ClearAllThreat(); - owner->GetMotionMaster()->Clear(false); + owner->GetMotionMaster()->Clear(); owner->GetMotionMaster()->MoveFollow(GetCaster(), 4.0f, 0.0f); owner->CastSpell(owner, SPELL_SUBDUED, true); GetCaster()->CastSpell(GetCaster(), SPELL_DRAKE_HATCHLING_SUBDUED, true); diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index d414a82bcd7..c85840a0e80 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -900,7 +900,7 @@ public: { _finished = false; me->SetVisible(true); - me->GetMotionMaster()->Clear(true); + me->GetMotionMaster()->Clear(); } void DoAction(int32 /*action*/) override diff --git a/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp b/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp index 0b4c45472d6..c93a47b243b 100644 --- a/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp +++ b/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp @@ -151,8 +151,7 @@ class boss_nexusprince_shaffar : public CreatureScript // expire movement, will prevent from running right back to victim after cast // (but should MoveChase be used again at a certain time or should he not move?) - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL); DoCast(me, SPELL_BLINK); break; diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index 0e9583202ae..3535c5b4ea1 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -724,7 +724,7 @@ struct npc_ashtongue_sorcerer : public ScriptedAI { _inBanish = true; me->StopMoving(); - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + frand(-8.0f, 8.0f), me->GetPositionY() + frand(-8.0f, 8.0f), me->GetPositionZ()); _scheduler.Schedule(Seconds(1) + Milliseconds(500), [this](TaskContext sorcer_channel) diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp index 897f759ea88..ced2e6c624f 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp @@ -250,7 +250,7 @@ public: { Talk(EMOTE_SPOUT); me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveRotate(20000, urand(0, 1) ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); + me->GetMotionMaster()->MoveRotate(0, 20000, urand(0, 1) ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); SpoutTimer = 45000; WhirlTimer = 20000; // whirl directly after spout RotTimer = 20000; @@ -268,7 +268,7 @@ public: else WhirlTimer -= diff; - if (CheckTimer <= diff)//check if there are players in melee range + if (CheckTimer <= diff) // check if there are players in melee range { InRange = false; Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 72c0442e617..68c4cae48c5 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -288,9 +288,6 @@ public: { if (GameObject* go = unit->FindNearestGameObject(GO_CARCASS, 10)) { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MoveIdle(); me->StopMoving(); @@ -329,7 +326,9 @@ public: { DoCastVictim(SPELL_NETHER_BREATH); CastTimer = 5000; - } else CastTimer -= diff; + } + else + CastTimer -= diff; DoMeleeAttackIfReady(); } diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp index dddd00c0c4e..57caaa93cf9 100644 --- a/src/server/scripts/Pet/pet_dk.cpp +++ b/src/server/scripts/Pet/pet_dk.cpp @@ -96,7 +96,7 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript float x = me->GetPositionX() + 20 * std::cos(me->GetOrientation()); float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation()); float z = me->GetPositionZ() + 40; - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(0, x, y, z); // Despawn as soon as possible diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp index b71efa9a8bc..fe1f9fb4841 100644 --- a/src/server/scripts/Pet/pet_mage.cpp +++ b/src/server/scripts/Pet/pet_mage.cpp @@ -190,8 +190,8 @@ class npc_pet_mage_mirror_image : public CreatureScript me->CombatStop(true); if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); } } diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp index 5da91c1e850..c7ee26287c1 100644 --- a/src/server/scripts/World/boss_emerald_dragons.cpp +++ b/src/server/scripts/World/boss_emerald_dragons.cpp @@ -200,13 +200,13 @@ class npc_dream_fog : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { _roamTimer = urand(15000, 30000); - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveChase(target, 0.2f); } else { _roamTimer = 2500; - me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveRandom(25.0f); } // Seeping fog movement is slow enough for a player to be able to walk backwards and still outpace it diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 7abc1acbbda..e27fa9ab280 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -2925,7 +2925,7 @@ public: init.DisableTransportPathTransformations(); init.MoveTo(x, y, z, false); init.SetFacing(o); - who->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_SLOT_CONTROLLED); + who->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_PRIORITY_HIGHEST); 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); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 3b55598687e..325a1bbac2d 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -3875,7 +3875,9 @@ Logger.mmaps=3,Server #Logger.maps.script=3,Console Server #Logger.maps=3,Console Server #Logger.misc=3,Console Server +#Logger.movement.flightpath=3,Console Server #Logger.movement.motionmaster=3,Console Server +#Logger.movement.splinechain=3,Console Server #Logger.network=3,Console Server #Logger.network.opcode=3,Console Server #Logger.network.soap=3,Console Server |
