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:
ccrs
2021-09-28 00:15:13 +02:00
committed by Shauren
parent 3e0af19b77
commit 426f9f2f92
96 changed files with 2412 additions and 1486 deletions
+3 -5
View File
@@ -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
+22 -9
View File
@@ -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
{
+1 -6
View File
@@ -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())
{
+11 -10
View File
@@ -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();
+2 -1
View File
@@ -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; }
+15 -21
View File
@@ -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();
}
+1 -1
View File
@@ -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());
+7 -9
View File
@@ -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();
+2 -2
View File
@@ -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);
+2 -3
View File
@@ -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());
}
+1 -1
View File
@@ -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);
-1
View File
@@ -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
+118 -51
View File
@@ -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
+18 -13
View File
@@ -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
+48 -9
View File
@@ -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());
}
}
}
}
+1 -5
View File
@@ -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()
+24 -66
View File
@@ -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;
+2 -7
View File
@@ -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;
+28 -61
View File
@@ -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;
}
}
+13 -15
View File
@@ -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;
}
+11 -24
View File
@@ -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
@@ -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);
}
@@ -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();
}
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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