aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/game/AI/CreatureAI.cpp8
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp6
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp31
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp10
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h8
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp7
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp13
-rw-r--r--src/server/game/Entities/Creature/CreatureGroups.cpp8
-rw-r--r--src/server/game/Entities/Player/Player.cpp21
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp36
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.cpp2
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp7
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp16
-rw-r--r--src/server/game/Handlers/PetHandler.cpp4
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp5
-rw-r--r--src/server/game/Maps/Map.cpp2
-rw-r--r--src/server/game/Maps/MapScripts.cpp1
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h3
-rw-r--r--src/server/game/Movement/MotionMaster.cpp846
-rw-r--r--src/server/game/Movement/MotionMaster.h177
-rw-r--r--src/server/game/Movement/MovementDefines.h31
-rwxr-xr-xsrc/server/game/Movement/MovementGenerator.h59
-rw-r--r--src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp72
-rw-r--r--src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h9
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp72
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h12
-rw-r--r--src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp133
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h18
-rw-r--r--src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp245
-rw-r--r--src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h70
-rw-r--r--src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp52
-rw-r--r--src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h9
-rw-r--r--src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp56
-rw-r--r--src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h11
-rw-r--r--src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp50
-rw-r--r--src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h9
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp108
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h8
-rw-r--r--src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp173
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/IdleMovementGenerator.h26
-rw-r--r--src/server/game/Movement/MovementGenerators/PathMovementBase.h14
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp104
-rw-r--r--src/server/game/Movement/MovementGenerators/PointMovementGenerator.h22
-rw-r--r--src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp73
-rw-r--r--src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h12
-rw-r--r--src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp196
-rw-r--r--src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h26
-rw-r--r--src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp364
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h43
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp16
-rw-r--r--src/server/game/Spells/SpellEffects.cpp6
-rw-r--r--src/server/scripts/Commands/cs_go.cpp90
-rw-r--r--src/server/scripts/Commands/cs_group.cpp9
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp87
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp22
-rw-r--r--src/server/scripts/Commands/cs_tele.cpp35
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp4
-rw-r--r--src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp2
-rw-r--r--src/server/scripts/Kalimdor/Firelands/firelands.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp54
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h38
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp8
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp15
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp3
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp8
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp8
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp14
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp2
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp4
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_borean_tundra.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_grizzly_hills.cpp2
-rw-r--r--src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp3
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp2
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp4
-rw-r--r--src/server/scripts/Outland/zone_shadowmoon_valley.cpp7
-rw-r--r--src/server/scripts/Pet/pet_dk.cpp2
-rw-r--r--src/server/scripts/Pet/pet_mage.cpp4
-rw-r--r--src/server/scripts/World/boss_emerald_dragons.cpp4
-rw-r--r--src/server/scripts/World/npcs_special.cpp2
-rw-r--r--src/server/worldserver/worldserver.conf.dist2
96 files changed, 2361 insertions, 1435 deletions
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index e41d104c380..4e8e035bf5b 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -160,9 +160,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)
@@ -176,8 +174,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 bb118886b79..fd9c7421c0f 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -204,7 +204,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);
}
}
@@ -328,7 +328,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->SetNpcFlags(UNIT_NPC_FLAG_NONE);
@@ -366,7 +366,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 950b1d10fa3..f4a775bee69 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -113,7 +113,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();
@@ -546,8 +546,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();
}
@@ -593,7 +596,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)
{
@@ -772,13 +776,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 e0516b76abf..2d191d2082b 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1642,10 +1642,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;
}
@@ -2323,16 +2325,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 34ac2eea2ac..42353663540 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -25,7 +25,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"
@@ -1757,7 +1757,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 " SI64FMTD " 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 dd29f0e3185..0e1fe59b06e 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -590,7 +590,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, // id, type (0 = oneShot, 1 = aiAnim, 2 = meleeAnim, 3 = movementAnim)
SMART_ACTION_SCENE_PLAY = 129, // sceneId
SMART_ACTION_SCENE_CANCEL = 130, // sceneId
@@ -1162,9 +1162,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 9cae257d87b..faeee1e4b67 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -30,7 +30,6 @@
#include "LFGScripts.h"
#include "Log.h"
#include "Map.h"
-#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"
@@ -1363,11 +1362,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_TELEPORT_RESULT_NO_RETURN_LOCATION;
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 08b57f37fed..162fd6fc1f0 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -371,7 +371,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;
@@ -817,8 +817,7 @@ void Creature::Update(uint32 diff)
IsAIEnabled = true;
if (!IsInEvadeMode() && !LastCharmerGUID.IsEmpty())
if (Unit* charmer = ObjectAccessor::GetUnit(*this, LastCharmerGUID))
- if (CanStartAttack(charmer, true))
- i_AI->AttackStart(charmer);
+ EngageWithTarget(charmer);
LastCharmerGUID.Clear();
}
@@ -1020,7 +1019,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
@@ -1089,7 +1087,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;
}
}
@@ -2230,8 +2228,9 @@ void Creature::Respawn(bool force)
SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
}
- 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 8e285f3e931..e54e3f33ec6 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.cpp
+++ b/src/server/game/Entities/Creature/CreatureGroups.cpp
@@ -268,7 +268,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: %s", dismiss ? "default" : "idle", pair.first->GetGUID().ToString().c_str());
+ TC_LOG_DEBUG("entities.unit", "CreatureGroup::FormationReset: Set %s movement for member %s", dismiss ? "default" : "idle", pair.first->GetGUID().ToString().c_str());
}
}
@@ -316,16 +316,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 f8eedbe9752..0350d2b3833 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -22735,9 +22735,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();
RemoveUnitFlag(UnitFlags(UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT));
}
@@ -25153,11 +25162,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
@@ -25554,13 +25559,9 @@ void Player::SetClientControl(Unit* target, bool allowMove)
void Player::SetMover(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();
WorldPackets::Movement::MoveSetActiveMover packet;
packet.MoverGUID = target->GetGUID();
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index f6ee48328ad..4695eb8d21a 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1120,9 +1120,10 @@ 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, uint32 preferredMountDisplay = 0);
bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0);
+ void FinishTaxiFlight();
void CleanupAfterTaxiFlight();
void ContinueTaxiFlight() const;
- // 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 a6d6b8b0bde..a1b85a33ff1 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -473,7 +473,7 @@ void Unit::Update(uint32 p_time)
}
UpdateSplineMovement(p_time);
- i_motionMaster->UpdateMotion(p_time);
+ i_motionMaster->Update(p_time);
}
bool Unit::haveOffhandWeapon() const
@@ -489,7 +489,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)
@@ -8065,7 +8065,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);
@@ -8206,7 +8206,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();
@@ -9787,10 +9787,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();
}
@@ -9799,7 +9799,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);
}
@@ -10775,8 +10775,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());
}
@@ -10801,8 +10800,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());
}
@@ -10894,10 +10892,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();
@@ -11016,7 +11012,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
RestoreFaction();
///@todo Handle SLOT_IDLE motion resume
- GetMotionMaster()->InitDefault();
+ GetMotionMaster()->InitializeDefault();
if (Creature* creature = ToCreature())
{
@@ -11085,8 +11081,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();
@@ -11939,7 +11933,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();
@@ -12300,7 +12294,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();
}
@@ -12315,7 +12309,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 6025d5f8692..152751c91ad 100644
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -847,7 +847,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32)
init.MoveTo(veSeat->AttachmentOffset.X, veSeat->AttachmentOffset.Y, veSeat->AttachmentOffset.Z, 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 15d34caa157..d1409b24626 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 "NPCPackets.h"
#include "Object.h"
#include "ObjectAccessor.h"
@@ -364,11 +363,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl
_player->SpawnCorpseBones();
}
// stop taxi flight at port
- if (_player->IsInFlight())
- {
- _player->GetMotionMaster()->MovementExpired();
- _player->CleanupAfterTaxiFlight();
- }
+ _player->FinishTaxiFlight();
WorldPackets::Battleground::BattlefieldStatusActive battlefieldStatus;
sBattlegroundMgr->BuildBattlegroundStatusActive(&battlefieldStatus, bg, _player, battlefieldPort.Ticket.Id, _player->GetBattlegroundQueueJoinTime(bgQueueTypeId), bg->GetArenaType());
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index ac873eb6d01..523bcc7c7a5 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -145,32 +145,32 @@ void WorldSession::HandleMoveWorldportAck()
}
// flight fast teleport case
- if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
+ if (GetPlayer()->IsInFlight())
{
if (!_player->InBattleground())
{
if (!seamlessTeleport)
{
// 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->ID)
{
GetPlayer()->ResurrectPlayer(0.5f, false);
GetPlayer()->SpawnCorpseBones();
}
+ }
bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena();
if (mInstance)
@@ -674,13 +674,11 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPackets::Movement::MoveSpline
TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
// far teleport case
- if (curDestNode && curDestNode->ContinentID != GetPlayer()->GetMapId())
+ if (curDestNode && curDestNode->ContinentID != 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/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index bb5e3323b11..67d9c4f00b0 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -153,7 +153,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);
@@ -261,7 +261,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
break;
case COMMAND_MOVE_TO:
pet->StopMoving();
- pet->GetMotionMaster()->Clear(false);
+ pet->GetMotionMaster()->Clear();
pet->GetMotionMaster()->MovePoint(0, pos);
charmInfo->SetCommandState(COMMAND_MOVE_TO);
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index 2b8c1098e8c..da4800ca319 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -130,7 +130,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);
@@ -231,11 +231,10 @@ void WorldSession::SendActivateTaxiReply(ActivateTaxiReply reply)
void WorldSession::HandleTaxiRequestEarlyLanding(WorldPackets::Taxi::TaxiRequestEarlyLanding& /*taxiRequestEarlyLanding*/)
{
- if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
+ if (FlightPathMovementGenerator* flight = dynamic_cast<FlightPathMovementGenerator*>(GetPlayer()->GetMotionMaster()->GetCurrentMovementGenerator()))
{
if (GetPlayer()->m_taxi.RequestEarlyLanding())
{
- FlightPathMovementGenerator* flight = static_cast<FlightPathMovementGenerator*>(GetPlayer()->GetMotionMaster()->top());
flight->LoadPath(GetPlayer(), flight->GetPath()[flight->GetCurrentNode()]->NodeIndex);
flight->Reset(GetPlayer());
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index ad84dd0e38c..3e935230c24 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1642,7 +1642,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 ad2c744b844..c82bb7212fa 100644
--- a/src/server/game/Maps/MapScripts.cpp
+++ b/src/server/game/Maps/MapScripts.cpp
@@ -849,7 +849,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 8a15659481c..402b89a8387 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -5764,7 +5764,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 d2ebbf22faa..b03fbd08497 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -16,13 +16,15 @@
*/
#include "MotionMaster.h"
+#include "AbstractFollower.h"
#include "Creature.h"
#include "CreatureAISelector.h"
+#include "Containers.h"
#include "DB2Stores.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, nullptr, nullptr, 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, nullptr, nullptr, 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,24 +682,31 @@ 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*/,
Unit const* target /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/)
{
+/*
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, target, spellEffectExtraData), MOTION_SLOT_CONTROLLED);
+ PointMovementGenerator<Player>* movement = new PointMovementGenerator<Player>(id, x, y, z, generatePath, speed, {}, target, spellEffectExtraData);
+ 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, target, spellEffectExtraData), MOTION_SLOT_CONTROLLED);
+ PointMovementGenerator<Creature>* movement = new PointMovementGenerator<Creature>(id, x, y, z, generatePath, speed, {}, target, spellEffectExtraData);
+ movement->Priority = MOTION_PRIORITY_HIGHEST;
+ movement->BaseUnitState = UNIT_STATE_CHARGING;
+ Add(movement);
}
}
@@ -400,7 +730,7 @@ void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_C
void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/)
{
- // this function may make players fall below map
+ // This function may make players fall below map
if (_owner->GetTypeId() == TYPEID_PLAYER)
return;
@@ -422,12 +752,14 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa
if (spellEffectExtraData)
init.SetSpellEffectExtraData(*spellEffectExtraData);
- 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;
@@ -475,7 +807,10 @@ void MotionMaster::MoveJump(float x, float y, float z, float o, float speedXY, f
arrivalSpellTargetGuid = arrivalCast->Target;
}
- Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id, arrivalSpellId, arrivalSpellTargetGuid), MOTION_SLOT_CONTROLLED);
+ GenericMovementGenerator* movement = new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, id, arrivalSpellId, arrivalSpellTargetGuid);
+ 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)
@@ -512,7 +847,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, bool fly)
@@ -535,9 +870,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)
@@ -559,7 +894,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)
@@ -569,12 +904,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)
{
@@ -589,7 +924,7 @@ void MotionMaster::MoveFall(uint32 id/* = 0*/)
_owner->SetFall(true);
- // 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());
@@ -599,7 +934,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)
@@ -610,7 +948,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());
@@ -621,7 +959,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());
@@ -634,9 +972,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();
movement->LoadPath(_owner->ToPlayer(), pathnode);
- 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);
@@ -645,17 +987,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)
@@ -664,22 +1003,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*/)
@@ -687,49 +1026,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
@@ -751,131 +1126,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 5d78c875c7f..c02c71d3b53 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -19,14 +19,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
struct SpellEffectExtraData;
}
-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 5e93e72eb76..3600e349aab 100644
--- a/src/server/game/Movement/MovementDefines.h
+++ b/src/server/game/Movement/MovementDefines.h
@@ -30,36 +30,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 03f96ba1538..235743dc429 100755
--- a/src/server/game/Movement/MovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerator.h
@@ -27,22 +27,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>
@@ -54,11 +88,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));
@@ -68,6 +97,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 490b98da128..c20e34c2bfb 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 72de4c6da0c..d8d35307efb 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 d949ea5655f..e61c8d4cafe 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
@@ -25,7 +25,13 @@
#include "Random.h"
template<class T>
-ConfusedMovementGenerator<T>::~ConfusedMovementGenerator() = default;
+ConfusedMovementGenerator<T>::ConfusedMovementGenerator() : _timer(0), _reference(0.f, 0.f, 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>
MovementGeneratorType ConfusedMovementGenerator<T>::GetMovementGeneratorType() const
@@ -36,10 +42,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->AddUnitFlag(UNIT_FLAG_CONFUSED);
owner->StopMoving();
@@ -51,6 +60,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);
}
@@ -62,20 +73,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(_reference);
float distance = 4.0f * frand(0.0f, 1.0f) - 2.0f;
@@ -95,6 +105,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);
@@ -106,32 +118,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->RemoveUnitFlag(UNIT_FLAG_CONFUSED);
- unit->ClearUnitState(UNIT_STATE_CONFUSED);
- unit->StopMoving();
+ AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED);
+
+ if (active)
+ {
+ owner->RemoveUnitFlag(UNIT_FLAG_CONFUSED);
+ owner->StopMoving();
+ }
}
template<>
-void ConfusedMovementGenerator<Creature>::DoFinalize(Creature* unit)
+void ConfusedMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool/* movementInform*/)
{
- unit->RemoveUnitFlag(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->RemoveUnitFlag(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 b571603ce36..22773470259 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), _reference(0.f, 0.f, 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;
Position _reference;
- bool _interrupt;
};
#endif
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
index 621cae86d12..536ffa736e1 100644
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
@@ -19,8 +19,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,7 +31,13 @@
#define MAX_QUIET_DISTANCE 43.0f
template<class T>
-FleeingMovementGenerator<T>::~FleeingMovementGenerator() = default;
+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>
MovementGeneratorType FleeingMovementGenerator<T>::GetMovementGeneratorType() const
@@ -42,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->AddUnitFlag(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->RemoveUnitFlag(UNIT_FLAG_FLEEING);
- owner->ClearUnitState(UNIT_STATE_FLEEING);
- owner->StopMoving();
-}
-template<>
-void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner)
-{
- owner->RemoveUnitFlag(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);
}
@@ -87,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->RemoveUnitFlag(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->RemoveUnitFlag(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);
@@ -141,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);
@@ -186,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*);
@@ -196,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 &);
@@ -203,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->RemoveUnitFlag(UNIT_FLAG_FLEEING);
- owner->ClearUnitState(UNIT_STATE_FLEEING);
owner->StopMoving();
if (Unit* victim = owner->GetVictim())
{
@@ -236,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 b4b27c4dd38..1b44e92dff1 100755
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
@@ -27,28 +27,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>
@@ -56,9 +56,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 7e04a0ff831..ab8cbf734a8 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,103 +37,44 @@ FlightPathMovementGenerator::FlightPathMovementGenerator()
_endGridY = 0.0f;
_endMapId = 0;
_preloadTargetNode = 0;
-}
-
-uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
-{
- if (_currentNode >= _path.size())
- return _path.size();
-
- uint32 curMapId = _path[_currentNode]->ContinentID;
- for (uint32 itr = _currentNode; itr < _path.size(); ++itr)
- if (_path[itr]->ContinentID != curMapId)
- return itr;
- return _path.size();
+ Mode = MOTION_MODE_DEFAULT;
+ Priority = MOTION_PRIORITY_HIGHEST;
+ Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING;
+ BaseUnitState = UNIT_STATE_IN_FLIGHT;
}
-bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntry const* p2)
+MovementGeneratorType FlightPathMovementGenerator::GetMovementGeneratorType() const
{
- return p1->ContinentID != p2->ContinentID || std::pow(p1->Loc.X - p2->Loc.X, 2) + std::pow(p1->Loc.Y - p2->Loc.Y, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ;
+ return FLIGHT_MOTION_TYPE;
}
-void FlightPathMovementGenerator::LoadPath(Player* player, uint32 startNode /*= 0*/)
+bool FlightPathMovementGenerator::GetResetPosition(Unit* /*owner*/, float& x, float& y, float& z)
{
- _path.clear();
- _currentNode = startNode;
- _pointsForPathSwitch.clear();
- std::deque<uint32> const& taxi = player->m_taxi.GetPath();
- float discount = player->GetReputationPriceDiscount(player->m_taxi.GetFlightMasterFactionTemplate());
- for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++)
- {
- uint32 path, cost;
- sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost);
- if (path > sTaxiPathNodesByPath.size())
- return;
-
- TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path];
- if (!nodes.empty())
- {
- TaxiPathNodeEntry const* start = nodes[0];
- TaxiPathNodeEntry const* end = nodes[nodes.size() - 1];
- bool passedPreviousSegmentProximityCheck = false;
- for (uint32 i = 0; i < nodes.size(); ++i)
- {
- if (passedPreviousSegmentProximityCheck || !src || _path.empty() || IsNodeIncludedInShortenedPath(_path.back(), nodes[i]))
- {
- if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) &&
- (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1)))
- {
- passedPreviousSegmentProximityCheck = true;
- _path.push_back(nodes[i]);
- }
- }
- else
- {
- _path.pop_back();
- --_pointsForPathSwitch.back().PathIndex;
- }
- }
- }
-
- _pointsForPathSwitch.push_back({ uint32(_path.size() - 1), int64(ceil(cost * discount)) });
- }
+ TaxiPathNodeEntry const* node = _path[_currentNode];
+ x = node->Loc.X;
+ y = node->Loc.Y;
+ z = node->Loc.Z;
+ return true;
}
-void FlightPathMovementGenerator::DoInitialize(Player* player)
+void FlightPathMovementGenerator::DoInitialize(Player* owner)
{
- Reset(player);
+ RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING);
+ AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED);
+
+ DoReset(owner);
InitEndGridInfo();
}
-void FlightPathMovementGenerator::DoFinalize(Player* player)
+void FlightPathMovementGenerator::DoReset(Player* owner)
{
- // 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);
+ RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
- player->Dismount();
- player->RemoveUnitFlag(UnitFlags(UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT));
+ owner->CombatStopWithPets();
+ owner->AddUnitFlag(UnitFlags(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->RemovePlayerFlag(PLAYER_FLAGS_TAXI_BENCHMARK);
- player->RestoreDisplayId();
-}
-
-void FlightPathMovementGenerator::DoReset(Player* player)
-{
- player->AddUnitState(UNIT_STATE_IN_FLIGHT);
- player->CombatStopWithPets();
- player->AddUnitFlag(UnitFlags(UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT));
-
- Movement::MoveSplineInit init(player);
+ Movement::MoveSplineInit init(owner);
uint32 end = GetPathAtMapEnd();
for (uint32 i = GetCurrentNode(); i != end; ++i)
{
@@ -151,23 +90,26 @@ void FlightPathMovementGenerator::DoReset(Player* player)
init.Launch();
}
-bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
+bool FlightPathMovementGenerator::DoUpdate(Player* owner, uint32 /*diff*/)
{
- uint32 pointId = (uint32)player->movespline->currentPathIdx();
+ if (!owner)
+ return false;
+
+ uint32 pointId = owner->movespline->currentPathIdx() < 0 ? 0 : owner->movespline->currentPathIdx();
if (pointId > _currentNode)
{
bool departureEvent = true;
do
{
- DoEventIfAny(player, _path[_currentNode], departureEvent);
+ DoEventIfAny(owner, _path[_currentNode], departureEvent);
while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode)
{
_pointsForPathSwitch.pop_front();
- player->m_taxi.NextTaxiDestination();
+ owner->m_taxi.NextTaxiDestination();
if (!_pointsForPathSwitch.empty())
{
- player->UpdateCriteria(CriteriaType::MoneySpentOnTaxis, _pointsForPathSwitch.front().Cost);
- player->ModifyMoney(-_pointsForPathSwitch.front().Cost);
+ owner->UpdateCriteria(CriteriaType::MoneySpentOnTaxis, _pointsForPathSwitch.front().Cost);
+ owner->ModifyMoney(-_pointsForPathSwitch.front().Cost);
}
}
@@ -176,17 +118,107 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
if (_currentNode == _preloadTargetNode)
PreloadEndGrid();
+
_currentNode += departureEvent ? 1 : 0;
departureEvent = !departureEvent;
} while (true);
}
- return _currentNode < (_path.size() - 1);
+ if (_currentNode >= (_path.size() - 1))
+ {
+ AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED);
+ return false;
+ }
+ return true;
}
-MovementGeneratorType FlightPathMovementGenerator::GetMovementGeneratorType() const
+void FlightPathMovementGenerator::DoDeactivate(Player* /*owner*/)
{
- return FLIGHT_MOTION_TYPE;
+ AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
+}
+
+void FlightPathMovementGenerator::DoFinalize(Player* owner, bool active, bool/* movementInform*/)
+{
+ AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED);
+ if (!active)
+ return;
+
+ owner->Dismount();
+ owner->RemoveUnitFlag(UnitFlags(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->RemovePlayerFlag(PLAYER_FLAGS_TAXI_BENCHMARK);
+}
+
+uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
+{
+ if (_currentNode >= _path.size())
+ return _path.size();
+
+ uint32 curMapId = _path[_currentNode]->ContinentID;
+ for (uint32 itr = _currentNode; itr < _path.size(); ++itr)
+ {
+ if (_path[itr]->ContinentID != curMapId)
+ return itr;
+ }
+
+ return _path.size();
+}
+
+bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntry const* p2)
+{
+ return p1->ContinentID != p2->ContinentID || std::pow(p1->Loc.X - p2->Loc.X, 2) + std::pow(p1->Loc.Y - p2->Loc.Y, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ;
+}
+
+void FlightPathMovementGenerator::LoadPath(Player* owner, uint32 startNode /*= 0*/)
+{
+ _path.clear();
+ _currentNode = startNode;
+ _pointsForPathSwitch.clear();
+ 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;
+ sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost);
+ if (path > sTaxiPathNodesByPath.size())
+ return;
+
+ TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path];
+ if (!nodes.empty())
+ {
+ TaxiPathNodeEntry const* start = nodes[0];
+ TaxiPathNodeEntry const* end = nodes[nodes.size() - 1];
+ bool passedPreviousSegmentProximityCheck = false;
+ for (uint32 i = 0; i < nodes.size(); ++i)
+ {
+ if (passedPreviousSegmentProximityCheck || !src || _path.empty() || IsNodeIncludedInShortenedPath(_path.back(), nodes[i]))
+ {
+ if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) &&
+ (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1)))
+ {
+ passedPreviousSegmentProximityCheck = true;
+ _path.push_back(nodes[i]);
+ }
+ }
+ else
+ {
+ _path.pop_back();
+ --_pointsForPathSwitch.back().PathIndex;
+ }
+ }
+ }
+
+ _pointsForPathSwitch.push_back({ uint32(_path.size() - 1), int64(ceil(cost * discount)) });
+ }
}
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
@@ -205,29 +237,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->Loc.X;
- y = node->Loc.Y;
- z = node->Loc.Z;
- 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]->ContinentID; //! MapId of last node
_preloadTargetNode = nodeCount - 3;
_endGridX = _path[nodeCount - 1]->Loc.X;
@@ -236,15 +261,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 4f850ab3147..6dc32e9ec84 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 "MovementGenerator.h"
#include "PathMovementBase.h"
@@ -26,46 +26,46 @@ class Player;
struct TaxiPathNodeEntry;
/**
-* 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, std::vector<TaxiPathNodeEntry const*>>
{
-public:
- explicit FlightPathMovementGenerator();
-
- void LoadPath(Player* player, uint32 startNode = 0);
- void DoInitialize(Player*);
- void DoReset(Player*);
- void DoFinalize(Player*);
- bool DoUpdate(Player*, uint32);
- MovementGeneratorType GetMovementGeneratorType() const override;
+ public:
+ explicit FlightPathMovementGenerator();
- std::vector<TaxiPathNodeEntry const*> 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:
+ std::vector<TaxiPathNodeEntry const*> 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, uint32 startNode = 0);
+ void SetCurrentNodeAfterTeleport();
+ void SkipCurrentNode() { ++_currentNode; }
+ void DoEventIfAny(Player* owner, TaxiPathNodeEntry const* node, bool departure);
+ void InitEndGridInfo();
+ void PreloadEndGrid();
- struct TaxiNodeChangeInfo
- {
- uint32 PathIndex;
- int64 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;
+ int64 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 9c83684dbca..c4b3e8cc571 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 347cccdafc6..0140e991ac6 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 d7a228eef53..902803e41e7 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 f9d46c23583..d00e6e3a73a 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 254fcd34110..70f6861f8eb 100644
--- a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.cpp
@@ -18,27 +18,67 @@
#include "GenericMovementGenerator.h"
#include "Creature.h"
#include "CreatureAI.h"
+#include "MovementDefines.h"
#include "MoveSpline.h"
#include "ObjectAccessor.h"
#include "Unit.h"
+GenericMovementGenerator::GenericMovementGenerator(Movement::MoveSplineInit&& splineInit, MovementGeneratorType type, uint32 id,
+ uint32 arrivalSpellId /*= 0*/, ObjectGuid const& arrivalSpellTargetGuid /*= ObjectGuid::Empty*/)
+ : _splineInit(std::move(splineInit)), _type(type), _pointId(id), _duration(0),
+ _arrivalSpellId(arrivalSpellId), _arrivalSpellTargetGuid(arrivalSpellTargetGuid)
+{
+ 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)
@@ -47,6 +87,8 @@ void GenericMovementGenerator::MovementInform(Unit* owner)
owner->CastSpell(ObjectAccessor::GetUnit(*owner, _arrivalSpellTargetGuid), _arrivalSpellId, true);
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 6db8009b897..bd9bfcf9680 100644
--- a/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/GenericMovementGenerator.h
@@ -29,13 +29,14 @@ enum MovementGeneratorType : uint8;
class GenericMovementGenerator : public MovementGenerator
{
public:
- explicit GenericMovementGenerator(Movement::MoveSplineInit&& splineInit, MovementGeneratorType type, uint32 id, uint32 arrivalSpellId = 0, ObjectGuid const& arrivalSpellTargetGuid = ObjectGuid::Empty)
- : _splineInit(std::move(splineInit)), _type(type), _pointId(id), _duration(0), _arrivalSpellId(arrivalSpellId), _arrivalSpellTargetGuid(arrivalSpellTargetGuid) { }
+ explicit GenericMovementGenerator(Movement::MoveSplineInit&& splineInit, MovementGeneratorType type, uint32 id,
+ uint32 arrivalSpellId = 0, ObjectGuid const& arrivalSpellTargetGuid = ObjectGuid::Empty);
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 d058b70ef6f..46c14e27fb2 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -18,11 +18,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
@@ -38,29 +49,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>
@@ -69,23 +85,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>
@@ -94,6 +97,8 @@ void HomeMovementGenerator<T>::DoReset(T*) { }
template<>
void HomeMovementGenerator<Creature>::DoReset(Creature* owner)
{
+ RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
+
DoInitialize(owner);
}
@@ -106,6 +111,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 3126b2ac6e2..3c0dbf696a9 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
@@ -24,20 +24,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 2089c0fc18d..a91a7c65df5 100644
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
@@ -18,20 +18,42 @@
#include "IdleMovementGenerator.h"
#include "Creature.h"
#include "CreatureAI.h"
+#include "G3DPosition.hpp"
#include "MovementDefines.h"
-#include <G3D/g3dmath.h>
+#include "MoveSpline.h"
+#include "MoveSplineInit.h"
+#include "Unit.h"
+#include "advstd.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,79 +63,149 @@ 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();
+ */
+}
+void RotateMovementGenerator::Reset(Unit* owner)
+{
+ RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
- owner->AddUnitState(UNIT_STATE_ROTATING);
- owner->AttackStop();
+ Initialize(owner);
}
bool RotateMovementGenerator::Update(Unit* owner, uint32 diff)
{
+ if (!owner)
+ return false;
+
float angle = owner->GetOrientation();
angle += (float(diff) * static_cast<float>(M_PI * 2) / _maxDuration) * (_direction == ROTATE_DIRECTION_LEFT ? 1.0f : -1.0f);
- angle = G3D::wrap(angle, 0.0f, float(G3D::twoPi()));
+ angle = advstd::clamp(angle, 0.0f, static_cast<float>(M_PI * 2));
- owner->SetOrientation(angle); // UpdateSplinePosition does not set orientation with UNIT_STATE_ROTATING
- owner->SetFacingTo(angle); // Send spline movement to clients
+ Movement::MoveSplineInit init(owner);
+ init.MoveTo(PositionToVector3(*owner), false);
+ if (!owner->GetTransGUID().IsEmpty())
+ 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->GetTransGUID().IsEmpty())
+ 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;
@@ -121,13 +213,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 5e41413c019..46d5d4d932b 100755
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
@@ -26,51 +26,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 5b9be57ff7f..a11f06a20c3 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 bb78cc881e2..7418f345b41 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
@@ -28,6 +28,18 @@
//----- Point Movement Generator
template<class T>
+PointMovementGenerator<T>::PointMovementGenerator(uint32 id, float x, float y, float z, bool generatePath, float speed /*= 0.0f*/, Optional<float> finalOrient /*= {}*/,
+ Unit const* faceTarget /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/)
+ : _movementId(id), _destination(x, y, z), _speed(speed), _generatePath(generatePath), _finalOrient(finalOrient),
+ i_faceTarget(faceTarget), i_spellEffectExtra(spellEffectExtraData)
+{
+ 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;
@@ -36,17 +48,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;
}
@@ -72,25 +85,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);
@@ -105,23 +133,31 @@ bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/)
creature->SignalFormationMovement(_destination, _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>
@@ -134,30 +170,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>, Unit const*, Movement::SpellEffectExtraData const*);
+template PointMovementGenerator<Creature>::PointMovementGenerator(uint32, float, float, float, bool, float, Optional<float>, Unit const*, Movement::SpellEffectExtraData const*);
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 bd3c1ad3380..4a2f1a2631a 100644
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
@@ -29,19 +29,23 @@ namespace Movement
}
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, Unit const* faceTarget = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr, Optional<float> finalOrient = {}) : _movementId(id), _destination(x, y, z), _speed(speed), i_faceTarget(faceTarget), i_spellEffectExtra(spellEffectExtraData), _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 = {},
+ Unit const* faceTarget = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr);
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*);
@@ -49,22 +53,20 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG
uint32 _movementId;
Position _destination;
float _speed;
- Unit const* i_faceTarget;
- Movement::SpellEffectExtraData const* i_spellEffectExtra;
bool _generatePath;
- bool _recalculateSpeed;
- bool _interrupt;
//! if set then unit will turn to specified _orient in provided _pos
Optional<float> _finalOrient;
+ Unit const* i_faceTarget;
+ Movement::SpellEffectExtraData const* i_spellEffectExtra;
};
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 8c9844df6af..26d4268d15e 100644
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -19,15 +19,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() = default;
+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
@@ -43,10 +49,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();
@@ -58,22 +66,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);
}
@@ -88,14 +87,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;
@@ -116,6 +113,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);
@@ -136,21 +135,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 1788161f70d..cdb523e5d20 100644
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
@@ -25,19 +25,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*);
@@ -46,7 +47,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 476766aa1f6..3b72deafe53 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 8abe8e81e48..05ccc6a69fd 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 0017f89e9f8..56a1bb1fb2f 100644
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -18,6 +18,7 @@
#include "WaypointMovementGenerator.h"
#include "Creature.h"
#include "CreatureAI.h"
+#include "Errors.h"
#include "Log.h"
#include "Map.h"
#include "MovementDefines.h"
@@ -27,15 +28,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
@@ -43,51 +51,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 (%s DB GUID: " UI64FMTD ") doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), 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->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;
@@ -96,103 +243,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->GetTransport() != nullptr;
+ bool const transportPath = !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);
@@ -229,95 +378,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->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 1be8373cfd4..c808cfb5492 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -18,19 +18,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;
-struct TaxiPathNodeEntry;
+class Unit;
struct WaypointPath;
template<class T>
@@ -42,36 +35,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 b5da3c00b0f..056ee76a5d8 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2579,8 +2579,10 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode
target->SetCanTransitionBetweenSwimAndFly(apply);
if (target->SetCanFly(apply))
+ {
if (!apply && !target->IsLevitating())
target->GetMotionMaster()->MoveFall();
+ }
}
void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -2847,8 +2849,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;
@@ -2856,7 +2856,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;
@@ -2865,15 +2865,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
@@ -2887,13 +2883,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 b9137c8ab91..5a48f16948b 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2216,11 +2216,7 @@ void Spell::EffectDistract()
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()
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp
index 7e0c3624cd5..3be61113c6d 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 "PhasingHandler.h"
#include "Player.h"
@@ -152,13 +151,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;
@@ -197,13 +192,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->Loc);
return true;
@@ -239,13 +230,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* map = sMapMgr->CreateBaseMap(mapId);
float z = std::max(map->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y));
@@ -289,13 +276,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;
@@ -352,13 +335,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* map = sMapMgr->CreateBaseMap(mapId);
z = std::max(map->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y));
@@ -400,13 +379,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->ContinentID, node->Pos.X, node->Pos.Y, node->Pos.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
player->TeleportTo(at->ContinentID, at->Pos.X, at->Pos.Y, at->Pos.Z, player->GetOrientation());
return true;
@@ -519,13 +490,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->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y));
@@ -580,13 +547,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;
@@ -614,13 +577,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;
@@ -658,13 +620,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 67358c03243..2f5c92a0082 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 "ObjectMgr.h"
#include "PhasingHandler.h"
@@ -144,13 +143,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 ffc895f159a..db5c9be254a 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -20,12 +20,10 @@
#include "ArenaTeamMgr.h"
#include "CellImpl.h"
#include "CharacterCache.h"
-#include "ChaseMovementGenerator.h"
#include "Chat.h"
#include "DatabaseEnv.h"
#include "DB2Stores.h"
#include "DisableMgr.h"
-#include "FollowMovementGenerator.h"
#include "GridNotifiers.h"
#include "Group.h"
#include "GroupMgr.h"
@@ -41,7 +39,6 @@
#include "MMapFactory.h"
#include "MotionMaster.h"
#include "MovementDefines.h"
-#include "MovementGenerator.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
@@ -459,13 +456,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;
@@ -494,13 +487,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());
}
@@ -590,14 +579,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;
@@ -899,12 +884,7 @@ public:
return false;
}
- // stop flight if need
- if (target->IsInFlight())
- {
- target->GetMotionMaster()->MovementExpired();
- target->CleanupAfterTaxiFlight();
- }
+ target->FinishTaxiFlight();
target->Recall();
return true;
@@ -2210,20 +2190,19 @@ public:
handler->PSendSysMessage(LANG_MOVEGENS_LIST, (unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), unit->GetGUID().ToString().c_str());
- 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);
@@ -2238,45 +2217,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().ToString().c_str());
+ else if (info.TargetGUID.IsPlayer())
+ handler->PSendSysMessage(LANG_MOVEGENS_CHASE_PLAYER, info.TargetName.c_str(), info.TargetGUID.ToString().c_str());
else
- handler->PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, target->GetName().c_str(), target->GetGUID().ToString().c_str());
+ handler->PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, info.TargetName.c_str(), info.TargetGUID.ToString().c_str());
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().ToString().c_str());
+ else if (info.TargetGUID.IsPlayer())
+ handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_PLAYER, info.TargetName.c_str(), info.TargetGUID.ToString().c_str());
else
- handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, target->GetName().c_str(), target->GetGUID().ToString().c_str());
+ handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, info.TargetName.c_str(), info.TargetGUID.ToString().c_str());
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;
@@ -2287,7 +2254,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 c5ec5bd5f75..c6b0805de0f 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -1370,7 +1370,7 @@ public:
return true;
}
- //npc unfollow handling
+ // npc unfollow handling
static bool HandleNpcUnFollowCommand(ChatHandler* handler, char const* /*args*/)
{
Player* player = handler->GetSession()->GetPlayer();
@@ -1383,26 +1383,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 93b55b5d1ef..dc1ac20ac86 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 "PhasingHandler.h"
#include "Player.h"
@@ -186,13 +185,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);
}
@@ -284,13 +279,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);
}
@@ -303,7 +294,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);
@@ -314,7 +305,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);
@@ -322,7 +313,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);
@@ -330,16 +321,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/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp
index 73b2583c5da..0a21c2da912 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp
@@ -538,7 +538,7 @@ public:
Talk(SAY_ATIESH);
me->SetFacingTo(me->GetAbsoluteAngle(player));
me->ClearUnitState(UNIT_STATE_MOVING);
- me->GetMotionMaster()->MoveDistract(7 * IN_MILLISECONDS);
+ me->GetMotionMaster()->MoveDistract(7 * IN_MILLISECONDS, me->GetAbsoluteAngle(who));
break;
}
}
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
index 04e7e60d7c5..6f8157e3306 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
@@ -1021,7 +1021,7 @@ void PretendToDie(Creature* creature)
creature->RemoveAllAuras();
creature->SetHealth(0);
creature->AddUnitFlag(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 5314fa4388b..d94bf9c3ce5 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -391,7 +391,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 eebd0736f39..a92a344c6fb 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 50687a89ac9..f3812ae24b2 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
@@ -322,7 +322,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());
}
}
@@ -337,7 +337,7 @@ public:
wait = 1000;
if (!me->GetVictim())
return;
- me->GetMotionMaster()->Clear(false);
+ me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveFleeing(me->GetVictim());
}
else wait -= diff;
@@ -602,7 +602,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)));
}
}
@@ -677,7 +677,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 935b5b21515..684a98927ee 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp
@@ -128,19 +128,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 37040fde6d7..fd73ccfbb46 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/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp
index 87e7d87458d..c959dd6a251 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp
@@ -407,7 +407,7 @@ public:
if (!HasProtected)
{
- me->GetMotionMaster()->Clear(false);
+ me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
// All members of raid must get this buff
@@ -494,7 +494,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/Firelands/boss_alysrazor.cpp b/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp
index e0198304477..9af59225fdb 100644
--- a/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp
+++ b/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp
@@ -367,7 +367,7 @@ class npc_molten_barrage : public CreatureScript
void AttackStart(Unit* target) override
{
if (target)
- me->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f, MOTION_SLOT_IDLE);
+ me->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f, MOTION_SLOT_DEFAULT);
}
void IsSummonedBy(Unit* /*summoner*/) override
diff --git a/src/server/scripts/Kalimdor/Firelands/firelands.cpp b/src/server/scripts/Kalimdor/Firelands/firelands.cpp
index 6367bc88611..aaf01b371f2 100644
--- a/src/server/scripts/Kalimdor/Firelands/firelands.cpp
+++ b/src/server/scripts/Kalimdor/Firelands/firelands.cpp
@@ -79,7 +79,7 @@ void firelands_bossAI::EnterEvadeMode(EvadeReason why)
{
if (Unit* owner = me->GetCharmerOrOwner())
{
- me->GetMotionMaster()->Clear(false);
+ me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
}
else
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 10df5692fa5..b07d285b8e8 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
@@ -824,7 +824,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 6fa26569833..c2bea8f0443 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 acfe6234da1..a9f82a9fb46 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h
@@ -19,21 +19,20 @@
#define HALLS_OF_REFLECTION_H_
#include "CreatureAIImpl.h"
-#include "EventProcessor.h"
-#include "ObjectGuid.h"
class Unit;
#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
{
@@ -198,29 +197,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 6c7694feebb..7609c5c6992 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);
}
}
@@ -937,7 +937,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);
}
@@ -1201,7 +1201,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 00fd567bb2a..0ec4ace8d67 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -22,6 +22,7 @@
#include "MoveSplineInit.h"
#include "ObjectAccessor.h"
#include "Player.h"
+#include "PointMovementGenerator.h"
#include "ScriptedCreature.h"
#include "SpellAuras.h"
#include "SpellScript.h"
@@ -241,8 +242,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);
@@ -472,7 +481,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 d09530233f7..7343575dade 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -242,8 +242,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 6d249e6ce16..a1844f131c5 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -394,8 +394,7 @@ class boss_sindragosa : public CreatureScript
me->SetDisableGravity(false);
me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false);
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 607c0952c34..9ab10f8d876 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -418,10 +418,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)
{
}
@@ -714,7 +714,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:
{
@@ -1667,7 +1667,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 c521d04512d..422fd57eb0b 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 66915182e6b..b3ed1c677c1 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -500,7 +500,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 318daa780f1..10a669be163 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
@@ -417,21 +417,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 6e52598d11a..706bf99204a 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 2bf2ae3b58f..e1ac92ff165 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -1134,7 +1134,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 fc143e2727b..b78f7289f1e 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
@@ -335,7 +335,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 3e3b103f312..01c7f92d576 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp
@@ -641,7 +641,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 a8e9c27b93a..6b4b3a1aa1f 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 511bfde03d0..1505be8eca0 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
@@ -363,7 +363,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 68ad8bfacd0..da00bc6e3f5 100644
--- a/src/server/scripts/Northrend/zone_borean_tundra.cpp
+++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp
@@ -718,7 +718,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 021fb8e7701..3dff0fff0ba 100644
--- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp
+++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
@@ -898,7 +898,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 4807a0fbcb5..bd0ff4a4ad2 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 36d04389514..76d31bd203e 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 1a84c014d0f..1034a1f8039 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp
@@ -248,7 +248,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;
@@ -266,7 +266,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 8bacf1d283d..7d9a3956fd4 100644
--- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
+++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
@@ -287,9 +287,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();
@@ -328,7 +325,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 1dbdf9aabcc..547b97df956 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 213c578aae7..f626159a650 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 39b16715a71..10e814dc1e9 100644
--- a/src/server/scripts/World/boss_emerald_dragons.cpp
+++ b/src/server/scripts/World/boss_emerald_dragons.cpp
@@ -198,13 +198,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 55801cdc7b2..83feb183d5c 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -2821,7 +2821,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 (Creature* creature = who->ToCreature())
creature->SetDisplayFromModel(0);
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index cb6e515885e..b26b2ae45dd 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -4035,7 +4035,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