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:
bash
2025-10-19 22:34:18 +02:00
448 changed files with 22792 additions and 5924 deletions
@@ -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
#
###################################################################################################
+1 -5
View File
@@ -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)
{
+4 -4
View File
@@ -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));
}
}
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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:
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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
+7 -28
View File
@@ -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);
}
+2 -6
View File
@@ -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;
+13 -15
View File
@@ -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
+2 -2
View File
@@ -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;
+3 -2
View File
@@ -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;
+12 -15
View File
@@ -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;
}
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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());
+1 -1
View File
@@ -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); }
+41 -114
View File
@@ -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);
}
}
+12 -7
View File
@@ -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; }
+39 -15
View File
@@ -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();
+3
View File
@@ -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;
+1 -1
View File
@@ -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(); }
+3 -3
View File
@@ -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;
}
+1 -1
View File
@@ -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
+8 -5
View File
@@ -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
{
+143 -118
View File
@@ -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();
+10 -11
View File
@@ -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)
+10 -10
View File
@@ -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);
+13 -13
View File
@@ -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;
+3 -3
View File
@@ -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;
}
+1 -1
View File
@@ -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; }
+366 -271
View File
@@ -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)
+23 -15
View File
@@ -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);
+5 -1
View File
@@ -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
+2 -2
View File
@@ -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
+12 -12
View File
@@ -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);
+12 -12
View File
@@ -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
+16 -2
View File
@@ -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)
{
+11 -25
View File
@@ -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?
}
+16 -1
View File
@@ -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;
+37 -44
View File
@@ -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*/)
+212 -242
View File
@@ -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);
}
+13 -10
View File
@@ -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);
}
+13 -15
View File
@@ -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)
+15 -7
View File
@@ -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);
+28 -14
View File
@@ -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());
}
}
+2
View File
@@ -158,6 +158,8 @@ private:
TransportInstanceMap _instanceTransports;
TransportAnimationContainer _transportAnimations;
void PreloadGridsFromQuery(std::string const& query, uint32& count);
};
#define sTransportMgr TransportMgr::instance()
+2 -1
View File
@@ -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,
+21 -24
View File
@@ -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);
}
}
+14 -5
View File
@@ -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)
+2 -3
View File
@@ -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;
};
}
}
+5 -5
View File
@@ -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 );
+7
View File
@@ -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;
+26 -12
View File
@@ -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;
+3 -3
View File
@@ -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()));
+5
View File
@@ -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
+3 -3
View File
@@ -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))
+10 -3
View File
@@ -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