Merge remote-tracking branch 'upstream/master' into feature/core_merge_10_2025
# Conflicts: # src/server/game/Entities/Unit/Unit.cpp # src/server/game/Movement/MovementGenerators/PointMovementGenerator.h # src/server/game/Server/WorldSession.cpp # src/server/game/Server/WorldSession.h # src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp # src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp # src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp # src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp # src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
This commit is contained in:
@@ -2352,6 +2352,18 @@ Rate.Reputation.LowLevel.Quest = 1
|
||||
|
||||
Rate.Reputation.RecruitAFriendBonus = 0.1
|
||||
|
||||
#
|
||||
# Rate.Reputation.Gain.WSG
|
||||
# Rate.Reputation.Gain.AB
|
||||
# Rate.Reputation.Gain.AV
|
||||
# Description: Reputation bonus rate for WSG, AB and AV battlegrounds.
|
||||
# This is applied IN ADDITION to the global Rate.Reputation.Gain.
|
||||
# Default: 1
|
||||
|
||||
Rate.Reputation.Gain.WSG = 1
|
||||
Rate.Reputation.Gain.AB = 1
|
||||
Rate.Reputation.Gain.AV = 1
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
@@ -554,17 +554,13 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
|
||||
if (ssl == "ssl")
|
||||
args.emplace_back("--ssl-mode=REQUIRED");
|
||||
|
||||
// Execute sql file
|
||||
args.emplace_back("-e");
|
||||
args.emplace_back(Acore::StringFormat("BEGIN; SOURCE {}; COMMIT;", path.generic_string()));
|
||||
|
||||
// Database
|
||||
if (!database.empty())
|
||||
args.emplace_back(database);
|
||||
|
||||
// Invokes a mysql process which doesn't leak credentials to logs
|
||||
int const ret = Acore::StartProcess(DBUpdaterUtil::GetCorrectedMySQLExecutable(), args,
|
||||
"sql.updates", "", true);
|
||||
"sql.updates", path.generic_string(), true);
|
||||
|
||||
if (ret != EXIT_SUCCESS)
|
||||
{
|
||||
|
||||
@@ -80,7 +80,7 @@ void CombatAI::JustEngagedWith(Unit* who)
|
||||
if (AISpellInfo[*i].condition == AICOND_AGGRO)
|
||||
me->CastSpell(who, *i, false);
|
||||
else if (AISpellInfo[*i].condition == AICOND_COMBAT)
|
||||
events.ScheduleEvent(*i, AISpellInfo[*i].cooldown + rand() % AISpellInfo[*i].cooldown);
|
||||
events.ScheduleEvent(*i, Milliseconds(AISpellInfo[*i].cooldown + rand() % AISpellInfo[*i].cooldown));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ void CombatAI::UpdateAI(uint32 diff)
|
||||
if (uint32 spellId = events.ExecuteEvent())
|
||||
{
|
||||
DoCast(spellId);
|
||||
events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + rand() % AISpellInfo[spellId].cooldown);
|
||||
events.ScheduleEvent(spellId, Milliseconds(AISpellInfo[spellId].cooldown + rand() % AISpellInfo[spellId].cooldown));
|
||||
}
|
||||
else
|
||||
DoMeleeAttackIfReady();
|
||||
@@ -143,7 +143,7 @@ void CasterAI::JustEngagedWith(Unit* who)
|
||||
DoCast(spells[spell]);
|
||||
cooldown += me->GetCurrentSpellCastTime(*itr);
|
||||
}
|
||||
events.ScheduleEvent(*itr, cooldown);
|
||||
events.ScheduleEvent(*itr, Milliseconds(cooldown));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,7 +168,7 @@ void CasterAI::UpdateAI(uint32 diff)
|
||||
{
|
||||
DoCast(spellId);
|
||||
uint32 casttime = me->GetCurrentSpellCastTime(spellId);
|
||||
events.ScheduleEvent(spellId, (casttime ? casttime : 500) + GetAISpellInfo(spellId)->realCooldown);
|
||||
events.ScheduleEvent(spellId, Milliseconds((casttime ? casttime : 500) + GetAISpellInfo(spellId)->realCooldown));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
|
||||
// Pass parameters between AI
|
||||
virtual void DoAction(int32 /*param = 0 */) {}
|
||||
virtual void SetGUID(ObjectGuid /*guid*/, int32 /*id = 0 */) {}
|
||||
virtual void SetGUID(ObjectGuid const& /*guid*/, int32 /*id = 0 */) {}
|
||||
virtual ObjectGuid GetGUID(int32 /*id = 0 */) const { return ObjectGuid::Empty; }
|
||||
|
||||
static int32 Permissible(GameObject const* go);
|
||||
|
||||
@@ -217,7 +217,7 @@ public:
|
||||
virtual void DoAction(int32 /*param*/) {}
|
||||
virtual uint32 GetData(uint32 /*id = 0*/) const { return 0; }
|
||||
virtual void SetData(uint32 /*id*/, uint32 /*value*/) {}
|
||||
virtual void SetGUID(ObjectGuid /*guid*/, int32 /*id*/ = 0) {}
|
||||
virtual void SetGUID(ObjectGuid const& /*guid*/, int32 /*id*/ = 0) {}
|
||||
virtual ObjectGuid GetGUID(int32 /*id*/ = 0) const { return ObjectGuid::Empty; }
|
||||
|
||||
// Select the best target (in <targetType> order) from the threat list that fulfill the following:
|
||||
|
||||
@@ -50,9 +50,9 @@ AISpellInfoType* GetAISpellInfo(uint32 i) { return &CreatureAI::AISpellInfo[i];
|
||||
* @param WorldObject target The target of the speech, in case it has elements such as $n, where the target's name will be referrenced.
|
||||
* @param Milliseconds delay Delay until the creature says the text line. Creatures will talk immediately by default.
|
||||
*/
|
||||
void CreatureAI::Talk(uint8 id, WorldObject const* target /*= nullptr*/, Milliseconds delay /*= 0s*/)
|
||||
void CreatureAI::Talk(uint8 id, WorldObject const* target /*= nullptr*/, Milliseconds delay /*= 0ms*/)
|
||||
{
|
||||
if (delay > Seconds::zero())
|
||||
if (delay > 0ms)
|
||||
{
|
||||
ObjectGuid targetGuid;
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
EVADE_REASON_OTHER
|
||||
};
|
||||
|
||||
void Talk(uint8 id, WorldObject const* whisperTarget = nullptr, Milliseconds delay = 0s);
|
||||
void Talk(uint8 id, WorldObject const* whisperTarget = nullptr, Milliseconds delay = 0ms);
|
||||
void Talk(uint8 id, Milliseconds delay) { Talk(id, nullptr, delay); }
|
||||
|
||||
WorldObject* GetSummoner() const;
|
||||
|
||||
@@ -68,7 +68,7 @@ void SummonList::DespawnEntry(uint32 entry)
|
||||
}
|
||||
}
|
||||
|
||||
void SummonList::DespawnAll(uint32 delay /*= 0*/)
|
||||
void SummonList::DespawnAll(Milliseconds delay /*= 0ms*/)
|
||||
{
|
||||
while (!storage_.empty())
|
||||
{
|
||||
@@ -325,13 +325,13 @@ void ScriptedAI::ScheduleTimedEvent(Milliseconds timerMin, Milliseconds timerMax
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler.Schedule(timerMin == 0s ? timerMax : timerMin, timerMax, [exec, repeatMin, repeatMax, uniqueId](TaskContext context)
|
||||
scheduler.Schedule(timerMin == 0ms ? timerMax : timerMin, timerMax, [exec, repeatMin, repeatMax, uniqueId](TaskContext context)
|
||||
{
|
||||
exec();
|
||||
|
||||
if (!uniqueId)
|
||||
{
|
||||
repeatMax > 0s ? context.Repeat(repeatMin, repeatMax) : context.Repeat(repeatMin);
|
||||
repeatMax > 0ms ? context.Repeat(repeatMin, repeatMax) : context.Repeat(repeatMin);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -552,6 +552,11 @@ void ScriptedAI::SetEquipmentSlots(bool loadDefault, int32 mainHand /*= EQUIP_NO
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptedAI::SetRun(bool run)
|
||||
{
|
||||
me->SetWalk(!run);
|
||||
}
|
||||
|
||||
enum eNPCs
|
||||
{
|
||||
NPC_BROODLORD = 12017,
|
||||
@@ -654,7 +659,7 @@ void BossAI::_JustEngagedWith()
|
||||
ScheduleTasks();
|
||||
if (callForHelpRange)
|
||||
{
|
||||
ScheduleTimedEvent(0s, [&]
|
||||
ScheduleTimedEvent(0ms, [&]
|
||||
{
|
||||
me->CallForHelp(callForHelpRange);
|
||||
}, 2s);
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
void Summon(Creature const* summon) { storage_.push_back(summon->GetGUID()); }
|
||||
void Despawn(Creature const* summon) { storage_.remove(summon->GetGUID()); }
|
||||
void DespawnEntry(uint32 entry);
|
||||
void DespawnAll(uint32 delay = 0);
|
||||
void DespawnAll(Milliseconds delay = 0ms);
|
||||
bool IsAnyCreatureAlive() const;
|
||||
bool IsAnyCreatureWithEntryAlive(uint32 entry) const;
|
||||
bool IsAnyCreatureInCombat() const;
|
||||
@@ -227,6 +227,8 @@ struct ScriptedAI : public CreatureAI
|
||||
// Called when AI is temporarily replaced or put back when possess is applied or removed
|
||||
void OnPossess(bool /*apply*/) {}
|
||||
|
||||
void SetRun(bool run);
|
||||
|
||||
enum class Axis
|
||||
{
|
||||
AXIS_X,
|
||||
@@ -355,11 +357,11 @@ struct ScriptedAI : public CreatureAI
|
||||
void ClearUniqueTimedEventsDone() { _uniqueTimedEvents.clear(); }
|
||||
|
||||
// Schedules a timed event using task scheduler.
|
||||
void ScheduleTimedEvent(Milliseconds timerMin, Milliseconds timerMax, std::function<void()> exec, Milliseconds repeatMin, Milliseconds repeatMax = 0s, uint32 uniqueId = 0);
|
||||
void ScheduleTimedEvent(Milliseconds timerMax, std::function<void()> exec, Milliseconds repeatMin, Milliseconds repeatMax = 0s, uint32 uniqueId = 0) { ScheduleTimedEvent(0s, timerMax, exec, repeatMin, repeatMax, uniqueId); };
|
||||
void ScheduleTimedEvent(Milliseconds timerMin, Milliseconds timerMax, std::function<void()> exec, Milliseconds repeatMin, Milliseconds repeatMax = 0ms, uint32 uniqueId = 0);
|
||||
void ScheduleTimedEvent(Milliseconds timerMax, std::function<void()> exec, Milliseconds repeatMin, Milliseconds repeatMax = 0ms, uint32 uniqueId = 0) { ScheduleTimedEvent(0ms, timerMax, exec, repeatMin, repeatMax, uniqueId); };
|
||||
|
||||
// Schedules a timed event using task scheduler that never repeats. Requires an unique non-zero ID.
|
||||
void ScheduleUniqueTimedEvent(Milliseconds timer, std::function<void()> exec, uint32 uniqueId) { ScheduleTimedEvent(0s, timer, exec, 0s, 0s, uniqueId); };
|
||||
void ScheduleUniqueTimedEvent(Milliseconds timer, std::function<void()> exec, uint32 uniqueId) { ScheduleTimedEvent(0ms, timer, exec, 0ms, 0ms, uniqueId); };
|
||||
|
||||
bool HealthBelowPct(uint32 pct) const { return me->HealthBelowPct(pct); }
|
||||
bool HealthAbovePct(uint32 pct) const { return me->HealthAbovePct(pct); }
|
||||
@@ -463,7 +465,7 @@ enum HealthCheckStatus
|
||||
|
||||
struct HealthCheckEventData
|
||||
{
|
||||
HealthCheckEventData(uint8 healthPct, std::function<void()> exec, uint8 status = HEALTH_CHECK_SCHEDULED, bool allowedWhileCasting = true, Milliseconds Delay = 0s) : _healthPct(healthPct), _exec(exec), _status(status), _allowedWhileCasting(allowedWhileCasting), _delay(Delay) { };
|
||||
HealthCheckEventData(uint8 healthPct, std::function<void()> exec, uint8 status = HEALTH_CHECK_SCHEDULED, bool allowedWhileCasting = true, Milliseconds Delay = 0ms) : _healthPct(healthPct), _exec(exec), _status(status), _allowedWhileCasting(allowedWhileCasting), _delay(Delay) { };
|
||||
|
||||
uint8 _healthPct;
|
||||
std::function<void()> _exec;
|
||||
|
||||
@@ -33,7 +33,6 @@ npc_escortAI::npc_escortAI(Creature* creature) : ScriptedAI(creature),
|
||||
MaxPlayerDistance(DEFAULT_MAX_PLAYER_DISTANCE),
|
||||
m_pQuestForEscort(nullptr),
|
||||
m_bIsActiveAttacker(true),
|
||||
m_bIsRunning(false),
|
||||
m_bCanInstantRespawn(false),
|
||||
m_bCanReturnToStart(false),
|
||||
DespawnAtEnd(true),
|
||||
@@ -186,9 +185,8 @@ void npc_escortAI::JustRespawned()
|
||||
void npc_escortAI::ReturnToLastPoint()
|
||||
{
|
||||
float x, y, z, o;
|
||||
me->SetWalk(false);
|
||||
me->GetHomePosition(x, y, z, o);
|
||||
me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, x, y, z);
|
||||
me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, x, y, z, FORCED_MOVEMENT_RUN);
|
||||
}
|
||||
|
||||
void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
@@ -329,7 +327,6 @@ void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
|
||||
{
|
||||
LOG_DEBUG("scripts.ai", "EscortAI has returned to original position before combat");
|
||||
|
||||
me->SetWalk(!m_bIsRunning);
|
||||
RemoveEscortState(STATE_ESCORT_RETURNING);
|
||||
|
||||
if (!m_uiWPWaitTimer)
|
||||
@@ -418,28 +415,8 @@ void npc_escortAI::FillPointMovementListForCreature()
|
||||
}
|
||||
}
|
||||
|
||||
void npc_escortAI::SetRun(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
if (!m_bIsRunning)
|
||||
me->SetWalk(false);
|
||||
else
|
||||
LOG_DEBUG("scripts.ai", "EscortAI attempt to set run mode, but is already running.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_bIsRunning)
|
||||
me->SetWalk(true);
|
||||
else
|
||||
LOG_DEBUG("scripts.ai", "EscortAI attempt to set walk mode, but is already walking.");
|
||||
}
|
||||
|
||||
m_bIsRunning = on;
|
||||
}
|
||||
|
||||
//TODO: get rid of this many variables passed in function.
|
||||
void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */, ObjectGuid playerGUID /* = ObjectGuid::Empty */, Quest const* quest /* = nullptr */, bool instantRespawn /* = false */, bool canLoopPath /* = false */, bool resetWaypoints /* = true */)
|
||||
void npc_escortAI::Start(bool isActiveAttacker /* = true*/, ObjectGuid playerGUID /* = ObjectGuid::Empty */, Quest const* quest /* = nullptr */, bool instantRespawn /* = false */, bool canLoopPath /* = false */, bool resetWaypoints /* = true */)
|
||||
{
|
||||
if (me->GetVictim())
|
||||
{
|
||||
@@ -469,7 +446,6 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
|
||||
|
||||
//set variables
|
||||
m_bIsActiveAttacker = isActiveAttacker;
|
||||
m_bIsRunning = run;
|
||||
|
||||
m_uiPlayerGUID = playerGUID;
|
||||
m_pQuestForEscort = quest;
|
||||
@@ -495,17 +471,11 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
|
||||
me->SetImmuneToNPC(false);
|
||||
}
|
||||
|
||||
LOG_DEBUG("scripts.ai", "EscortAI started with {} waypoints. ActiveAttacker = {}, Run = {}, PlayerGUID = {}",
|
||||
uint64(WaypointList.size()), m_bIsActiveAttacker, m_bIsRunning, m_uiPlayerGUID.ToString());
|
||||
LOG_DEBUG("scripts.ai", "EscortAI started with {} waypoints. ActiveAttacker = {}, PlayerGUID = {}",
|
||||
uint64(WaypointList.size()), m_bIsActiveAttacker, m_uiPlayerGUID.ToString());
|
||||
|
||||
CurrentWP = WaypointList.begin();
|
||||
|
||||
//Set initial speed
|
||||
if (m_bIsRunning)
|
||||
me->SetWalk(false);
|
||||
else
|
||||
me->SetWalk(true);
|
||||
|
||||
AddEscortState(STATE_ESCORT_ESCORTING);
|
||||
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == ESCORT_MOTION_TYPE)
|
||||
me->GetMotionMaster()->MovementExpired();
|
||||
|
||||
@@ -90,9 +90,8 @@ public:
|
||||
virtual void WaypointReached(uint32 pointId) = 0;
|
||||
virtual void WaypointStart(uint32 /*pointId*/) {}
|
||||
|
||||
void Start(bool isActiveAttacker = true, bool run = false, ObjectGuid playerGUID = ObjectGuid::Empty, Quest const* quest = nullptr, bool instantRespawn = false, bool canLoopPath = false, bool resetWaypoints = true);
|
||||
void Start(bool isActiveAttacker = true, ObjectGuid playerGUID = ObjectGuid::Empty, Quest const* quest = nullptr, bool instantRespawn = false, bool canLoopPath = false, bool resetWaypoints = true);
|
||||
|
||||
void SetRun(bool on = true);
|
||||
void SetEscortPaused(bool on);
|
||||
|
||||
bool HasEscortState(uint32 escortState) { return (m_uiEscortState & escortState); }
|
||||
@@ -130,7 +129,6 @@ private:
|
||||
std::list<Escort_Waypoint>::iterator CurrentWP;
|
||||
|
||||
bool m_bIsActiveAttacker; //obsolete, determined by faction.
|
||||
bool m_bIsRunning; //all creatures are walking by default (has flag MOVEMENTFLAG_WALK)
|
||||
bool m_bCanInstantRespawn; //if creature should respawn instantly after escort over (if not, database respawntime are used)
|
||||
bool m_bCanReturnToStart; //if creature can walk same path (loop) without despawn. Not for regular escort quests.
|
||||
bool DespawnAtEnd;
|
||||
|
||||
@@ -42,7 +42,7 @@ void AddGossipItemFor(Player* player, uint32 gossipMenuID, uint32 gossipMenuItem
|
||||
player->PlayerTalkClass->GetGossipMenu().AddMenuItem(gossipMenuID, gossipMenuItemID, sender, action, boxMoney);
|
||||
}
|
||||
|
||||
void SendGossipMenuFor(Player* player, uint32 npcTextID, ObjectGuid const guid)
|
||||
void SendGossipMenuFor(Player* player, uint32 npcTextID, ObjectGuid const& guid)
|
||||
{
|
||||
player->PlayerTalkClass->SendGossipMenu(npcTextID, guid);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ void AddGossipItemFor(Player* player, uint32 icon, std::string const& text, uint
|
||||
void AddGossipItemFor(Player* player, uint32 gossipMenuID, uint32 gossipMenuItemID, uint32 sender, uint32 action, uint32 boxMoney = 0);
|
||||
|
||||
// Send menu text
|
||||
void SendGossipMenuFor(Player* player, uint32 npcTextID, ObjectGuid const guid);
|
||||
void SendGossipMenuFor(Player* player, uint32 npcTextID, ObjectGuid const& guid);
|
||||
void SendGossipMenuFor(Player* player, uint32 npcTextID, Creature const* creature);
|
||||
|
||||
// Close menu
|
||||
|
||||
@@ -43,9 +43,6 @@ SmartAI::SmartAI(Creature* c) : CreatureAI(c)
|
||||
|
||||
mCanRepeatPath = false;
|
||||
|
||||
// spawn in run mode
|
||||
// Xinef: spawn in run mode and set mRun to run... this overrides SetWalk EVERYWHERE
|
||||
mRun = true;
|
||||
mEvadeDisabled = false;
|
||||
|
||||
mCanAutoAttack = true;
|
||||
@@ -190,7 +187,7 @@ void SmartAI::GenerateWayPointArray(Movement::PointsArray* points)
|
||||
}
|
||||
}
|
||||
|
||||
void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
|
||||
void SmartAI::StartPath(ForcedMovement forcedMovement, uint32 path, bool repeat, Unit* invoker)
|
||||
{
|
||||
if (HasEscortState(SMART_ESCORT_ESCORTING))
|
||||
StopPath();
|
||||
@@ -208,7 +205,6 @@ void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
|
||||
{
|
||||
AddEscortState(SMART_ESCORT_ESCORTING);
|
||||
mCanRepeatPath = repeat;
|
||||
SetRun(run);
|
||||
|
||||
if (invoker && invoker->IsPlayer())
|
||||
{
|
||||
@@ -219,7 +215,7 @@ void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
|
||||
Movement::PointsArray pathPoints;
|
||||
GenerateWayPointArray(&pathPoints);
|
||||
|
||||
me->GetMotionMaster()->MoveSplinePath(&pathPoints);
|
||||
me->GetMotionMaster()->MoveSplinePath(&pathPoints, forcedMovement);
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_START, nullptr, wp->id, GetScript()->GetPathId());
|
||||
}
|
||||
}
|
||||
@@ -256,7 +252,6 @@ void SmartAI::PausePath(uint32 delay, bool forced)
|
||||
if (forced && !mWPReached)
|
||||
{
|
||||
mForcedPaused = forced;
|
||||
SetRun(mRun);
|
||||
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == ESCORT_MOTION_TYPE)
|
||||
me->GetMotionMaster()->MovementExpired();
|
||||
|
||||
@@ -362,7 +357,7 @@ void SmartAI::EndPath(bool fail)
|
||||
if (mCanRepeatPath)
|
||||
{
|
||||
if (IsAIControlled())
|
||||
StartPath(mRun, GetScript()->GetPathId(), true);
|
||||
StartPath(FORCED_MOVEMENT_NONE, GetScript()->GetPathId(), true);
|
||||
}
|
||||
else
|
||||
GetScript()->SetPathId(0);
|
||||
@@ -373,8 +368,6 @@ void SmartAI::EndPath(bool fail)
|
||||
|
||||
void SmartAI::ResumePath()
|
||||
{
|
||||
SetRun(mRun);
|
||||
|
||||
if (mLastWP)
|
||||
{
|
||||
Movement::PointsArray pathPoints;
|
||||
@@ -389,10 +382,9 @@ void SmartAI::ReturnToLastOOCPos()
|
||||
if (!IsAIControlled())
|
||||
return;
|
||||
|
||||
me->SetWalk(false);
|
||||
float x, y, z, o;
|
||||
me->GetHomePosition(x, y, z, o);
|
||||
me->GetMotionMaster()->MovePoint(SMART_ESCORT_LAST_OOC_POINT, x, y, z);
|
||||
me->GetMotionMaster()->MovePoint(SMART_ESCORT_LAST_OOC_POINT, x, y, z, FORCED_MOVEMENT_RUN);
|
||||
}
|
||||
|
||||
void SmartAI::UpdatePath(const uint32 diff)
|
||||
@@ -410,7 +402,7 @@ void SmartAI::UpdatePath(const uint32 diff)
|
||||
|
||||
// Xinef: allow to properly hook out of range despawn action, which in most cases should perform the same operation as dying
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, me);
|
||||
me->DespawnOrUnsummon(1);
|
||||
me->DespawnOrUnsummon(1ms);
|
||||
return;
|
||||
}
|
||||
mEscortInvokerCheckTimer = 1000;
|
||||
@@ -469,7 +461,6 @@ void SmartAI::UpdatePath(const uint32 diff)
|
||||
EndPath();
|
||||
else if (GetNextWayPoint())
|
||||
{
|
||||
SetRun(mRun);
|
||||
// xinef: if we have reached waypoint, and there is no working spline movement it means our splitted array has ended, make new one
|
||||
if (me->movespline->Finalized())
|
||||
ResumePath();
|
||||
@@ -629,7 +620,6 @@ void SmartAI::MovepointReached(uint32 id)
|
||||
EndPath();
|
||||
else if (GetNextWayPoint())
|
||||
{
|
||||
SetRun(mRun);
|
||||
// xinef: if we have reached waypoint, and there is no working spline movement it means our splitted array has ended, make new one
|
||||
if (me->movespline->Finalized())
|
||||
ResumePath();
|
||||
@@ -675,7 +665,6 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_EVADE); //must be after aura clear so we can cast spells from db
|
||||
|
||||
SetRun(mRun);
|
||||
if (HasEscortState(SMART_ESCORT_ESCORTING))
|
||||
{
|
||||
AddEscortState(SMART_ESCORT_RETURNING);
|
||||
@@ -850,7 +839,6 @@ void SmartAI::AttackStart(Unit* who)
|
||||
{
|
||||
if (!me->HasUnitState(UNIT_STATE_NO_COMBAT_MOVEMENT))
|
||||
{
|
||||
SetRun(mRun);
|
||||
MovementGeneratorType type = me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE);
|
||||
if (type == ESCORT_MOTION_TYPE || type == POINT_MOTION_TYPE)
|
||||
{
|
||||
@@ -952,9 +940,7 @@ void SmartAI::OnCharmed(bool /* apply */)
|
||||
if (!charmed && !me->IsInEvadeMode())
|
||||
{
|
||||
if (mCanRepeatPath)
|
||||
StartPath(mRun, GetScript()->GetPathId(), true);
|
||||
else
|
||||
me->SetWalk(!mRun);
|
||||
StartPath(FORCED_MOVEMENT_NONE, GetScript()->GetPathId(), true);
|
||||
|
||||
if (Unit* charmer = me->GetCharmer())
|
||||
AttackStart(charmer);
|
||||
@@ -993,7 +979,7 @@ void SmartAI::SetData(uint32 id, uint32 value, WorldObject* invoker)
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, unit, id, value, false, nullptr, gob);
|
||||
}
|
||||
|
||||
void SmartAI::SetGUID(ObjectGuid /*guid*/, int32 /*id*/)
|
||||
void SmartAI::SetGUID(ObjectGuid const& /*guid*/, int32 /*id*/)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1002,12 +988,6 @@ ObjectGuid SmartAI::GetGUID(int32 /*id*/) const
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
void SmartAI::SetRun(bool run)
|
||||
{
|
||||
me->SetWalk(!run);
|
||||
mRun = run;
|
||||
}
|
||||
|
||||
void SmartAI::SetFly(bool fly)
|
||||
{
|
||||
// xinef: set proper flag!
|
||||
@@ -1108,7 +1088,6 @@ void SmartAI::SetFollow(Unit* target, float dist, float angle, uint32 credit, ui
|
||||
mFollowArrivedEntry = end;
|
||||
mFollowArrivedAlive = !aliveState; // negate - 0 is alive
|
||||
mFollowCreditType = creditType;
|
||||
SetRun(mRun);
|
||||
me->GetMotionMaster()->MoveFollow(target, mFollowDist, mFollowAngle);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
bool IsAIControlled() const;
|
||||
|
||||
// Start moving to the desired MovePoint
|
||||
void StartPath(bool run = false, uint32 path = 0, bool repeat = false, Unit* invoker = nullptr);
|
||||
void StartPath(ForcedMovement forcedMovement = FORCED_MOVEMENT_NONE, uint32 path = 0, bool repeat = false, Unit* invoker = nullptr);
|
||||
bool LoadPath(uint32 entry);
|
||||
void PausePath(uint32 delay, bool forced = false);
|
||||
void StopPath(uint32 DespawnTime = 0, uint32 quest = 0, bool fail = false);
|
||||
@@ -164,7 +164,7 @@ public:
|
||||
void SetData(uint32 id, uint32 value, WorldObject* invoker);
|
||||
|
||||
// Used in scripts to share variables
|
||||
void SetGUID(ObjectGuid guid, int32 id = 0) override;
|
||||
void SetGUID(ObjectGuid const& guid, int32 id = 0) override;
|
||||
|
||||
// Used in scripts to share variables
|
||||
ObjectGuid GetGUID(int32 id = 0) const override;
|
||||
@@ -175,9 +175,6 @@ public:
|
||||
// Called at movepoint reached
|
||||
void MovepointReached(uint32 id);
|
||||
|
||||
// Makes the creature run/walk
|
||||
void SetRun(bool run = true);
|
||||
|
||||
void SetFly(bool fly = true);
|
||||
|
||||
void SetSwim(bool swim = true);
|
||||
@@ -240,7 +237,6 @@ private:
|
||||
uint32 mEscortNPCFlags;
|
||||
uint32 GetWPCount() { return mWayPoints ? mWayPoints->size() : 0; }
|
||||
bool mCanRepeatPath;
|
||||
bool mRun;
|
||||
bool mEvadeDisabled;
|
||||
bool mCanAutoAttack;
|
||||
bool mForcedPaused;
|
||||
|
||||
@@ -1683,10 +1683,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
{
|
||||
if (IsCreature(target))
|
||||
{
|
||||
if (IsSmart(target->ToCreature()))
|
||||
CAST_AI(SmartAI, target->ToCreature()->AI())->SetRun(e.action.setRun.run);
|
||||
else
|
||||
target->ToCreature()->SetWalk(e.action.setRun.run ? false : true); // Xinef: reversed
|
||||
target->ToCreature()->SetWalk(e.action.setRun.run ? false : true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1731,7 +1728,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (!IsSmart())
|
||||
break;
|
||||
|
||||
bool run = e.action.wpStart.run != 0;
|
||||
ForcedMovement forcedMovement = static_cast<ForcedMovement>(e.action.wpStart.forcedMovement);
|
||||
uint32 entry = e.action.wpStart.pathID;
|
||||
bool repeat = e.action.wpStart.repeat != 0;
|
||||
|
||||
@@ -1745,7 +1742,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
}
|
||||
|
||||
me->SetReactState((ReactStates)e.action.wpStart.reactState);
|
||||
CAST_AI(SmartAI, me->AI())->StartPath(run, entry, repeat, unit);
|
||||
CAST_AI(SmartAI, me->AI())->StartPath(forcedMovement, entry, repeat, unit);
|
||||
|
||||
uint32 quest = e.action.wpStart.quest;
|
||||
uint32 DespawnTime = e.action.wpStart.despawnTime;
|
||||
@@ -1854,8 +1851,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (TransportBase* trans = me->GetDirectTransport())
|
||||
trans->CalculatePassengerPosition(dest.x, dest.y, dest.z);
|
||||
|
||||
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, true, isForced,
|
||||
isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE, e.target.o);
|
||||
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, FORCED_MOVEMENT_NONE,
|
||||
0.f, e.target.o, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1871,9 +1868,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
randomPoint.m_positionX,
|
||||
randomPoint.m_positionY,
|
||||
randomPoint.m_positionZ,
|
||||
true,
|
||||
isForced,
|
||||
isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE
|
||||
FORCED_MOVEMENT_NONE,
|
||||
0.f, 0.f, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1897,7 +1893,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
else if (e.action.moveToPos.ContactDistance)
|
||||
target->GetNearPoint(me, x, y, z, e.action.moveToPos.ContactDistance, 0, target->GetAngle(me));
|
||||
|
||||
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, FORCED_MOVEMENT_NONE,
|
||||
0.f, 0.f, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1914,7 +1911,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
SAIBool isForced = !e.action.moveToPosTarget.disableForceDestination;
|
||||
|
||||
Creature* ctarget = target->ToCreature();
|
||||
ctarget->GetMotionMaster()->MovePoint(e.action.moveToPosTarget.pointId, e.target.x, e.target.y, e.target.z, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
ctarget->GetMotionMaster()->MovePoint(e.action.moveToPosTarget.pointId, e.target.x, e.target.y, e.target.z, FORCED_MOVEMENT_NONE,
|
||||
0.f, 0.f, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2543,9 +2541,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (closestWpId)
|
||||
{
|
||||
bool repeat = e.action.startClosestWaypoint.repeat;
|
||||
bool run = e.action.startClosestWaypoint.run;
|
||||
ForcedMovement forcedMovement = static_cast<ForcedMovement>(e.action.startClosestWaypoint.forcedMovement);
|
||||
|
||||
CAST_AI(SmartAI, creature->AI())->StartPath(repeat, closestWpId, run);
|
||||
CAST_AI(SmartAI, creature->AI())->StartPath(forcedMovement, closestWpId, repeat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,6 +555,7 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e)
|
||||
case SMART_TARGET_RANDOM_POINT:
|
||||
case SMART_TARGET_ROLE_SELECTION:
|
||||
case SMART_TARGET_LOOT_RECIPIENTS:
|
||||
case SMART_TARGET_VEHICLE_PASSENGER:
|
||||
case SMART_EVENT_SUMMONED_UNIT_DIES:
|
||||
case SMART_EVENT_SUMMONED_UNIT_EVADE:
|
||||
case SMART_TARGET_PLAYER_RANGE:
|
||||
@@ -866,6 +867,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_ZONE_UNDER_ATTACK: return NO_PARAMS;
|
||||
case SMART_ACTION_LOAD_GRID: return NO_PARAMS;
|
||||
case SMART_ACTION_MUSIC: return sizeof(SmartAction::music);
|
||||
case SMART_ACTION_DO_ACTION: return sizeof(SmartAction::doAction);
|
||||
case SMART_ACTION_SET_GUID: return sizeof(SmartAction::setGuid);
|
||||
case SMART_ACTION_SCRIPTED_SPAWN: return sizeof(SmartAction::scriptSpawn);
|
||||
case SMART_ACTION_SET_SCALE: return sizeof(SmartAction::setScale);
|
||||
@@ -1562,11 +1564,11 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
return false;
|
||||
}
|
||||
if (e.action.startClosestWaypoint.repeat > 1 || e.action.startClosestWaypoint.run > 1)
|
||||
if (e.action.startClosestWaypoint.repeat > 1 || e.action.startClosestWaypoint.forcedMovement >= FORCED_MOVEMENT_MAX)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invalid run ({}) or repeat ({}) parameter, must be 0 or 1.",
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invalid forcedMovement ({}) or repeat ({}) parameter, must be 0 or 1.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(),
|
||||
e.action.startClosestWaypoint.repeat, e.action.startClosestWaypoint.run);
|
||||
e.action.startClosestWaypoint.repeat, e.action.startClosestWaypoint.forcedMovement);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -1743,8 +1745,13 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsSAIBoolValid(e, e.action.wpStart.run) &&
|
||||
IsSAIBoolValid(e, e.action.wpStart.repeat);
|
||||
if (e.action.wpStart.forcedMovement >= FORCED_MOVEMENT_MAX)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Creature {} Event {} Action {} uses invalid forcedMovement {}, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.forcedMovement);
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsSAIBoolValid(e, e.action.wpStart.repeat);
|
||||
}
|
||||
case SMART_ACTION_CREATE_TIMED_EVENT:
|
||||
{
|
||||
|
||||
@@ -1041,7 +1041,7 @@ struct SmartAction
|
||||
|
||||
struct
|
||||
{
|
||||
SAIBool run;
|
||||
uint32 forcedMovement;
|
||||
uint32 pathID;
|
||||
SAIBool repeat;
|
||||
uint32 quest;
|
||||
@@ -1295,7 +1295,7 @@ struct SmartAction
|
||||
uint32 pathId1;
|
||||
uint32 pathId2;
|
||||
uint32 repeat;
|
||||
uint32 run;
|
||||
uint32 forcedMovement;
|
||||
} startClosestWaypoint;
|
||||
|
||||
struct
|
||||
|
||||
@@ -855,7 +855,7 @@ GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z
|
||||
return go;
|
||||
}
|
||||
|
||||
Creature* Battlefield::GetCreature(ObjectGuid const guid)
|
||||
Creature* Battlefield::GetCreature(ObjectGuid const& guid)
|
||||
{
|
||||
if (!m_Map)
|
||||
return nullptr;
|
||||
@@ -863,7 +863,7 @@ Creature* Battlefield::GetCreature(ObjectGuid const guid)
|
||||
return m_Map->GetCreature(guid);
|
||||
}
|
||||
|
||||
GameObject* Battlefield::GetGameObject(ObjectGuid const guid)
|
||||
GameObject* Battlefield::GetGameObject(ObjectGuid const& guid)
|
||||
{
|
||||
if (!m_Map)
|
||||
return nullptr;
|
||||
|
||||
@@ -146,6 +146,7 @@ class BfGraveyard
|
||||
{
|
||||
public:
|
||||
BfGraveyard(Battlefield* Bf);
|
||||
virtual ~BfGraveyard() = default;
|
||||
|
||||
// Method to changing who controls the graveyard
|
||||
void GiveControlTo(TeamId team);
|
||||
@@ -302,8 +303,8 @@ public:
|
||||
Creature* SpawnCreature(uint32 entry, Position pos, TeamId teamId);
|
||||
GameObject* SpawnGameObject(uint32 entry, float x, float y, float z, float o);
|
||||
|
||||
Creature* GetCreature(ObjectGuid const guid);
|
||||
GameObject* GetGameObject(ObjectGuid const guid);
|
||||
Creature* GetCreature(ObjectGuid const& guid);
|
||||
GameObject* GetGameObject(ObjectGuid const& guid);
|
||||
|
||||
// Script-methods
|
||||
|
||||
|
||||
@@ -415,7 +415,7 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
|
||||
{
|
||||
for (GuidUnorderedSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
|
||||
if (Creature* creature = GetCreature(*itr))
|
||||
creature->DespawnOrUnsummon(1);
|
||||
creature->DespawnOrUnsummon(1ms);
|
||||
|
||||
m_vehicles[team].clear();
|
||||
}
|
||||
|
||||
@@ -366,7 +366,7 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount)
|
||||
|
||||
void BattlegroundQueue::AddEvent(BasicEvent* Event, uint64 e_time)
|
||||
{
|
||||
m_events.AddEvent(Event, m_events.CalculateTime(e_time));
|
||||
m_events.AddEventAtOffset(Event, Milliseconds(e_time));
|
||||
}
|
||||
|
||||
bool BattlegroundQueue::IsPlayerInvitedToRatedArena(ObjectGuid pl_guid)
|
||||
|
||||
@@ -101,7 +101,7 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff)
|
||||
uint8 controlledPoints = _controlledPoints[teamId];
|
||||
if (controlledPoints == 0)
|
||||
{
|
||||
_bgEvents.ScheduleEvent(eventId, 3000);
|
||||
_bgEvents.ScheduleEvent(eventId, 3s);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff)
|
||||
if (honorRewards < uint8(m_TeamScores[teamId] / _honorTics))
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(1), teamId);
|
||||
if (reputationRewards < uint8(m_TeamScores[teamId] / _reputationTics))
|
||||
RewardReputationToTeam(teamId == TEAM_ALLIANCE ? 509 : 510, 10, teamId);
|
||||
RewardReputationToTeam(teamId == TEAM_ALLIANCE ? 509 : 510, uint32(10 * _abReputationRate), teamId);
|
||||
if (information < uint8(m_TeamScores[teamId] / BG_AB_WARNING_NEAR_VICTORY_SCORE))
|
||||
{
|
||||
if (teamId == TEAM_ALLIANCE)
|
||||
@@ -170,8 +170,8 @@ void BattlegroundAB::StartingEventOpenDoors()
|
||||
DoorOpen(BG_AB_OBJECT_GATE_A);
|
||||
DoorOpen(BG_AB_OBJECT_GATE_H);
|
||||
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, BG_AB_EVENT_START_BATTLE);
|
||||
_bgEvents.ScheduleEvent(BG_AB_EVENT_ALLIANCE_TICK, 3000);
|
||||
_bgEvents.ScheduleEvent(BG_AB_EVENT_HORDE_TICK, 3000);
|
||||
_bgEvents.ScheduleEvent(BG_AB_EVENT_ALLIANCE_TICK, 3s);
|
||||
_bgEvents.ScheduleEvent(BG_AB_EVENT_HORDE_TICK, 3s);
|
||||
}
|
||||
|
||||
void BattlegroundAB::AddPlayer(Player* player)
|
||||
@@ -421,6 +421,7 @@ bool BattlegroundAB::SetupBattleground()
|
||||
{
|
||||
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)) ? BG_AB_HONOR_TICK_WEEKEND : BG_AB_HONOR_TICK_NORMAL;
|
||||
_reputationTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)) ? BG_AB_REP_TICK_WEEKEND : BG_AB_REP_TICK_NORMAL;
|
||||
_abReputationRate = sWorld->getRate(RATE_REPUTATION_GAIN_AB);
|
||||
|
||||
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
|
||||
{
|
||||
|
||||
@@ -170,12 +170,11 @@ enum BG_AB_Misc
|
||||
|
||||
BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400,
|
||||
BG_AB_MAX_TEAM_SCORE = 1600,
|
||||
|
||||
BG_AB_FLAG_CAPTURING_TIME = 60000,
|
||||
BG_AB_BANNER_UPDATE_TIME = 2000
|
||||
};
|
||||
constexpr Milliseconds BG_AB_FLAG_CAPTURING_TIME = 60s;
|
||||
constexpr Milliseconds BG_AB_BANNER_UPDATE_TIME = 2s;
|
||||
|
||||
const uint32 BG_AB_TickIntervals[BG_AB_DYNAMIC_NODES_COUNT + 1] = {0, 12000, 9000, 6000, 3000, 1000};
|
||||
const Milliseconds BG_AB_TickIntervals[BG_AB_DYNAMIC_NODES_COUNT + 1] = {0ms, 12s, 9s, 6s, 3s, 1s};
|
||||
const uint32 BG_AB_TickPoints[BG_AB_DYNAMIC_NODES_COUNT + 1] = {0, 10, 10, 10, 10, 30};
|
||||
const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 896, 898, 899};
|
||||
|
||||
@@ -300,6 +299,7 @@ private:
|
||||
EventMap _bgEvents;
|
||||
uint32 _honorTics;
|
||||
uint32 _reputationTics;
|
||||
float _abReputationRate;
|
||||
uint8 _controlledPoints[PVP_TEAMS_COUNT] {};
|
||||
bool _teamScores500Disadvantage[PVP_TEAMS_COUNT] {};
|
||||
uint32 _configurableMaxTeamScore;
|
||||
|
||||
@@ -194,21 +194,21 @@ void BattlegroundAV::HandleQuestComplete(uint32 questid, Player* player)
|
||||
case AV_QUEST_A_COMMANDER1:
|
||||
case AV_QUEST_H_COMMANDER1:
|
||||
m_Team_QuestStatus[teamId][1]++;
|
||||
RewardReputationToTeam(teamId, 1, teamId);
|
||||
RewardReputationToTeam(teamId, uint32(1 * _avReputationRate), teamId);
|
||||
if (m_Team_QuestStatus[teamId][1] == 30)
|
||||
LOG_DEBUG("bg.battleground", "BG_AV Quest {} completed (need to implement some events here", questid);
|
||||
break;
|
||||
case AV_QUEST_A_COMMANDER2:
|
||||
case AV_QUEST_H_COMMANDER2:
|
||||
m_Team_QuestStatus[teamId][2]++;
|
||||
RewardReputationToTeam(teamId, 1, teamId);
|
||||
RewardReputationToTeam(teamId, uint32(1 * _avReputationRate), teamId);
|
||||
if (m_Team_QuestStatus[teamId][2] == 60)
|
||||
LOG_DEBUG("bg.battleground", "BG_AV Quest {} completed (need to implement some events here", questid);
|
||||
break;
|
||||
case AV_QUEST_A_COMMANDER3:
|
||||
case AV_QUEST_H_COMMANDER3:
|
||||
m_Team_QuestStatus[teamId][3]++;
|
||||
RewardReputationToTeam(teamId, 1, teamId);
|
||||
RewardReputationToTeam(teamId, uint32(1 * _avReputationRate), teamId);
|
||||
if (m_Team_QuestStatus[teamId][3] == 120)
|
||||
LOG_DEBUG("bg.battleground", "BG_AV Quest {} completed (need to implement some events here", questid);
|
||||
break;
|
||||
@@ -316,21 +316,21 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type)
|
||||
type -= AV_CPLACE_MAX;
|
||||
cinfoid = uint16(BG_AV_StaticCreaturePos[type][4]);
|
||||
creature = AddCreature(BG_AV_StaticCreatureInfo[cinfoid],
|
||||
type + AV_CPLACE_MAX,
|
||||
BG_AV_StaticCreaturePos[type][0],
|
||||
BG_AV_StaticCreaturePos[type][1],
|
||||
BG_AV_StaticCreaturePos[type][2],
|
||||
BG_AV_StaticCreaturePos[type][3]);
|
||||
type + AV_CPLACE_MAX,
|
||||
BG_AV_StaticCreaturePos[type][0],
|
||||
BG_AV_StaticCreaturePos[type][1],
|
||||
BG_AV_StaticCreaturePos[type][2],
|
||||
BG_AV_StaticCreaturePos[type][3]);
|
||||
isStatic = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
creature = AddCreature(BG_AV_CreatureInfo[cinfoid],
|
||||
type,
|
||||
BG_AV_CreaturePos[type][0],
|
||||
BG_AV_CreaturePos[type][1],
|
||||
BG_AV_CreaturePos[type][2],
|
||||
BG_AV_CreaturePos[type][3]);
|
||||
type,
|
||||
BG_AV_CreaturePos[type][0],
|
||||
BG_AV_CreaturePos[type][1],
|
||||
BG_AV_CreaturePos[type][2],
|
||||
BG_AV_CreaturePos[type][3]);
|
||||
}
|
||||
if (!creature)
|
||||
return nullptr;
|
||||
@@ -344,7 +344,7 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type)
|
||||
(cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3))))
|
||||
{
|
||||
if (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3)
|
||||
|| (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3)))
|
||||
|| (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3)))
|
||||
{
|
||||
CreatureData& data = sObjectMgr->NewOrExistCreatureData(creature->GetSpawnId());
|
||||
data.wander_distance = 5;
|
||||
@@ -814,11 +814,11 @@ void BattlegroundAV::PopulateNode(BG_AV_Nodes node)
|
||||
if (!trigger)
|
||||
{
|
||||
trigger = AddCreature(WORLD_TRIGGER,
|
||||
node + 302,
|
||||
BG_AV_CreaturePos[node + 302][0],
|
||||
BG_AV_CreaturePos[node + 302][1],
|
||||
BG_AV_CreaturePos[node + 302][2],
|
||||
BG_AV_CreaturePos[node + 302][3]);
|
||||
node + 302,
|
||||
BG_AV_CreaturePos[node + 302][0],
|
||||
BG_AV_CreaturePos[node + 302][1],
|
||||
BG_AV_CreaturePos[node + 302][2],
|
||||
BG_AV_CreaturePos[node + 302][3]);
|
||||
}
|
||||
|
||||
//add bonus honor aura trigger creature when node is accupied
|
||||
@@ -1240,25 +1240,28 @@ GraveyardStruct const* BattlegroundAV::GetClosestGraveyard(Player* player)
|
||||
|
||||
bool BattlegroundAV::SetupBattleground()
|
||||
{
|
||||
_avReputationRate = sWorld->getRate(RATE_REPUTATION_GAIN_AV);
|
||||
|
||||
if (sBattlegroundMgr->IsBGWeekend(GetBgTypeID(true)))
|
||||
{
|
||||
_reputationTower = 18;
|
||||
_reputationCaptain = 185;
|
||||
_reputationBoss = 525;
|
||||
_reputationPerOwnedGraveyard = 18;
|
||||
_reputationSurvivingCaptain = 175;
|
||||
_reputationSurvivingTower = 18;
|
||||
_reputationPerOwnedMine = 36;
|
||||
_reputationTower = uint32(18 * _avReputationRate);
|
||||
_reputationCaptain = uint32(185 * _avReputationRate);
|
||||
_reputationBoss = uint32(525 * _avReputationRate);
|
||||
_reputationPerOwnedGraveyard = uint32(18 * _avReputationRate);
|
||||
_reputationSurvivingCaptain = uint32(175 * _avReputationRate);
|
||||
_reputationSurvivingTower = uint32(18 * _avReputationRate);
|
||||
_reputationPerOwnedMine = uint32(36 * _avReputationRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
_reputationTower = 12;
|
||||
_reputationCaptain = 125;
|
||||
_reputationBoss = sWorld->getIntConfig(CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH);
|
||||
_reputationPerOwnedGraveyard = 12;
|
||||
_reputationSurvivingCaptain = 125;
|
||||
_reputationSurvivingTower = 12;
|
||||
_reputationPerOwnedMine = 24;
|
||||
_reputationTower = uint32(12 * _avReputationRate);
|
||||
_reputationCaptain = uint32(125 * _avReputationRate);
|
||||
// Special case: This value comes from another config setting, but we still apply our multiplier
|
||||
_reputationBoss = uint32(sWorld->getIntConfig(CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH) * _avReputationRate);
|
||||
_reputationPerOwnedGraveyard = uint32(12 * _avReputationRate);
|
||||
_reputationSurvivingCaptain = uint32(125 * _avReputationRate);
|
||||
_reputationSurvivingTower = uint32(12 * _avReputationRate);
|
||||
_reputationPerOwnedMine = uint32(24 * _avReputationRate);
|
||||
}
|
||||
|
||||
// Create starting objects
|
||||
|
||||
@@ -1850,6 +1850,7 @@ private:
|
||||
uint32 _reputationSurvivingCaptain = 0; // 125, 175
|
||||
uint32 _reputationSurvivingTower = 0; // 12, 18
|
||||
uint32 _reputationPerOwnedMine = 0; // 24, 36
|
||||
float _avReputationRate;
|
||||
|
||||
bool m_IsInformedNearVictory[2] {};
|
||||
};
|
||||
|
||||
@@ -68,7 +68,7 @@ void BattlegroundEY::PostUpdateImpl(uint32 diff)
|
||||
AddPoints(TEAM_ALLIANCE, BG_EY_TickPoints[_ownedPointsCount[TEAM_ALLIANCE] - 1]);
|
||||
if (_ownedPointsCount[TEAM_HORDE] > 0)
|
||||
AddPoints(TEAM_HORDE, BG_EY_TickPoints[_ownedPointsCount[TEAM_HORDE] - 1]);
|
||||
_bgEvents.ScheduleEvent(BG_EY_EVENT_ADD_POINTS, BG_EY_FPOINTS_TICK_TIME - (GameTime::GetGameTimeMS().count() % BG_EY_FPOINTS_TICK_TIME));
|
||||
_bgEvents.ScheduleEvent(BG_EY_EVENT_ADD_POINTS, BG_EY_FPOINTS_TICK_TIME - (GameTime::GetGameTimeMS() % BG_EY_FPOINTS_TICK_TIME));
|
||||
break;
|
||||
case BG_EY_EVENT_FLAG_ON_GROUND:
|
||||
RespawnFlagAfterDrop();
|
||||
@@ -78,7 +78,7 @@ void BattlegroundEY::PostUpdateImpl(uint32 diff)
|
||||
break;
|
||||
case BG_EY_EVENT_CHECK_CPOINTS:
|
||||
UpdatePointsState();
|
||||
_bgEvents.ScheduleEvent(BG_EY_EVENT_CHECK_CPOINTS, BG_EY_FPOINTS_CHECK_TIME - (GameTime::GetGameTimeMS().count() % BG_EY_FPOINTS_CHECK_TIME));
|
||||
_bgEvents.ScheduleEvent(BG_EY_EVENT_CHECK_CPOINTS, BG_EY_FPOINTS_CHECK_TIME - (GameTime::GetGameTimeMS() % BG_EY_FPOINTS_CHECK_TIME));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -106,8 +106,8 @@ void BattlegroundEY::StartingEventOpenDoors()
|
||||
|
||||
// Achievement: Flurry
|
||||
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, BG_EY_EVENT_START_BATTLE);
|
||||
_bgEvents.ScheduleEvent(BG_EY_EVENT_ADD_POINTS, 0);
|
||||
_bgEvents.ScheduleEvent(BG_EY_EVENT_CHECK_CPOINTS, 0);
|
||||
_bgEvents.ScheduleEvent(BG_EY_EVENT_ADD_POINTS, 0ms);
|
||||
_bgEvents.ScheduleEvent(BG_EY_EVENT_CHECK_CPOINTS, 0ms);
|
||||
}
|
||||
|
||||
void BattlegroundEY::AddPoints(TeamId teamId, uint32 points)
|
||||
|
||||
@@ -31,13 +31,10 @@ enum BG_EY_Events
|
||||
BG_EY_EVENT_CHECK_CPOINTS = 4
|
||||
};
|
||||
|
||||
enum BG_EY_Timers
|
||||
{
|
||||
BG_EY_FLAG_RESPAWN_TIME = 10 * IN_MILLISECONDS,
|
||||
BG_EY_FLAG_ON_GROUND_TIME = 10 * IN_MILLISECONDS,
|
||||
BG_EY_FPOINTS_CHECK_TIME = 2 * IN_MILLISECONDS,
|
||||
BG_EY_FPOINTS_TICK_TIME = 2 * IN_MILLISECONDS
|
||||
};
|
||||
constexpr Milliseconds BG_EY_FLAG_RESPAWN_TIME = 10s;
|
||||
constexpr Milliseconds BG_EY_FLAG_ON_GROUND_TIME = 10s;
|
||||
constexpr Milliseconds BG_EY_FPOINTS_CHECK_TIME = 2s;
|
||||
constexpr Milliseconds BG_EY_FPOINTS_TICK_TIME = 2s;
|
||||
|
||||
enum BG_EY_ProgressBarConsts
|
||||
{
|
||||
|
||||
@@ -63,7 +63,7 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff)
|
||||
{
|
||||
case BG_WS_EVENT_UPDATE_GAME_TIME:
|
||||
UpdateWorldState(WORLD_STATE_BATTLEGROUND_WS_STATE_TIMER, GetMatchTime());
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_UPDATE_GAME_TIME, ((BG_WS_TOTAL_GAME_TIME - GetStartTime()) % (MINUTE * IN_MILLISECONDS)) + 1);
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_UPDATE_GAME_TIME, Milliseconds(((BG_WS_TOTAL_GAME_TIME - GetStartTime()) % (MINUTE * IN_MILLISECONDS)) + 1));
|
||||
break;
|
||||
case BG_WS_EVENT_NO_TIME_LEFT:
|
||||
if (GetTeamScore(TEAM_ALLIANCE) == GetTeamScore(TEAM_HORDE))
|
||||
@@ -137,8 +137,8 @@ void BattlegroundWS::StartingEventOpenDoors()
|
||||
|
||||
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, WS_EVENT_START_BATTLE);
|
||||
UpdateWorldState(WORLD_STATE_BATTLEGROUND_WS_STATE_TIMER_ACTIVE, 1);
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_UPDATE_GAME_TIME, 0);
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_NO_TIME_LEFT, BG_WS_TOTAL_GAME_TIME - 2 * MINUTE * IN_MILLISECONDS); // 27 - 2 = 25 minutes
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_UPDATE_GAME_TIME, 0ms);
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_NO_TIME_LEFT, Milliseconds(BG_WS_TOTAL_GAME_TIME - 2 * MINUTE * IN_MILLISECONDS)); // 27 - 2 = 25 minutes
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_DESPAWN_DOORS, BG_WS_DOOR_DESPAWN_TIME);
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* player)
|
||||
EndBattleground(GetTeamScore(TEAM_HORDE) == _configurableMaxTeamScore ? TEAM_HORDE : TEAM_ALLIANCE);
|
||||
}
|
||||
else
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_RESPAWN_BOTH_FLAGS, BG_WS_FLAG_RESPAWN_TIME);
|
||||
_bgEvents.ScheduleEvent(BG_WS_EVENT_RESPAWN_BOTH_FLAGS, Milliseconds(BG_WS_FLAG_RESPAWN_TIME));
|
||||
|
||||
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
|
||||
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
|
||||
@@ -426,15 +426,17 @@ void BattlegroundWS::HandleAreaTrigger(Player* player, uint32 trigger)
|
||||
|
||||
bool BattlegroundWS::SetupBattleground()
|
||||
{
|
||||
_wsReputationRate = sWorld->getRate(RATE_REPUTATION_GAIN_WSG);
|
||||
|
||||
if (sBattlegroundMgr->IsBGWeekend(GetBgTypeID(true)))
|
||||
{
|
||||
_reputationCapture = 45;
|
||||
_reputationCapture = uint32(45 * _wsReputationRate);
|
||||
_honorWinKills = 3;
|
||||
_honorEndKills = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
_reputationCapture = 35;
|
||||
_reputationCapture = uint32(35 * _wsReputationRate);
|
||||
_honorWinKills = 1;
|
||||
_honorEndKills = 2;
|
||||
}
|
||||
@@ -578,10 +580,10 @@ uint32 BattlegroundWS::GetAssaultSpellId() const
|
||||
{
|
||||
if ((!GetFlagPickerGUID(TEAM_ALLIANCE) && GetFlagState(TEAM_ALLIANCE) != BG_WS_FLAG_STATE_ON_GROUND) ||
|
||||
(!GetFlagPickerGUID(TEAM_HORDE) && GetFlagState(TEAM_HORDE) != BG_WS_FLAG_STATE_ON_GROUND) ||
|
||||
_bgEvents.GetNextEventTime(BG_WS_EVENT_BOTH_FLAGS_KEPT10) > 0)
|
||||
_bgEvents.HasTimeUntilEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10))
|
||||
return 0;
|
||||
|
||||
return _bgEvents.GetNextEventTime(BG_WS_EVENT_BOTH_FLAGS_KEPT15) > 0 ? BG_WS_SPELL_FOCUSED_ASSAULT : BG_WS_SPELL_BRUTAL_ASSAULT;
|
||||
return _bgEvents.HasTimeUntilEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15) ? BG_WS_SPELL_FOCUSED_ASSAULT : BG_WS_SPELL_BRUTAL_ASSAULT;
|
||||
}
|
||||
|
||||
void BattlegroundWS::RemoveAssaultAuras()
|
||||
|
||||
@@ -39,12 +39,12 @@ enum BG_WS_TimerOrScore
|
||||
BG_WS_MAX_TEAM_SCORE = 3,
|
||||
|
||||
BG_WS_TOTAL_GAME_TIME = 27 * MINUTE * IN_MILLISECONDS,
|
||||
BG_WS_FLAG_RESPAWN_TIME = 23 * IN_MILLISECONDS,
|
||||
BG_WS_FLAG_DROP_TIME = 10 * IN_MILLISECONDS,
|
||||
BG_WS_SPELL_FORCE_TIME = 10 * MINUTE * IN_MILLISECONDS,
|
||||
BG_WS_SPELL_BRUTAL_TIME = 15 * MINUTE * IN_MILLISECONDS,
|
||||
BG_WS_DOOR_DESPAWN_TIME = 5 * IN_MILLISECONDS
|
||||
BG_WS_FLAG_RESPAWN_TIME = 23 * IN_MILLISECONDS
|
||||
};
|
||||
constexpr Milliseconds BG_WS_FLAG_DROP_TIME = 10s;
|
||||
constexpr Milliseconds BG_WS_SPELL_FORCE_TIME = 600s;
|
||||
constexpr Milliseconds BG_WS_SPELL_BRUTAL_TIME = 900s;
|
||||
constexpr Milliseconds BG_WS_DOOR_DESPAWN_TIME = 5s;
|
||||
|
||||
enum BG_WS_BroadcastTexts
|
||||
{
|
||||
@@ -258,6 +258,7 @@ private:
|
||||
ObjectGuid _droppedFlagGUID[2];
|
||||
uint8 _flagState[2];
|
||||
TeamId _lastFlagCaptureTeam;
|
||||
float _wsReputationRate;
|
||||
uint32 _reputationCapture;
|
||||
uint32 _honorWinKills;
|
||||
uint32 _honorEndKills;
|
||||
|
||||
@@ -1508,7 +1508,7 @@ namespace lfg
|
||||
lockMap.clear();
|
||||
}
|
||||
|
||||
uint8 LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true*/)
|
||||
uint8 LFGMgr::CheckGroupRoles(LfgRolesMap& groles)
|
||||
{
|
||||
if (groles.empty())
|
||||
return 0;
|
||||
@@ -1517,21 +1517,18 @@ namespace lfg
|
||||
uint8 tank = 0;
|
||||
uint8 healer = 0;
|
||||
|
||||
if (removeLeaderFlag)
|
||||
for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it)
|
||||
it->second &= ~PLAYER_ROLE_LEADER;
|
||||
|
||||
for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it)
|
||||
{
|
||||
if (it->second == PLAYER_ROLE_NONE)
|
||||
uint8 const role = it->second & ~PLAYER_ROLE_LEADER;
|
||||
if (role == PLAYER_ROLE_NONE)
|
||||
return 0;
|
||||
|
||||
if (it->second & PLAYER_ROLE_DAMAGE)
|
||||
if (role & PLAYER_ROLE_DAMAGE)
|
||||
{
|
||||
if (it->second != PLAYER_ROLE_DAMAGE)
|
||||
if (role != PLAYER_ROLE_DAMAGE)
|
||||
{
|
||||
it->second -= PLAYER_ROLE_DAMAGE;
|
||||
if (uint8 x = CheckGroupRoles(groles, false))
|
||||
if (uint8 x = CheckGroupRoles(groles))
|
||||
return x;
|
||||
it->second += PLAYER_ROLE_DAMAGE;
|
||||
}
|
||||
@@ -1541,12 +1538,12 @@ namespace lfg
|
||||
damage++;
|
||||
}
|
||||
|
||||
if (it->second & PLAYER_ROLE_HEALER)
|
||||
if (role & PLAYER_ROLE_HEALER)
|
||||
{
|
||||
if (it->second != PLAYER_ROLE_HEALER)
|
||||
if (role != PLAYER_ROLE_HEALER)
|
||||
{
|
||||
it->second -= PLAYER_ROLE_HEALER;
|
||||
if (uint8 x = CheckGroupRoles(groles, false))
|
||||
if (uint8 x = CheckGroupRoles(groles))
|
||||
return x;
|
||||
it->second += PLAYER_ROLE_HEALER;
|
||||
}
|
||||
@@ -1556,12 +1553,12 @@ namespace lfg
|
||||
healer++;
|
||||
}
|
||||
|
||||
if (it->second & PLAYER_ROLE_TANK)
|
||||
if (role & PLAYER_ROLE_TANK)
|
||||
{
|
||||
if (it->second != PLAYER_ROLE_TANK)
|
||||
if (role != PLAYER_ROLE_TANK)
|
||||
{
|
||||
it->second -= PLAYER_ROLE_TANK;
|
||||
if (uint8 x = CheckGroupRoles(groles, false))
|
||||
if (uint8 x = CheckGroupRoles(groles))
|
||||
return x;
|
||||
it->second += PLAYER_ROLE_TANK;
|
||||
}
|
||||
|
||||
@@ -568,7 +568,7 @@ namespace lfg
|
||||
/// Checks if all players are queued
|
||||
bool AllQueued(Lfg5Guids const& check);
|
||||
/// Checks if given roles match, modifies given roles map with new roles
|
||||
static uint8 CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag = true);
|
||||
static uint8 CheckGroupRoles(LfgRolesMap& groles);
|
||||
/// Checks if given players are ignoring each other
|
||||
static bool HasIgnore(ObjectGuid guid1, ObjectGuid guid2);
|
||||
/// Sends queue status to player
|
||||
|
||||
@@ -121,7 +121,7 @@ void Corpse::DeleteFromDB(CharacterDatabaseTransaction trans)
|
||||
DeleteFromDB(GetOwnerGUID(), trans);
|
||||
}
|
||||
|
||||
void Corpse::DeleteFromDB(ObjectGuid const ownerGuid, CharacterDatabaseTransaction trans)
|
||||
void Corpse::DeleteFromDB(ObjectGuid const& ownerGuid, CharacterDatabaseTransaction trans)
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE);
|
||||
stmt->SetData(0, ownerGuid.GetCounter());
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
bool LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields);
|
||||
|
||||
void DeleteFromDB(CharacterDatabaseTransaction trans);
|
||||
static void DeleteFromDB(ObjectGuid const ownerGuid, CharacterDatabaseTransaction trans);
|
||||
static void DeleteFromDB(ObjectGuid const& ownerGuid, CharacterDatabaseTransaction trans);
|
||||
|
||||
[[nodiscard]] ObjectGuid GetOwnerGUID() const { return GetGuidValue(CORPSE_FIELD_OWNER); }
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ CreatureBaseStats const* CreatureBaseStats::GetBaseStats(uint8 level, uint8 unit
|
||||
|
||||
bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
{
|
||||
m_owner.DespawnOrUnsummon(0s, m_respawnTimer); // since we are here, we are not TempSummon as object type cannot change during runtime
|
||||
m_owner.DespawnOrUnsummon(0ms, m_respawnTimer); // since we are here, we are not TempSummon as object type cannot change during runtime
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1999,7 +1999,7 @@ void Creature::setDeathState(DeathState state, bool despawn)
|
||||
m_formation->FormationReset(true, false);
|
||||
|
||||
bool needsFalling = !despawn && (IsFlying() || IsHovering()) && !IsUnderWater();
|
||||
SetHover(false, false, false);
|
||||
SetHover(false);
|
||||
SetDisableGravity(false, false, false);
|
||||
|
||||
if (needsFalling)
|
||||
@@ -2160,12 +2160,12 @@ void Creature::Respawn(bool force)
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer)
|
||||
void Creature::ForcedDespawn(Milliseconds timeMSToDespawn, Seconds forceRespawnTimer)
|
||||
{
|
||||
if (timeMSToDespawn)
|
||||
if (timeMSToDespawn > 0ms)
|
||||
{
|
||||
ForcedDespawnDelayEvent* pEvent = new ForcedDespawnDelayEvent(*this, forceRespawnTimer);
|
||||
m_Events.AddEvent(pEvent, m_Events.CalculateTime(timeMSToDespawn));
|
||||
m_Events.AddEventAtOffset(pEvent, timeMSToDespawn);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2175,17 +2175,17 @@ void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer)
|
||||
// Xinef: Set new respawn time, ignore corpse decay time...
|
||||
RemoveCorpse(true);
|
||||
|
||||
if (forceRespawnTimer > Seconds::zero())
|
||||
if (forceRespawnTimer > 0s)
|
||||
if (GetMap())
|
||||
GetMap()->ScheduleCreatureRespawn(GetGUID(), forceRespawnTimer);
|
||||
}
|
||||
|
||||
void Creature::DespawnOrUnsummon(Milliseconds msTimeToDespawn /*= 0*/, Seconds forcedRespawnTimer)
|
||||
void Creature::DespawnOrUnsummon(Milliseconds msTimeToDespawn /*= 0ms*/, Seconds forcedRespawnTimer /*= 0s*/)
|
||||
{
|
||||
if (TempSummon* summon = this->ToTempSummon())
|
||||
summon->UnSummon(msTimeToDespawn.count());
|
||||
summon->UnSummon(msTimeToDespawn);
|
||||
else
|
||||
ForcedDespawn(msTimeToDespawn.count(), forcedRespawnTimer);
|
||||
ForcedDespawn(msTimeToDespawn, forcedRespawnTimer);
|
||||
}
|
||||
|
||||
void Creature::DespawnOnEvade(Seconds respawnDelay)
|
||||
@@ -2205,7 +2205,7 @@ void Creature::DespawnOnEvade(Seconds respawnDelay)
|
||||
return;
|
||||
}
|
||||
|
||||
DespawnOrUnsummon(Milliseconds(0), respawnDelay);
|
||||
DespawnOrUnsummon(0ms, respawnDelay);
|
||||
}
|
||||
|
||||
void Creature::InitializeReactState()
|
||||
@@ -2465,7 +2465,7 @@ void Creature::CallAssistance(Unit* target /*= nullptr*/)
|
||||
e->AddAssistant((*assistList.begin())->GetGUID());
|
||||
assistList.pop_front();
|
||||
}
|
||||
m_Events.AddEvent(e, m_Events.CalculateTime(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)));
|
||||
m_Events.AddEventAtOffset(e, Milliseconds(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3245,8 +3245,9 @@ bool Creature::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool
|
||||
{
|
||||
WorldPacket data(disable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
data << m_movedByPlayer->ToPlayer()->GetSession()->GetOrderCounter(); // movement counter
|
||||
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
|
||||
m_movedByPlayer->ToPlayer()->GetSession()->IncrementOrderCounter();
|
||||
|
||||
data.Initialize(MSG_MOVE_GRAVITY_CHNG, 64);
|
||||
data << GetPackGUID();
|
||||
@@ -3319,107 +3320,6 @@ void Creature::RefreshSwimmingFlag(bool recheck)
|
||||
SetUnitFlag(UNIT_FLAG_SWIMMING);
|
||||
}
|
||||
|
||||
bool Creature::SetCanFly(bool enable, bool /*packetOnly*/ /* = false */)
|
||||
{
|
||||
if (!Unit::SetCanFly(enable))
|
||||
return false;
|
||||
|
||||
if (m_movedByPlayer)
|
||||
{
|
||||
sScriptMgr->AnticheatSetCanFlybyServer(m_movedByPlayer->ToPlayer(), enable);
|
||||
|
||||
if (!enable)
|
||||
m_movedByPlayer->ToPlayer()->SetFallInformation(GameTime::GetGameTime().count(), m_movedByPlayer->ToPlayer()->GetPositionZ());
|
||||
|
||||
WorldPacket data(enable ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
|
||||
|
||||
data.Initialize(MSG_MOVE_UPDATE_CAN_FLY, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
m_movedByPlayer->ToPlayer()->SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_FLYING : SMSG_SPLINE_MOVE_UNSET_FLYING, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Creature::SetWaterWalking(bool enable, bool packetOnly /* = false */)
|
||||
{
|
||||
if (!packetOnly && !Unit::SetWaterWalking(enable))
|
||||
return false;
|
||||
|
||||
if (m_movedByPlayer)
|
||||
{
|
||||
WorldPacket data(enable ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
|
||||
|
||||
data.Initialize(MSG_MOVE_WATER_WALK, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
m_movedByPlayer->ToPlayer()->SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_WATER_WALK : SMSG_SPLINE_MOVE_LAND_WALK, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Creature::SetFeatherFall(bool enable, bool packetOnly /* = false */)
|
||||
{
|
||||
if (!packetOnly && !Unit::SetFeatherFall(enable))
|
||||
return false;
|
||||
|
||||
if (m_movedByPlayer)
|
||||
{
|
||||
WorldPacket data(enable ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
|
||||
|
||||
data.Initialize(MSG_MOVE_FEATHER_FALL, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
m_movedByPlayer->ToPlayer()->SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_FEATHER_FALL : SMSG_SPLINE_MOVE_NORMAL_FALL, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Creature::SetHover(bool enable, bool packetOnly /*= false*/, bool updateAnimationTier /*= true*/)
|
||||
{
|
||||
if (!packetOnly && !Unit::SetHover(enable))
|
||||
return false;
|
||||
|
||||
if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !IsRooted())
|
||||
{
|
||||
if (IsLevitating())
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_FLY);
|
||||
else if (IsHovering())
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_HOVER);
|
||||
else
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_GROUND);
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_HOVER : SMSG_SPLINE_MOVE_UNSET_HOVER, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
float Creature::GetAggroRange(Unit const* target) const
|
||||
{
|
||||
// Determines the aggro range for creatures
|
||||
@@ -3814,6 +3714,33 @@ bool Creature::CanGeneratePickPocketLoot() const
|
||||
return (lootPickPocketRestoreTime == 0 || lootPickPocketRestoreTime < GameTime::GetGameTime().count());
|
||||
}
|
||||
|
||||
void Creature::SetTextRepeatId(uint8 textGroup, uint8 id)
|
||||
{
|
||||
CreatureTextRepeatIds& repeats = m_textRepeat[textGroup];
|
||||
if (std::find(repeats.begin(), repeats.end(), id) == repeats.end())
|
||||
repeats.push_back(id);
|
||||
else
|
||||
LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup {} for Creature({}) {}, id {} already added", uint32(textGroup), GetName(), GetGUID().ToString(), uint32(id));
|
||||
}
|
||||
|
||||
CreatureTextRepeatIds const& Creature::GetTextRepeatGroup(uint8 textGroup)
|
||||
{
|
||||
static CreatureTextRepeatIds const emptyIds;
|
||||
|
||||
CreatureTextRepeatGroup::const_iterator groupItr = m_textRepeat.find(textGroup);
|
||||
if (groupItr != m_textRepeat.end())
|
||||
return groupItr->second;
|
||||
|
||||
return emptyIds;
|
||||
}
|
||||
|
||||
void Creature::ClearTextRepeatGroup(uint8 textGroup)
|
||||
{
|
||||
CreatureTextRepeatGroup::iterator groupItr = m_textRepeat.find(textGroup);
|
||||
if (groupItr != m_textRepeat.end())
|
||||
groupItr->second.clear();
|
||||
}
|
||||
|
||||
void Creature::SetRespawnTime(uint32 respawn)
|
||||
{
|
||||
m_respawnTime = respawn ? GameTime::GetGameTime().count() + respawn : 0;
|
||||
@@ -3836,7 +3763,7 @@ void Creature::ModifyThreatPercentTemp(Unit* victim, int32 percent, Milliseconds
|
||||
}
|
||||
|
||||
TemporaryThreatModifierEvent* pEvent = new TemporaryThreatModifierEvent(*this, victim->GetGUID(), currentThreat);
|
||||
m_Events.AddEvent(pEvent, m_Events.CalculateTime(duration.count()));
|
||||
m_Events.AddEventAtOffset(pEvent, duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@ class CreatureGroup;
|
||||
|
||||
#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
|
||||
|
||||
//used for handling non-repeatable random texts
|
||||
typedef std::vector<uint8> CreatureTextRepeatIds;
|
||||
typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup;
|
||||
|
||||
class Creature : public Unit, public GridObject<Creature>, public MovableMapObject, public UpdatableMapObject
|
||||
{
|
||||
public:
|
||||
@@ -143,10 +147,6 @@ public:
|
||||
bool SetWalk(bool enable) override;
|
||||
bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override;
|
||||
bool SetSwim(bool enable) override;
|
||||
bool SetCanFly(bool enable, bool packetOnly = false) override;
|
||||
bool SetWaterWalking(bool enable, bool packetOnly = false) override;
|
||||
bool SetFeatherFall(bool enable, bool packetOnly = false) override;
|
||||
bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true) override;
|
||||
bool HasSpellFocus(Spell const* focusSpell = nullptr) const;
|
||||
|
||||
struct
|
||||
@@ -283,8 +283,7 @@ public:
|
||||
|
||||
void RemoveCorpse(bool setSpawnTime = true, bool skipVisibility = false);
|
||||
|
||||
void DespawnOrUnsummon(Milliseconds msTimeToDespawn, Seconds forcedRespawnTimer);
|
||||
void DespawnOrUnsummon(uint32 msTimeToDespawn = 0) { DespawnOrUnsummon(Milliseconds(msTimeToDespawn), 0s); };
|
||||
void DespawnOrUnsummon(Milliseconds msTimeToDespawn = 0ms, Seconds forcedRespawnTimer = 0s);
|
||||
void DespawnOnEvade(Seconds respawnDelay = 20s);
|
||||
|
||||
[[nodiscard]] time_t const& GetRespawnTime() const { return m_respawnTime; }
|
||||
@@ -392,6 +391,10 @@ public:
|
||||
void UpdateLeashExtensionTime();
|
||||
uint8 GetLeashTimer() const;
|
||||
|
||||
CreatureTextRepeatIds const& GetTextRepeatGroup(uint8 textGroup);
|
||||
void SetTextRepeatId(uint8 textGroup, uint8 id);
|
||||
void ClearTextRepeatGroup(uint8 textGroup);
|
||||
|
||||
bool IsFreeToMove();
|
||||
static constexpr uint32 MOVE_CIRCLE_CHECK_INTERVAL = 3000;
|
||||
static constexpr uint32 MOVE_BACKWARDS_CHECK_INTERVAL = 2000;
|
||||
@@ -502,7 +505,7 @@ protected:
|
||||
bool IsAlwaysDetectableFor(WorldObject const* seer) const override;
|
||||
|
||||
private:
|
||||
void ForcedDespawn(uint32 timeMSToDespawn = 0, Seconds forcedRespawnTimer = 0s);
|
||||
void ForcedDespawn(Milliseconds timeMSToDespawn = 0ms, Seconds forcedRespawnTimer = 0s);
|
||||
|
||||
[[nodiscard]] bool CanPeriodicallyCallForAssistance() const;
|
||||
|
||||
@@ -523,6 +526,8 @@ private:
|
||||
|
||||
Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing
|
||||
|
||||
CreatureTextRepeatGroup m_textRepeat;
|
||||
|
||||
bool _isMissingSwimmingFlagOutOfCombat;
|
||||
|
||||
uint32 m_assistanceTimer;
|
||||
|
||||
@@ -99,18 +99,18 @@ enum class CreatureFlightMovementType : uint8
|
||||
|
||||
enum class CreatureChaseMovementType : uint8
|
||||
{
|
||||
Run,
|
||||
CanWalk,
|
||||
AlwaysWalk,
|
||||
Run = 0,
|
||||
CanWalk = 1,
|
||||
AlwaysWalk = 2,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
enum class CreatureRandomMovementType : uint8
|
||||
{
|
||||
Walk,
|
||||
CanRun,
|
||||
AlwaysRun,
|
||||
Walk = 0,
|
||||
CanRun = 1,
|
||||
AlwaysRun = 2,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
@@ -284,13 +284,12 @@ void TempSummon::SetTempSummonType(TempSummonType type)
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
void TempSummon::UnSummon(uint32 msTime)
|
||||
void TempSummon::UnSummon(Milliseconds msTime)
|
||||
{
|
||||
if (msTime)
|
||||
if (msTime > 0ms)
|
||||
{
|
||||
ForcedUnsummonDelayEvent* pEvent = new ForcedUnsummonDelayEvent(*this);
|
||||
|
||||
m_Events.AddEvent(pEvent, m_Events.CalculateTime(msTime));
|
||||
m_Events.AddEventAtOffset(pEvent, msTime);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
void Update(uint32 time) override;
|
||||
virtual void InitStats(uint32 lifetime);
|
||||
virtual void InitSummon();
|
||||
virtual void UnSummon(uint32 msTime = 0);
|
||||
virtual void UnSummon(Milliseconds msTime = 0ms);
|
||||
void UpdateObjectVisibilityOnCreate() override;
|
||||
void RemoveFromWorld() override;
|
||||
void SetTempSummonType(TempSummonType type);
|
||||
@@ -133,4 +133,5 @@ public:
|
||||
private:
|
||||
TempSummon& m_owner;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -929,7 +929,7 @@ void GameObject::AddUniqueUse(Player* player)
|
||||
m_unique_users.insert(player->GetGUID());
|
||||
}
|
||||
|
||||
void GameObject::DespawnOrUnsummon(Milliseconds delay, Seconds forceRespawnTime)
|
||||
void GameObject::DespawnOrUnsummon(Milliseconds delay /*= 0ms*/, Seconds forceRespawnTime /*= 0s*/)
|
||||
{
|
||||
if (delay > 0ms)
|
||||
{
|
||||
@@ -1731,34 +1731,40 @@ void GameObject::Use(Unit* user)
|
||||
uint32 zone, subzone;
|
||||
GetZoneAndAreaId(zone, subzone);
|
||||
|
||||
int32 zone_skill = sObjectMgr->GetFishingBaseSkillLevel(subzone);
|
||||
if (!zone_skill)
|
||||
zone_skill = sObjectMgr->GetFishingBaseSkillLevel(zone);
|
||||
int32 zoneSkill = sObjectMgr->GetFishingBaseSkillLevel(subzone);
|
||||
if (!zoneSkill)
|
||||
zoneSkill = sObjectMgr->GetFishingBaseSkillLevel(zone);
|
||||
|
||||
//provide error, no fishable zone or area should be 0
|
||||
if (!zone_skill)
|
||||
if (!zoneSkill)
|
||||
LOG_ERROR("sql.sql", "Fishable areaId {} are not properly defined in `skill_fishing_base_level`.", subzone);
|
||||
|
||||
int32 skill = player->GetSkillValue(SKILL_FISHING);
|
||||
// no miss skill is zone skill + 95 since at least patch 2.1
|
||||
int32 const noMissSkill = zoneSkill + 95;
|
||||
|
||||
int32 const skill = player->GetSkillValue(SKILL_FISHING);
|
||||
|
||||
int32 chance;
|
||||
if (skill < zone_skill)
|
||||
// fishing pool catches are 100%
|
||||
//TODO: find reasonable value for fishing hole search
|
||||
GameObject* fishingHole = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
|
||||
if (fishingHole)
|
||||
chance = 100;
|
||||
else if (skill < noMissSkill)
|
||||
{
|
||||
chance = int32(pow((double)skill / zone_skill, 2) * 100);
|
||||
chance = int32(pow((double)skill / noMissSkill, 2) * 100);
|
||||
if (chance < 1)
|
||||
chance = 1;
|
||||
}
|
||||
else
|
||||
chance = 100;
|
||||
|
||||
int32 roll = irand(1, 100);
|
||||
int32 const roll = irand(1, 100);
|
||||
|
||||
LOG_DEBUG("entities.gameobject", "Fishing check (skill: {} zone min skill: {} chance {} roll: {}", skill, zone_skill, chance, roll);
|
||||
LOG_DEBUG("entities.gameobject", "Fishing check (skill: {} zone min skill: {} no-miss skill: {} chance {} roll: {})", skill, zoneSkill, noMissSkill, chance, roll);
|
||||
|
||||
if (sScriptMgr->OnPlayerUpdateFishingSkill(player, skill, zone_skill, chance, roll))
|
||||
{
|
||||
if (sScriptMgr->OnPlayerUpdateFishingSkill(player, skill, zoneSkill, chance, roll))
|
||||
player->UpdateFishingSkill();
|
||||
}
|
||||
// but you will likely cause junk in areas that require a high fishing skill (not yet implemented)
|
||||
if (chance >= roll)
|
||||
{
|
||||
@@ -1768,11 +1774,10 @@ void GameObject::Use(Unit* user)
|
||||
SetOwnerGUID(player->GetGUID());
|
||||
SetSpellId(0); // prevent removing unintended auras at Unit::RemoveGameObject
|
||||
|
||||
//TODO: find reasonable value for fishing hole search
|
||||
GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
|
||||
if (ok)
|
||||
// fishing pool catch
|
||||
if (fishingHole)
|
||||
{
|
||||
ok->Use(player);
|
||||
fishingHole->Use(player);
|
||||
SetLootState(GO_JUST_DEACTIVATED);
|
||||
}
|
||||
else
|
||||
@@ -3046,13 +3051,13 @@ SpellInfo const* GameObject::GetSpellForLock(Player const* player) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GameObject::AddToSkillupList(ObjectGuid playerGuid)
|
||||
void GameObject::AddToSkillupList(ObjectGuid const& playerGuid)
|
||||
{
|
||||
int32 timer = GetMap()->IsDungeon() ? -1 : 10 * MINUTE * IN_MILLISECONDS;
|
||||
m_SkillupList[playerGuid] = timer;
|
||||
}
|
||||
|
||||
bool GameObject::IsInSkillupList(ObjectGuid playerGuid) const
|
||||
bool GameObject::IsInSkillupList(ObjectGuid const& playerGuid) const
|
||||
{
|
||||
for (auto const& itr : m_SkillupList)
|
||||
{
|
||||
|
||||
@@ -231,8 +231,8 @@ public:
|
||||
void RemoveLootMode(uint16 lootMode) { m_LootMode &= ~lootMode; }
|
||||
void ResetLootMode() { m_LootMode = LOOT_MODE_DEFAULT; }
|
||||
|
||||
void AddToSkillupList(ObjectGuid playerGuid);
|
||||
[[nodiscard]] bool IsInSkillupList(ObjectGuid playerGuid) const;
|
||||
void AddToSkillupList(ObjectGuid const& playerGuid);
|
||||
[[nodiscard]] bool IsInSkillupList(ObjectGuid const& playerGuid) const;
|
||||
|
||||
void AddUniqueUse(Player* player);
|
||||
void AddUse() { ++m_usetimes; }
|
||||
|
||||
@@ -1095,23 +1095,45 @@ void WorldObject::SetVisibilityDistanceOverride(VisibilityDistanceType type)
|
||||
if (type == GetVisibilityOverrideType())
|
||||
return;
|
||||
|
||||
if (IsPlayer())
|
||||
if (!IsCreature() && !IsGameObject() && !IsDynamicObject())
|
||||
return;
|
||||
|
||||
if (IsVisibilityOverridden())
|
||||
{
|
||||
if (IsFarVisible())
|
||||
GetMap()->RemoveWorldObjectFromFarVisibleMap(this);
|
||||
else if (IsZoneWideVisible())
|
||||
GetMap()->RemoveWorldObjectFromZoneWideVisibleMap(GetZoneId(), this);
|
||||
}
|
||||
|
||||
if (type == VisibilityDistanceType::Large || type == VisibilityDistanceType::Gigantic)
|
||||
GetMap()->AddWorldObjectToFarVisibleMap(this);
|
||||
else if (type == VisibilityDistanceType::Infinite)
|
||||
GetMap()->AddWorldObjectToZoneWideVisibleMap(GetZoneId(), this);
|
||||
// Important to remove from old visibility override containers first
|
||||
RemoveFromMapVisibilityOverrideContainers();
|
||||
|
||||
// Always update _visibilityDistanceOverrideType, even when not in world
|
||||
_visibilityDistanceOverrideType = type;
|
||||
|
||||
// Finally, add to new visibility override containers
|
||||
AddToMapVisibilityOverrideContainers();
|
||||
}
|
||||
|
||||
void WorldObject::RemoveFromMapVisibilityOverrideContainers()
|
||||
{
|
||||
if (!IsVisibilityOverridden())
|
||||
return;
|
||||
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
|
||||
if (IsFarVisible())
|
||||
GetMap()->RemoveWorldObjectFromFarVisibleMap(this);
|
||||
else if (IsZoneWideVisible())
|
||||
GetMap()->RemoveWorldObjectFromZoneWideVisibleMap(_zoneId, this);
|
||||
}
|
||||
|
||||
void WorldObject::AddToMapVisibilityOverrideContainers()
|
||||
{
|
||||
if (!IsVisibilityOverridden())
|
||||
return;
|
||||
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
|
||||
if (IsFarVisible())
|
||||
GetMap()->AddWorldObjectToFarVisibleMap(this);
|
||||
else if (IsZoneWideVisible())
|
||||
GetMap()->AddWorldObjectToZoneWideVisibleMap(_zoneId, this);
|
||||
}
|
||||
|
||||
void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
|
||||
@@ -1177,6 +1199,9 @@ void WorldObject::AddToWorld()
|
||||
Object::AddToWorld();
|
||||
GetMap()->GetZoneAndAreaId(GetPhaseMask(), _zoneId, _areaId, GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
GetMap()->AddObjectToPendingUpdateList(this);
|
||||
|
||||
if (IsZoneWideVisible())
|
||||
GetMap()->AddWorldObjectToZoneWideVisibleMap(_zoneId, this);
|
||||
}
|
||||
|
||||
void WorldObject::RemoveFromWorld()
|
||||
@@ -1184,8 +1209,7 @@ void WorldObject::RemoveFromWorld()
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
|
||||
if (IsZoneWideVisible())
|
||||
GetMap()->RemoveWorldObjectFromZoneWideVisibleMap(GetZoneId(), this);
|
||||
RemoveFromMapVisibilityOverrideContainers();
|
||||
|
||||
DestroyForVisiblePlayers();
|
||||
|
||||
|
||||
@@ -780,6 +780,9 @@ private:
|
||||
//bool CanDetectStealthOf(WorldObject const* obj) const;
|
||||
bool CanDetectStealthOf(WorldObject const* obj, bool checkAlert = false) const;
|
||||
|
||||
void RemoveFromMapVisibilityOverrideContainers();
|
||||
void AddToMapVisibilityOverrideContainers();
|
||||
|
||||
GuidUnorderedSet _allowedLooters;
|
||||
|
||||
ObjectVisibilityContainer _objectVisibilityContainer;
|
||||
|
||||
@@ -269,7 +269,7 @@ class PackedGuid
|
||||
explicit PackedGuid(ObjectGuid guid) : _packedGuid(PACKED_GUID_MIN_BUFFER_SIZE) { _packedGuid.appendPackGUID(guid.GetRawValue()); }
|
||||
|
||||
void Set(uint64 guid) { _packedGuid.wpos(0); _packedGuid.appendPackGUID(guid); }
|
||||
void Set(ObjectGuid guid) { _packedGuid.wpos(0); _packedGuid.appendPackGUID(guid.GetRawValue()); }
|
||||
void Set(ObjectGuid const& guid) { _packedGuid.wpos(0); _packedGuid.appendPackGUID(guid.GetRawValue()); }
|
||||
|
||||
[[nodiscard]] std::size_t size() const { return _packedGuid.size(); }
|
||||
|
||||
|
||||
@@ -692,7 +692,7 @@ void Pet::Update(uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
if (m_duration > 0s)
|
||||
if (m_duration > 0ms)
|
||||
{
|
||||
if (m_duration > _diff)
|
||||
m_duration -= _diff;
|
||||
@@ -708,7 +708,7 @@ void Pet::Update(uint32 diff)
|
||||
if (getPowerType() == POWER_FOCUS)
|
||||
{
|
||||
m_petRegenTimer -= _diff;
|
||||
if (m_petRegenTimer <= 0s)
|
||||
if (m_petRegenTimer <= 0ms)
|
||||
{
|
||||
m_petRegenTimer += PET_FOCUS_REGEN_INTERVAL;
|
||||
Regenerate(POWER_FOCUS);
|
||||
@@ -1026,7 +1026,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
||||
Unit* owner = GetOwner();
|
||||
if (!owner) // just to be sure, asynchronous now
|
||||
{
|
||||
DespawnOrUnsummon(1000);
|
||||
DespawnOrUnsummon(1s);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
PetType getPetType() const { return m_petType; }
|
||||
void setPetType(PetType type) { m_petType = type; }
|
||||
bool isControlled() const { return getPetType() == SUMMON_PET || getPetType() == HUNTER_PET; }
|
||||
bool isTemporarySummoned() const { return m_duration > 0s; }
|
||||
bool isTemporarySummoned() const { return m_duration > 0ms; }
|
||||
|
||||
bool IsPermanentPetFor(Player* owner) const; // pet have tab in character windows and set UNIT_FIELD_PETNUMBER
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <numbers>
|
||||
|
||||
enum ReactStates : uint8;
|
||||
|
||||
@@ -75,10 +76,10 @@ enum ActionFeedback
|
||||
FEEDBACK_CANT_ATT_TARGET = 3
|
||||
};
|
||||
|
||||
enum PetTalk
|
||||
enum PetAction : int32
|
||||
{
|
||||
PET_TALK_SPECIAL_SPELL = 0,
|
||||
PET_TALK_ATTACK = 1
|
||||
PET_ACTION_SPECIAL_SPELL = 0,
|
||||
PET_ACTION_ATTACK = 1
|
||||
};
|
||||
|
||||
enum PetLoadState
|
||||
@@ -202,8 +203,10 @@ enum PetScalingSpells
|
||||
SPELL_RISEN_GHOUL_SELF_STUN = 47466,
|
||||
};
|
||||
|
||||
#define PET_FOLLOW_DIST 1.0f
|
||||
#define PET_FOLLOW_ANGLE (M_PI/2)
|
||||
constexpr float PET_FOLLOW_DIST = 2.0f;
|
||||
constexpr float PET_FOLLOW_ANGLE = std::numbers::pi_v<float> / 2;
|
||||
constexpr float MINI_PET_SUMMON_ANGLE = std::numbers::pi_v<float> / 4;
|
||||
constexpr float MINI_PET_FOLLOW_ANGLE = std::numbers::pi_v<float>;
|
||||
|
||||
class PetStable
|
||||
{
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
#include "WorldStateDefines.h"
|
||||
#include "WorldStatePackets.h"
|
||||
#include <cmath>
|
||||
#include <queue>
|
||||
|
||||
/// @todo: this import is not necessary for compilation and marked as unused by the IDE
|
||||
// however, for some reasons removing it would cause a damn linking issue
|
||||
@@ -1337,9 +1338,10 @@ void Player::SendTeleportAckPacket()
|
||||
{
|
||||
WorldPacket data(MSG_MOVE_TELEPORT_ACK, 41);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); // this value increments every time
|
||||
data << GetSession()->GetOrderCounter(); // movement counter
|
||||
BuildMovementPacket(&data);
|
||||
GetSession()->SendPacket(&data);
|
||||
GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
|
||||
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options /*= 0*/, Unit* target /*= nullptr*/, bool newInstance /*= false*/)
|
||||
@@ -2086,7 +2088,7 @@ bool Player::CanInteractWithQuestGiver(Object* questGiver)
|
||||
return false;
|
||||
}
|
||||
|
||||
Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
|
||||
Creature* Player::GetNPCIfCanInteractWith(ObjectGuid const& guid, uint32 npcflagmask)
|
||||
{
|
||||
// unit checks
|
||||
if (!guid)
|
||||
@@ -2143,7 +2145,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
|
||||
return creature;
|
||||
}
|
||||
|
||||
GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, GameobjectTypes type) const
|
||||
GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid, GameobjectTypes type) const
|
||||
{
|
||||
if (GameObject* go = GetMap()->GetGameObject(guid))
|
||||
{
|
||||
@@ -2499,6 +2501,7 @@ void Player::GiveLevel(uint8 level)
|
||||
m_Played_time[PLAYED_TIME_LEVEL] = 0; // Level Played Time reset
|
||||
|
||||
_ApplyAllLevelScaleItemMods(false);
|
||||
_RemoveAllAuraStatMods();
|
||||
|
||||
SetLevel(level);
|
||||
|
||||
@@ -2521,6 +2524,7 @@ void Player::GiveLevel(uint8 level)
|
||||
UpdateSkillsToMaxSkillsForLevel();
|
||||
|
||||
_ApplyAllLevelScaleItemMods(true);
|
||||
_ApplyAllAuraStatMods();
|
||||
|
||||
if (!isDead())
|
||||
{
|
||||
@@ -4427,27 +4431,23 @@ void Player::DeleteOldRecoveryItems(uint32 keepDays)
|
||||
void Player::SetMovement(PlayerMovementType pType)
|
||||
{
|
||||
WorldPacket data;
|
||||
const PackedGuid& guid = GetPackGUID();
|
||||
switch (pType)
|
||||
{
|
||||
case MOVE_ROOT:
|
||||
data.Initialize(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size() + 4);
|
||||
break;
|
||||
case MOVE_UNROOT:
|
||||
data.Initialize(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size() + 4);
|
||||
break;
|
||||
case MOVE_WATER_WALK:
|
||||
data.Initialize(SMSG_MOVE_WATER_WALK, GetPackGUID().size() + 4);
|
||||
data.Initialize(SMSG_MOVE_WATER_WALK, guid.size() + 4);
|
||||
break;
|
||||
case MOVE_LAND_WALK:
|
||||
data.Initialize(SMSG_MOVE_LAND_WALK, GetPackGUID().size() + 4);
|
||||
data.Initialize(SMSG_MOVE_LAND_WALK, guid.size() + 4);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("entities.player", "Player::SetMovement: Unsupported move type ({}), data not sent to client.", pType);
|
||||
return;
|
||||
}
|
||||
data << GetPackGUID();
|
||||
data << uint32(0);
|
||||
data << guid;
|
||||
data << GetSession()->GetOrderCounter(); // movement counter
|
||||
GetSession()->SendPacket(&data);
|
||||
GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
|
||||
/* Preconditions:
|
||||
@@ -4487,10 +4487,10 @@ void Player::BuildPlayerRepop()
|
||||
SetHealth(1); // convert player body to ghost
|
||||
SetMovement(MOVE_WATER_WALK);
|
||||
SetWaterWalking(true);
|
||||
if (!GetSession()->isLogingOut())
|
||||
{
|
||||
SetMovement(MOVE_UNROOT);
|
||||
}
|
||||
|
||||
if (!IsImmobilizedState())
|
||||
SendMoveRoot(false);
|
||||
|
||||
RemoveUnitFlag(UNIT_FLAG_SKINNABLE); // BG - remove insignia related
|
||||
int32 corpseReclaimDelay = CalculateCorpseReclaimDelay();
|
||||
if (corpseReclaimDelay >= 0)
|
||||
@@ -4527,7 +4527,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
|
||||
|
||||
setDeathState(DeathState::Alive);
|
||||
SetMovement(MOVE_LAND_WALK);
|
||||
SetMovement(MOVE_UNROOT);
|
||||
SendMoveRoot(false);
|
||||
SetWaterWalking(false);
|
||||
m_deathTimer = 0;
|
||||
|
||||
@@ -4591,7 +4591,7 @@ void Player::KillPlayer()
|
||||
if (IsFlying() && !GetTransport())
|
||||
GetMotionMaster()->MoveFall();
|
||||
|
||||
SetMovement(MOVE_ROOT);
|
||||
SendMoveRoot(true);
|
||||
|
||||
StopMirrorTimers(); //disable timers(bars)
|
||||
|
||||
@@ -4618,7 +4618,7 @@ void Player::KillPlayer()
|
||||
//UpdateObjectVisibility(); // pussywizard: not needed
|
||||
}
|
||||
|
||||
void Player::OfflineResurrect(ObjectGuid const guid, CharacterDatabaseTransaction trans)
|
||||
void Player::OfflineResurrect(ObjectGuid const& guid, CharacterDatabaseTransaction trans)
|
||||
{
|
||||
Corpse::DeleteFromDB(guid, trans);
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
|
||||
@@ -9025,7 +9025,7 @@ Pet* Player::GetPet() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, Milliseconds duration /*= 0s*/, uint32 healthPct /*= 0*/)
|
||||
Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, Milliseconds duration /*= 0ms*/, uint32 healthPct /*= 0*/)
|
||||
{
|
||||
PetStable& petStable = GetOrInitPetStable();
|
||||
|
||||
@@ -9046,7 +9046,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
|
||||
++itr;
|
||||
}
|
||||
|
||||
if (duration > 0s)
|
||||
if (duration > 0ms)
|
||||
pet->SetDuration(duration);
|
||||
|
||||
// Generate a new name for the newly summoned ghoul
|
||||
@@ -9140,7 +9140,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
|
||||
}
|
||||
}
|
||||
|
||||
if (duration > 0s)
|
||||
if (duration > 0ms)
|
||||
pet->SetDuration(duration);
|
||||
|
||||
if (NeedSendSpectatorData() && pet->GetCreatureTemplate()->family)
|
||||
@@ -11709,16 +11709,56 @@ void Player::SendInitialPacketsAfterAddToMap()
|
||||
GetZoneAndAreaId(newzone, newarea);
|
||||
UpdateZone(newzone, newarea); // also call SendInitWorldStates();
|
||||
|
||||
if (HasStunAura())
|
||||
SetMovement(MOVE_ROOT);
|
||||
WorldPacket setCompoundState(SMSG_MULTIPLE_MOVES, 100);
|
||||
setCompoundState << uint32(0); // size placeholder
|
||||
|
||||
// manual send package (have code in HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); that must not be re-applied.
|
||||
if (HasRootAura())
|
||||
if (IsImmobilizedState())
|
||||
{
|
||||
WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10);
|
||||
data2 << GetPackGUID();
|
||||
data2 << (uint32)2;
|
||||
SendMessageToSet(&data2, true);
|
||||
auto const counter = GetSession()->GetOrderCounter();
|
||||
setCompoundState << uint8(2 + GetPackGUID().size() + 4);
|
||||
setCompoundState << uint16(SMSG_FORCE_MOVE_ROOT);
|
||||
setCompoundState << GetPackGUID();
|
||||
setCompoundState << uint32(counter);
|
||||
GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
|
||||
if (HasAuraType(SPELL_AURA_FEATHER_FALL))
|
||||
{
|
||||
auto const counter = GetSession()->GetOrderCounter();
|
||||
setCompoundState << uint8(2 + GetPackGUID().size() + 4);
|
||||
setCompoundState << uint16(SMSG_MOVE_FEATHER_FALL);
|
||||
setCompoundState << GetPackGUID();
|
||||
setCompoundState << uint32(counter);
|
||||
GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
|
||||
if (HasAuraType(SPELL_AURA_WATER_WALK))
|
||||
{
|
||||
auto const counter = GetSession()->GetOrderCounter();
|
||||
setCompoundState << uint8(2 + GetPackGUID().size() + 4);
|
||||
setCompoundState << uint16(SMSG_MOVE_WATER_WALK);
|
||||
setCompoundState << GetPackGUID();
|
||||
setCompoundState << uint32(counter);
|
||||
GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
|
||||
if (HasAuraType(SPELL_AURA_HOVER))
|
||||
{
|
||||
auto const counter = GetSession()->GetOrderCounter();
|
||||
setCompoundState << uint8(2 + GetPackGUID().size() + 4);
|
||||
setCompoundState << uint16(SMSG_MOVE_SET_HOVER);
|
||||
setCompoundState << GetPackGUID();
|
||||
setCompoundState << uint32(counter);
|
||||
GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
|
||||
// TODO: Pending mount protocol
|
||||
|
||||
if (setCompoundState.size() > 4)
|
||||
{
|
||||
setCompoundState.put<uint32>(0, setCompoundState.size() - 4);
|
||||
SendDirectMessage(&setCompoundState);
|
||||
}
|
||||
|
||||
SendEnchantmentDurations(); // must be after add to map
|
||||
@@ -14336,6 +14376,73 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if any vendor option is available in the gossip menu tree for a given creature.
|
||||
*
|
||||
* @param menuId The starting gossip menu ID to check.
|
||||
* @param creature Pointer to the creature whose gossip menus are being checked.
|
||||
* @return true if a vendor option is available in any accessible menu; false otherwise.
|
||||
*/
|
||||
bool Player::AnyVendorOptionAvailable(uint32 menuId, Creature const* creature) const
|
||||
{
|
||||
{
|
||||
GossipMenuItemsMapBounds menuItemBounds = sObjectMgr->GetGossipMenuItemsMapBounds(menuId);
|
||||
if (menuItemBounds.first == menuItemBounds.second)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<uint32> visitedMenus;
|
||||
std::queue<uint32> menusToCheck;
|
||||
menusToCheck.push(menuId);
|
||||
|
||||
while (!menusToCheck.empty())
|
||||
{
|
||||
uint32 const currentMenuId = menusToCheck.front();
|
||||
menusToCheck.pop();
|
||||
|
||||
if (visitedMenus.find(currentMenuId) != visitedMenus.end())
|
||||
continue;
|
||||
|
||||
visitedMenus.insert(currentMenuId);
|
||||
|
||||
GossipMenuItemsMapBounds menuItemBounds = sObjectMgr->GetGossipMenuItemsMapBounds(currentMenuId);
|
||||
|
||||
if (menuItemBounds.first == menuItemBounds.second && currentMenuId != 0)
|
||||
continue;
|
||||
|
||||
for (auto itr = menuItemBounds.first; itr != menuItemBounds.second; ++itr)
|
||||
{
|
||||
if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(this), const_cast<Creature*>(creature), itr->second.Conditions))
|
||||
continue;
|
||||
|
||||
if (itr->second.OptionType == GOSSIP_OPTION_VENDOR)
|
||||
return true;
|
||||
else if (itr->second.ActionMenuID)
|
||||
{
|
||||
GossipMenusMapBounds menuBounds = sObjectMgr->GetGossipMenusMapBounds(itr->second.ActionMenuID);
|
||||
bool menuAccessible = false;
|
||||
|
||||
if (menuBounds.first == menuBounds.second)
|
||||
menuAccessible = true;
|
||||
else
|
||||
{
|
||||
for (auto menuItr = menuBounds.first; menuItr != menuBounds.second; ++menuItr)
|
||||
if (sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(this), const_cast<Creature*>(creature), menuItr->second.Conditions))
|
||||
{
|
||||
menuAccessible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (menuAccessible)
|
||||
menusToCheck.push(itr->second.ActionMenuID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Player::CanSeeVendor(Creature const* creature) const
|
||||
{
|
||||
if (!creature->HasNpcFlag(UNIT_NPC_FLAG_VENDOR))
|
||||
@@ -14343,9 +14450,11 @@ bool Player::CanSeeVendor(Creature const* creature) const
|
||||
|
||||
ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(creature->GetEntry(), 0);
|
||||
if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(this), const_cast<Creature*>(creature), conditions))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 const menuId = creature->GetCreatureTemplate()->GossipMenuId;
|
||||
if (!AnyVendorOptionAvailable(menuId, creature))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -15943,8 +16052,9 @@ bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool /
|
||||
|
||||
WorldPacket data(disable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
data << GetSession()->GetOrderCounter(); // movement counter
|
||||
SendDirectMessage(&data);
|
||||
GetSession()->IncrementOrderCounter();
|
||||
|
||||
data.Initialize(MSG_MOVE_GRAVITY_CHNG, 64);
|
||||
data << GetPackGUID();
|
||||
@@ -15953,91 +16063,6 @@ bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool /
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::SetCanFly(bool apply, bool packetOnly /*= false*/)
|
||||
{
|
||||
sScriptMgr->AnticheatSetCanFlybyServer(this, apply);
|
||||
|
||||
if (!packetOnly && !Unit::SetCanFly(apply))
|
||||
return false;
|
||||
|
||||
if (!apply)
|
||||
SetFallInformation(GameTime::GetGameTime().count(), GetPositionZ());
|
||||
|
||||
WorldPacket data(apply ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
SendDirectMessage(&data);
|
||||
|
||||
data.Initialize(MSG_MOVE_UPDATE_CAN_FLY, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::SetHover(bool apply, bool packetOnly /*= false*/, bool /*updateAnimationTier = true*/)
|
||||
{
|
||||
// moved inside, flag can be removed on landing and wont send appropriate packet to client when aura is removed
|
||||
if (!packetOnly /* && !Unit::SetHover(apply)*/)
|
||||
{
|
||||
Unit::SetHover(apply);
|
||||
// return false;
|
||||
}
|
||||
|
||||
WorldPacket data(apply ? SMSG_MOVE_SET_HOVER : SMSG_MOVE_UNSET_HOVER, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
SendDirectMessage(&data);
|
||||
|
||||
data.Initialize(MSG_MOVE_HOVER, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::SetWaterWalking(bool apply, bool packetOnly /*= false*/)
|
||||
{
|
||||
// moved inside, flag can be removed on landing and wont send appropriate packet to client when aura is removed
|
||||
if (!packetOnly /* && !Unit::SetWaterWalking(apply)*/)
|
||||
{
|
||||
Unit::SetWaterWalking(apply);
|
||||
// return false;
|
||||
}
|
||||
|
||||
WorldPacket data(apply ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
SendDirectMessage(&data);
|
||||
|
||||
data.Initialize(MSG_MOVE_WATER_WALK, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::SetFeatherFall(bool apply, bool packetOnly /*= false*/)
|
||||
{
|
||||
// Xinef: moved inside, flag can be removed on landing and wont send appropriate packet to client when aura is removed
|
||||
if (!packetOnly/* && !Unit::SetFeatherFall(apply)*/)
|
||||
{
|
||||
Unit::SetFeatherFall(apply);
|
||||
//return false;
|
||||
}
|
||||
|
||||
WorldPacket data(apply ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, 12);
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); //! movement counter
|
||||
SendDirectMessage(&data);
|
||||
|
||||
data.Initialize(MSG_MOVE_FEATHER_FALL, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
Guild* Player::GetGuild() const
|
||||
{
|
||||
uint32 guildId = GetGuildId();
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "TradeData.h"
|
||||
#include "Unit.h"
|
||||
#include "WorldSession.h"
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -448,8 +449,6 @@ typedef std::list<Item*> ItemDurationList;
|
||||
|
||||
enum PlayerMovementType
|
||||
{
|
||||
MOVE_ROOT = 1,
|
||||
MOVE_UNROOT = 2,
|
||||
MOVE_WATER_WALK = 3,
|
||||
MOVE_LAND_WALK = 4
|
||||
};
|
||||
@@ -1119,8 +1118,8 @@ public:
|
||||
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time, bool onEnterMap);
|
||||
|
||||
bool CanInteractWithQuestGiver(Object* questGiver);
|
||||
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
|
||||
[[nodiscard]] GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, GameobjectTypes type) const;
|
||||
Creature* GetNPCIfCanInteractWith(ObjectGuid const& guid, uint32 npcflagmask);
|
||||
[[nodiscard]] GameObject* GetGameObjectIfCanInteractWith(ObjectGuid const& guid, GameobjectTypes type) const;
|
||||
|
||||
void ToggleAFK();
|
||||
void ToggleDND();
|
||||
@@ -1146,6 +1145,7 @@ public:
|
||||
void SetCommentator(bool on) { ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_COMMENTATOR2, on); }
|
||||
[[nodiscard]] bool IsDeveloper() const { return HasPlayerFlag(PLAYER_FLAGS_DEVELOPER); }
|
||||
void SetDeveloper(bool on) { ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_DEVELOPER, on); }
|
||||
void SetBeastMaster(bool on) { if (on) SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); else RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); }
|
||||
[[nodiscard]] bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; }
|
||||
void SetAcceptWhispers(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; }
|
||||
[[nodiscard]] bool IsGameMaster() const { return m_ExtraFlags & PLAYER_EXTRA_GM_ON; }
|
||||
@@ -1200,7 +1200,7 @@ public:
|
||||
[[nodiscard]] PetStable const* GetPetStable() const { return m_petStable.get(); }
|
||||
|
||||
[[nodiscard]] Pet* GetPet() const;
|
||||
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, Milliseconds duration = 0s, uint32 healthPct = 0);
|
||||
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, Milliseconds duration = 0ms, uint32 healthPct = 0);
|
||||
void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
|
||||
bool CanPetResurrect();
|
||||
bool IsExistPet();
|
||||
@@ -2024,7 +2024,7 @@ public:
|
||||
Corpse* CreateCorpse();
|
||||
void RemoveCorpse();
|
||||
void KillPlayer();
|
||||
static void OfflineResurrect(ObjectGuid const guid, CharacterDatabaseTransaction trans);
|
||||
static void OfflineResurrect(ObjectGuid const& guid, CharacterDatabaseTransaction trans);
|
||||
[[nodiscard]] bool HasCorpse() const { return _corpseLocation.GetMapId() != MAPID_INVALID; }
|
||||
[[nodiscard]] WorldLocation GetCorpseLocation() const { return _corpseLocation; }
|
||||
uint32 GetResurrectionSpellId();
|
||||
@@ -2541,7 +2541,9 @@ public:
|
||||
//bool isActiveObject() const { return true; }
|
||||
bool CanSeeSpellClickOn(Creature const* creature) const;
|
||||
[[nodiscard]] bool CanSeeVendor(Creature const* creature) const;
|
||||
|
||||
private:
|
||||
[[nodiscard]] bool AnyVendorOptionAvailable(uint32 menuId, Creature const* creature) const;
|
||||
public:
|
||||
[[nodiscard]] uint32 GetChampioningFaction() const { return m_ChampioningFaction; }
|
||||
void SetChampioningFaction(uint32 faction) { m_ChampioningFaction = faction; }
|
||||
Spell* m_spellModTakingSpell;
|
||||
@@ -2556,13 +2558,10 @@ public:
|
||||
void RemoveFromWhisperWhiteList(ObjectGuid guid) { WhisperList.remove(guid); }
|
||||
|
||||
bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override;
|
||||
bool SetCanFly(bool apply, bool packetOnly = false) override;
|
||||
bool SetWaterWalking(bool apply, bool packetOnly = false) override;
|
||||
bool SetFeatherFall(bool apply, bool packetOnly = false) override;
|
||||
bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true) override;
|
||||
|
||||
[[nodiscard]] bool CanFly() const override { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
|
||||
[[nodiscard]] bool CanEnterWater() const override { return true; }
|
||||
bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY); }
|
||||
|
||||
// saving
|
||||
void AdditionalSavingAddMask(uint8 mask) { m_additionalSaveTimer = 2000; m_additionalSaveMask |= mask; }
|
||||
|
||||
@@ -740,9 +740,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
|
||||
if (log_slot < MAX_QUEST_LOG_SIZE)
|
||||
SetQuestSlot(log_slot, 0);
|
||||
|
||||
bool rewarded = IsQuestRewarded(quest_id) && !quest->IsDFQuest();
|
||||
bool const rewarded = IsQuestRewarded(quest_id) && !quest->IsDFQuest() && !(quest->IsDaily() || quest->IsWeekly() || quest->IsMonthly());
|
||||
|
||||
// Not give XP in case already completed once repeatable quest
|
||||
// Repeatable quests (not time-based reset ones) should not give XP on subsequent completions
|
||||
uint32 XP = rewarded ? 0 : CalculateQuestRewardXP(quest);
|
||||
|
||||
sScriptMgr->OnPlayerQuestComputeXP(this, quest, XP);
|
||||
|
||||
@@ -6858,7 +6858,7 @@ bool Player::Satisfy(DungeonProgressionRequirements const* ar, uint32 target_map
|
||||
|| missingPlayerItems.size() || missingPlayerQuests.size() || missingPlayerAchievements.size()
|
||||
|| missingLeaderItems.size() || missingLeaderQuests.size() || missingLeaderAchievements.size())
|
||||
{
|
||||
if (!sScriptMgr->OnPlayerNotAvoidSatisfy(partyLeader, ar, target_map, report))
|
||||
if (!sScriptMgr->OnPlayerNotAvoidSatisfy(this, ar, target_map, report))
|
||||
return true;
|
||||
|
||||
if (report)
|
||||
|
||||
@@ -37,7 +37,7 @@ uint32 PlayerSocial::GetNumberOfSocialsWithFlag(SocialFlag flag) const
|
||||
return counter;
|
||||
}
|
||||
|
||||
bool PlayerSocial::AddToSocialList(ObjectGuid friendGuid, SocialFlag flag)
|
||||
bool PlayerSocial::AddToSocialList(ObjectGuid const& friendGuid, SocialFlag flag)
|
||||
{
|
||||
// check client limits
|
||||
if (GetNumberOfSocialsWithFlag(flag) >= (((flag & SOCIAL_FLAG_FRIEND) != 0) ? SOCIALMGR_FRIEND_LIMIT : SOCIALMGR_IGNORE_LIMIT))
|
||||
@@ -71,7 +71,7 @@ bool PlayerSocial::AddToSocialList(ObjectGuid friendGuid, SocialFlag flag)
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerSocial::RemoveFromSocialList(ObjectGuid friendGuid, SocialFlag flag)
|
||||
void PlayerSocial::RemoveFromSocialList(ObjectGuid const& friendGuid, SocialFlag flag)
|
||||
{
|
||||
auto itr = m_playerSocialMap.find(friendGuid);
|
||||
if (itr == m_playerSocialMap.end()) // not exist
|
||||
@@ -102,7 +102,7 @@ void PlayerSocial::RemoveFromSocialList(ObjectGuid friendGuid, SocialFlag flag)
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSocial::SetFriendNote(ObjectGuid friendGuid, std::string note)
|
||||
void PlayerSocial::SetFriendNote(ObjectGuid const& friendGuid, std::string note)
|
||||
{
|
||||
auto itr = m_playerSocialMap.find(friendGuid);
|
||||
if (itr == m_playerSocialMap.end()) // not exist
|
||||
@@ -176,7 +176,7 @@ void PlayerSocial::SendSocialList(Player* player, uint32 flags)
|
||||
LOG_DEBUG("network", "WORLD: Sent SMSG_CONTACT_LIST");
|
||||
}
|
||||
|
||||
bool PlayerSocial::_checkContact(ObjectGuid guid, SocialFlag flags) const
|
||||
bool PlayerSocial::_checkContact(ObjectGuid const& guid, SocialFlag flags) const
|
||||
{
|
||||
auto const& itr = m_playerSocialMap.find(guid);
|
||||
if (itr != m_playerSocialMap.end())
|
||||
@@ -185,12 +185,12 @@ bool PlayerSocial::_checkContact(ObjectGuid guid, SocialFlag flags) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlayerSocial::HasFriend(ObjectGuid friend_guid) const
|
||||
bool PlayerSocial::HasFriend(ObjectGuid const& friend_guid) const
|
||||
{
|
||||
return _checkContact(friend_guid, SOCIAL_FLAG_FRIEND);
|
||||
}
|
||||
|
||||
bool PlayerSocial::HasIgnore(ObjectGuid ignore_guid) const
|
||||
bool PlayerSocial::HasIgnore(ObjectGuid const& ignore_guid) const
|
||||
{
|
||||
return _checkContact(ignore_guid, SOCIAL_FLAG_IGNORED);
|
||||
}
|
||||
@@ -209,7 +209,7 @@ SocialMgr* SocialMgr::instance()
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void SocialMgr::GetFriendInfo(Player* player, ObjectGuid friendGUID, FriendInfo& friendInfo)
|
||||
void SocialMgr::GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo)
|
||||
{
|
||||
if (!player)
|
||||
return;
|
||||
@@ -247,14 +247,14 @@ void SocialMgr::GetFriendInfo(Player* player, ObjectGuid friendGUID, FriendInfo&
|
||||
}
|
||||
}
|
||||
|
||||
void SocialMgr::MakeFriendStatusPacket(FriendsResult result, ObjectGuid guid, WorldPacket* data)
|
||||
void SocialMgr::MakeFriendStatusPacket(FriendsResult result, ObjectGuid const& guid, WorldPacket* data)
|
||||
{
|
||||
data->Initialize(SMSG_FRIEND_STATUS, 9);
|
||||
*data << uint8(result);
|
||||
*data << guid;
|
||||
}
|
||||
|
||||
void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, ObjectGuid friendGuid, bool broadcast)
|
||||
void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, ObjectGuid const& friendGuid, bool broadcast)
|
||||
{
|
||||
FriendInfo fi;
|
||||
GetFriendInfo(player, friendGuid, fi);
|
||||
@@ -316,7 +316,7 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet)
|
||||
}
|
||||
}
|
||||
|
||||
PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, ObjectGuid guid)
|
||||
PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, ObjectGuid const& guid)
|
||||
{
|
||||
PlayerSocial* social = &m_socialMap[guid];
|
||||
social->SetPlayerGUID(guid);
|
||||
|
||||
@@ -104,19 +104,19 @@ class PlayerSocial
|
||||
public:
|
||||
PlayerSocial();
|
||||
// adding/removing
|
||||
bool AddToSocialList(ObjectGuid friend_guid, SocialFlag flag);
|
||||
void RemoveFromSocialList(ObjectGuid friend_guid, SocialFlag flag);
|
||||
void SetFriendNote(ObjectGuid friendGuid, std::string note);
|
||||
bool AddToSocialList(ObjectGuid const& friend_guid, SocialFlag flag);
|
||||
void RemoveFromSocialList(ObjectGuid const& friend_guid, SocialFlag flag);
|
||||
void SetFriendNote(ObjectGuid const& friendGuid, std::string note);
|
||||
// Packet send's
|
||||
void SendSocialList(Player* player, uint32 flags);
|
||||
// Misc
|
||||
bool HasFriend(ObjectGuid friend_guid) const;
|
||||
bool HasIgnore(ObjectGuid ignore_guid) const;
|
||||
ObjectGuid GetPlayerGUID() const { return m_playerGUID; }
|
||||
void SetPlayerGUID(ObjectGuid guid) { m_playerGUID = guid; }
|
||||
bool HasFriend(ObjectGuid const& friend_guid) const;
|
||||
bool HasIgnore(ObjectGuid const& ignore_guid) const;
|
||||
ObjectGuid const& GetPlayerGUID() const { return m_playerGUID; }
|
||||
void SetPlayerGUID(ObjectGuid const& guid) { m_playerGUID = guid; }
|
||||
uint32 GetNumberOfSocialsWithFlag(SocialFlag flag) const;
|
||||
private:
|
||||
bool _checkContact(ObjectGuid guid, SocialFlag flags) const;
|
||||
bool _checkContact(ObjectGuid const& guid, SocialFlag flags) const;
|
||||
typedef std::map<ObjectGuid, FriendInfo> PlayerSocialMap;
|
||||
PlayerSocialMap m_playerSocialMap;
|
||||
ObjectGuid m_playerGUID;
|
||||
@@ -131,14 +131,14 @@ class SocialMgr
|
||||
public:
|
||||
static SocialMgr* instance();
|
||||
// Misc
|
||||
void RemovePlayerSocial(ObjectGuid guid) { m_socialMap.erase(guid); }
|
||||
static void GetFriendInfo(Player* player, ObjectGuid friendGUID, FriendInfo& friendInfo);
|
||||
void RemovePlayerSocial(ObjectGuid const& guid) { m_socialMap.erase(guid); }
|
||||
static void GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo);
|
||||
// Packet management
|
||||
void MakeFriendStatusPacket(FriendsResult result, ObjectGuid friend_guid, WorldPacket* data);
|
||||
void SendFriendStatus(Player* player, FriendsResult result, ObjectGuid friend_guid, bool broadcast);
|
||||
void MakeFriendStatusPacket(FriendsResult result, ObjectGuid const& friend_guid, WorldPacket* data);
|
||||
void SendFriendStatus(Player* player, FriendsResult result, ObjectGuid const& friend_guid, bool broadcast);
|
||||
void BroadcastToFriendListers(Player* player, WorldPacket* packet);
|
||||
// Loading
|
||||
PlayerSocial* LoadFromDB(PreparedQueryResult result, ObjectGuid guid);
|
||||
PlayerSocial* LoadFromDB(PreparedQueryResult result, ObjectGuid const& guid);
|
||||
private:
|
||||
typedef std::map<ObjectGuid, PlayerSocial> SocialMap;
|
||||
SocialMap m_socialMap;
|
||||
|
||||
@@ -119,11 +119,11 @@ void Totem::InitSummon()
|
||||
}
|
||||
}
|
||||
|
||||
void Totem::UnSummon(uint32 msTime)
|
||||
void Totem::UnSummon(Milliseconds msTime)
|
||||
{
|
||||
if (msTime)
|
||||
if (msTime > 0ms)
|
||||
{
|
||||
m_Events.AddEvent(new ForcedUnsummonDelayEvent(*this), m_Events.CalculateTime(msTime));
|
||||
m_Events.AddEventAtOffset(new ForcedUnsummonDelayEvent(*this), msTime);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
void Update(uint32 time) override;
|
||||
void InitStats(uint32 duration) override;
|
||||
void InitSummon() override;
|
||||
void UnSummon(uint32 msTime = 0) override;
|
||||
void UnSummon(Milliseconds msTime = 0ms) override;
|
||||
uint32 GetSpell(uint8 slot = 0) const { return m_spells[slot]; }
|
||||
uint32 GetTotemDuration() const { return m_duration; }
|
||||
void SetTotemDuration(uint32 duration) { m_duration = duration; }
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "PassiveAI.h"
|
||||
#include "Pet.h"
|
||||
#include "PetAI.h"
|
||||
#include "PetPackets.h"
|
||||
#include "Player.h"
|
||||
#include "ReputationMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
@@ -244,8 +245,6 @@ Unit::Unit() : WorldObject(),
|
||||
|
||||
_dualWieldMode = DualWieldMode::AUTO;
|
||||
|
||||
m_rootTimes = 0;
|
||||
|
||||
m_state = 0;
|
||||
m_deathState = DeathState::Alive;
|
||||
|
||||
@@ -868,6 +867,9 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
// interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras)
|
||||
if (spellProto)
|
||||
{
|
||||
if (attacker && damagetype != DOT && spellProto->DmgClass == SPELL_DAMAGE_CLASS_MELEE && !(spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_HOLY))
|
||||
attacker->DealDamageShieldDamage(victim);
|
||||
|
||||
if (!spellProto->HasAttribute(SPELL_ATTR4_REACTIVE_DAMAGE_PROC))
|
||||
victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TAKE_DAMAGE, spellProto->Id);
|
||||
}
|
||||
@@ -1085,12 +1087,10 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(SPELL_AURA_DAMAGE_SHIELD)))
|
||||
victim->ToCreature()->UpdateLeashExtensionTime();
|
||||
|
||||
if (attacker)
|
||||
if (attacker && attacker != victim)
|
||||
{
|
||||
if (spellProto && victim->CanHaveThreatList() && !victim->HasUnitState(UNIT_STATE_EVADE) && !victim->IsInCombatWith(attacker))
|
||||
{
|
||||
victim->CombatStart(attacker, !(spellProto->AttributesEx3 & SPELL_ATTR3_SUPPRESS_TARGET_PROCS));
|
||||
}
|
||||
|
||||
victim->AddThreat(attacker, float(damage), damageSchoolMask, spellProto);
|
||||
}
|
||||
@@ -1975,57 +1975,60 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
||||
|
||||
// Do effect if any damage done to target
|
||||
if (damageInfo->damages[0].damage + damageInfo->damages[1].damage)
|
||||
DealDamageShieldDamage(victim);
|
||||
}
|
||||
|
||||
void Unit::DealDamageShieldDamage(Unit* victim)
|
||||
{
|
||||
// We're going to call functions which can modify content of the list during iteration over it's elements
|
||||
// Let's copy the list so we can prevent iterator invalidation
|
||||
AuraEffectList vDamageShieldsCopy(victim->GetAuraEffectsByType(SPELL_AURA_DAMAGE_SHIELD));
|
||||
for (AuraEffectList::const_iterator dmgShieldItr = vDamageShieldsCopy.begin(); dmgShieldItr != vDamageShieldsCopy.end(); ++dmgShieldItr)
|
||||
{
|
||||
// We're going to call functions which can modify content of the list during iteration over it's elements
|
||||
// Let's copy the list so we can prevent iterator invalidation
|
||||
AuraEffectList vDamageShieldsCopy(victim->GetAuraEffectsByType(SPELL_AURA_DAMAGE_SHIELD));
|
||||
for (AuraEffectList::const_iterator dmgShieldItr = vDamageShieldsCopy.begin(); dmgShieldItr != vDamageShieldsCopy.end(); ++dmgShieldItr)
|
||||
SpellInfo const* i_spellProto = (*dmgShieldItr)->GetSpellInfo();
|
||||
// Damage shield can be resisted...
|
||||
if (SpellMissInfo missInfo = victim->SpellHitResult(this, i_spellProto, false))
|
||||
{
|
||||
SpellInfo const* i_spellProto = (*dmgShieldItr)->GetSpellInfo();
|
||||
// Damage shield can be resisted...
|
||||
if (SpellMissInfo missInfo = victim->SpellHitResult(this, i_spellProto, false))
|
||||
{
|
||||
victim->SendSpellMiss(this, i_spellProto->Id, missInfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ...or immuned
|
||||
if (IsImmunedToDamageOrSchool(i_spellProto))
|
||||
{
|
||||
victim->SendSpellDamageImmune(this, i_spellProto->Id);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 damage = uint32(std::max(0, (*dmgShieldItr)->GetAmount())); // xinef: done calculated at amount calculation
|
||||
|
||||
if (Unit* caster = (*dmgShieldItr)->GetCaster())
|
||||
{
|
||||
damage = caster->SpellDamageBonusDone(this, i_spellProto, damage, SPELL_DIRECT_DAMAGE, (*dmgShieldItr)->GetEffIndex());
|
||||
damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
|
||||
}
|
||||
|
||||
uint32 absorb = 0;
|
||||
|
||||
DamageInfo dmgInfo(victim, this, damage, i_spellProto, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE);
|
||||
Unit::CalcAbsorbResist(dmgInfo);
|
||||
absorb = dmgInfo.GetAbsorb();
|
||||
damage = dmgInfo.GetDamage();
|
||||
|
||||
Unit::DealDamageMods(this, damage, &absorb);
|
||||
|
||||
/// @todo: Move this to a packet handler
|
||||
WorldPacket data(SMSG_SPELLDAMAGESHIELD, (8 + 8 + 4 + 4 + 4 + 4));
|
||||
data << victim->GetGUID();
|
||||
data << GetGUID();
|
||||
data << uint32(i_spellProto->Id);
|
||||
data << uint32(damage); // Damage
|
||||
int32 overkill = int32(damage) - int32(GetHealth());
|
||||
data << uint32(overkill > 0 ? overkill : 0); // Overkill
|
||||
data << uint32(i_spellProto->GetSchoolMask());
|
||||
victim->SendMessageToSet(&data, true);
|
||||
|
||||
Unit::DealDamage(victim, this, damage, 0, SPELL_DIRECT_DAMAGE, i_spellProto->GetSchoolMask(), i_spellProto, true);
|
||||
victim->SendSpellMiss(this, i_spellProto->Id, missInfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ...or immuned
|
||||
if (IsImmunedToDamageOrSchool(i_spellProto))
|
||||
{
|
||||
victim->SendSpellDamageImmune(this, i_spellProto->Id);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 damage = uint32(std::max(0, (*dmgShieldItr)->GetAmount())); // xinef: done calculated at amount calculation
|
||||
|
||||
if (Unit* caster = (*dmgShieldItr)->GetCaster())
|
||||
{
|
||||
damage = caster->SpellDamageBonusDone(this, i_spellProto, damage, SPELL_DIRECT_DAMAGE, (*dmgShieldItr)->GetEffIndex());
|
||||
damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
|
||||
}
|
||||
|
||||
uint32 absorb = 0;
|
||||
|
||||
DamageInfo dmgInfo(victim, this, damage, i_spellProto, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE);
|
||||
Unit::CalcAbsorbResist(dmgInfo);
|
||||
absorb = dmgInfo.GetAbsorb();
|
||||
damage = dmgInfo.GetDamage();
|
||||
|
||||
Unit::DealDamageMods(this, damage, &absorb);
|
||||
|
||||
/// @todo: Move this to a packet handler
|
||||
WorldPacket data(SMSG_SPELLDAMAGESHIELD, (8 + 8 + 4 + 4 + 4 + 4));
|
||||
data << victim->GetGUID();
|
||||
data << GetGUID();
|
||||
data << uint32(i_spellProto->Id);
|
||||
data << uint32(damage); // Damage
|
||||
int32 overkill = int32(damage) - int32(GetHealth());
|
||||
data << uint32(overkill > 0 ? overkill : 0); // Overkill
|
||||
data << uint32(i_spellProto->GetSchoolMask());
|
||||
victim->SendMessageToSet(&data, true);
|
||||
|
||||
Unit::DealDamage(victim, this, damage, 0, SPELL_DIRECT_DAMAGE, i_spellProto->GetSchoolMask(), i_spellProto, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4332,10 +4335,10 @@ void Unit::ProcessTerrainStatusUpdate()
|
||||
|
||||
LiquidData const& liquidData = GetLiquidData();
|
||||
|
||||
// remove appropriate auras if we are swimming/not swimming respectively
|
||||
if (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING)
|
||||
// remove appropriate auras if we are swimming/not swimming respectively - exact mirror of client logic
|
||||
if (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING && (liquidData.Level - GetPositionZ()) > GetCollisionHeight() * 0.75f) // Shallow water at ~75% of collision height)
|
||||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_ABOVEWATER);
|
||||
else if (!isSwimming())
|
||||
else
|
||||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER);
|
||||
|
||||
// liquid aura handling
|
||||
@@ -9285,28 +9288,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
|
||||
{
|
||||
switch (auraSpellInfo->Id)
|
||||
{
|
||||
// Soul Preserver
|
||||
case 60510:
|
||||
{
|
||||
switch (getClass())
|
||||
{
|
||||
case CLASS_DRUID:
|
||||
trigger_spell_id = 60512;
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
trigger_spell_id = 60513;
|
||||
break;
|
||||
case CLASS_PRIEST:
|
||||
trigger_spell_id = 60514;
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
trigger_spell_id = 60515;
|
||||
break;
|
||||
}
|
||||
|
||||
target = this;
|
||||
break;
|
||||
}
|
||||
case 37657: // Lightning Capacitor
|
||||
case 54841: // Thunder Capacitor
|
||||
case 67712: // Item - Coliseum 25 Normal Caster Trinket
|
||||
@@ -10297,24 +10278,13 @@ ReputationRank Unit::GetFactionReactionTo(FactionTemplateEntry const* factionTem
|
||||
{
|
||||
// common faction based check
|
||||
if (factionTemplateEntry->IsHostileTo(*targetFactionTemplateEntry))
|
||||
{
|
||||
return REP_HOSTILE;
|
||||
}
|
||||
|
||||
if (factionTemplateEntry->IsFriendlyTo(*targetFactionTemplateEntry))
|
||||
{
|
||||
return REP_FRIENDLY;
|
||||
}
|
||||
|
||||
if (targetFactionTemplateEntry->IsFriendlyTo(*factionTemplateEntry))
|
||||
{
|
||||
return REP_FRIENDLY;
|
||||
}
|
||||
|
||||
if (factionTemplateEntry->factionFlags & FACTION_TEMPLATE_FLAG_HATES_ALL_EXCEPT_FRIENDS)
|
||||
{
|
||||
return REP_HOSTILE;
|
||||
}
|
||||
|
||||
// neutral by default
|
||||
return REP_NEUTRAL;
|
||||
@@ -11108,7 +11078,7 @@ int32 Unit::DealHeal(Unit* healer, Unit* victim, uint32 addhealth)
|
||||
return gain;
|
||||
}
|
||||
|
||||
bool RedirectSpellEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
bool RedirectSpellEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
{
|
||||
if (Unit* auraOwner = ObjectAccessor::GetUnit(_self, _auraOwnerGUID))
|
||||
{
|
||||
@@ -13624,9 +13594,10 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
|
||||
|
||||
WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
|
||||
data << GetPackGUID();
|
||||
data << uint32(GameTime::GetGameTime().count()); // Packet counter
|
||||
data << player->GetSession()->GetOrderCounter(); // movement counter
|
||||
data << player->GetCollisionHeight();
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
|
||||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT);
|
||||
@@ -13640,13 +13611,14 @@ void Unit::Dismount()
|
||||
SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
|
||||
RemoveUnitFlag(UNIT_FLAG_MOUNT);
|
||||
|
||||
if (Player* thisPlayer = ToPlayer())
|
||||
if (Player* player = ToPlayer())
|
||||
{
|
||||
WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
|
||||
data << GetPackGUID();
|
||||
data << uint32(GameTime::GetGameTime().count()); // Packet counter
|
||||
data << thisPlayer->GetCollisionHeight();
|
||||
thisPlayer->GetSession()->SendPacket(&data);
|
||||
data << player->GetSession()->GetOrderCounter(); // movement counter
|
||||
data << player->GetCollisionHeight();
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_DISMOUNT, 8);
|
||||
@@ -14660,11 +14632,13 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
|
||||
return;
|
||||
}
|
||||
data << GetPackGUID();
|
||||
data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39
|
||||
data << (IsPlayer() ? ToPlayer()->GetSession()->GetOrderCounter() : uint32(0)); // movement counter
|
||||
if (mtype == MOVE_RUN)
|
||||
data << uint8(0); // new 2.1.0
|
||||
data << float(GetSpeed(mtype));
|
||||
SendMessageToSet(&data, true);
|
||||
if (IsPlayer()) // TODO: Resolve this mess
|
||||
ToPlayer()->GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16705,7 +16679,7 @@ Player* Unit::GetSpellModOwner() const
|
||||
}
|
||||
|
||||
///----------Pet responses methods-----------------
|
||||
void Unit::SendPetActionFeedback(uint8 msg)
|
||||
void Unit::SendPetActionFeedback(uint8 msg) const
|
||||
{
|
||||
Unit* owner = GetOwner();
|
||||
if (!owner || !owner->IsPlayer())
|
||||
@@ -16716,19 +16690,18 @@ void Unit::SendPetActionFeedback(uint8 msg)
|
||||
owner->ToPlayer()->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Unit::SendPetTalk(uint32 pettalk)
|
||||
void Unit::SendPetActionSound(PetAction action) const
|
||||
{
|
||||
Unit* owner = GetOwner();
|
||||
if (!owner || !owner->IsPlayer())
|
||||
return;
|
||||
|
||||
WorldPacket data(SMSG_PET_ACTION_SOUND, 8 + 4);
|
||||
data << GetGUID();
|
||||
data << uint32(pettalk);
|
||||
owner->ToPlayer()->GetSession()->SendPacket(&data);
|
||||
SendMessageToSet(WorldPackets::Pet::PetActionSound(GetGUID(), static_cast<int32>(action)).Write(), false);
|
||||
}
|
||||
|
||||
void Unit::SendPetAIReaction(ObjectGuid guid)
|
||||
void Unit::SendPetDismissSound() const
|
||||
{
|
||||
if (CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId()))
|
||||
SendMessageToSet(WorldPackets::Pet::PetDismissSound(static_cast<int32>(displayInfo->ModelId), GetPosition()).Write(), false);
|
||||
}
|
||||
|
||||
void Unit::SendPetAIReaction(ObjectGuid guid) const
|
||||
{
|
||||
Unit* owner = GetOwner();
|
||||
if (!owner || !owner->IsPlayer())
|
||||
@@ -16823,6 +16796,15 @@ bool Unit::IsStandState() const
|
||||
return !IsSitState() && s != UNIT_STAND_STATE_SLEEP && s != UNIT_STAND_STATE_KNEEL;
|
||||
}
|
||||
|
||||
bool Unit::IsStandUpOnMovementState() const
|
||||
{
|
||||
uint8 s = getStandState();
|
||||
return
|
||||
s == UNIT_STAND_STATE_SIT_CHAIR || s == UNIT_STAND_STATE_SIT_LOW_CHAIR ||
|
||||
s == UNIT_STAND_STATE_SIT_MEDIUM_CHAIR || s == UNIT_STAND_STATE_SIT_HIGH_CHAIR ||
|
||||
s == UNIT_STAND_STATE_SIT || s == UNIT_STAND_STATE_SLEEP;
|
||||
}
|
||||
|
||||
void Unit::SetStandState(uint8 state)
|
||||
{
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, state);
|
||||
@@ -18317,74 +18299,65 @@ void Unit::SetStunned(bool apply)
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::SetRooted(bool apply, bool isStun)
|
||||
void Unit::SetRooted(bool apply, bool stun, bool logout)
|
||||
{
|
||||
const uint32 state = (stun ? (logout ? UNIT_STATE_LOGOUT_TIMER : UNIT_STATE_STUNNED) : UNIT_STATE_ROOT);
|
||||
|
||||
if (apply)
|
||||
{
|
||||
if (m_rootTimes > 0) // blizzard internal check?
|
||||
m_rootTimes++;
|
||||
AddUnitState(state);
|
||||
|
||||
// MOVEMENTFLAG_ROOT cannot be used in conjunction with MOVEMENTFLAG_MASK_MOVING (tested 3.3.5a)
|
||||
// this will freeze clients. That's why we remove MOVEMENTFLAG_MASK_MOVING before
|
||||
// setting MOVEMENTFLAG_ROOT
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING);
|
||||
|
||||
if (IsFalling())
|
||||
{
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_PENDING_ROOT);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
}
|
||||
|
||||
// Creature specific
|
||||
if (!IsPlayer())
|
||||
{
|
||||
if (isStun && movespline->Finalized())
|
||||
{
|
||||
StopMovingOnCurrentPos();
|
||||
}
|
||||
else
|
||||
{
|
||||
StopMoving();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_movedByPlayer)
|
||||
{
|
||||
WorldPacket data(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size() + 4);
|
||||
data << GetPackGUID();
|
||||
data << m_rootTimes;
|
||||
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldPacket data(SMSG_SPLINE_MOVE_ROOT, GetPackGUID().size());
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
SendMoveRoot(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT | MOVEMENTFLAG_PENDING_ROOT);
|
||||
ClearUnitState(state);
|
||||
|
||||
if (!HasUnitState(UNIT_STATE_STUNNED)) // prevent moving if it also has stun effect
|
||||
// Prevent giving ability to move if more immobilizers are active
|
||||
if (!IsImmobilizedState())
|
||||
SendMoveRoot(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::SendMoveRoot(bool apply)
|
||||
{
|
||||
const Player* client = GetClientControlling();
|
||||
|
||||
// Apply flags in-place when unit currently is not controlled by a player
|
||||
if (!client)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
if (m_movedByPlayer)
|
||||
{
|
||||
WorldPacket data(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size() + 4);
|
||||
data << GetPackGUID();
|
||||
data << m_rootTimes;
|
||||
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, GetPackGUID().size());
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY);
|
||||
m_movementInfo.AddMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
if (!client)
|
||||
StopMoving();
|
||||
}
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
}
|
||||
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
|
||||
const PackedGuid& guid = GetPackGUID();
|
||||
// Wrath+ spline root: when unit is currently not controlled by a player
|
||||
if (!client)
|
||||
{
|
||||
WorldPacket data(apply ? SMSG_SPLINE_MOVE_ROOT : SMSG_SPLINE_MOVE_UNROOT, guid.size());
|
||||
data << guid;
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
// Wrath+ force root: when unit is controlled by a player
|
||||
else
|
||||
{
|
||||
auto const counter = client->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(apply ? SMSG_FORCE_MOVE_ROOT : SMSG_FORCE_MOVE_UNROOT, guid.size() + 4);
|
||||
data << guid;
|
||||
data << counter;
|
||||
client->GetSession()->SendPacket(&data);
|
||||
client->GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19292,16 +19265,14 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
|
||||
|
||||
WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8 + 4 + 4 + 4 + 4 + 4));
|
||||
data << GetPackGUID();
|
||||
data << uint32(0); // counter
|
||||
data << player->GetSession()->GetOrderCounter(); // movement counter
|
||||
data << float(vcos); // x direction
|
||||
data << float(vsin); // y direction
|
||||
data << float(speedXY); // Horizontal speed
|
||||
data << float(-speedZ); // Z Movement speed (vertical)
|
||||
|
||||
player->GetSession()->SendPacket(&data);
|
||||
|
||||
if (player->HasIncreaseMountedFlightSpeedAura() || player->HasFlyAura())
|
||||
player->SetCanFly(true, true);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
|
||||
player->SetCanKnockback(true);
|
||||
}
|
||||
@@ -19621,7 +19592,7 @@ void Unit::ExitVehicle(Position const* /*exitPosition*/)
|
||||
}
|
||||
}
|
||||
|
||||
bool VehicleDespawnEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
bool VehicleDespawnEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
{
|
||||
Position pos = _self;
|
||||
_self.MovePositionToFirstCollision(pos, 20.0f, M_PI);
|
||||
@@ -19728,7 +19699,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
else if (vehicleBase->IsCreature())
|
||||
{
|
||||
vehicle->Uninstall();
|
||||
vehicleBase->m_Events.AddEvent(new VehicleDespawnEvent(*vehicleBase, 2000), vehicleBase->m_Events.CalculateTime(2000));
|
||||
vehicleBase->m_Events.AddEventAtOffset(new VehicleDespawnEvent(*vehicleBase, 2s), 2s);
|
||||
}
|
||||
|
||||
// xinef: ugly hack, no appripriate hook later to cast spell
|
||||
@@ -19748,7 +19719,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
setDeathState(DeathState::JustDied);
|
||||
// If for other reason we as minion are exiting the vehicle (ejected, master dismounted) - unsummon
|
||||
else
|
||||
ToTempSummon()->UnSummon(2000); // Approximation
|
||||
ToTempSummon()->UnSummon(2s); // Approximation
|
||||
}
|
||||
|
||||
if (player)
|
||||
@@ -20135,7 +20106,7 @@ class AuraMunchingQueue : public BasicEvent
|
||||
public:
|
||||
AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId, AuraEffect* aurEff, AuraType auraType) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId), _aurEff(aurEff), _auraType(auraType) { }
|
||||
|
||||
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
|
||||
bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
|
||||
{
|
||||
if (_owner.IsInWorld() && _owner.FindMap())
|
||||
if (Unit* target = ObjectAccessor::GetUnit(_owner, _targetGUID))
|
||||
@@ -20164,24 +20135,6 @@ private:
|
||||
AuraType _auraType;
|
||||
};
|
||||
|
||||
class ResetToHomeOrientation : public BasicEvent
|
||||
{
|
||||
public:
|
||||
ResetToHomeOrientation(Creature& self) : _self(self) { }
|
||||
|
||||
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
|
||||
{
|
||||
if (_self.IsInWorld() && _self.FindMap() && _self.IsAlive() && !_self.IsInCombat())
|
||||
{
|
||||
_self.SetFacingTo(_self.GetHomePosition().GetOrientation());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
Creature& _self;
|
||||
};
|
||||
|
||||
void Unit::CastDelayedSpellWithPeriodicAmount(Unit* caster, uint32 spellId, AuraType auraType, int32 addAmount, uint8 effectIndex)
|
||||
{
|
||||
AuraEffect* aurEff = nullptr;
|
||||
@@ -20407,7 +20360,7 @@ void Unit::SetFacingTo(float ori)
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
void Unit::SetFacingToObject(WorldObject* object)
|
||||
void Unit::SetFacingToObject(WorldObject* object, Milliseconds timed /*= 0ms*/)
|
||||
{
|
||||
// never face when already moving
|
||||
if (!IsStopped())
|
||||
@@ -20418,24 +20371,20 @@ void Unit::SetFacingToObject(WorldObject* object)
|
||||
init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
init.SetFacing(GetAngle(object)); // when on transport, GetAngle will still return global coordinates (and angle) that needs transforming
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
void Unit::SetTimedFacingToObject(WorldObject* object, uint32 time)
|
||||
{
|
||||
// never face when already moving
|
||||
if (!IsStopped() || !time)
|
||||
return;
|
||||
|
||||
/// @todo figure out under what conditions creature will move towards object instead of facing it where it currently is.
|
||||
Movement::MoveSplineInit init(this);
|
||||
init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
init.SetFacing(GetAngle(object)); // when on transport, GetAngle will still return global coordinates (and angle) that needs transforming
|
||||
init.Launch();
|
||||
|
||||
if (Creature* c = ToCreature())
|
||||
c->m_Events.AddEvent(new ResetToHomeOrientation(*c), c->m_Events.CalculateTime(time));
|
||||
else
|
||||
LOG_ERROR("entities.unit", "Unit::SetTimedFacingToObject called on non-creature unit {}. This should never happen.", GetEntry());
|
||||
if (timed > 0ms)
|
||||
{
|
||||
if (Creature* c = ToCreature())
|
||||
{
|
||||
c->m_Events.AddEventAtOffset([c]()
|
||||
{
|
||||
if (c->IsInWorld() && c->FindMap() && c->IsAlive() && !c->IsInCombat())
|
||||
c->SetFacingTo(c->GetHomePosition().GetOrientation());
|
||||
}, timed);
|
||||
}
|
||||
else
|
||||
LOG_ERROR("entities.unit", "Unit::SetFacingToObject called on non-creature unit {}. This should never happen.", GetEntry());
|
||||
}
|
||||
}
|
||||
|
||||
bool Unit::SetWalk(bool enable)
|
||||
@@ -20495,39 +20444,168 @@ bool Unit::SetSwim(bool enable)
|
||||
*
|
||||
* Doesn't inform the client.
|
||||
*/
|
||||
bool Unit::SetCanFly(bool enable, bool /*packetOnly = false */)
|
||||
void Unit::SetCanFly(bool enable)
|
||||
{
|
||||
if (enable == HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
|
||||
return false;
|
||||
bool isClientControlled = IsClientControlled();
|
||||
|
||||
if (enable)
|
||||
if (!isClientControlled)
|
||||
{
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_MASK_MOVING_FLY);
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEMENTFLAG_CAN_FLY);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_CAN_FLY);
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!IsInWorld()) // is sent on add to map
|
||||
return;
|
||||
|
||||
if (isClientControlled)
|
||||
{
|
||||
if (Player const* player = GetClientControlling())
|
||||
{
|
||||
auto const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(enable ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, GetPackGUID().size() + 4);
|
||||
data << GetPackGUID();
|
||||
data << counter;
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_FLYING : SMSG_SPLINE_MOVE_UNSET_FLYING, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allow to walk on water. Doesn't inform the client.
|
||||
* Need to use SendMovementWaterWalking() if it's for players.
|
||||
*/
|
||||
bool Unit::SetWaterWalking(bool enable, bool /*packetOnly = false*/)
|
||||
void Unit::SetFeatherFall(bool enable)
|
||||
{
|
||||
if (enable == HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING))
|
||||
return false;
|
||||
bool isClientControlled = IsClientControlled();
|
||||
|
||||
if (!isClientControlled)
|
||||
{
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
|
||||
}
|
||||
|
||||
if (!IsInWorld()) // is sent on add to map
|
||||
return;
|
||||
|
||||
if (isClientControlled)
|
||||
{
|
||||
if (Player const* player = GetClientControlling())
|
||||
{
|
||||
auto const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(enable ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, GetPackGUID().size() + 4);
|
||||
|
||||
data << GetPackGUID();
|
||||
data << counter;
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
|
||||
// start fall from current height
|
||||
if (!enable)
|
||||
const_cast<Player*>(player)->SetFallInformation(0, GetPositionZ());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_FEATHER_FALL : SMSG_SPLINE_MOVE_NORMAL_FALL);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Unit::SetHover(bool enable)
|
||||
{
|
||||
bool isClientControlled = IsClientControlled();
|
||||
|
||||
if (!isClientControlled)
|
||||
{
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEMENTFLAG_HOVER);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_HOVER);
|
||||
}
|
||||
|
||||
float hoverHeight = GetHoverHeight();
|
||||
|
||||
if (enable)
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
|
||||
{
|
||||
if (hoverHeight && GetPositionZ() - GetMap()->GetHeight(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ()) < hoverHeight)
|
||||
Relocate(GetPositionX(), GetPositionY(), GetPositionZ() + hoverHeight);
|
||||
}
|
||||
else
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
|
||||
{
|
||||
if (IsAlive() || !IsUnit())
|
||||
{
|
||||
float newZ = std::max<float>(GetMap()->GetHeight(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ()), GetPositionZ() - hoverHeight);
|
||||
UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ);
|
||||
Relocate(GetPositionX(), GetPositionY(), newZ);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!IsInWorld()) // is sent on add to map
|
||||
return;
|
||||
|
||||
if (isClientControlled)
|
||||
{
|
||||
if (Player const* player = GetClientControlling())
|
||||
{
|
||||
WorldPacket data(enable ? SMSG_MOVE_SET_HOVER : SMSG_MOVE_UNSET_HOVER, GetPackGUID().size() + 4);
|
||||
|
||||
auto const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
data << GetPackGUID();
|
||||
data << counter;
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_HOVER : SMSG_SPLINE_MOVE_UNSET_HOVER, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Unit::SetWaterWalking(bool enable)
|
||||
{
|
||||
bool isClientControlled = IsClientControlled();
|
||||
|
||||
if (!isClientControlled)
|
||||
{
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEMENTFLAG_WATERWALKING);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_WATERWALKING);
|
||||
}
|
||||
|
||||
if (!IsInWorld()) // is sent on add to map
|
||||
return;
|
||||
|
||||
if (isClientControlled)
|
||||
{
|
||||
if (Player const* player = GetClientControlling())
|
||||
{
|
||||
auto const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(enable ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, GetPackGUID().size() + 4);
|
||||
data << GetPackGUID();
|
||||
data << counter;
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_WATER_WALK : SMSG_SPLINE_MOVE_LAND_WALK, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Unit::SendMovementWaterWalking(Player* sendTo)
|
||||
@@ -20539,19 +20617,6 @@ void Unit::SendMovementWaterWalking(Player* sendTo)
|
||||
sendTo->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
bool Unit::SetFeatherFall(bool enable, bool /*packetOnly = false*/)
|
||||
{
|
||||
if (enable == HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW))
|
||||
return false;
|
||||
|
||||
if (enable)
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
|
||||
else
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unit::SendMovementFeatherFall(Player* sendTo)
|
||||
{
|
||||
if (!movespline->Initialized())
|
||||
@@ -20561,34 +20626,6 @@ void Unit::SendMovementFeatherFall(Player* sendTo)
|
||||
sendTo->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
bool Unit::SetHover(bool enable, bool /*packetOnly = false*/, bool /*updateAnimationTier = true*/)
|
||||
{
|
||||
if (enable == HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
|
||||
return false;
|
||||
|
||||
float hoverHeight = GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
|
||||
if (hoverHeight && GetPositionZ() - GetFloorZ() < hoverHeight)
|
||||
UpdateHeight(GetPositionZ() + hoverHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_HOVER);
|
||||
if (hoverHeight && (!isDying() || !IsCreature()))
|
||||
{
|
||||
float newZ = std::max<float>(GetFloorZ(), GetPositionZ() - hoverHeight);
|
||||
UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ);
|
||||
UpdateHeight(newZ);
|
||||
}
|
||||
SendMovementFlagUpdate(); // pussywizard: needed for falling after death (instead of falling onto air at hover height)
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unit::SendMovementHover(Player* sendTo)
|
||||
{
|
||||
if (!movespline->Initialized())
|
||||
@@ -20750,7 +20787,10 @@ void Unit::PatchValuesUpdate(ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPoi
|
||||
appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK;
|
||||
|
||||
if (!target->CanSeeVendor(creature))
|
||||
{
|
||||
appendValue &= ~UNIT_NPC_FLAG_REPAIR;
|
||||
appendValue &= ~UNIT_NPC_FLAG_VENDOR_MASK;
|
||||
}
|
||||
|
||||
if (!creature->IsValidTrainerForPlayer(target, &appendValue))
|
||||
appendValue &= ~UNIT_NPC_FLAG_TRAINER;
|
||||
@@ -21235,6 +21275,61 @@ std::string Unit::GetDebugInfo() const
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
bool Unit::IsClientControlled(Player const* exactClient /*= nullptr*/) const
|
||||
{
|
||||
// Severvide method to check if unit is client controlled (optionally check for specific client in control)
|
||||
|
||||
// Applies only to player controlled units
|
||||
if (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
|
||||
return false;
|
||||
|
||||
// These flags are meant to be used when server controls this unit, client control is taken away
|
||||
if (HasFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING)))
|
||||
return false;
|
||||
|
||||
// If unit is possessed, it has lost original control...
|
||||
if (ObjectGuid const& guid = GetCharmerGUID())
|
||||
{
|
||||
// ... but if it is a possessing charm, then we have to check if some other player controls it
|
||||
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED) && guid.IsPlayer())
|
||||
return (exactClient ? (exactClient->GetGUID() == guid) : true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// By default: players have client control over themselves
|
||||
if (IsPlayer())
|
||||
return (exactClient ? (exactClient == this) : true);
|
||||
return false;
|
||||
}
|
||||
|
||||
Player const* Unit::GetClientControlling() const
|
||||
{
|
||||
// Serverside reverse "mover" deduction logic at controlled unit
|
||||
|
||||
// Applies only to player controlled units
|
||||
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
|
||||
{
|
||||
// Charm always removes control from original client...
|
||||
if (GetCharmerGUID())
|
||||
{
|
||||
// ... but if it is a possessing charm, some other client may have control
|
||||
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED))
|
||||
{
|
||||
Unit const* charmer = GetCharmer();
|
||||
if (charmer && charmer->IsPlayer())
|
||||
return static_cast<Player const*>(charmer);
|
||||
}
|
||||
}
|
||||
else if (IsPlayer())
|
||||
{
|
||||
// Check if anything prevents original client from controlling
|
||||
if (IsClientControlled(static_cast<Player const*>(this)))
|
||||
return static_cast<Player const*>(this);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Unit::SetCannotReachTargetUnit(bool cannotReach, bool isChase)
|
||||
{
|
||||
if (cannotReach == m_cannotReachTarget)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ItemTemplate.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "Object.h"
|
||||
#include "PetDefines.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SpellAuraDefines.h"
|
||||
#include "SpellDefines.h"
|
||||
@@ -744,6 +745,7 @@ public:
|
||||
void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.flags2 = f; }
|
||||
|
||||
inline bool IsCrowdControlled() const { return HasFlag(UNIT_FIELD_FLAGS, (UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING | UNIT_FLAG_STUNNED)); }
|
||||
inline bool IsImmobilizedState() const { return HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED); }
|
||||
|
||||
/*********************************************************/
|
||||
/*** UNIT TYPES, CLASSES, RACES... ***/
|
||||
@@ -826,6 +828,11 @@ public:
|
||||
bool IsValidAssistTarget(Unit const* target) const;
|
||||
bool _IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) const;
|
||||
|
||||
// Client controlled: check if unit currently is under client control (has active "mover"), optionally check for specific client (server-side)
|
||||
bool IsClientControlled(Player const* exactClient = nullptr) const;
|
||||
// Controlling client: server PoV on which client (player) controls movement of the unit at the moment, obtain "mover" (server-side)
|
||||
Player const* GetClientControlling() const;
|
||||
|
||||
// Combat range
|
||||
[[nodiscard]] float GetBoundaryRadius() const { return m_floatValues[UNIT_FIELD_BOUNDINGRADIUS]; }
|
||||
[[nodiscard]] float GetCombatReach() const override { return m_floatValues[UNIT_FIELD_COMBATREACH]; }
|
||||
@@ -1165,6 +1172,7 @@ public:
|
||||
static uint32 DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true, bool allowGM = false, Spell const* spell = nullptr);
|
||||
void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss);
|
||||
void DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss, Spell const* spell = nullptr);
|
||||
void DealDamageShieldDamage(Unit* victim);
|
||||
static void DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb);
|
||||
|
||||
static void Kill(Unit* killer, Unit* victim, bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr, Spell const* spell = nullptr);
|
||||
@@ -1637,6 +1645,7 @@ public:
|
||||
[[nodiscard]] virtual bool CanFly() const = 0;
|
||||
[[nodiscard]] bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY); }
|
||||
[[nodiscard]] bool IsFalling() const;
|
||||
[[nodiscard]] bool IsRooted() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT); }
|
||||
|
||||
[[nodiscard]] float GetHoverHeight() const { return IsHovering() ? GetFloatValue(UNIT_FIELD_HOVERHEIGHT) : 0.0f; }
|
||||
|
||||
@@ -1669,17 +1678,15 @@ public:
|
||||
void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); }
|
||||
|
||||
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 TransitTime, SplineFlags sf = SPLINEFLAG_WALK_MODE); // pussywizard: need to just send packet, with no movement/spline
|
||||
void MonsterMoveWithSpeed(float x, float y, float z, float speed);
|
||||
//void SetFacing(float ori, WorldObject* obj = nullptr);
|
||||
//void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = nullptr);
|
||||
void MonsterMoveWithSpeed(float x, float y, float z, float speed); // Not to be used outside of cinematics
|
||||
|
||||
virtual bool SetWalk(bool enable);
|
||||
virtual bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true);
|
||||
virtual bool SetSwim(bool enable);
|
||||
virtual bool SetCanFly(bool enable, bool packetOnly = false);
|
||||
virtual bool SetWaterWalking(bool enable, bool packetOnly = false);
|
||||
virtual bool SetFeatherFall(bool enable, bool packetOnly = false);
|
||||
virtual bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true);
|
||||
void SetCanFly(bool enable);
|
||||
void SetWaterWalking(bool enable);
|
||||
void SetFeatherFall(bool enable);
|
||||
void SetHover(bool enable);
|
||||
|
||||
MotionMaster* GetMotionMaster() { return i_motionMaster; }
|
||||
[[nodiscard]] const MotionMaster* GetMotionMaster() const { return i_motionMaster; }
|
||||
@@ -1706,6 +1713,7 @@ public:
|
||||
[[nodiscard]] uint8 getStandState() const { return GetByteValue(UNIT_FIELD_BYTES_1, 0); }
|
||||
[[nodiscard]] bool IsSitState() const;
|
||||
[[nodiscard]] bool IsStandState() const;
|
||||
[[nodiscard]] bool IsStandUpOnMovementState() const;
|
||||
void SetStandState(uint8 state);
|
||||
|
||||
void SetStandFlags(uint8 flags) { SetByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_VIS_FLAG, flags); }
|
||||
@@ -1913,8 +1921,8 @@ public:
|
||||
|
||||
void SetInFront(WorldObject const* target);
|
||||
void SetFacingTo(float ori);
|
||||
void SetFacingToObject(WorldObject* object);
|
||||
void SetTimedFacingToObject(WorldObject* object, uint32 time); // Reset to home orientation after given time
|
||||
// <timed>Reset to home orientation after given time
|
||||
void SetFacingToObject(WorldObject* object, Milliseconds timed = 0ms);
|
||||
|
||||
bool isInAccessiblePlaceFor(Creature const* c) const;
|
||||
bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const;
|
||||
@@ -1957,9 +1965,10 @@ public:
|
||||
void SendPlaySpellVisual(ObjectGuid guid, uint32 id);
|
||||
void SendPlaySpellImpact(ObjectGuid guid, uint32 id);
|
||||
|
||||
void SendPetActionFeedback (uint8 msg);
|
||||
void SendPetTalk (uint32 pettalk);
|
||||
void SendPetAIReaction(ObjectGuid guid);
|
||||
void SendPetActionFeedback(uint8 msg) const;
|
||||
void SendPetActionSound(PetAction action) const;
|
||||
void SendPetDismissSound() const;
|
||||
void SendPetAIReaction(ObjectGuid guid) const;
|
||||
|
||||
void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo);
|
||||
|
||||
@@ -2063,7 +2072,8 @@ protected:
|
||||
void SetFeared(bool apply, Unit* fearedBy = nullptr, bool isFear = false);
|
||||
void SetConfused(bool apply);
|
||||
void SetStunned(bool apply);
|
||||
void SetRooted(bool apply, bool isStun = false);
|
||||
void SetRooted(bool apply, bool stun = false, bool logout = false);
|
||||
void SendMoveRoot(bool state);
|
||||
|
||||
//----------- Protected variables ----------//
|
||||
UnitAI* i_AI;
|
||||
@@ -2135,8 +2145,6 @@ protected:
|
||||
bool m_applyResilience;
|
||||
bool _instantCast;
|
||||
|
||||
uint32 m_rootTimes;
|
||||
|
||||
private:
|
||||
bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent, ProcEventInfo const& eventInfo);
|
||||
bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, ProcEventInfo const& eventInfo);
|
||||
|
||||
@@ -197,7 +197,9 @@ enum UnitState
|
||||
UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator
|
||||
UNIT_STATE_NO_ENVIRONMENT_UPD = 0x20000000,
|
||||
|
||||
UNIT_STATE_NO_COMBAT_MOVEMENT, // serverside only - should never be changed outside of core and hence shouldnt have a defined static value and be at the end
|
||||
// serverside region
|
||||
UNIT_STATE_NO_COMBAT_MOVEMENT = 0x40000000, // should not be changed outside the core and should be placed at the end
|
||||
UNIT_STATE_LOGOUT_TIMER = 0x80000000, // Unit is logging out
|
||||
|
||||
UNIT_STATE_ALL_STATE_SUPPORTED = UNIT_STATE_DIED | UNIT_STATE_MELEE_ATTACKING | UNIT_STATE_STUNNED | UNIT_STATE_ROAMING | UNIT_STATE_CHASE
|
||||
| UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | UNIT_STATE_FOLLOW | UNIT_STATE_ROOT | UNIT_STATE_CONFUSED
|
||||
@@ -412,6 +414,8 @@ enum MovementFlags
|
||||
MOVEMENTFLAG_MASK_PLAYER_ONLY =
|
||||
MOVEMENTFLAG_FLYING,
|
||||
|
||||
MOVEMENTFLAG_MASK_MOVING_OR_TURN = MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING,
|
||||
|
||||
/// Movement flags that have change status opcodes associated for players
|
||||
MOVEMENTFLAG_MASK_HAS_PLAYER_STATUS_OPCODE = MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_ROOT |
|
||||
MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_WATERWALKING | MOVEMENTFLAG_FALLING_SLOW | MOVEMENTFLAG_HOVER
|
||||
|
||||
@@ -100,12 +100,12 @@ private:
|
||||
class VehicleDespawnEvent : public BasicEvent
|
||||
{
|
||||
public:
|
||||
VehicleDespawnEvent(Unit& self, uint32 duration) : _self(self), _duration(duration) { }
|
||||
VehicleDespawnEvent(Unit& self, Milliseconds duration) : _self(self), _duration(duration) { }
|
||||
bool Execute(uint64 e_time, uint32 p_time) override;
|
||||
|
||||
protected:
|
||||
Unit& _self;
|
||||
uint32 _duration;
|
||||
Milliseconds _duration;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace PlayerNameMapHolder
|
||||
|
||||
} // namespace PlayerNameMapHolder
|
||||
|
||||
WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid const guid)
|
||||
WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid const& guid)
|
||||
{
|
||||
switch (guid.GetHigh())
|
||||
{
|
||||
@@ -138,7 +138,7 @@ WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid con
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid const guid, uint32 typemask)
|
||||
Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid const& guid, uint32 typemask)
|
||||
{
|
||||
switch (guid.GetHigh())
|
||||
{
|
||||
@@ -176,27 +176,27 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid con
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, ObjectGuid const guid)
|
||||
Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
return u.GetMap()->GetCorpse(guid);
|
||||
}
|
||||
|
||||
GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid const guid)
|
||||
GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
return u.GetMap()->GetGameObject(guid);
|
||||
}
|
||||
|
||||
Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid const guid)
|
||||
Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
return u.GetMap()->GetTransport(guid);
|
||||
}
|
||||
|
||||
DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid const guid)
|
||||
DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
return u.GetMap()->GetDynamicObject(guid);
|
||||
}
|
||||
|
||||
Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid const guid)
|
||||
Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
if (guid.IsPlayer())
|
||||
return GetPlayer(u, guid);
|
||||
@@ -207,17 +207,17 @@ Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid const guid)
|
||||
return GetCreature(u, guid);
|
||||
}
|
||||
|
||||
Creature* ObjectAccessor::GetCreature(WorldObject const& u, ObjectGuid const guid)
|
||||
Creature* ObjectAccessor::GetCreature(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
return u.GetMap()->GetCreature(guid);
|
||||
}
|
||||
|
||||
Pet* ObjectAccessor::GetPet(WorldObject const& u, ObjectGuid const guid)
|
||||
Pet* ObjectAccessor::GetPet(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
return u.GetMap()->GetPet(guid);
|
||||
}
|
||||
|
||||
Player* ObjectAccessor::GetPlayer(Map const* m, ObjectGuid const guid)
|
||||
Player* ObjectAccessor::GetPlayer(Map const* m, ObjectGuid const& guid)
|
||||
{
|
||||
if (Player * player = HashMapHolder<Player>::Find(guid))
|
||||
if (player->IsInWorld() && player->GetMap() == m)
|
||||
@@ -226,12 +226,12 @@ Player* ObjectAccessor::GetPlayer(Map const* m, ObjectGuid const guid)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Player* ObjectAccessor::GetPlayer(WorldObject const& u, ObjectGuid const guid)
|
||||
Player* ObjectAccessor::GetPlayer(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
return GetPlayer(u.GetMap(), guid);
|
||||
}
|
||||
|
||||
Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, ObjectGuid const guid)
|
||||
Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, ObjectGuid const& guid)
|
||||
{
|
||||
if (guid.IsPet())
|
||||
return GetPet(u, guid);
|
||||
|
||||
@@ -60,18 +60,18 @@ public:
|
||||
namespace ObjectAccessor
|
||||
{
|
||||
// these functions return objects only if in map of specified object
|
||||
WorldObject* GetWorldObject(WorldObject const&, ObjectGuid const guid);
|
||||
Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const guid, uint32 typemask);
|
||||
Corpse* GetCorpse(WorldObject const& u, ObjectGuid const guid);
|
||||
GameObject* GetGameObject(WorldObject const& u, ObjectGuid const guid);
|
||||
Transport* GetTransport(WorldObject const& u, ObjectGuid const guid);
|
||||
DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const guid);
|
||||
Unit* GetUnit(WorldObject const&, ObjectGuid const guid);
|
||||
Creature* GetCreature(WorldObject const& u, ObjectGuid const guid);
|
||||
Pet* GetPet(WorldObject const&, ObjectGuid const guid);
|
||||
Player* GetPlayer(Map const*, ObjectGuid const guid);
|
||||
Player* GetPlayer(WorldObject const&, ObjectGuid const guid);
|
||||
Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid const);
|
||||
WorldObject* GetWorldObject(WorldObject const&, ObjectGuid const& guid);
|
||||
Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const& guid, uint32 typemask);
|
||||
Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid);
|
||||
GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid);
|
||||
Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid);
|
||||
DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid);
|
||||
Unit* GetUnit(WorldObject const&, ObjectGuid const& guid);
|
||||
Creature* GetCreature(WorldObject const& u, ObjectGuid const& guid);
|
||||
Pet* GetPet(WorldObject const&, ObjectGuid const& guid);
|
||||
Player* GetPlayer(Map const*, ObjectGuid const& guid);
|
||||
Player* GetPlayer(WorldObject const&, ObjectGuid const& guid);
|
||||
Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid const&);
|
||||
|
||||
// these functions return objects if found in whole world
|
||||
// ACCESS LIKE THAT IS NOT THREAD SAFE
|
||||
|
||||
@@ -1122,8 +1122,22 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
|
||||
if (!cInfo->Models.size())
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) does not have any existing display id in creature_template_model.", cInfo->Entry);
|
||||
else if (std::accumulate(cInfo->Models.begin(), cInfo->Models.end(), 0.0f, [](float sum, CreatureModel const& model) { return sum + model.Probability; }) <= 0.0f)
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has zero total chance for all models in creature_template_model.", cInfo->Entry);
|
||||
else
|
||||
{
|
||||
float const totalProbability = std::accumulate(cInfo->Models.begin(), cInfo->Models.end(), 0.0f, [](float sum, CreatureModel const& model) { return sum + model.Probability; });
|
||||
|
||||
if (totalProbability <= 0.0f)
|
||||
{ // There are many cases in official data of all models having a probability of 0. Believe to be treated equivalent to equal chance ONLY if all are zeroed
|
||||
if (totalProbability == 0.0f)
|
||||
LOG_DEBUG("sql.sql", "Creature (Entry: {}) has zero total chance for all models in creature_template_model. Setting all to 1.0.", cInfo->Entry);
|
||||
else // Custom, likely bad data
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has less than zero total chance for all models in creature_template_model. Setting all to 1.0.", cInfo->Entry);
|
||||
|
||||
auto& models = const_cast<CreatureTemplate*>(cInfo)->Models;
|
||||
for (auto& model : models)
|
||||
model.Probability = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cInfo->unit_class || ((1 << (cInfo->unit_class - 1)) & CLASSMASK_ALL_CREATURES) == 0)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ Copied events should probably have a new owner
|
||||
|
||||
#include "ArenaTeamMgr.h"
|
||||
#include "CalendarMgr.h"
|
||||
#include "CalendarPackets.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DisableMgr.h"
|
||||
#include "GameEventMgr.h"
|
||||
@@ -184,43 +185,31 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/)
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarGetEvent(WorldPacket& recvData)
|
||||
void WorldSession::HandleCalendarGetEvent(WorldPackets::Calendar::GetEvent& packet)
|
||||
{
|
||||
uint64 eventId;
|
||||
recvData >> eventId;
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_GET_EVENT. Player [{}] Event [{}]", _player->GetGUID().ToString(), packet.EventId);
|
||||
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_GET_EVENT. Player [{}] Event [{}]", _player->GetGUID().ToString(), eventId);
|
||||
|
||||
if (CalendarEvent* calendarEvent = sCalendarMgr->GetEvent(eventId))
|
||||
if (CalendarEvent* calendarEvent = sCalendarMgr->GetEvent(packet.EventId))
|
||||
sCalendarMgr->SendCalendarEvent(_player->GetGUID(), *calendarEvent, CALENDAR_SENDTYPE_GET);
|
||||
else
|
||||
sCalendarMgr->SendCalendarCommandResult(_player->GetGUID(), CALENDAR_ERROR_EVENT_INVALID);
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarGuildFilter(WorldPacket& recvData)
|
||||
void WorldSession::HandleCalendarGuildFilter(WorldPackets::Calendar::GuildFilter& packet)
|
||||
{
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_GUILD_FILTER [{}]", _player->GetGUID().ToString());
|
||||
|
||||
uint32 minLevel;
|
||||
uint32 maxLevel;
|
||||
uint32 minRank;
|
||||
|
||||
recvData >> minLevel >> maxLevel >> minRank;
|
||||
|
||||
if (Guild* guild = sGuildMgr->GetGuildById(_player->GetGuildId()))
|
||||
guild->MassInviteToEvent(this, minLevel, maxLevel, minRank);
|
||||
guild->MassInviteToEvent(this, packet.MinimumLevel, packet.MaximumLevel, packet.MinimumRank);
|
||||
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_GUILD_FILTER: Min level [{}], Max level [{}], Min rank [{}]", minLevel, maxLevel, minRank);
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_GUILD_FILTER: Min level [{}], Max level [{}], Min rank [{}]", packet.MinimumLevel, packet.MaximumLevel, packet.MinimumRank);
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarArenaTeam(WorldPacket& recvData)
|
||||
void WorldSession::HandleCalendarArenaTeam(WorldPackets::Calendar::ArenaTeam& packet)
|
||||
{
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_ARENA_TEAM [{}]", _player->GetGUID().ToString());
|
||||
|
||||
uint32 arenaTeamId;
|
||||
recvData >> arenaTeamId;
|
||||
|
||||
if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(arenaTeamId))
|
||||
if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(packet.ArenaTeamId))
|
||||
team->MassInviteToEvent(this);
|
||||
}
|
||||
|
||||
@@ -763,14 +752,11 @@ void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket& recvData)
|
||||
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_INVALID);
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarComplain(WorldPacket& recvData)
|
||||
void WorldSession::HandleCalendarComplain(WorldPackets::Calendar::CalendarComplain& packet)
|
||||
{
|
||||
ObjectGuid guid = _player->GetGUID();
|
||||
uint64 eventId;
|
||||
ObjectGuid complainGUID;
|
||||
|
||||
recvData >> eventId >> complainGUID;
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_COMPLAIN [{}] EventId [{}] guid [{}]", guid.ToString(), eventId, complainGUID.ToString());
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_COMPLAIN [{}] EventId [{}] guid [{}]", guid.ToString(), packet.EventId, packet.ComplainGuid.ToString());
|
||||
|
||||
// what to do with complains?
|
||||
}
|
||||
|
||||
@@ -1159,8 +1159,11 @@ void WorldSession::HandlePlayerLoginToCharInWorld(Player* pCurrChar)
|
||||
SendPacket(&data);
|
||||
|
||||
// Xinef: fix possible problem with flag UNIT_FLAG_STUNNED added during logout
|
||||
if (!pCurrChar->HasUnitState(UNIT_STATE_STUNNED))
|
||||
if (pCurrChar->HasUnitState(UNIT_STATE_LOGOUT_TIMER))
|
||||
{
|
||||
pCurrChar->SetRooted(false, true, true);
|
||||
pCurrChar->RemoveUnitFlag(UNIT_FLAG_STUNNED);
|
||||
}
|
||||
|
||||
pCurrChar->SendInitialPacketsBeforeAddToMap();
|
||||
|
||||
@@ -1749,9 +1752,21 @@ void WorldSession::HandleEquipmentSetSave(WorldPacket& recvData)
|
||||
std::string name;
|
||||
recvData >> name;
|
||||
|
||||
if (name.length() > 16) // Client limitation
|
||||
{
|
||||
LOG_ERROR("entities.player.cheat", "Character GUID {} tried to create equipment set {} with too long a name!", _player->GetGUID().ToString(), setGuid);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string iconName;
|
||||
recvData >> iconName;
|
||||
|
||||
if (iconName.length() > 100) // DB limitation
|
||||
{
|
||||
LOG_ERROR("entities.player.cheat", "Character GUID {} tried to create equipment set {} with too long an icon name!", _player->GetGUID().ToString(), setGuid);
|
||||
return;
|
||||
}
|
||||
|
||||
EquipmentSet eqSet;
|
||||
|
||||
eqSet.Guid = setGuid;
|
||||
|
||||
@@ -468,7 +468,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequ
|
||||
GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
}
|
||||
|
||||
GetPlayer()->SetRooted(true);
|
||||
GetPlayer()->SetRooted(true, true, true);
|
||||
GetPlayer()->SetUnitFlag(UNIT_FLAG_STUNNED);
|
||||
}
|
||||
|
||||
@@ -492,7 +492,7 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPackets::Character::LogoutCance
|
||||
// not remove flags if can't free move - its not set in Logout request code.
|
||||
if (GetPlayer()->CanFreeMove())
|
||||
{
|
||||
GetPlayer()->SetRooted(false);
|
||||
GetPlayer()->SetRooted(false, true, true);
|
||||
|
||||
GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
GetPlayer()->RemoveUnitFlag(UNIT_FLAG_STUNNED);
|
||||
@@ -949,12 +949,6 @@ void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recv_data*/)
|
||||
GetPlayer()->GetCinematicMgr()->BeginCinematic();
|
||||
}
|
||||
|
||||
void WorldSession::HandleFeatherFallAck(WorldPacket& recv_data)
|
||||
{
|
||||
// no used
|
||||
recv_data.rfinish(); // prevent warnings spam
|
||||
}
|
||||
|
||||
void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data)
|
||||
{
|
||||
uint8 ActionBar;
|
||||
@@ -1144,45 +1138,18 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data)
|
||||
LOG_DEBUG("network", "Received whois command from player {} for character {}", GetPlayer()->GetName(), charname);
|
||||
}
|
||||
|
||||
void WorldSession::HandleComplainOpcode(WorldPacket& recv_data)
|
||||
void WorldSession::HandleComplainOpcode(WorldPackets::Misc::Complain& packet)
|
||||
{
|
||||
LOG_DEBUG("network", "WORLD: CMSG_COMPLAIN");
|
||||
|
||||
uint8 spam_type; // 0 - mail, 1 - chat
|
||||
ObjectGuid spammer_guid;
|
||||
uint32 unk1 = 0;
|
||||
uint32 unk2 = 0;
|
||||
uint32 unk3 = 0;
|
||||
uint32 unk4 = 0;
|
||||
std::string description = "";
|
||||
recv_data >> spam_type; // unk 0x01 const, may be spam type (mail/chat)
|
||||
recv_data >> spammer_guid; // player guid
|
||||
switch (spam_type)
|
||||
{
|
||||
case 0:
|
||||
recv_data >> unk1; // const 0
|
||||
recv_data >> unk2; // probably mail id
|
||||
recv_data >> unk3; // const 0
|
||||
break;
|
||||
case 1:
|
||||
recv_data >> unk1; // probably language
|
||||
recv_data >> unk2; // message type?
|
||||
recv_data >> unk3; // probably channel id
|
||||
recv_data >> unk4; // unk random value
|
||||
recv_data >> description; // spam description string (messagetype, channel name, player name, message)
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: all chat messages from this spammer automatically ignored by spam reporter until logout in case chat spam.
|
||||
// if it's mail spam - ALL mails from this spammer automatically removed by client
|
||||
|
||||
// Complaint Received message
|
||||
WorldPacket data(SMSG_COMPLAIN_RESULT, 1);
|
||||
data << uint8(0);
|
||||
SendPacket(&data);
|
||||
SendPacket(WorldPackets::Misc::ComplainResult().Write());
|
||||
|
||||
LOG_DEBUG("network", "REPORT SPAM: type {}, {}, unk1 {}, unk2 {}, unk3 {}, unk4 {}, message {}",
|
||||
spam_type, spammer_guid.ToString(), unk1, unk2, unk3, unk4, description);
|
||||
packet.SpamType, packet.SpammerGuid.ToString(), packet.Unk1, packet.Unk2, packet.Unk3, packet.Unk4, packet.Description);
|
||||
}
|
||||
|
||||
void WorldSession::HandleRealmSplitOpcode(WorldPacket& recv_data)
|
||||
@@ -1519,12 +1486,13 @@ void WorldSession::HandleCancelMountAuraOpcode(WorldPacket& /*recv_data*/)
|
||||
_player->RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data)
|
||||
void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
// fly mode on/off
|
||||
LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
|
||||
LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging((Opcodes)recv_data.GetOpcode()));
|
||||
|
||||
ObjectGuid guid;
|
||||
uint32 counter;
|
||||
uint32 isApplied;
|
||||
recv_data >> guid.ReadAsPacked();
|
||||
|
||||
if (!_player)
|
||||
@@ -1533,17 +1501,42 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data)
|
||||
return;
|
||||
}
|
||||
|
||||
recv_data.read_skip<uint32>(); // unk
|
||||
recv_data >> counter;
|
||||
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recv_data, &movementInfo);
|
||||
|
||||
recv_data.read_skip<float>(); // unk2
|
||||
recv_data >> isApplied;
|
||||
|
||||
sScriptMgr->AnticheatSetCanFlybyServer(_player, movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY));
|
||||
|
||||
_player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
|
||||
Unit* mover = _player->m_mover;
|
||||
Player* plrMover = mover->ToPlayer();
|
||||
|
||||
mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
|
||||
|
||||
Opcodes response;
|
||||
|
||||
switch (recv_data.GetOpcode())
|
||||
{
|
||||
case CMSG_MOVE_HOVER_ACK: response = MSG_MOVE_HOVER; break;
|
||||
case CMSG_MOVE_FEATHER_FALL_ACK: response = MSG_MOVE_FEATHER_FALL; break;
|
||||
case CMSG_MOVE_WATER_WALK_ACK: response = MSG_MOVE_WATER_WALK; break;
|
||||
case CMSG_MOVE_SET_CAN_FLY_ACK: response = MSG_MOVE_UPDATE_CAN_FLY; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
if (!ProcessMovementInfo(movementInfo, mover, plrMover, recv_data))
|
||||
{
|
||||
recv_data.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
WorldPacket data(response, 8);
|
||||
data << guid.WriteAsPacked();
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
_player->m_mover->SendMessageToSet(&data, _player);
|
||||
}
|
||||
|
||||
void WorldSession::HandleRequestPetInfo(WorldPackets::Pet::RequestPetInfo& /*packet*/)
|
||||
|
||||
@@ -370,82 +370,44 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
// Stop emote on move
|
||||
if (Player* plrMover = mover->ToPlayer())
|
||||
{
|
||||
if (plrMover->GetUInt32Value(UNIT_NPC_EMOTESTATE) != EMOTE_ONESHOT_NONE && movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING))
|
||||
{
|
||||
plrMover->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!movementInfo.pos.IsPositionValid())
|
||||
{
|
||||
if (plrMover)
|
||||
{
|
||||
sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
|
||||
}
|
||||
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mover->movespline->Finalized())
|
||||
if (!ProcessMovementInfo(movementInfo, mover, plrMover, recvData))
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
// Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE
|
||||
if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
{
|
||||
// Xinef: skip moving packets
|
||||
if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING))
|
||||
{
|
||||
if (plrMover)
|
||||
{
|
||||
sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ());
|
||||
/* process position-change */
|
||||
WorldPacket data(opcode, recvData.size());
|
||||
movementInfo.guid = mover->GetGUID();
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
}
|
||||
|
||||
if (mover->IsCreature())
|
||||
{
|
||||
movementInfo.transport.guid = mover->m_movementInfo.transport.guid;
|
||||
movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ());
|
||||
movementInfo.transport.seat = mover->m_movementInfo.transport.seat;
|
||||
}
|
||||
void WorldSession::SynchronizeMovement(MovementInfo& movementInfo)
|
||||
{
|
||||
int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta;
|
||||
if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF)
|
||||
{
|
||||
LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
|
||||
movementInfo.time = getMSTime();
|
||||
}
|
||||
|
||||
if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
|
||||
else
|
||||
{
|
||||
// We were teleported, skip packets that were broadcast before teleport
|
||||
if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS)
|
||||
{
|
||||
if (plrMover)
|
||||
{
|
||||
sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
|
||||
//LOG_INFO("anticheat", "MovementHandler:: 2 We were teleported, skip packets that were broadcast before teleport");
|
||||
}
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
movementInfo.time = (uint32)movementTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Acore::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
|
||||
movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
|
||||
{
|
||||
if (plrMover)
|
||||
{
|
||||
sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
|
||||
}
|
||||
void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo, Unit* mover)
|
||||
{
|
||||
SynchronizeMovement(movementInfo);
|
||||
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
mover->UpdatePosition(movementInfo.pos);
|
||||
mover->m_movementInfo = movementInfo;
|
||||
|
||||
if (mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
|
||||
{
|
||||
// if we boarded a transport, add us to it
|
||||
if (plrMover)
|
||||
if (Player* plrMover = mover->ToPlayer())
|
||||
{
|
||||
if (!plrMover->GetTransport())
|
||||
{
|
||||
@@ -483,13 +445,161 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
|
||||
else if (mover->IsPlayer())
|
||||
{
|
||||
sScriptMgr->AnticheatSetUnderACKmount(plrMover); // just for safe
|
||||
if (Player* plrMover = mover->ToPlayer())
|
||||
{
|
||||
if (plrMover->GetTransport()) // if we were on a transport, leave
|
||||
{
|
||||
sScriptMgr->AnticheatSetUnderACKmount(plrMover); // just for safe
|
||||
|
||||
plrMover->m_transport->RemovePassenger(plrMover);
|
||||
plrMover->m_transport = nullptr;
|
||||
movementInfo.transport.Reset();
|
||||
plrMover->m_transport->RemovePassenger(plrMover);
|
||||
plrMover->m_transport = nullptr;
|
||||
movementInfo.transport.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some vehicles allow the passenger to turn by himself
|
||||
if (Vehicle* vehicle = mover->GetVehicle())
|
||||
{
|
||||
if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover))
|
||||
{
|
||||
if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING && movementInfo.pos.GetOrientation() != mover->GetOrientation())
|
||||
{
|
||||
mover->SetOrientation(movementInfo.pos.GetOrientation());
|
||||
mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Player* plrMover = mover->ToPlayer()) // nothing is charmed, or player charmed
|
||||
{
|
||||
if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING)))
|
||||
plrMover->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
|
||||
if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()))
|
||||
{
|
||||
if (!plrMover->GetBattleground() || !plrMover->GetBattleground()->HandlePlayerUnderMap(_player))
|
||||
{
|
||||
if (plrMover->IsAlive())
|
||||
{
|
||||
plrMover->SetPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS);
|
||||
plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
|
||||
// player can be alive if GM
|
||||
if (plrMover->IsAlive())
|
||||
plrMover->KillPlayer();
|
||||
}
|
||||
else if (!plrMover->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS))
|
||||
{
|
||||
GraveyardStruct const* grave = sGraveyard->GetClosestGraveyard(plrMover, plrMover->GetTeamId());
|
||||
if (grave)
|
||||
{
|
||||
plrMover->TeleportTo(grave->Map, grave->x, grave->y, grave->z, plrMover->GetOrientation());
|
||||
plrMover->Relocate(grave->x, grave->y, grave->z, plrMover->GetOrientation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WorldSession::VerifyMovementInfo(MovementInfo const& movementInfo, Player* plrMover, Unit* mover, Opcodes opcode) const
|
||||
{
|
||||
if (!movementInfo.pos.IsPositionValid())
|
||||
{
|
||||
if (plrMover)
|
||||
{
|
||||
sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mover->movespline->Finalized())
|
||||
return false;
|
||||
|
||||
// Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE
|
||||
if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
{
|
||||
// Xinef: skip moving packets
|
||||
if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING))
|
||||
{
|
||||
if (plrMover)
|
||||
{
|
||||
sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool jumpopcode = false;
|
||||
if (opcode == MSG_MOVE_JUMP)
|
||||
{
|
||||
jumpopcode = true;
|
||||
if (plrMover && !sScriptMgr->AnticheatHandleDoubleJump(plrMover, mover))
|
||||
{
|
||||
plrMover->GetSession()->KickPlayer();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* start some hack detection */
|
||||
if (plrMover && !sScriptMgr->AnticheatCheckMovementInfo(plrMover, movementInfo, mover, jumpopcode))
|
||||
{
|
||||
plrMover->GetSession()->KickPlayer();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
|
||||
{
|
||||
// We were teleported, skip packets that were broadcast before teleport
|
||||
if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS)
|
||||
{
|
||||
if (plrMover)
|
||||
{
|
||||
sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
|
||||
//LOG_INFO("anticheat", "MovementHandler:: 2 We were teleported, skip packets that were broadcast before teleport");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Acore::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
|
||||
movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
|
||||
{
|
||||
if (plrMover)
|
||||
{
|
||||
sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// rooted mover sent packet without root or moving AND root - ignore, due to client crash possibility
|
||||
if (opcode != CMSG_FORCE_MOVE_UNROOT_ACK)
|
||||
if (mover->IsRooted() && (!movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT) || movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldSession::ProcessMovementInfo(MovementInfo& movementInfo, Unit* mover, Player* plrMover, WorldPacket& recvData)
|
||||
{
|
||||
Opcodes opcode = (Opcodes)recvData.GetOpcode();
|
||||
if (!VerifyMovementInfo(movementInfo, plrMover, mover, opcode))
|
||||
return false;
|
||||
|
||||
if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
{
|
||||
movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ());
|
||||
|
||||
if (mover->IsCreature())
|
||||
{
|
||||
movementInfo.transport.guid = mover->m_movementInfo.transport.guid;
|
||||
movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ());
|
||||
movementInfo.transport.seat = mover->m_movementInfo.transport.seat;
|
||||
}
|
||||
}
|
||||
|
||||
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
|
||||
@@ -523,89 +633,19 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
|
||||
sScriptMgr->OnPlayerMove(plrMover, movementInfo, opcode);
|
||||
}
|
||||
|
||||
bool jumpopcode = false;
|
||||
if (opcode == MSG_MOVE_JUMP)
|
||||
if (movementInfo.GetMovementFlags() & MOVEMENTFLAG_MASK_MOVING_OR_TURN)
|
||||
{
|
||||
jumpopcode = true;
|
||||
if (plrMover && !sScriptMgr->AnticheatHandleDoubleJump(plrMover, mover))
|
||||
{
|
||||
plrMover->GetSession()->KickPlayer();
|
||||
return;
|
||||
}
|
||||
if (mover->IsStandState())
|
||||
mover->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
mover->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
}
|
||||
|
||||
/* start some hack detection */
|
||||
if (plrMover && !sScriptMgr->AnticheatCheckMovementInfo(plrMover, movementInfo, mover, jumpopcode))
|
||||
{
|
||||
plrMover->GetSession()->KickPlayer();
|
||||
return;
|
||||
}
|
||||
|
||||
/* process position-change */
|
||||
WorldPacket data(opcode, recvData.size());
|
||||
int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta;
|
||||
if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF)
|
||||
{
|
||||
LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
|
||||
movementInfo.time = getMSTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
movementInfo.time = (uint32) movementTime;
|
||||
}
|
||||
|
||||
movementInfo.guid = mover->GetGUID();
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
|
||||
mover->m_movementInfo = movementInfo;
|
||||
|
||||
// Some vehicles allow the passenger to turn by himself
|
||||
if (Vehicle* vehicle = mover->GetVehicle())
|
||||
{
|
||||
if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover))
|
||||
{
|
||||
if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING && movementInfo.pos.GetOrientation() != mover->GetOrientation())
|
||||
{
|
||||
mover->SetOrientation(movementInfo.pos.GetOrientation());
|
||||
mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mover->UpdatePosition(movementInfo.pos);
|
||||
|
||||
if (plrMover) // nothing is charmed, or player charmed
|
||||
{
|
||||
if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING)))
|
||||
plrMover->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
HandleMoverRelocation(movementInfo, mover);
|
||||
|
||||
if (plrMover && opcode != CMSG_MOVE_KNOCK_BACK_ACK)
|
||||
plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
|
||||
|
||||
if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()))
|
||||
if (!plrMover->GetBattleground() || !plrMover->GetBattleground()->HandlePlayerUnderMap(_player))
|
||||
{
|
||||
if (plrMover->IsAlive())
|
||||
{
|
||||
plrMover->SetPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS);
|
||||
plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
|
||||
// player can be alive if GM
|
||||
if (plrMover->IsAlive())
|
||||
plrMover->KillPlayer();
|
||||
}
|
||||
else if (!plrMover->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS))
|
||||
{
|
||||
GraveyardStruct const* grave = sGraveyard->GetClosestGraveyard(plrMover, plrMover->GetTeamId());
|
||||
if (grave)
|
||||
{
|
||||
plrMover->TeleportTo(grave->Map, grave->x, grave->y, grave->z, plrMover->GetOrientation());
|
||||
plrMover->Relocate(grave->x, grave->y, grave->z, plrMover->GetOrientation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData)
|
||||
@@ -762,11 +802,13 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
|
||||
{
|
||||
LOG_DEBUG("network", "CMSG_MOVE_KNOCK_BACK_ACK");
|
||||
|
||||
Unit* mover = _player->m_mover;
|
||||
|
||||
ObjectGuid guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
|
||||
// pussywizard: typical check for incomming movement packets
|
||||
if (!_player->m_mover || !_player->m_mover->IsInWorld() || _player->m_mover->IsDuringRemoveFromWorld() || guid != _player->m_mover->GetGUID())
|
||||
if (!mover || !mover->IsInWorld() || mover->IsDuringRemoveFromWorld() || guid != mover->GetGUID())
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
@@ -778,7 +820,10 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
_player->m_mover->m_movementInfo = movementInfo;
|
||||
mover->m_movementInfo = movementInfo;
|
||||
|
||||
if (mover->IsPlayer() && static_cast<Player*>(mover)->IsFreeFlying())
|
||||
mover->SetCanFly(true);
|
||||
|
||||
WorldPacket data(MSG_MOVE_KNOCK_BACK, 66);
|
||||
data << guid.WriteAsPacked();
|
||||
@@ -793,38 +838,6 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
|
||||
_player->SendMessageToSet(&data, false);
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveHoverAck(WorldPacket& recvData)
|
||||
{
|
||||
LOG_DEBUG("network", "CMSG_MOVE_HOVER_ACK");
|
||||
|
||||
ObjectGuid guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
|
||||
recvData.read_skip<uint32>(); // unk
|
||||
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
recvData.read_skip<uint32>(); // unk2
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData)
|
||||
{
|
||||
LOG_DEBUG("network", "CMSG_MOVE_WATER_WALK_ACK");
|
||||
|
||||
ObjectGuid guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
|
||||
recvData.read_skip<uint32>(); // unk
|
||||
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
recvData.read_skip<uint32>(); // unk2
|
||||
}
|
||||
|
||||
void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData)
|
||||
{
|
||||
if (!_player->IsAlive() || _player->IsInCombat())
|
||||
@@ -954,79 +967,36 @@ void WorldSession::ComputeNewClockDelta()
|
||||
|
||||
void WorldSession::HandleMoveRootAck(WorldPacket& recvData)
|
||||
{
|
||||
LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging((Opcodes)recvData.GetOpcode()));
|
||||
|
||||
ObjectGuid guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
|
||||
Unit* mover = _player->m_mover;
|
||||
if (!mover || guid != mover->GetGUID())
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 movementCounter;
|
||||
recvData >> movementCounter;
|
||||
|
||||
uint32 counter;
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
recvData >> counter;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
/* process position-change */
|
||||
int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta;
|
||||
if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF)
|
||||
{
|
||||
LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
|
||||
movementInfo.time = getMSTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
movementInfo.time = (uint32)movementTime;
|
||||
}
|
||||
|
||||
movementInfo.guid = mover->GetGUID();
|
||||
mover->m_movementInfo = movementInfo;
|
||||
mover->UpdatePosition(movementInfo.pos);
|
||||
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData)
|
||||
{
|
||||
ObjectGuid guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
|
||||
Unit* mover = _player->m_mover;
|
||||
if (!mover || guid != mover->GetGUID())
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
|
||||
if (mover->GetGUID() != guid)
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 movementCounter;
|
||||
recvData >> movementCounter;
|
||||
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
/* process position-change */
|
||||
int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta;
|
||||
if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF)
|
||||
if (recvData.GetOpcode() == CMSG_FORCE_MOVE_UNROOT_ACK) // unroot case
|
||||
{
|
||||
LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
|
||||
movementInfo.time = getMSTime();
|
||||
if (!mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT))
|
||||
return;
|
||||
}
|
||||
else
|
||||
else // root case
|
||||
{
|
||||
movementInfo.time = (uint32)movementTime;
|
||||
if (mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT))
|
||||
return;
|
||||
}
|
||||
|
||||
if (G3D::fuzzyEq(movementInfo.fallTime, 0.f))
|
||||
{
|
||||
movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FALLING);
|
||||
}
|
||||
|
||||
movementInfo.guid = mover->GetGUID();
|
||||
mover->m_movementInfo = movementInfo;
|
||||
mover->UpdatePosition(movementInfo.pos);
|
||||
if (!ProcessMovementInfo(movementInfo, mover, _player, recvData))
|
||||
return;
|
||||
|
||||
WorldPacket data(recvData.GetOpcode() == CMSG_FORCE_MOVE_UNROOT_ACK ? MSG_MOVE_UNROOT : MSG_MOVE_ROOT);
|
||||
data << guid.WriteAsPacked();
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
}
|
||||
|
||||
@@ -262,8 +262,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
|
||||
pet->ToCreature()->AI()->AttackStart(TargetUnit);
|
||||
|
||||
//10% chance to play special pet attack talk, else growl
|
||||
if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
|
||||
pet->SendPetTalk((uint32)PET_TALK_ATTACK);
|
||||
if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10))
|
||||
pet->SendPetActionSound(PET_ACTION_ATTACK);
|
||||
else
|
||||
{
|
||||
// 90% chance for pet and 100% chance for charmed creature
|
||||
@@ -297,8 +297,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
|
||||
if (pet->ToPet()->getPetType() == HUNTER_PET)
|
||||
GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_AS_DELETED);
|
||||
else
|
||||
{
|
||||
pet->SendPetDismissSound();
|
||||
//dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
|
||||
pet->setDeathState(DeathState::Corpse);
|
||||
}
|
||||
}
|
||||
else if (pet->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLLABLE_GUARDIAN))
|
||||
{
|
||||
@@ -413,8 +416,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
|
||||
|
||||
//10% chance to play special pet attack talk, else growl
|
||||
//actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
|
||||
if (pet->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10))
|
||||
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
|
||||
if (pet->IsPet() && (pet->ToPet()->getPetType() == SUMMON_PET) && (pet != unit_target) && roll_chance_i(10))
|
||||
pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL);
|
||||
else
|
||||
{
|
||||
pet->SendPetAIReaction(guid1);
|
||||
@@ -509,8 +512,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
|
||||
|
||||
pet->ToCreature()->AI()->AttackStart(TargetUnit);
|
||||
|
||||
if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
|
||||
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
|
||||
if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10))
|
||||
pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL);
|
||||
else
|
||||
pet->SendPetAIReaction(guid1);
|
||||
}
|
||||
@@ -558,8 +561,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
|
||||
|
||||
pet->GetMotionMaster()->MoveFollow(unit_target, PET_FOLLOW_DIST, rand_norm() * 2 * M_PI);
|
||||
|
||||
if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && urand(0, 100) < 10)
|
||||
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
|
||||
if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10))
|
||||
pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL);
|
||||
else
|
||||
{
|
||||
pet->SendPetAIReaction(guid1);
|
||||
@@ -1059,8 +1062,8 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
// 10% chance to play special pet attack talk, else growl
|
||||
// actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
|
||||
if (pet->getPetType() == SUMMON_PET && (urand(0, 100) < 10))
|
||||
pet->SendPetTalk(PET_TALK_SPECIAL_SPELL);
|
||||
if (pet->getPetType() == SUMMON_PET && roll_chance_i(10))
|
||||
pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL);
|
||||
else
|
||||
pet->SendPetAIReaction(guid);
|
||||
}
|
||||
|
||||
@@ -417,12 +417,12 @@ void Map::UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone)
|
||||
if (oldZone != MAP_INVALID_ZONE)
|
||||
{
|
||||
uint32& oldZoneCount = _zonePlayerCountMap[oldZone];
|
||||
if (!oldZoneCount)
|
||||
LOG_ERROR("maps", "A player left zone {} (went to {}) - but there were no players in the zone!", oldZone, newZone);
|
||||
else
|
||||
if (oldZoneCount)
|
||||
--oldZoneCount;
|
||||
}
|
||||
++_zonePlayerCountMap[newZone];
|
||||
|
||||
if (newZone != MAP_INVALID_ZONE)
|
||||
++_zonePlayerCountMap[newZone];
|
||||
}
|
||||
|
||||
void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
@@ -696,8 +696,8 @@ struct ResetNotifier
|
||||
|
||||
void Map::RemovePlayerFromMap(Player* player, bool remove)
|
||||
{
|
||||
// Before leaving map, update zone/area for stats
|
||||
player->UpdateZone(MAP_INVALID_ZONE, 0);
|
||||
UpdatePlayerZoneStats(player->GetZoneId(), MAP_INVALID_ZONE);
|
||||
|
||||
player->getHostileRefMgr().deleteReferences(true); // pussywizard: multithreading crashfix
|
||||
|
||||
player->RemoveFromWorld();
|
||||
@@ -725,8 +725,6 @@ void Map::RemoveFromMap(T* obj, bool remove)
|
||||
obj->RemoveFromWorld();
|
||||
|
||||
obj->RemoveFromGrid();
|
||||
if (obj->IsFarVisible())
|
||||
RemoveWorldObjectFromFarVisibleMap(obj);
|
||||
|
||||
obj->ResetMap();
|
||||
|
||||
@@ -2364,27 +2362,27 @@ void BattlegroundMap::RemoveAllPlayers()
|
||||
player->TeleportTo(player->GetEntryPoint());
|
||||
}
|
||||
|
||||
Corpse* Map::GetCorpse(ObjectGuid const guid)
|
||||
Corpse* Map::GetCorpse(ObjectGuid const& guid)
|
||||
{
|
||||
return _objectsStore.Find<Corpse>(guid);
|
||||
}
|
||||
|
||||
Creature* Map::GetCreature(ObjectGuid const guid)
|
||||
Creature* Map::GetCreature(ObjectGuid const& guid)
|
||||
{
|
||||
return _objectsStore.Find<Creature>(guid);
|
||||
}
|
||||
|
||||
GameObject* Map::GetGameObject(ObjectGuid const guid)
|
||||
GameObject* Map::GetGameObject(ObjectGuid const& guid)
|
||||
{
|
||||
return _objectsStore.Find<GameObject>(guid);
|
||||
}
|
||||
|
||||
Pet* Map::GetPet(ObjectGuid const guid)
|
||||
Pet* Map::GetPet(ObjectGuid const& guid)
|
||||
{
|
||||
return dynamic_cast<Pet*>(_objectsStore.Find<Creature>(guid));
|
||||
}
|
||||
|
||||
Transport* Map::GetTransport(ObjectGuid guid)
|
||||
Transport* Map::GetTransport(ObjectGuid const& guid)
|
||||
{
|
||||
if (guid.GetHigh() != HighGuid::Mo_Transport && guid.GetHigh() != HighGuid::Transport)
|
||||
return nullptr;
|
||||
@@ -2393,7 +2391,7 @@ Transport* Map::GetTransport(ObjectGuid guid)
|
||||
return go ? go->ToTransport() : nullptr;
|
||||
}
|
||||
|
||||
DynamicObject* Map::GetDynamicObject(ObjectGuid guid)
|
||||
DynamicObject* Map::GetDynamicObject(ObjectGuid const& guid)
|
||||
{
|
||||
return _objectsStore.Find<DynamicObject>(guid);
|
||||
}
|
||||
@@ -2685,7 +2683,7 @@ void Map::RemoveCorpse(Corpse* corpse)
|
||||
_corpseBones.erase(corpse);
|
||||
}
|
||||
|
||||
Corpse* Map::ConvertCorpseToBones(ObjectGuid const ownerGuid, bool insignia /*= false*/)
|
||||
Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= false*/)
|
||||
{
|
||||
Corpse* corpse = GetCorpseByPlayer(ownerGuid);
|
||||
if (!corpse)
|
||||
|
||||
@@ -338,12 +338,12 @@ public:
|
||||
GameObject* SummonGameObject(uint32 entry, Position const& pos, float rotation0 = 0.0f, float rotation1 = 0.0f, float rotation2 = 0.0f, float rotation3 = 0.0f, uint32 respawnTime = 100, bool checkTransport = true);
|
||||
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = nullptr);
|
||||
|
||||
Corpse* GetCorpse(ObjectGuid const guid);
|
||||
Creature* GetCreature(ObjectGuid const guid);
|
||||
GameObject* GetGameObject(ObjectGuid const guid);
|
||||
Transport* GetTransport(ObjectGuid const guid);
|
||||
DynamicObject* GetDynamicObject(ObjectGuid const guid);
|
||||
Pet* GetPet(ObjectGuid const guid);
|
||||
Corpse* GetCorpse(ObjectGuid const& guid);
|
||||
Creature* GetCreature(ObjectGuid const& guid);
|
||||
GameObject* GetGameObject(ObjectGuid const& guid);
|
||||
Transport* GetTransport(ObjectGuid const& guid);
|
||||
DynamicObject* GetDynamicObject(ObjectGuid const& guid);
|
||||
Pet* GetPet(ObjectGuid const& guid);
|
||||
|
||||
MapStoredObjectTypesContainer& GetObjectsStore() { return _objectsStore; }
|
||||
|
||||
@@ -438,7 +438,7 @@ public:
|
||||
void DeleteCorpseData();
|
||||
void AddCorpse(Corpse* corpse);
|
||||
void RemoveCorpse(Corpse* corpse);
|
||||
Corpse* ConvertCorpseToBones(ObjectGuid const ownerGuid, bool insignia = false);
|
||||
Corpse* ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia = false);
|
||||
void RemoveOldCorpses();
|
||||
|
||||
static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId);
|
||||
@@ -514,6 +514,14 @@ public:
|
||||
void RemoveWorldObjectFromZoneWideVisibleMap(uint32 zoneId, WorldObject* obj);
|
||||
ZoneWideVisibleWorldObjectsSet const* GetZoneWideVisibleWorldObjectsForZone(uint32 zoneId) const;
|
||||
|
||||
[[nodiscard]] uint32 GetPlayerCountInZone(uint32 zoneId) const
|
||||
{
|
||||
if (auto const& it = _zonePlayerCountMap.find(zoneId); it != _zonePlayerCountMap.end())
|
||||
return it->second;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
template<class T> void InitializeObject(T* obj);
|
||||
|
||||
@@ -448,31 +448,45 @@ void TransportMgr::SpawnContinentTransports()
|
||||
LOG_INFO("server.loading", ">> Spawned {} continent motion transports in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
// Preloads Deeprun Tram to fix issues with Subway carts syncronization
|
||||
/// @todo: This is a temporary workaround. Consider removing TransportMgr::PreloadGridsFromQuery() as part of fix.
|
||||
/**
|
||||
Takenbacon: "In the long run the most likely ideal fix would be to always spawn all transport types (and thus loading their grid) on map creation"
|
||||
See https://github.com/azerothcore/azerothcore-wotlk/pull/23009 for more details.
|
||||
*/
|
||||
PreloadGridsFromQuery("SELECT map, position_x, position_y FROM gameobject g JOIN gameobject_template t ON g.id = t.entry WHERE t.type = 11 AND g.map = 369", count);
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING))
|
||||
{
|
||||
// pussywizard: preload grids for continent static transports
|
||||
QueryResult result2 = WorldDatabase.Query("SELECT map, position_x, position_y FROM gameobject g JOIN gameobject_template t ON g.id = t.entry WHERE t.type = 11");
|
||||
PreloadGridsFromQuery("SELECT map, position_x, position_y FROM gameobject g JOIN gameobject_template t ON g.id = t.entry WHERE t.type = 11 AND g.map != 369", count);
|
||||
LOG_INFO("server.loading", ">> Preloaded grids for {} continent static transports in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
}
|
||||
|
||||
if (result2)
|
||||
void TransportMgr::PreloadGridsFromQuery(std::string const& query, uint32& count)
|
||||
{
|
||||
if (QueryResult result = WorldDatabase.Query(query))
|
||||
{
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result2->Fetch();
|
||||
uint16 mapId = fields[0].Get<uint16>();
|
||||
float x = fields[1].Get<float>();
|
||||
float y = fields[2].Get<float>();
|
||||
Field* fields = result->Fetch();
|
||||
uint16 mapId = fields[0].Get<uint16>();
|
||||
float x = fields[1].Get<float>();
|
||||
float y = fields[2].Get<float>();
|
||||
|
||||
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
|
||||
if (mapEntry && !mapEntry->Instanceable())
|
||||
if (MapEntry const* mapEntry = sMapStore.LookupEntry(mapId))
|
||||
{
|
||||
if (!mapEntry->Instanceable())
|
||||
{
|
||||
if (Map* map = sMapMgr->CreateBaseMap(mapId))
|
||||
{
|
||||
map->LoadGrid(x, y);
|
||||
++count;
|
||||
}
|
||||
} while (result2->NextRow());
|
||||
}
|
||||
|
||||
LOG_INFO("server.loading", ">> Preloaded grids for {} continent static transports in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
}
|
||||
} while (result->NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,8 @@ private:
|
||||
TransportInstanceMap _instanceTransports;
|
||||
|
||||
TransportAnimationContainer _transportAnimations;
|
||||
|
||||
void PreloadGridsFromQuery(std::string const& query, uint32& count);
|
||||
};
|
||||
|
||||
#define sTransportMgr TransportMgr::instance()
|
||||
|
||||
@@ -978,7 +978,8 @@ enum AcoreStrings
|
||||
LANG_GUILD_INFO_EXTRA_INFO = 1183,
|
||||
LANG_GUILD_INFO_RANKS = 1184,
|
||||
LANG_GUILD_INFO_RANKS_LIST = 1185,
|
||||
// Room for more level 3 1186-1198 not used
|
||||
LANG_COMMAND_BEASTMASTER_MODE = 1186,
|
||||
// Room for more level 3 1187-1198 not used
|
||||
|
||||
// Debug commands
|
||||
LANG_DO_NOT_USE_6X_DEBUG_AREATRIGGER_LEFT = 1999,
|
||||
|
||||
@@ -387,6 +387,7 @@ void MotionMaster::MoveBackwards(Unit* target, float dist)
|
||||
|
||||
Movement::MoveSplineInit init(_owner);
|
||||
init.MoveTo(point.x, point.y, point.z, false);
|
||||
init.SetWalk(true);
|
||||
init.SetFacing(target);
|
||||
init.SetOrientationInversed();
|
||||
init.Launch();
|
||||
@@ -469,7 +470,7 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo
|
||||
*
|
||||
* For transition movement between the ground and the air, use MoveLand or MoveTakeoff instead.
|
||||
*/
|
||||
void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generatePath, bool forceDestination, MovementSlot slot, float orientation /* = 0.0f*/)
|
||||
void MotionMaster::MovePoint(uint32 id, float x, float y, float z, ForcedMovement forcedMovement, float speed, float orientation, bool generatePath, bool forceDestination, MovementSlot slot)
|
||||
{
|
||||
if (_owner->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
return;
|
||||
@@ -477,16 +478,16 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generate
|
||||
if (_owner->IsPlayer())
|
||||
{
|
||||
LOG_DEBUG("movement.motionmaster", "Player ({}) targeted point (Id: {} X: {} Y: {} Z: {})", _owner->GetGUID().ToString(), id, x, y, z);
|
||||
Mutate(new PointMovementGenerator<Player>(id, x, y, z, 0.0f, orientation, nullptr, generatePath, forceDestination), slot);
|
||||
Mutate(new PointMovementGenerator<Player>(id, x, y, z, forcedMovement, speed, orientation, nullptr, generatePath, forceDestination), slot);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("movement.motionmaster", "Creature ({}) targeted point (ID: {} X: {} Y: {} Z: {})", _owner->GetGUID().ToString(), id, x, y, z);
|
||||
Mutate(new PointMovementGenerator<Creature>(id, x, y, z, 0.0f, orientation, nullptr, generatePath, forceDestination), slot);
|
||||
Mutate(new PointMovementGenerator<Creature>(id, x, y, z, forcedMovement, speed, orientation, nullptr, generatePath, forceDestination), slot);
|
||||
}
|
||||
}
|
||||
|
||||
void MotionMaster::MoveSplinePath(Movement::PointsArray* path)
|
||||
void MotionMaster::MoveSplinePath(Movement::PointsArray* path, ForcedMovement forcedMovement)
|
||||
{
|
||||
// Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE
|
||||
if (_owner->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
@@ -494,15 +495,15 @@ void MotionMaster::MoveSplinePath(Movement::PointsArray* path)
|
||||
|
||||
if (_owner->IsPlayer())
|
||||
{
|
||||
Mutate(new EscortMovementGenerator<Player>(path), MOTION_SLOT_ACTIVE);
|
||||
Mutate(new EscortMovementGenerator<Player>(forcedMovement, path), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mutate(new EscortMovementGenerator<Creature>(path), MOTION_SLOT_ACTIVE);
|
||||
Mutate(new EscortMovementGenerator<Creature>(forcedMovement, path), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void MotionMaster::MoveSplinePath(uint32 path_id)
|
||||
void MotionMaster::MoveSplinePath(uint32 path_id, ForcedMovement forcedMovement)
|
||||
{
|
||||
// convert the path id to a Movement::PointsArray*
|
||||
Movement::PointsArray* points = new Movement::PointsArray();
|
||||
@@ -514,7 +515,7 @@ void MotionMaster::MoveSplinePath(uint32 path_id)
|
||||
}
|
||||
|
||||
// pass the new PointsArray* to the appropriate MoveSplinePath function
|
||||
MoveSplinePath(points);
|
||||
MoveSplinePath(points, forcedMovement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -539,8 +540,8 @@ void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed /* = 0.0
|
||||
}
|
||||
|
||||
init.SetAnimation(Movement::ToGround);
|
||||
init.Launch();
|
||||
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
|
||||
|
||||
Mutate(new EffectMovementGenerator(init, id), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,16 +570,12 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed /* =
|
||||
init.MoveTo(x, y, z);
|
||||
|
||||
if (speed > 0.0f)
|
||||
{
|
||||
init.SetVelocity(speed);
|
||||
}
|
||||
|
||||
if (!skipAnimation)
|
||||
{
|
||||
init.SetAnimation(Movement::ToFly);
|
||||
}
|
||||
init.Launch();
|
||||
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
|
||||
|
||||
Mutate(new EffectMovementGenerator(init, id), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -612,8 +609,8 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa
|
||||
init.SetParabolic(max_height, 0);
|
||||
init.SetOrientationFixed(true);
|
||||
init.SetVelocity(speedXY);
|
||||
init.Launch();
|
||||
Mutate(new EffectMovementGenerator(0), MOTION_SLOT_CONTROLLED);
|
||||
|
||||
Mutate(new EffectMovementGenerator(init, 0), MOTION_SLOT_CONTROLLED);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -652,8 +649,8 @@ void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float spee
|
||||
init.SetVelocity(speedXY);
|
||||
if (target)
|
||||
init.SetFacing(target);
|
||||
init.Launch();
|
||||
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
|
||||
|
||||
Mutate(new EffectMovementGenerator(init, id), MOTION_SLOT_CONTROLLED);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -695,8 +692,8 @@ void MotionMaster::MoveFall(uint32 id /*=0*/, bool addFlagForNPC)
|
||||
Movement::MoveSplineInit init(_owner);
|
||||
init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz + _owner->GetHoverHeight());
|
||||
init.SetFall();
|
||||
init.Launch();
|
||||
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
|
||||
|
||||
Mutate(new EffectMovementGenerator(init, id), MOTION_SLOT_CONTROLLED);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -713,12 +710,12 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id,
|
||||
if (_owner->IsPlayer())
|
||||
{
|
||||
LOG_DEBUG("movement.motionmaster", "Player ({}) charge point (X: {} Y: {} Z: {})", _owner->GetGUID().ToString(), x, y, z);
|
||||
Mutate(new PointMovementGenerator<Player>(id, x, y, z, speed, orientation, path, generatePath, generatePath, targetGUID), MOTION_SLOT_CONTROLLED);
|
||||
Mutate(new PointMovementGenerator<Player>(id, x, y, z, FORCED_MOVEMENT_NONE, speed, orientation, path, generatePath, generatePath, targetGUID), MOTION_SLOT_CONTROLLED);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("movement.motionmaster", "Creature ({}) charge point (X: {} Y: {} Z: {})", _owner->GetGUID().ToString(), x, y, z);
|
||||
Mutate(new PointMovementGenerator<Creature>(id, x, y, z, speed, orientation, path, generatePath, generatePath, targetGUID), MOTION_SLOT_CONTROLLED);
|
||||
Mutate(new PointMovementGenerator<Creature>(id, x, y, z, FORCED_MOVEMENT_NONE, speed, orientation, path, generatePath, generatePath, targetGUID), MOTION_SLOT_CONTROLLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,15 @@ enum RotateDirection
|
||||
ROTATE_DIRECTION_RIGHT
|
||||
};
|
||||
|
||||
enum ForcedMovement
|
||||
{
|
||||
FORCED_MOVEMENT_NONE = 0,
|
||||
FORCED_MOVEMENT_WALK = 1,
|
||||
FORCED_MOVEMENT_RUN = 2,
|
||||
|
||||
FORCED_MOVEMENT_MAX
|
||||
};
|
||||
|
||||
struct ChaseRange
|
||||
{
|
||||
ChaseRange(float range);
|
||||
@@ -210,11 +219,11 @@ public:
|
||||
void MoveForwards(Unit* target, float dist);
|
||||
void MoveConfused();
|
||||
void MoveFleeing(Unit* enemy, uint32 time = 0);
|
||||
void MovePoint(uint32 id, const Position& pos, bool generatePath = true, bool forceDestination = true)
|
||||
{ MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath, forceDestination, MOTION_SLOT_ACTIVE, pos.GetOrientation()); }
|
||||
void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true, bool forceDestination = true, MovementSlot slot = MOTION_SLOT_ACTIVE, float orientation = 0.0f);
|
||||
void MoveSplinePath(Movement::PointsArray* path);
|
||||
void MoveSplinePath(uint32 path_id);
|
||||
void MovePoint(uint32 id, const Position& pos, ForcedMovement forcedMovement = FORCED_MOVEMENT_NONE, float speed = 0.f, bool generatePath = true, bool forceDestination = true)
|
||||
{ MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, forcedMovement, speed, pos.GetOrientation(), generatePath, forceDestination, MOTION_SLOT_ACTIVE); }
|
||||
void MovePoint(uint32 id, float x, float y, float z, ForcedMovement forcedMovement = FORCED_MOVEMENT_NONE, float speed = 0.f, float orientation = 0.0f, bool generatePath = true, bool forceDestination = true, MovementSlot slot = MOTION_SLOT_ACTIVE);
|
||||
void MoveSplinePath(Movement::PointsArray* path, ForcedMovement forcedMovement = FORCED_MOVEMENT_NONE);
|
||||
void MoveSplinePath(uint32 path_id, ForcedMovement forcedMovement = FORCED_MOVEMENT_NONE);
|
||||
|
||||
// These two movement types should only be used with creatures having landing/takeoff animations
|
||||
void MoveLand(uint32 id, Position const& pos, float speed = 0.0f);
|
||||
|
||||
@@ -146,6 +146,7 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff)
|
||||
float z = i_waypoints[i_nextMove][2];
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.MoveTo(x, y, z, true);
|
||||
init.SetWalk(true);
|
||||
init.Launch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@ void EscortMovementGenerator<T>::DoInitialize(T* unit)
|
||||
else if (m_precomputedPath.size())
|
||||
init.MovebyPath(m_precomputedPath);
|
||||
|
||||
if (_forcedMovement == FORCED_MOVEMENT_WALK)
|
||||
init.SetWalk(true);
|
||||
else if (_forcedMovement == FORCED_MOVEMENT_RUN)
|
||||
init.SetWalk(false);
|
||||
|
||||
init.Launch();
|
||||
|
||||
_splineId = unit->movespline->GetId();
|
||||
@@ -79,6 +84,11 @@ bool EscortMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
||||
init.MoveTo(m_precomputedPath[1].x, m_precomputedPath[1].y, m_precomputedPath[1].z, true);
|
||||
}
|
||||
|
||||
if (_forcedMovement == FORCED_MOVEMENT_WALK)
|
||||
init.SetWalk(true);
|
||||
else if (_forcedMovement == FORCED_MOVEMENT_RUN)
|
||||
init.SetWalk(false);
|
||||
|
||||
init.Launch();
|
||||
// Xinef: Override spline Id on recalculate launch
|
||||
_splineId = unit->movespline->GetId();
|
||||
|
||||
@@ -24,7 +24,7 @@ template<class T>
|
||||
class EscortMovementGenerator : public MovementGeneratorMedium< T, EscortMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
EscortMovementGenerator(Movement::PointsArray* _path = nullptr) : i_recalculateSpeed(false)
|
||||
EscortMovementGenerator(ForcedMovement forcedMovement, Movement::PointsArray* _path = nullptr) : i_recalculateSpeed(false), _forcedMovement(forcedMovement)
|
||||
{
|
||||
if (_path)
|
||||
m_precomputedPath = *_path;
|
||||
@@ -46,6 +46,7 @@ private:
|
||||
Movement::PointsArray m_precomputedPath;
|
||||
|
||||
uint32 _splineId;
|
||||
ForcedMovement _forcedMovement;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,8 +31,6 @@ void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner)
|
||||
owner->ClearUnitState(UNIT_STATE_EVADE);
|
||||
if (arrived)
|
||||
{
|
||||
// Xinef: npc run by default
|
||||
//owner->SetWalk(true);
|
||||
owner->LoadCreaturesAddon(true);
|
||||
owner->AI()->JustReachedHome();
|
||||
}
|
||||
|
||||
@@ -88,6 +88,11 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
|
||||
if (speed > 0.0f)
|
||||
init.SetVelocity(speed);
|
||||
|
||||
if (_forcedMovement == FORCED_MOVEMENT_WALK)
|
||||
init.SetWalk(true);
|
||||
else if (_forcedMovement == FORCED_MOVEMENT_RUN)
|
||||
init.SetWalk(false);
|
||||
|
||||
if (i_orientation > 0.0f)
|
||||
{
|
||||
init.SetFacing(i_orientation);
|
||||
@@ -146,6 +151,11 @@ bool PointMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
||||
if (speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit
|
||||
init.SetVelocity(speed);
|
||||
|
||||
if (_forcedMovement == FORCED_MOVEMENT_WALK)
|
||||
init.SetWalk(true);
|
||||
else if (_forcedMovement == FORCED_MOVEMENT_RUN)
|
||||
init.SetWalk(false);
|
||||
|
||||
if (i_orientation > 0.0f)
|
||||
{
|
||||
init.SetFacing(i_orientation);
|
||||
@@ -232,6 +242,11 @@ bool EffectMovementGenerator::Update(Unit* unit, uint32)
|
||||
return !unit->movespline->Finalized();
|
||||
}
|
||||
|
||||
void EffectMovementGenerator::Initialize(Unit*)
|
||||
{
|
||||
i_spline.Launch();
|
||||
}
|
||||
|
||||
void EffectMovementGenerator::Finalize(Unit* unit)
|
||||
{
|
||||
if (!unit->IsCreature())
|
||||
|
||||
@@ -20,15 +20,16 @@
|
||||
|
||||
#include "Creature.h"
|
||||
#include "MovementGenerator.h"
|
||||
#include "MoveSplineInit.h"
|
||||
|
||||
template<class T>
|
||||
class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
PointMovementGenerator(uint32 _id, float _x, float _y, float _z, float _speed = 0.0f, float orientation = 0.0f, const Movement::PointsArray* _path = nullptr,
|
||||
bool generatePath = false, bool forceDestination = false, ObjectGuid chargeTargetGUID = ObjectGuid::Empty, bool orientationInversed = false)
|
||||
: id(_id), i_x(_x), i_y(_y), i_z(_z), speed(_speed), i_orientation(orientation), _generatePath(generatePath), _forceDestination(forceDestination),
|
||||
_chargeTargetGUID(chargeTargetGUID), _orientationInversed(orientationInversed)
|
||||
PointMovementGenerator(uint32 _id, float _x, float _y, float _z, ForcedMovement forcedMovement, float _speed = 0.0f, float orientation = 0.0f, const Movement::PointsArray* _path = nullptr,
|
||||
bool generatePath = false, bool forceDestination = false, ObjectGuid chargeTargetGUID = ObjectGuid::Empty, bool reverseOrientation = false, ObjectGuid facingTargetGuid = ObjectGuid())
|
||||
: id(_id), i_x(_x), i_y(_y), i_z(_z), speed(_speed), i_orientation(orientation), _generatePath(generatePath), _forceDestination(forceDestination), _reverseOrientation(reverseOrientation),
|
||||
_chargeTargetGUID(chargeTargetGUID), _forcedMovement(forcedMovement), _facingTargetGuid(facingTargetGuid)
|
||||
{
|
||||
if (_path)
|
||||
m_precomputedPath = *_path;
|
||||
@@ -55,17 +56,17 @@ private:
|
||||
Movement::PointsArray m_precomputedPath;
|
||||
bool _generatePath;
|
||||
bool _forceDestination;
|
||||
bool _reverseOrientation;
|
||||
ObjectGuid _chargeTargetGUID;
|
||||
/// Added by mod-playerbots
|
||||
bool _orientationInversed;
|
||||
/// End added
|
||||
ForcedMovement _forcedMovement;
|
||||
ObjectGuid _facingTargetGuid;
|
||||
};
|
||||
|
||||
class AssistanceMovementGenerator : public PointMovementGenerator<Creature>
|
||||
{
|
||||
public:
|
||||
AssistanceMovementGenerator(float _x, float _y, float _z) :
|
||||
PointMovementGenerator<Creature>(0, _x, _y, _z) {}
|
||||
PointMovementGenerator<Creature>(0, _x, _y, _z, FORCED_MOVEMENT_NONE) {}
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_MOTION_TYPE; }
|
||||
void Finalize(Unit*);
|
||||
@@ -75,14 +76,15 @@ public:
|
||||
class EffectMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
explicit EffectMovementGenerator(uint32 Id) : m_Id(Id) {}
|
||||
void Initialize(Unit*) override {}
|
||||
explicit EffectMovementGenerator(Movement::MoveSplineInit& spline, uint32 Id) : m_Id(Id), i_spline(spline) {}
|
||||
void Initialize(Unit*) override;
|
||||
void Finalize(Unit*) override;
|
||||
void Reset(Unit*) override {}
|
||||
bool Update(Unit*, uint32) override;
|
||||
MovementGeneratorType GetMovementGeneratorType() override { return EFFECT_MOTION_TYPE; }
|
||||
private:
|
||||
uint32 m_Id;
|
||||
Movement::MoveSplineInit i_spline;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -51,7 +51,21 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
|
||||
creature->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
Movement::MoveSplineInit init(creature);
|
||||
init.MoveTo(_currDestPosition.GetPositionX(), _currDestPosition.GetPositionY(), _currDestPosition.GetPositionZ());
|
||||
init.SetWalk(true);
|
||||
|
||||
bool walk = true;
|
||||
switch (creature->GetMovementTemplate().GetRandom())
|
||||
{
|
||||
case CreatureRandomMovementType::CanRun:
|
||||
walk = creature->IsWalking();
|
||||
break;
|
||||
case CreatureRandomMovementType::AlwaysRun:
|
||||
walk = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
init.SetWalk(walk);
|
||||
init.Launch();
|
||||
if (creature->GetFormation() && creature->GetFormation()->GetLeader() == creature)
|
||||
creature->GetFormation()->LeaderMoveTo(_currDestPosition.GetPositionX(), _currDestPosition.GetPositionY(), _currDestPosition.GetPositionZ(), 0);
|
||||
@@ -270,7 +284,6 @@ template<>
|
||||
void RandomMovementGenerator<Creature>::DoFinalize(Creature* creature)
|
||||
{
|
||||
creature->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
creature->SetWalk(false);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@@ -365,7 +365,6 @@ void ChaseMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
_lastTargetPosition.reset();
|
||||
i_recheckDistance.Reset(0);
|
||||
i_leashExtensionTimer.Reset(owner->GetAttackTime(BASE_ATTACK));
|
||||
owner->SetWalk(false);
|
||||
owner->AddUnitState(UNIT_STATE_CHASE);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ void WaypointMovementGenerator<Creature>::DoInitialize(Creature* creature)
|
||||
void WaypointMovementGenerator<Creature>::DoFinalize(Creature* creature)
|
||||
{
|
||||
creature->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
creature->SetWalk(false);
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::DoReset(Creature* creature)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "Unit.h"
|
||||
#include "Vehicle.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace Movement
|
||||
{
|
||||
@@ -103,7 +104,13 @@ namespace Movement
|
||||
|
||||
bool isOrientationOnly = args.path.size() == 2 && args.path[0] == args.path[1];
|
||||
|
||||
if ((moveFlags & MOVEMENTFLAG_ROOT) || isOrientationOnly)
|
||||
if (moveFlags & MOVEMENTFLAG_ROOT) // This case should essentially never occur - hence the trace logging - hints to issues elsewhere
|
||||
{
|
||||
LOG_TRACE("movement", "Invalid movement during root. Entry: {} IsImmobilized {}, moveflags {}", unit->GetEntry(), unit->IsImmobilizedState() ? "true" : "false", moveFlags);
|
||||
moveFlags &= ~MOVEMENTFLAG_MASK_MOVING;
|
||||
}
|
||||
|
||||
if (isOrientationOnly)
|
||||
moveFlags &= ~MOVEMENTFLAG_MASK_MOVING;
|
||||
|
||||
if (!args.HasVelocity)
|
||||
|
||||
@@ -442,7 +442,7 @@ void Map::ScriptsProcess()
|
||||
if (step.script->MoveTo.TravelTime != 0)
|
||||
{
|
||||
float speed = unit->GetDistance(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ) / ((float)step.script->MoveTo.TravelTime * 0.001f);
|
||||
unit->MonsterMoveWithSpeed(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, speed);
|
||||
unit->GetMotionMaster()->MovePoint(0, step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, FORCED_MOVEMENT_NONE, speed);
|
||||
}
|
||||
else
|
||||
unit->NearTeleportTo(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, unit->GetOrientation());
|
||||
@@ -757,7 +757,7 @@ void Map::ScriptsProcess()
|
||||
case SCRIPT_COMMAND_DESPAWN_SELF:
|
||||
// Target or source must be Creature.
|
||||
if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script, true))
|
||||
cSource->DespawnOrUnsummon(step.script->DespawnSelf.DespawnDelay);
|
||||
cSource->DespawnOrUnsummon(Milliseconds(step.script->DespawnSelf.DespawnDelay));
|
||||
break;
|
||||
|
||||
case SCRIPT_COMMAND_LOAD_PATH:
|
||||
@@ -880,7 +880,6 @@ void Map::ScriptsProcess()
|
||||
if (!cSource->IsAlive())
|
||||
return;
|
||||
|
||||
cSource->GetMotionMaster()->MovementExpired();
|
||||
cSource->GetMotionMaster()->MoveIdle();
|
||||
|
||||
switch (step.script->Movement.MovementType)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define AllPackets_h__
|
||||
|
||||
#include "BankPackets.h"
|
||||
#include "CalendarPackets.h"
|
||||
#include "CharacterPackets.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "CombatLogPackets.h"
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CalendarPackets.h"
|
||||
|
||||
void WorldPackets::Calendar::GetEvent::Read()
|
||||
{
|
||||
_worldPacket >> EventId;
|
||||
}
|
||||
|
||||
void WorldPackets::Calendar::GuildFilter::Read()
|
||||
{
|
||||
_worldPacket >> MinimumLevel;
|
||||
_worldPacket >> MaximumLevel;
|
||||
_worldPacket >> MinimumRank;
|
||||
}
|
||||
|
||||
void WorldPackets::Calendar::ArenaTeam::Read()
|
||||
{
|
||||
_worldPacket >> ArenaTeamId;
|
||||
}
|
||||
|
||||
void WorldPackets::Calendar::CalendarComplain::Read()
|
||||
{
|
||||
_worldPacket >> EventId;
|
||||
_worldPacket >> ComplainGuid;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CalendarPackets_h__
|
||||
#define CalendarPackets_h__
|
||||
|
||||
#include "Guild.h"
|
||||
#include "Packet.h"
|
||||
|
||||
namespace WorldPackets
|
||||
{
|
||||
namespace Calendar
|
||||
{
|
||||
class GetEvent final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
GetEvent(WorldPacket&& packet) : ClientPacket(CMSG_CALENDAR_GET_EVENT, std::move(packet)) {}
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint64 EventId = 0;
|
||||
};
|
||||
|
||||
class GuildFilter final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
GuildFilter(WorldPacket&& packet) : ClientPacket(CMSG_CALENDAR_GUILD_FILTER, std::move(packet)) {}
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint32 MinimumLevel = 1;
|
||||
uint32 MaximumLevel = 1;
|
||||
uint32 MinimumRank = GR_GUILDMASTER;
|
||||
};
|
||||
|
||||
class ArenaTeam final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
ArenaTeam(WorldPacket&& packet) : ClientPacket(CMSG_CALENDAR_ARENA_TEAM, std::move(packet)) {}
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint32 ArenaTeamId = 0;
|
||||
};
|
||||
|
||||
class CalendarComplain final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
CalendarComplain(WorldPacket&& packet) : ClientPacket(CMSG_CALENDAR_COMPLAIN, std::move(packet)) {}
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint64 EventId = 0;
|
||||
ObjectGuid ComplainGuid;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CalendarPackets_h__
|
||||
@@ -140,3 +140,31 @@ WorldPacket const* WorldPackets::Misc::UITime::Write()
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
void WorldPackets::Misc::Complain::Read()
|
||||
{
|
||||
_worldPacket >> SpamType; // 0 - mail, 1 - chat
|
||||
_worldPacket >> SpammerGuid;
|
||||
switch (SpamType)
|
||||
{
|
||||
case 0:
|
||||
_worldPacket >> Unk1; // const 0
|
||||
_worldPacket >> Unk2; // probably mail id
|
||||
_worldPacket >> Unk3; // const 0
|
||||
break;
|
||||
case 1:
|
||||
_worldPacket >> Unk1; // probably language
|
||||
_worldPacket >> Unk2; // message type?
|
||||
_worldPacket >> Unk3; // probably channel id
|
||||
_worldPacket >> Unk4; // unk random value
|
||||
_worldPacket >> Description; // spam description string (messagetype, channel name, player name, message)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Misc::ComplainResult::Write()
|
||||
{
|
||||
_worldPacket << Unk;
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
@@ -210,6 +210,32 @@ namespace WorldPackets
|
||||
|
||||
uint32 Time = 0;
|
||||
};
|
||||
|
||||
class Complain final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
Complain(WorldPacket&& packet) : ClientPacket(CMSG_COMPLAIN, std::move(packet)) {}
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint8 SpamType = 0; // 0 - mail, 1 - chat
|
||||
ObjectGuid SpammerGuid;
|
||||
uint32 Unk1 = 0;
|
||||
uint32 Unk2 = 0;
|
||||
uint32 Unk3 = 0;
|
||||
uint32 Unk4 = 0;
|
||||
std::string Description = "";
|
||||
};
|
||||
|
||||
class ComplainResult final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
ComplainResult() : ServerPacket(SMSG_COMPLAIN_RESULT, 1) {}
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint8 Unk = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,3 +50,19 @@ WorldPacket const* WorldPackets::Pet::PetUnlearnedSpell::Write()
|
||||
_worldPacket << uint32(SpellID);
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Pet::PetActionSound::Write()
|
||||
{
|
||||
_worldPacket << UnitGUID;
|
||||
_worldPacket << int32(Action);
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Pet::PetDismissSound::Write()
|
||||
{
|
||||
_worldPacket << int32(ModelId);
|
||||
_worldPacket << float(ModelPosition.x);
|
||||
_worldPacket << float(ModelPosition.y);
|
||||
_worldPacket << float(ModelPosition.z);
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "ObjectGuid.h"
|
||||
#include "Packet.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace WorldPackets
|
||||
{
|
||||
@@ -94,6 +95,30 @@ namespace WorldPackets
|
||||
|
||||
void Read() override { }
|
||||
};
|
||||
|
||||
class PetActionSound final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
PetActionSound(ObjectGuid unitGUID, int32 action)
|
||||
: ServerPacket(SMSG_PET_ACTION_SOUND, 8 + 4), UnitGUID(unitGUID), Action(action) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
ObjectGuid UnitGUID;
|
||||
int32 Action = 0;
|
||||
};
|
||||
|
||||
class PetDismissSound final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
PetDismissSound(int32 modelId, G3D::Vector3 modelPosition)
|
||||
: ServerPacket(SMSG_PET_DISMISS_SOUND, 4 + 12), ModelId(modelId), ModelPosition(modelPosition) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
int32 ModelId = 0;
|
||||
G3D::Vector3 ModelPosition;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@ void OpcodeTable::Initialize()
|
||||
/*0x0E8*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_MOVE_ROOT, STATUS_NEVER);
|
||||
/*0x0E9*/ DEFINE_HANDLER(CMSG_FORCE_MOVE_ROOT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck );
|
||||
/*0x0EA*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_MOVE_UNROOT, STATUS_NEVER);
|
||||
/*0x0EB*/ DEFINE_HANDLER(CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveUnRootAck );
|
||||
/*0x0EB*/ DEFINE_HANDLER(CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck );
|
||||
/*0x0EC*/ DEFINE_HANDLER(MSG_MOVE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x0ED*/ DEFINE_HANDLER(MSG_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x0EE*/ DEFINE_HANDLER(MSG_MOVE_HEARTBEAT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
|
||||
@@ -374,7 +374,7 @@ void OpcodeTable::Initialize()
|
||||
/*0x0F3*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_NORMAL_FALL, STATUS_NEVER);
|
||||
/*0x0F4*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_HOVER, STATUS_NEVER);
|
||||
/*0x0F5*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UNSET_HOVER, STATUS_NEVER);
|
||||
/*0x0F6*/ DEFINE_HANDLER(CMSG_MOVE_HOVER_ACK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveHoverAck );
|
||||
/*0x0F6*/ DEFINE_HANDLER(CMSG_MOVE_HOVER_ACK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveFlagChangeOpcode );
|
||||
/*0x0F7*/ DEFINE_SERVER_OPCODE_HANDLER(MSG_MOVE_HOVER, STATUS_NEVER);
|
||||
/*0x0F8*/ DEFINE_HANDLER(CMSG_TRIGGER_CINEMATIC_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x0F9*/ DEFINE_HANDLER(CMSG_OPENING_CINEMATIC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
@@ -847,8 +847,8 @@ void OpcodeTable::Initialize()
|
||||
/*0x2CC*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_INSTANCE_INFO, STATUS_NEVER);
|
||||
/*0x2CD*/ DEFINE_HANDLER(CMSG_REQUEST_RAID_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode );
|
||||
/*0x2CE*/ DEFINE_HANDLER(CMSG_MOVE_TIME_SKIPPED, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveTimeSkippedOpcode );
|
||||
/*0x2CF*/ DEFINE_HANDLER(CMSG_MOVE_FEATHER_FALL_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleFeatherFallAck );
|
||||
/*0x2D0*/ DEFINE_HANDLER(CMSG_MOVE_WATER_WALK_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveWaterWalkAck );
|
||||
/*0x2CF*/ DEFINE_HANDLER(CMSG_MOVE_FEATHER_FALL_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveFlagChangeOpcode );
|
||||
/*0x2D0*/ DEFINE_HANDLER(CMSG_MOVE_WATER_WALK_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveFlagChangeOpcode );
|
||||
/*0x2D1*/ DEFINE_HANDLER(CMSG_MOVE_NOT_ACTIVE_MOVER, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveNotActiveMover );
|
||||
/*0x2D2*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PLAY_SOUND, STATUS_NEVER);
|
||||
/*0x2D3*/ DEFINE_HANDLER(CMSG_BATTLEFIELD_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldStatusOpcode );
|
||||
@@ -965,7 +965,7 @@ void OpcodeTable::Initialize()
|
||||
/*0x342*/ DEFINE_HANDLER(MSG_MOVE_STOP_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x343*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_CAN_FLY, STATUS_NEVER);
|
||||
/*0x344*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UNSET_CAN_FLY, STATUS_NEVER);
|
||||
/*0x345*/ DEFINE_HANDLER(CMSG_MOVE_SET_CAN_FLY_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSetCanFlyAckOpcode );
|
||||
/*0x345*/ DEFINE_HANDLER(CMSG_MOVE_SET_CAN_FLY_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveFlagChangeOpcode );
|
||||
/*0x346*/ DEFINE_HANDLER(CMSG_MOVE_SET_FLY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
|
||||
/*0x347*/ DEFINE_HANDLER(CMSG_SOCKET_GEMS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSocketOpcode );
|
||||
/*0x348*/ DEFINE_HANDLER(CMSG_ARENA_TEAM_CREATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
|
||||
@@ -137,6 +137,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 accountFlags, s
|
||||
_timeSyncClockDeltaQueue(6),
|
||||
_timeSyncClockDelta(0),
|
||||
_pendingTimeSyncRequests(),
|
||||
_orderCounter(0),
|
||||
_isBot(isBot)
|
||||
{
|
||||
memset(m_Tutorials, 0, sizeof(m_Tutorials));
|
||||
@@ -1543,6 +1544,12 @@ void WorldSession::InitializeSessionCallback(CharacterDatabaseQueryHolder const&
|
||||
SendTutorialsData();
|
||||
}
|
||||
|
||||
void WorldSession::SetPacketLogging(bool state)
|
||||
{
|
||||
if (m_Socket)
|
||||
m_Socket->SetPacketLogging(state);
|
||||
}
|
||||
|
||||
LockedQueue<WorldPacket*>& WorldSession::GetPacketQueue()
|
||||
{
|
||||
return _recvQueue;
|
||||
|
||||
@@ -150,6 +150,7 @@ namespace WorldPackets
|
||||
{
|
||||
class MinimapPingClient;
|
||||
class RandomRollClient;
|
||||
class Complain;
|
||||
}
|
||||
|
||||
namespace Pet
|
||||
@@ -189,6 +190,14 @@ namespace WorldPackets
|
||||
class ItemRefundInfo;
|
||||
class ItemRefund;
|
||||
}
|
||||
|
||||
namespace Calendar
|
||||
{
|
||||
class GetEvent;
|
||||
class GuildFilter;
|
||||
class ArenaTeam;
|
||||
class CalendarComplain;
|
||||
}
|
||||
}
|
||||
|
||||
enum AccountDataType
|
||||
@@ -398,6 +407,10 @@ public:
|
||||
|
||||
void ReadMovementInfo(WorldPacket& data, MovementInfo* mi);
|
||||
void WriteMovementInfo(WorldPacket* data, MovementInfo* mi);
|
||||
void SynchronizeMovement(MovementInfo& movementInfo);
|
||||
void HandleMoverRelocation(MovementInfo& movementInfo, Unit* mover);
|
||||
bool VerifyMovementInfo(MovementInfo const& movementInfo, Player* plrMover, Unit* mover, Opcodes opcode) const;
|
||||
bool ProcessMovementInfo(MovementInfo& movementInfo, Unit* mover, Player* plrMover, WorldPacket& recvData);
|
||||
|
||||
void SendPacket(WorldPacket const* packet);
|
||||
void SendPetNameInvalid(uint32 error, std::string const& name, DeclinedName* declinedName);
|
||||
@@ -602,6 +615,9 @@ public:
|
||||
void ResetTimeSync();
|
||||
void SendTimeSync();
|
||||
|
||||
// Movement packet order
|
||||
uint32 GetOrderCounter() const { return _orderCounter; }
|
||||
void IncrementOrderCounter() { ++_orderCounter; }
|
||||
public: // opcodes handlers
|
||||
void Handle_NULL(WorldPacket& null); // not used
|
||||
void Handle_EarlyProccess(WorldPacket& recvPacket); // just mark packets processed in WorldSocket::OnRead
|
||||
@@ -631,7 +647,6 @@ public: // opcodes handlers
|
||||
void HandlePlayedTime(WorldPackets::Character::PlayedTimeClient& packet);
|
||||
|
||||
// new
|
||||
void HandleMoveUnRootAck(WorldPacket& recvPacket);
|
||||
void HandleMoveRootAck(WorldPacket& recvPacket);
|
||||
|
||||
// new inspect
|
||||
@@ -640,11 +655,6 @@ public: // opcodes handlers
|
||||
// new party stats
|
||||
void HandleInspectHonorStatsOpcode(WorldPacket& recvPacket);
|
||||
|
||||
void HandleMoveWaterWalkAck(WorldPacket& recvPacket);
|
||||
void HandleFeatherFallAck(WorldPacket& recvData);
|
||||
|
||||
void HandleMoveHoverAck(WorldPacket& recvData);
|
||||
|
||||
void HandleMountSpecialAnimOpcode(WorldPacket& recvdata);
|
||||
|
||||
// character view
|
||||
@@ -989,7 +999,7 @@ public: // opcodes handlers
|
||||
void HandleFarSightOpcode(WorldPacket& recvData);
|
||||
void HandleSetDungeonDifficultyOpcode(WorldPacket& recvData);
|
||||
void HandleSetRaidDifficultyOpcode(WorldPacket& recvData);
|
||||
void HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData);
|
||||
void HandleMoveFlagChangeOpcode(WorldPacket& recvData);
|
||||
void HandleSetTitleOpcode(WorldPacket& recvData);
|
||||
void HandleRealmSplitOpcode(WorldPacket& recvData);
|
||||
void HandleTimeSyncResp(WorldPacket& recvData);
|
||||
@@ -1053,7 +1063,7 @@ public: // opcodes handlers
|
||||
void HandleAreaSpiritHealerQueueOpcode(WorldPacket& recvData);
|
||||
void HandleCancelMountAuraOpcode(WorldPacket& recvData);
|
||||
void HandleSelfResOpcode(WorldPacket& recvData);
|
||||
void HandleComplainOpcode(WorldPacket& recvData);
|
||||
void HandleComplainOpcode(WorldPackets::Misc::Complain& packet);
|
||||
void HandleRequestPetInfo(WorldPackets::Pet::RequestPetInfo& packet);
|
||||
|
||||
// Socket gem
|
||||
@@ -1090,9 +1100,9 @@ public: // opcodes handlers
|
||||
|
||||
// Calendar
|
||||
void HandleCalendarGetCalendar(WorldPacket& recvData);
|
||||
void HandleCalendarGetEvent(WorldPacket& recvData);
|
||||
void HandleCalendarGuildFilter(WorldPacket& recvData);
|
||||
void HandleCalendarArenaTeam(WorldPacket& recvData);
|
||||
void HandleCalendarGetEvent(WorldPackets::Calendar::GetEvent& packet);
|
||||
void HandleCalendarGuildFilter(WorldPackets::Calendar::GuildFilter& packet);
|
||||
void HandleCalendarArenaTeam(WorldPackets::Calendar::ArenaTeam& packet);
|
||||
void HandleCalendarAddEvent(WorldPacket& recvData);
|
||||
void HandleCalendarUpdateEvent(WorldPacket& recvData);
|
||||
void HandleCalendarRemoveEvent(WorldPacket& recvData);
|
||||
@@ -1102,7 +1112,7 @@ public: // opcodes handlers
|
||||
void HandleCalendarEventRemoveInvite(WorldPacket& recvData);
|
||||
void HandleCalendarEventStatus(WorldPacket& recvData);
|
||||
void HandleCalendarEventModeratorStatus(WorldPacket& recvData);
|
||||
void HandleCalendarComplain(WorldPacket& recvData);
|
||||
void HandleCalendarComplain(WorldPackets::Calendar::CalendarComplain& packet);
|
||||
void HandleCalendarGetNumPending(WorldPacket& recvData);
|
||||
void HandleCalendarEventSignup(WorldPacket& recvData);
|
||||
|
||||
@@ -1149,6 +1159,8 @@ public: // opcodes handlers
|
||||
void InitializeSession();
|
||||
void InitializeSessionCallback(CharacterDatabaseQueryHolder const& realmHolder, uint32 clientCacheVersion);
|
||||
|
||||
void SetPacketLogging(bool state);
|
||||
|
||||
LockedQueue<WorldPacket*>& GetPacketQueue();
|
||||
|
||||
[[nodiscard]] bool IsBot() const
|
||||
@@ -1266,6 +1278,8 @@ private:
|
||||
uint32 _timeSyncNextCounter;
|
||||
uint32 _timeSyncTimer;
|
||||
|
||||
uint32 _orderCounter;
|
||||
|
||||
bool _isBot;
|
||||
|
||||
WorldSession(WorldSession const& right) = delete;
|
||||
|
||||
@@ -117,7 +117,7 @@ void EncryptableAndCompressiblePacket::CompressIfNeeded()
|
||||
}
|
||||
|
||||
WorldSocket::WorldSocket(tcp::socket&& socket)
|
||||
: Socket(std::move(socket)), _OverSpeedPings(0), _worldSession(nullptr), _authed(false), _sendBufferSize(4096)
|
||||
: Socket(std::move(socket)), _OverSpeedPings(0), _worldSession(nullptr), _authed(false), _sendBufferSize(4096), _loggingPackets(false)
|
||||
{
|
||||
Acore::Crypto::GetRandomBytes(_authSeed);
|
||||
_headerBuffer.Resize(sizeof(ClientPktHeader));
|
||||
@@ -406,7 +406,7 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
|
||||
WorldPacket packet(opcode, std::move(_packetBuffer));
|
||||
WorldPacket* packetToQueue;
|
||||
|
||||
if (sPacketLog->CanLogPacket())
|
||||
if (sPacketLog->CanLogPacket() && IsLoggingPackets())
|
||||
sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort());
|
||||
|
||||
std::unique_lock<std::mutex> sessionGuard(_worldSessionLock, std::defer_lock);
|
||||
@@ -520,7 +520,7 @@ void WorldSocket::SendPacket(WorldPacket const& packet)
|
||||
if (!IsOpen())
|
||||
return;
|
||||
|
||||
if (sPacketLog->CanLogPacket())
|
||||
if (sPacketLog->CanLogPacket() && IsLoggingPackets())
|
||||
sPacketLog->LogPacket(packet, SERVER_TO_CLIENT, GetRemoteIpAddress(), GetRemotePort());
|
||||
|
||||
_bufferQueue.Enqueue(new EncryptableAndCompressiblePacket(packet, _authCrypt.IsInitialized()));
|
||||
|
||||
@@ -85,6 +85,9 @@ public:
|
||||
|
||||
void SetSendBufferSize(std::size_t sendBufferSize) { _sendBufferSize = sendBufferSize; }
|
||||
|
||||
bool IsLoggingPackets() const { return _loggingPackets; }
|
||||
void SetPacketLogging(bool state) { _loggingPackets = state; }
|
||||
|
||||
protected:
|
||||
void OnClose() override;
|
||||
void ReadHandler() override;
|
||||
@@ -133,6 +136,8 @@ private:
|
||||
|
||||
QueryCallbackProcessor _queryProcessor;
|
||||
std::string _ipCountry;
|
||||
|
||||
bool _loggingPackets;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2392,7 +2392,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
|
||||
targetInfo.reflectResult = SPELL_MISS_PARRY;
|
||||
|
||||
// Increase time interval for reflected spells by 1.5
|
||||
m_caster->m_Events.AddEvent(new ReflectEvent(m_caster, targetInfo.targetGUID, m_spellInfo), m_caster->m_Events.CalculateTime(targetInfo.timeDelay));
|
||||
m_caster->m_Events.AddEventAtOffset(new ReflectEvent(m_caster, targetInfo.targetGUID, m_spellInfo), Milliseconds(targetInfo.timeDelay));
|
||||
targetInfo.timeDelay += targetInfo.timeDelay >> 1;
|
||||
|
||||
m_spellFlags |= SPELL_FLAG_REFLECTED;
|
||||
@@ -3439,7 +3439,7 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const
|
||||
|
||||
// create and add update event for this spell
|
||||
_spellEvent = new SpellEvent(this);
|
||||
m_caster->m_Events.AddEvent(_spellEvent, m_caster->m_Events.CalculateTime(1));
|
||||
m_caster->m_Events.AddEventAtOffset(_spellEvent, 1ms);
|
||||
|
||||
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, m_caster))
|
||||
{
|
||||
@@ -8166,7 +8166,7 @@ bool SpellEvent::IsDeletable() const
|
||||
return m_Spell->IsDeletable();
|
||||
}
|
||||
|
||||
bool ReflectEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
bool ReflectEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*_caster, _targetGUID);
|
||||
if (target && _caster->IsInMap(target))
|
||||
|
||||
@@ -2429,8 +2429,14 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SUMMON_TYPE_JEEVES:
|
||||
case SUMMON_TYPE_MINIPET:
|
||||
// For companions, recalculate the position to ensure they spawn at the intended π/4 angle.
|
||||
destTarget->Relocate(m_originalCaster->GetNearPosition(
|
||||
m_originalCaster->GetDistance2d(destTarget->GetPositionX(), destTarget->GetPositionY()),
|
||||
MINI_PET_SUMMON_ANGLE
|
||||
));
|
||||
[[fallthrough]];
|
||||
case SUMMON_TYPE_JEEVES:
|
||||
{
|
||||
summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
|
||||
if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION))
|
||||
@@ -2446,8 +2452,9 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
|
||||
//summon->AI()->EnterEvadeMode();
|
||||
if (properties->Type != SUMMON_TYPE_JEEVES)
|
||||
{
|
||||
summon->SetFacingToObject(m_originalCaster);
|
||||
summon->GetMotionMaster()->Clear(false);
|
||||
summon->GetMotionMaster()->MoveFollow(m_originalCaster, PET_FOLLOW_DIST, summon->GetFollowAngle(), MOTION_SLOT_ACTIVE);
|
||||
summon->GetMotionMaster()->MoveFollow(m_originalCaster, PET_FOLLOW_DIST, MINI_PET_FOLLOW_ANGLE, MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5206,7 +5213,7 @@ void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
// Position passed to SummonPet is irrelevant with current implementation,
|
||||
// pet will be relocated without using these coords in Pet::LoadPetFromDB
|
||||
player->SummonPet(0, 0.0f, 0.0f, 0.0f, 0.0f, SUMMON_PET, 0s, damage);
|
||||
player->SummonPet(0, 0.0f, 0.0f, 0.0f, 0.0f, SUMMON_PET, 0ms, damage);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5151,6 +5151,12 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->AttributesEx3 |= SPELL_ATTR3_ALWAYS_HIT;
|
||||
});
|
||||
|
||||
// Earth Shield
|
||||
ApplySpellFix({ 55599, 58981 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->AttributesEx5 |= SPELL_ATTR5_LIMIT_N;
|
||||
});
|
||||
|
||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||
{
|
||||
SpellInfo* spellInfo = mSpellInfoMap[i];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user