Core/Movement: MotionMaster reimplementation (#21888)
Internal structure and handling changes, nothing behavioural (or thats the intention at least). (cherry picked from commit 982643cd96790ffc54e7a3e507469649f3b074d2)
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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->GetMotionMaster()->MoveFormation(id, point, moveType, !member->IsWithinDist(_leader, dist + MAX_DESYNC), orientation);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -849,7 +849,6 @@ void Map::ScriptsProcess()
|
||||
if (!cSource->IsAlive())
|
||||
return;
|
||||
|
||||
cSource->GetMotionMaster()->MovementExpired();
|
||||
cSource->GetMotionMaster()->MoveIdle();
|
||||
|
||||
switch (step.script->Movement.MovementType)
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
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:
|
||||
bool operator()(MovementGenerator const* a, MovementGenerator const* b) const;
|
||||
};
|
||||
|
||||
struct MovementGeneratorInformation
|
||||
{
|
||||
MovementGeneratorInformation(MovementGeneratorType type, ObjectGuid targetGUID, std::string const& targetName);
|
||||
|
||||
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 Resolve() { Action(); }
|
||||
|
||||
std::function<void()> Action;
|
||||
uint8 Type;
|
||||
};
|
||||
|
||||
class TC_GAME_API MotionMaster
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
explicit MotionMaster(Unit* unit);
|
||||
~MotionMaster();
|
||||
|
||||
bool empty() const { return (_top < 0); }
|
||||
int size() const { return _top + 1; }
|
||||
MovementGenerator* top() const;
|
||||
|
||||
void Initialize();
|
||||
void InitDefault();
|
||||
|
||||
void UpdateMotion(uint32 diff);
|
||||
|
||||
void Clear(bool reset = true);
|
||||
void Clear(MovementSlot slot);
|
||||
void MovementExpired(bool reset = true);
|
||||
void InitializeDefault();
|
||||
|
||||
bool Empty() const;
|
||||
uint32 Size() const;
|
||||
std::vector<MovementGeneratorInformation> GetMovementGeneratorsInformation() const;
|
||||
MovementSlot GetCurrentSlot() const;
|
||||
MovementGenerator* GetCurrentMovementGenerator() const;
|
||||
MovementGeneratorType GetCurrentMovementGeneratorType() const;
|
||||
MovementGeneratorType GetMotionSlotType(MovementSlot slot) const;
|
||||
MovementGenerator* GetMotionSlot(MovementSlot slot) 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;
|
||||
typedef std::unique_ptr<MovementGenerator, MovementGeneratorDeleter> MovementGeneratorPointer;
|
||||
typedef std::multiset<MovementGenerator*, MovementGeneratorComparator> MotionMasterContainer;
|
||||
typedef std::unordered_multimap<uint32, MovementGenerator const*> MotionMasterUnitStatesContainer;
|
||||
|
||||
void pop();
|
||||
void AddFlag(uint8 const flag) { _flags |= flag; }
|
||||
bool HasFlag(uint8 const flag) const { return (_flags & flag) != 0; }
|
||||
void RemoveFlag(uint8 const flag) { _flags &= ~flag; }
|
||||
|
||||
bool NeedInitTop() const;
|
||||
void InitTop();
|
||||
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 Mutate(MovementGenerator* m, 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();
|
||||
|
||||
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();
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
// 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; }
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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*);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
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
|
||||
bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 diff)
|
||||
{
|
||||
return TIMED_FLEEING_MOTION_TYPE;
|
||||
}
|
||||
|
||||
bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
|
||||
//----------------------------------------------------//
|
||||
|
||||
#define FLIGHT_TRAVEL_UPDATE 100
|
||||
#define TIMEDIFF_NEXT_WP 250
|
||||
#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.f * 40.f)
|
||||
@@ -39,6 +37,125 @@ FlightPathMovementGenerator::FlightPathMovementGenerator()
|
||||
_endGridY = 0.0f;
|
||||
_endMapId = 0;
|
||||
_preloadTargetNode = 0;
|
||||
|
||||
Mode = MOTION_MODE_DEFAULT;
|
||||
Priority = MOTION_PRIORITY_HIGHEST;
|
||||
Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING;
|
||||
BaseUnitState = UNIT_STATE_IN_FLIGHT;
|
||||
}
|
||||
|
||||
MovementGeneratorType FlightPathMovementGenerator::GetMovementGeneratorType() const
|
||||
{
|
||||
return FLIGHT_MOTION_TYPE;
|
||||
}
|
||||
|
||||
bool FlightPathMovementGenerator::GetResetPosition(Unit* /*owner*/, float& x, float& y, float& z)
|
||||
{
|
||||
TaxiPathNodeEntry const* node = _path[_currentNode];
|
||||
x = node->Loc.X;
|
||||
y = node->Loc.Y;
|
||||
z = node->Loc.Z;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::DoInitialize(Player* owner)
|
||||
{
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING);
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED);
|
||||
|
||||
DoReset(owner);
|
||||
InitEndGridInfo();
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::DoReset(Player* owner)
|
||||
{
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
|
||||
|
||||
owner->CombatStopWithPets();
|
||||
owner->AddUnitFlag(UnitFlags(UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT));
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
uint32 end = GetPathAtMapEnd();
|
||||
for (uint32 i = GetCurrentNode(); i != end; ++i)
|
||||
{
|
||||
G3D::Vector3 vertice(_path[i]->Loc.X, _path[i]->Loc.Y, _path[i]->Loc.Z);
|
||||
init.Path().push_back(vertice);
|
||||
}
|
||||
init.SetFirstPointId(GetCurrentNode());
|
||||
init.SetFly();
|
||||
init.SetSmooth();
|
||||
init.SetUncompressed();
|
||||
init.SetWalk(true);
|
||||
init.SetVelocity(PLAYER_FLIGHT_SPEED);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
bool FlightPathMovementGenerator::DoUpdate(Player* owner, uint32 /*diff*/)
|
||||
{
|
||||
if (!owner)
|
||||
return false;
|
||||
|
||||
uint32 pointId = owner->movespline->currentPathIdx() < 0 ? 0 : owner->movespline->currentPathIdx();
|
||||
if (pointId > _currentNode)
|
||||
{
|
||||
bool departureEvent = true;
|
||||
do
|
||||
{
|
||||
DoEventIfAny(owner, _path[_currentNode], departureEvent);
|
||||
while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode)
|
||||
{
|
||||
_pointsForPathSwitch.pop_front();
|
||||
owner->m_taxi.NextTaxiDestination();
|
||||
if (!_pointsForPathSwitch.empty())
|
||||
{
|
||||
owner->UpdateCriteria(CriteriaType::MoneySpentOnTaxis, _pointsForPathSwitch.front().Cost);
|
||||
owner->ModifyMoney(-_pointsForPathSwitch.front().Cost);
|
||||
}
|
||||
}
|
||||
|
||||
if (pointId == _currentNode)
|
||||
break;
|
||||
|
||||
if (_currentNode == _preloadTargetNode)
|
||||
PreloadEndGrid();
|
||||
|
||||
_currentNode += departureEvent ? 1 : 0;
|
||||
departureEvent = !departureEvent;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
if (_currentNode >= (_path.size() - 1))
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::DoDeactivate(Player* /*owner*/)
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::DoFinalize(Player* owner, bool active, bool/* movementInform*/)
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED);
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
owner->Dismount();
|
||||
owner->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
|
||||
@@ -48,8 +165,10 @@ uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
|
||||
|
||||
uint32 curMapId = _path[_currentNode]->ContinentID;
|
||||
for (uint32 itr = _currentNode; itr < _path.size(); ++itr)
|
||||
{
|
||||
if (_path[itr]->ContinentID != curMapId)
|
||||
return itr;
|
||||
}
|
||||
|
||||
return _path.size();
|
||||
}
|
||||
@@ -59,13 +178,13 @@ bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntr
|
||||
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* player, uint32 startNode /*= 0*/)
|
||||
void FlightPathMovementGenerator::LoadPath(Player* owner, uint32 startNode /*= 0*/)
|
||||
{
|
||||
_path.clear();
|
||||
_currentNode = startNode;
|
||||
_pointsForPathSwitch.clear();
|
||||
std::deque<uint32> const& taxi = player->m_taxi.GetPath();
|
||||
float discount = player->GetReputationPriceDiscount(player->m_taxi.GetFlightMasterFactionTemplate());
|
||||
std::deque<uint32> const& taxi = owner->m_taxi.GetPath();
|
||||
float discount = owner->GetReputationPriceDiscount(owner->m_taxi.GetFlightMasterFactionTemplate());
|
||||
for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++)
|
||||
{
|
||||
uint32 path, cost;
|
||||
@@ -102,93 +221,6 @@ void FlightPathMovementGenerator::LoadPath(Player* player, uint32 startNode /*=
|
||||
}
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::DoInitialize(Player* player)
|
||||
{
|
||||
Reset(player);
|
||||
InitEndGridInfo();
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::DoFinalize(Player* player)
|
||||
{
|
||||
// remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack)
|
||||
player->ClearUnitState(UNIT_STATE_IN_FLIGHT);
|
||||
|
||||
player->Dismount();
|
||||
player->RemoveUnitFlag(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);
|
||||
uint32 end = GetPathAtMapEnd();
|
||||
for (uint32 i = GetCurrentNode(); i != end; ++i)
|
||||
{
|
||||
G3D::Vector3 vertice(_path[i]->Loc.X, _path[i]->Loc.Y, _path[i]->Loc.Z);
|
||||
init.Path().push_back(vertice);
|
||||
}
|
||||
init.SetFirstPointId(GetCurrentNode());
|
||||
init.SetFly();
|
||||
init.SetSmooth();
|
||||
init.SetUncompressed();
|
||||
init.SetWalk(true);
|
||||
init.SetVelocity(PLAYER_FLIGHT_SPEED);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
|
||||
{
|
||||
uint32 pointId = (uint32)player->movespline->currentPathIdx();
|
||||
if (pointId > _currentNode)
|
||||
{
|
||||
bool departureEvent = true;
|
||||
do
|
||||
{
|
||||
DoEventIfAny(player, _path[_currentNode], departureEvent);
|
||||
while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode)
|
||||
{
|
||||
_pointsForPathSwitch.pop_front();
|
||||
player->m_taxi.NextTaxiDestination();
|
||||
if (!_pointsForPathSwitch.empty())
|
||||
{
|
||||
player->UpdateCriteria(CriteriaType::MoneySpentOnTaxis, _pointsForPathSwitch.front().Cost);
|
||||
player->ModifyMoney(-_pointsForPathSwitch.front().Cost);
|
||||
}
|
||||
}
|
||||
|
||||
if (pointId == _currentNode)
|
||||
break;
|
||||
|
||||
if (_currentNode == _preloadTargetNode)
|
||||
PreloadEndGrid();
|
||||
_currentNode += departureEvent ? 1 : 0;
|
||||
departureEvent = !departureEvent;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
return _currentNode < (_path.size() - 1);
|
||||
}
|
||||
|
||||
MovementGeneratorType FlightPathMovementGenerator::GetMovementGeneratorType() const
|
||||
{
|
||||
return FLIGHT_MOTION_TYPE;
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
|
||||
{
|
||||
if (_path.empty() || _currentNode >= _path.size())
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
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;
|
||||
MovementGeneratorType GetMovementGeneratorType() const override;
|
||||
bool GetResetPosition(Unit* owner, float& x, float& y, float& z) override;
|
||||
|
||||
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);
|
||||
void DoInitialize(Player*);
|
||||
void DoReset(Player*);
|
||||
bool DoUpdate(Player*, uint32);
|
||||
void DoDeactivate(Player*);
|
||||
void DoFinalize(Player*, bool, bool);
|
||||
|
||||
bool GetResetPos(Player*, float& x, float& y, float& z);
|
||||
void InitEndGridInfo();
|
||||
void PreloadEndGrid();
|
||||
std::vector<TaxiPathNodeEntry const*> const& GetPath() { return _path; }
|
||||
uint32 GetPathAtMapEnd() const;
|
||||
bool HasArrived() const { return _currentNode >= _path.size(); }
|
||||
|
||||
private:
|
||||
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();
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
struct TaxiNodeChangeInfo
|
||||
{
|
||||
uint32 PathIndex;
|
||||
int64 Cost;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::DoFinalize(Creature* owner)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
if (owner->movespline->Finalized())
|
||||
MovementInform(owner);
|
||||
{
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY);
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::DoReset(Creature* owner)
|
||||
void FormationMovementGenerator::DoDeactivate(Creature* owner)
|
||||
{
|
||||
owner->StopMoving();
|
||||
DoInitialize(owner);
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::DoFinalize(Creature* owner, bool active, bool movementInform)
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
_duration.Update(diff);
|
||||
if (_duration.Passed())
|
||||
if (!owner || HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED))
|
||||
return false;
|
||||
|
||||
return !owner->movespline->Finalized();
|
||||
_duration.Update(diff);
|
||||
if (_duration.Passed() || owner->movespline->Finalized())
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GenericMovementGenerator::Finalize(Unit* owner)
|
||||
void GenericMovementGenerator::Deactivate(Unit*)
|
||||
{
|
||||
MovementInform(owner);
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
|
||||
}
|
||||
|
||||
void GenericMovementGenerator::Finalize(Unit* owner, bool/* active*/, bool movementInform)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,31 +85,20 @@ void HomeMovementGenerator<T>::DoInitialize(T*) { }
|
||||
template<>
|
||||
void HomeMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
{
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING);
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED);
|
||||
|
||||
SetTargetLocation(owner);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
//----------------------------------------------------//
|
||||
|
||||
RotateMovementGenerator::RotateMovementGenerator(uint32 id, uint32 time, RotateDirection direction) : _id(id), _duration(time), _maxDuration(time), _direction(direction)
|
||||
{
|
||||
Mode = MOTION_MODE_DEFAULT;
|
||||
Priority = MOTION_PRIORITY_NORMAL;
|
||||
Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING;
|
||||
BaseUnitState = UNIT_STATE_ROTATING;
|
||||
}
|
||||
|
||||
void RotateMovementGenerator::Initialize(Unit* owner)
|
||||
{
|
||||
if (!owner->IsStopped())
|
||||
owner->StopMoving();
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING);
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED);
|
||||
|
||||
if (owner->GetVictim())
|
||||
owner->SetInFront(owner->GetVictim());
|
||||
owner->StopMoving();
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_ROTATING);
|
||||
owner->AttackStop();
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void RotateMovementGenerator::Deactivate(Unit*)
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
|
||||
}
|
||||
|
||||
void RotateMovementGenerator::Finalize(Unit* owner, bool/* active*/, bool movementInform)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void RotateMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_ROTATING);
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
owner->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------//
|
||||
|
||||
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);
|
||||
|
||||
Initialize(owner);
|
||||
}
|
||||
|
||||
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 (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature())
|
||||
if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) && owner->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
float angle = owner->ToCreature()->GetHomePosition().GetOrientation();
|
||||
owner->SetFacingTo(angle);
|
||||
}
|
||||
}
|
||||
|
||||
bool DistractMovementGenerator::Update(Unit* /*owner*/, uint32 diff)
|
||||
{
|
||||
if (diff > _timer)
|
||||
return false;
|
||||
|
||||
_timer -= diff;
|
||||
return true;
|
||||
}
|
||||
|
||||
MovementGeneratorType DistractMovementGenerator::GetMovementGeneratorType() const
|
||||
{
|
||||
return DISTRACT_MOTION_TYPE;
|
||||
@@ -121,13 +213,20 @@ MovementGeneratorType DistractMovementGenerator::GetMovementGeneratorType() cons
|
||||
|
||||
//----------------------------------------------------//
|
||||
|
||||
AssistanceDistractMovementGenerator::AssistanceDistractMovementGenerator(uint32 timer, float orientation) : DistractMovementGenerator(timer, orientation)
|
||||
{
|
||||
Priority = MOTION_PRIORITY_NORMAL;
|
||||
}
|
||||
|
||||
void AssistanceDistractMovementGenerator::Finalize(Unit* owner, bool/* active*/, bool movementInform)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void AssistanceDistractMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_DISTRACTED);
|
||||
owner->ToCreature()->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -27,6 +27,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
|
||||
{
|
||||
@@ -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;
|
||||
}
|
||||
@@ -71,6 +84,15 @@ void PointMovementGenerator<T>::DoInitialize(T* owner)
|
||||
creature->SignalFormationMovement(_destination, _movementId);
|
||||
}
|
||||
|
||||
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*/)
|
||||
{
|
||||
@@ -78,19 +100,25 @@ bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/)
|
||||
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();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::DoFinalize(T* owner)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
if (owner->movespline->Finalized())
|
||||
MovementInform(owner);
|
||||
{
|
||||
MovementGenerator::RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY);
|
||||
MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::DoReset(T* owner)
|
||||
void PointMovementGenerator<T>::DoDeactivate(T* owner)
|
||||
{
|
||||
owner->StopMoving();
|
||||
DoInitialize(owner);
|
||||
MovementGenerator::AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::DoFinalize(T* owner, bool active, bool movementInform)
|
||||
{
|
||||
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
|
||||
|
||||
void AssistanceMovementGenerator::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();
|
||||
ownerCreature->SetNoCallAssistance(false);
|
||||
ownerCreature->CallAssistance();
|
||||
if (ownerCreature->IsAlive())
|
||||
ownerCreature->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY));
|
||||
}
|
||||
}
|
||||
|
||||
MovementGeneratorType AssistanceMovementGenerator::GetMovementGeneratorType() const
|
||||
{
|
||||
return ASSISTANCE_MOTION_TYPE;
|
||||
}
|
||||
|
||||
void AssistanceMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -57,23 +65,14 @@ void RandomMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
_path = nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
uint32 SplineChainMovementGenerator::SendPathSpline(Unit* me, Movement::PointsArray const& wp) const
|
||||
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)
|
||||
{
|
||||
uint32 numWp = wp.size();
|
||||
ASSERT(numWp > 1 && "Every path must have source & destination");
|
||||
Movement::MoveSplineInit init(me);
|
||||
if (numWp > 2)
|
||||
init.MovebyPath(wp);
|
||||
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;
|
||||
|
||||
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 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)
|
||||
{
|
||||
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
|
||||
{
|
||||
_msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u);
|
||||
SendSplineFor(me, _nextIndex, _msToNext);
|
||||
++_nextIndex;
|
||||
if (_nextIndex >= _chainSize)
|
||||
_msToNext = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TC_LOG_ERROR("movement", "SplineChainMovementGenerator::Initialize - empty spline chain passed for %s.", me->GetGUID().ToString().c_str());
|
||||
}
|
||||
}
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING);
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED);
|
||||
|
||||
void SplineChainMovementGenerator::Finalize(Unit* me)
|
||||
{
|
||||
if (!finished)
|
||||
if (!_chainSize)
|
||||
{
|
||||
TC_LOG_ERROR("movement", "SplineChainMovementGenerator::Initialize: couldn't initialize generator, referenced spline is empty! (%s)", owner->GetGUID().ToString().c_str());
|
||||
return;
|
||||
Creature* cMe = me->ToCreature();
|
||||
if (cMe && cMe->IsAIEnabled)
|
||||
cMe->AI()->MovementInform(SPLINE_CHAIN_MOTION_TYPE, _id);
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
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
|
||||
{
|
||||
_msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u);
|
||||
SendSplineFor(owner, _nextIndex, _msToNext);
|
||||
|
||||
++_nextIndex;
|
||||
if (_nextIndex >= _chainSize)
|
||||
_msToNext = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool SplineChainMovementGenerator::Update(Unit* me, uint32 diff)
|
||||
void SplineChainMovementGenerator::Reset(Unit* owner)
|
||||
{
|
||||
if (finished)
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
|
||||
|
||||
owner->StopMoving();
|
||||
Initialize(owner);
|
||||
}
|
||||
|
||||
bool SplineChainMovementGenerator::Update(Unit* owner, uint32 diff)
|
||||
{
|
||||
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 (movement->GetMovementGeneratorType() == SPLINE_CHAIN_MOTION_TYPE)
|
||||
{
|
||||
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(me);
|
||||
return;
|
||||
}
|
||||
info = reinterpret_cast<SplineChainMovementGenerator const*>(activeGenerator)->GetResumeInfo(owner);
|
||||
}
|
||||
info.Chain = nullptr;
|
||||
else
|
||||
info.Chain = nullptr;
|
||||
}
|
||||
|
||||
@@ -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) { }
|
||||
explicit SplineChainMovementGenerator(uint32 id, std::vector<SplineChainLink> const& chain, bool walk = false);
|
||||
explicit SplineChainMovementGenerator(SplineChainResumeInfo const& info);
|
||||
|
||||
void Initialize(Unit* me) override;
|
||||
void Finalize(Unit* me) override;
|
||||
void Reset(Unit* /*me*/) override { };
|
||||
bool Update(Unit* me, uint32 diff) 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;
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -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*/)
|
||||
{
|
||||
_done = false;
|
||||
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)
|
||||
{
|
||||
// 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())
|
||||
{
|
||||
// mimic IdleMovementGenerator
|
||||
if (!creature->IsStopped())
|
||||
creature->StopMoving();
|
||||
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())
|
||||
{
|
||||
// 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>::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>::OnArrived(Creature* creature)
|
||||
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 ((_currentNode == _path->nodes.size() - 1) && !_repeating) // If that's our last waypoint
|
||||
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);
|
||||
|
||||
// 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);
|
||||
owner->SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation && waypoint.delay) ? true : false);
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 diff)
|
||||
bool WaypointMovementGenerator<Creature>::ComputeNextNode()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
float x, y, z;
|
||||
motionMaster->GetDestination(x, y, z);
|
||||
|
||||
for (uint8 itr = 0; itr < MAX_MOTION_SLOT; ++itr)
|
||||
if (unit->GetMotionMaster()->Empty())
|
||||
{
|
||||
MovementGenerator* movementGenerator = motionMaster->GetMotionSlot(MovementSlot(itr));
|
||||
if (!movementGenerator)
|
||||
{
|
||||
handler->SendSysMessage("Empty");
|
||||
continue;
|
||||
}
|
||||
handler->SendSysMessage("Empty");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (movementGenerator->GetMovementGeneratorType())
|
||||
float x, y, z;
|
||||
unit->GetMotionMaster()->GetDestination(x, y, z);
|
||||
|
||||
std::vector<MovementGeneratorInformation> list = unit->GetMotionMaster()->GetMovementGeneratorsInformation();
|
||||
for (MovementGeneratorInformation info : list)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
if (a->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE)
|
||||
{
|
||||
FollowMovementGenerator const* followMovement = dynamic_cast<FollowMovementGenerator const*>(a);
|
||||
return followMovement && followMovement->GetTarget() == player;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!movement)
|
||||
{
|
||||
handler->PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName().c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
FollowMovementGenerator const* mgen = static_cast<FollowMovementGenerator const*>((creature->GetMotionMaster()->top()));
|
||||
|
||||
if (mgen->GetTarget() != player)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+37
-17
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -898,7 +898,7 @@ public:
|
||||
{
|
||||
_finished = false;
|
||||
me->SetVisible(true);
|
||||
me->GetMotionMaster()->Clear(true);
|
||||
me->GetMotionMaster()->Clear();
|
||||
}
|
||||
|
||||
void DoAction(int32 /*action*/) override
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user