From dc4c874206ccd8d7266d8f034faa00e0acda0732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E9=B9=BF?= <18535853+PkllonG@users.noreply.github.com> Date: Sat, 7 Sep 2024 18:05:18 +0800 Subject: [PATCH 01/26] fix(Scripts/BlackTemple): blade_of_azzinoth...and Possible crash (#19891) * Update boss_illidan.cpp * Update boss_illidan.cpp --- .../scripts/Outland/BlackTemple/boss_illidan.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index a07fc810d..e4de895c3 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -1209,7 +1209,10 @@ enum WarbladeTear struct npc_blade_of_azzinoth : public ScriptedAI { - npc_blade_of_azzinoth(Creature* creature) : ScriptedAI(creature) { } + npc_blade_of_azzinoth(Creature* creature) : ScriptedAI(creature) + { + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + } void IsSummonedBy(WorldObject* /*summoner*/) override { @@ -1257,12 +1260,13 @@ enum FlameAzzinoth struct npc_flame_of_azzinoth : public ScriptedAI { - npc_flame_of_azzinoth(Creature* creature) : ScriptedAI(creature), _bladeSummoner(nullptr) { } + npc_flame_of_azzinoth(Creature* creature) : ScriptedAI(creature) { } void IsSummonedBy(WorldObject* /*summoner*/) override { // Flame is set to be Illidan's summon, so we check for nearest blade - _bladeSummoner = me->FindNearestCreature(NPC_BLADE_OF_AZZINOTH, 15.0f); + if (Creature* _blade = me->FindNearestCreature(NPC_BLADE_OF_AZZINOTH, 15.0f)) + _bladeGUID = _blade->GetGUID(); me->SetCorpseDelay(2); me->SetReactState(REACT_DEFENSIVE); @@ -1285,8 +1289,8 @@ struct npc_flame_of_azzinoth : public ScriptedAI void JustEngagedWith(Unit* /*who*/) override { ScheduleTimedEvent(10s, [&] { - if (_bladeSummoner) - if (Unit* target = _bladeSummoner->AI()->SelectTarget(SelectTargetMethod::Random, 0, 30.f, true)) + if (Creature* _blade = ObjectAccessor::GetCreature(*me, _bladeGUID)) + if (Unit* target = _blade->AI()->SelectTarget(SelectTargetMethod::Random, 0, 30.0f, true)) DoCast(target, SPELL_CHARGE); }, 5s, 20s); @@ -1301,7 +1305,7 @@ struct npc_flame_of_azzinoth : public ScriptedAI } private: - Creature* _bladeSummoner; + ObjectGuid _bladeGUID; }; class spell_illidan_draw_soul : public SpellScript From 7eee1345d0a7be4132e8baa06189a2eafc26b0fb Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 7 Sep 2024 07:05:43 -0300 Subject: [PATCH 02/26] =?UTF-8?q?fix(Scripts/BlackTemple):=20Gurtogg=20Blo?= =?UTF-8?q?odboil=20shouldnt=20cast=20bloodboil=20o=E2=80=A6=20(#19886)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Scripts/BlackTemple): Gurtogg Bloodboil shouldnt cast bloodboil on phase 2 and shouldnt chase immune targets --- .../Outland/BlackTemple/boss_bloodboil.cpp | 181 ++++++++---------- 1 file changed, 82 insertions(+), 99 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp index 97c2a096d..af5189dad 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp @@ -65,127 +65,110 @@ enum Misc GROUP_DELAY = 1 }; -class boss_gurtogg_bloodboil : public CreatureScript +struct boss_gurtogg_bloodboil : public BossAI { -public: - boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { } + boss_gurtogg_bloodboil(Creature* creature) : BossAI(creature, DATA_GURTOGG_BLOODBOIL), _recentlySpoken(false) { } - CreatureAI* GetAI(Creature* creature) const override + void Reset() override { - return GetBlackTempleAI(creature); + BossAI::Reset(); + _recentlySpoken = false; } - struct boss_gurtogg_bloodboilAI : public BossAI + void JustEngagedWith(Unit* who) override { - boss_gurtogg_bloodboilAI(Creature* creature) : BossAI(creature, DATA_GURTOGG_BLOODBOIL), _recentlySpoken(false) { } + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); - void Reset() override - { - BossAI::Reset(); - _recentlySpoken = false; - } + DoCastSelf(SPELL_ACIDIC_WOUND, true); - void JustEngagedWith(Unit* who) override - { - BossAI::JustEngagedWith(who); - Talk(SAY_AGGRO); - - DoCastSelf(SPELL_ACIDIC_WOUND, true); - - ScheduleTimedEvent(10s, [&] { + ScheduleTimedEvent(10s, [&] { + if (!me->HasAura(SPELL_FEL_RAGE_SELF)) me->CastCustomSpell(SPELL_BLOODBOIL, SPELLVALUE_MAX_TARGETS, 5, me, false); - }, 10s); + }, 10s); - ScheduleTimedEvent(38s, [&] { - DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_FEL_ACID_BREATH2 : SPELL_FEL_ACID_BREATH1); - }, 30s); + ScheduleTimedEvent(38s, [&] { + DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_FEL_ACID_BREATH2 : SPELL_FEL_ACID_BREATH1); + }, 30s); - ScheduleTimedEvent(14s, [&] { - DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_EJECT2 : SPELL_EJECT1); - }, 20s); + ScheduleTimedEvent(14s, [&] { + DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_EJECT2 : SPELL_EJECT1); + }, 20s); - ScheduleTimedEvent(5s, [&] { - DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_ARCING_SMASH2 : SPELL_ARCING_SMASH1); - }, 15s); + ScheduleTimedEvent(5s, [&] { + DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_ARCING_SMASH2 : SPELL_ARCING_SMASH1); + }, 15s); - ScheduleTimedEvent(1min, [&] { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 40.0f, true)) - { - me->RemoveAurasByType(SPELL_AURA_MOD_TAUNT); - DoCastSelf(SPELL_FEL_RAGE_SELF, true); - DoCast(target, SPELL_FEL_RAGE_TARGET, true); - DoCast(target, SPELL_FEL_RAGE_2, true); - DoCast(target, SPELL_FEL_RAGE_3, true); - DoCast(target, SPELL_FEL_RAGE_SIZE, true); - target->CastSpell(me, SPELL_TAUNT_GURTOGG, true); - - DoCast(target, SPELL_FEL_GEYSER_SUMMON, true); - DoCastSelf(SPELL_FEL_GEYSER_STUN, true); - DoCastSelf(SPELL_INSIGNIFICANCE, true); - - me->m_Events.AddEventAtOffset([&] { - DoCastVictim(SPELL_CHARGE); - }, 2s); - - scheduler.DelayGroup(GROUP_DELAY, 30s); - } - }, 90s); - - ScheduleUniqueTimedEvent(10min, [&] { - Talk(SAY_ENRAGE); - DoCastSelf(SPELL_BERSERK, true); - }, EVENT_SPELL_BERSERK); - - scheduler.Schedule(28s, [this](TaskContext context) { - context.SetGroup(GROUP_DELAY); - DoCastVictim(SPELL_BEWILDERING_STRIKE); - context.Repeat(30s); - }); - } - - void KilledUnit(Unit* /*victim*/) override - { - if (!_recentlySpoken) + ScheduleTimedEvent(1min, [&] { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 40.0f, true)) { - Talk(SAY_SLAY); + me->RemoveAurasByType(SPELL_AURA_MOD_TAUNT); + DoCastSelf(SPELL_FEL_RAGE_SELF, true); + DoCast(target, SPELL_FEL_RAGE_TARGET, true); + DoCast(target, SPELL_FEL_RAGE_2, true); + DoCast(target, SPELL_FEL_RAGE_3, true); + DoCast(target, SPELL_FEL_RAGE_SIZE, true); + target->CastSpell(me, SPELL_TAUNT_GURTOGG, true); + + DoCast(target, SPELL_FEL_GEYSER_SUMMON, true); + DoCastSelf(SPELL_FEL_GEYSER_STUN, true); + DoCastSelf(SPELL_INSIGNIFICANCE, true); + me->m_Events.AddEventAtOffset([&] { - _recentlySpoken = false; - }, 6s); + DoCastVictim(SPELL_CHARGE); + }, 2s); + + scheduler.DelayGroup(GROUP_DELAY, 30s); } - } + }, 90s); - void JustSummoned(Creature* summon) override + ScheduleUniqueTimedEvent(10min, [&] { + Talk(SAY_ENRAGE); + DoCastSelf(SPELL_BERSERK, true); + }, EVENT_SPELL_BERSERK); + + scheduler.Schedule(28s, [this](TaskContext context) { + context.SetGroup(GROUP_DELAY); + DoCastVictim(SPELL_BEWILDERING_STRIKE); + context.Repeat(30s); + }); + } + + bool CanAIAttack(Unit const* who) const override + { + return !who->IsImmunedToDamage(SPELL_SCHOOL_MASK_ALL); + } + + void KilledUnit(Unit* /*victim*/) override + { + if (!_recentlySpoken) { - summons.Summon(summon); - summon->CastSpell(summon, SPELL_FEL_GEYSER_DAMAGE, false); + Talk(SAY_SLAY); + me->m_Events.AddEventAtOffset([&] { + _recentlySpoken = false; + }, 6s); } + } - void JustDied(Unit* killer) override - { - BossAI::JustDied(killer); - Talk(SAY_DEATH); - } + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + summon->CastSpell(summon, SPELL_FEL_GEYSER_DAMAGE, false); + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } - scheduler.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + bool CheckEvadeIfOutOfCombatArea() const override + { + return me->GetHomePosition().GetExactDist2d(me) > 105.0f; + } - DoMeleeAttackIfReady(); - } - - bool CheckEvadeIfOutOfCombatArea() const override - { - return me->GetHomePosition().GetExactDist2d(me) > 105.0f; - } - - private: - bool _recentlySpoken; - }; +private: + bool _recentlySpoken; }; class spell_gurtogg_bloodboil : public SpellScript @@ -231,7 +214,7 @@ class spell_gurtogg_eject : public SpellScript void AddSC_boss_gurtogg_bloodboil() { - new boss_gurtogg_bloodboil(); + RegisterBlackTempleCreatureAI(boss_gurtogg_bloodboil); RegisterSpellScript(spell_gurtogg_bloodboil); RegisterSpellScript(spell_gurtogg_eject); } From cf95c1dfbdb252cfd18e32f8bdfef0da8ff01092 Mon Sep 17 00:00:00 2001 From: kissingers <33601959+kissingers@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:39:31 +0800 Subject: [PATCH 03/26] fix(Scripts/ZulAman): Nalorakk sometimes not move when player close (#19893) * Fix nalorakk sometimes not move when player close * init _phase * Revert "Fix nalorakk sometimes not move when player close" This reverts commit b42cd4634bb4ffd225eaa7480428c6ba6b4817c6. --- src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index af0e1e19d..4a290c253 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -89,6 +89,7 @@ struct boss_nalorakk : public BossAI { boss_nalorakk(Creature* creature) : BossAI(creature, DATA_NALORAKKEVENT) { + _phase = PHASE_SEND_GUARDS_1; _ranIntro = false; _active = true; creature->SetReactState(REACT_PASSIVE); From 0dd5c6e3b4703e93cf5c4015caf0e5d2f68d650f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefano=20Borz=C3=AC?= Date: Sun, 8 Sep 2024 20:05:58 +0200 Subject: [PATCH 04/26] feat(Battlegrounds): make it compatible with custom arena type (#18679) * feat(Battlegrounds): make it compatible with custom arena type * fix(BattlegroundQueue.cpp): ignore bg for arena condition * feat(Scripting): add OnQueueUpdateValidity hook * fix: codestyle --- src/server/game/Battlegrounds/ArenaTeam.cpp | 5 ++++- src/server/game/Battlegrounds/BattlegroundQueue.cpp | 4 ++++ .../game/Scripting/ScriptDefines/AllBattlegroundScript.cpp | 5 +++++ .../game/Scripting/ScriptDefines/AllBattlegroundScript.h | 3 +++ src/server/game/Scripting/ScriptMgr.h | 1 + 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index c0a6025a0..552b229ad 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -1034,7 +1034,10 @@ void ArenaTeam::CreateTempArenaTeam(std::vector playerList, uint8 type, { auto playerCountInTeam = static_cast(playerList.size()); - ASSERT(playerCountInTeam == GetReqPlayersForType(type)); + const auto standardArenaType = { ARENA_TYPE_2v2, ARENA_TYPE_3v3, ARENA_TYPE_5v5 }; + bool isStandardArenaType = std::find(std::begin(standardArenaType), std::end(standardArenaType), type) != std::end(standardArenaType); + if (isStandardArenaType) + ASSERT(playerCountInTeam == GetReqPlayersForType(type)); // Generate new arena team id TeamId = sArenaTeamMgr->GenerateTempArenaTeamId(); diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index 1d602967d..395a62a16 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -773,6 +773,10 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundTypeId sScriptMgr->OnQueueUpdate(this, diff, bgTypeId, bracket_id, arenaType, isRated, arenaRating); + if (!sScriptMgr->OnQueueUpdateValidity(this, diff, bgTypeId, bracket_id, arenaType, isRated, arenaRating)) { + return; + } + m_SelectionPools[TEAM_ALLIANCE].Init(); m_SelectionPools[TEAM_HORDE].Init(); diff --git a/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.cpp b/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.cpp index 9367a748b..af617ddba 100644 --- a/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.cpp @@ -54,6 +54,11 @@ void ScriptMgr::OnQueueUpdate(BattlegroundQueue* queue, uint32 diff, Battlegroun CALL_ENABLED_HOOKS(AllBattlegroundScript, ALLBATTLEGROUNDHOOK_ON_QUEUE_UPDATE, script->OnQueueUpdate(queue, diff, bgTypeId, bracket_id, arenaType, isRated, arenaRating)); } +bool ScriptMgr::OnQueueUpdateValidity(BattlegroundQueue* queue, uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating) +{ + CALL_ENABLED_BOOLEAN_HOOKS(AllBattlegroundScript, ALLBATTLEGROUNDHOOK_ON_QUEUE_UPDATE_VALIDITY, !script->OnQueueUpdateValidity(queue, diff, bgTypeId, bracket_id, arenaType, isRated, arenaRating)); +} + void ScriptMgr::OnAddGroup(BattlegroundQueue* queue, GroupQueueInfo* ginfo, uint32& index, Player* leader, Group* group, BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 matchmakerRating, uint32 arenaTeamId, uint32 opponentsArenaTeamId) { CALL_ENABLED_HOOKS(AllBattlegroundScript, ALLBATTLEGROUNDHOOK_ON_ADD_GROUP, script->OnAddGroup(queue, ginfo, index, leader, group, bgTypeId, bracketEntry, arenaType, isRated, isPremade, arenaRating, matchmakerRating, arenaTeamId, opponentsArenaTeamId)); diff --git a/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.h b/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.h index 880518b5d..9e8baba15 100644 --- a/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.h +++ b/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.h @@ -30,6 +30,7 @@ enum AllBattlegroundHook ALLBATTLEGROUNDHOOK_ON_BATTLEGROUND_BEFORE_ADD_PLAYER, ALLBATTLEGROUNDHOOK_ON_BATTLEGROUND_REMOVE_PLAYER_AT_LEAVE, ALLBATTLEGROUNDHOOK_ON_QUEUE_UPDATE, + ALLBATTLEGROUNDHOOK_ON_QUEUE_UPDATE_VALIDITY, ALLBATTLEGROUNDHOOK_ON_ADD_GROUP, ALLBATTLEGROUNDHOOK_CAN_FILL_PLAYERS_TO_BG, ALLBATTLEGROUNDHOOK_IS_CHECK_NORMAL_MATCH, @@ -78,6 +79,8 @@ public: virtual void OnQueueUpdate(BattlegroundQueue* /*queue*/, uint32 /* diff */, BattlegroundTypeId /* bgTypeId */, BattlegroundBracketId /* bracket_id */, uint8 /* arenaType */, bool /* isRated */, uint32 /* arenaRating */) { } + [[nodiscard]] virtual bool OnQueueUpdateValidity(BattlegroundQueue* /*queue*/, uint32 /* diff */, BattlegroundTypeId /* bgTypeId */, BattlegroundBracketId /* bracket_id */, uint8 /* arenaType */, bool /* isRated */, uint32 /* arenaRating */) { return true; } + virtual void OnAddGroup(BattlegroundQueue* /*queue*/, GroupQueueInfo* /*ginfo*/, uint32& /*index*/, Player* /*leader*/, Group* /*group*/, BattlegroundTypeId /* bgTypeId */, PvPDifficultyEntry const* /* bracketEntry */, uint8 /* arenaType */, bool /* isRated */, bool /* isPremade */, uint32 /* arenaRating */, uint32 /* matchmakerRating */, uint32 /* arenaTeamId */, uint32 /* opponentsArenaTeamId */) { } diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index a81bda71f..f7fe63ae2 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -584,6 +584,7 @@ public: /* BGScript */ void OnBattlegroundBeforeAddPlayer(Battleground* bg, Player* player); void OnBattlegroundRemovePlayerAtLeave(Battleground* bg, Player* player); void OnQueueUpdate(BattlegroundQueue* queue, uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating); + bool OnQueueUpdateValidity(BattlegroundQueue* queue, uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating); void OnAddGroup(BattlegroundQueue* queue, GroupQueueInfo* ginfo, uint32& index, Player* leader, Group* group, BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 matchmakerRating, uint32 arenaTeamId, uint32 opponentsArenaTeamId); bool CanFillPlayersToBG(BattlegroundQueue* queue, Battleground* bg, BattlegroundBracketId bracket_id); From cdc00b42bd86f07e1beb0a1327238a9163650ae3 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Sun, 8 Sep 2024 14:49:28 -0400 Subject: [PATCH 05/26] fix(Core/AI): Add back leash update. (#19916) Init. --- src/server/game/Entities/Unit/Unit.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 1f0dd7832..659a42dbf 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13542,6 +13542,9 @@ void Unit::SetInCombatWith(Unit* enemy, uint32 duration) } } + if (Creature* pCreature = ToCreature()) + pCreature->UpdateLeashExtensionTime(); + SetInCombatState(false, enemy, duration); } From b47b5d2c519ec4909f0b59fabfa2a4319117b94e Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Sun, 8 Sep 2024 20:44:09 -0400 Subject: [PATCH 06/26] fix(Core/AI): Initialize movement leash timer to five seconds. (#19898) Init. https: //github.com/vmangos/core/commit/c8510cbbd4dccbdac9900cc507910ef3ae0e6c43 Co-authored-by: ratkosrb <35845488+ratkosrb@users.noreply.github.com> --- .../Movement/MovementGenerators/TargetedMovementGenerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 4e7df89db..003e967d4 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -39,7 +39,7 @@ class ChaseMovementGenerator : public MovementGeneratorMedium range = {}, Optional angle = {}) - : TargetedMovementGeneratorBase(target), i_leashExtensionTimer(0), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {} + : TargetedMovementGeneratorBase(target), i_leashExtensionTimer(5000), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {} ~ChaseMovementGenerator() { } MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; } From fafd351e44b4556b9ceda4bfaa72c6e5f22c3f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E9=B9=BF?= <18535853+PkllonG@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:07:11 +0800 Subject: [PATCH 07/26] fix(Core/AI): creature leashing behavior. (#19897) * Update Unit.cpp * Update TargetedMovementGenerator.cpp * Update Unit.cpp * Update Unit.cpp --- .../TargetedMovementGenerator.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 4dc2f55bd..a394c7758 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -148,15 +148,16 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); owner->SetInFront(target); MovementInform(owner); + } - // Mobs should chase you infinitely if you stop and wait every few seconds. - i_leashExtensionTimer.Update(time_diff); - if (i_leashExtensionTimer.Passed()) - { - i_leashExtensionTimer.Reset(5000); + // Mobs should chase you infinitely if you stop and wait every few seconds. + i_leashExtensionTimer.Update(time_diff); + if (i_leashExtensionTimer.Passed()) + { + i_leashExtensionTimer.Reset(5000); + if (owner->HasUnitState(UNIT_STATE_CHASE) && owner->movespline->Finalized() && !target->isMoving()) if (Creature* creature = owner->ToCreature()) creature->UpdateLeashExtensionTime(); - } } // if the target moved, we have to consider whether to adjust From 56e03c495d15b75f3c9d35c322bbf3b1cdb826de Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 9 Sep 2024 07:45:23 -0300 Subject: [PATCH 08/26] fix(Scripts/BlackTemple): Shade of Akama should despawn on evade and Akama despawns before dying (#19894) * fix(Scripts/BlackTemple): Shade of Akama should despawn on evade and Akama despawns before dying * Create rev_1725714358950337100.sql * Update boss_shade_of_akama.cpp --- .../rev_1725714358950337100.sql | 2 + .../BlackTemple/boss_shade_of_akama.cpp | 47 ++++++++----------- 2 files changed, 22 insertions(+), 27 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1725714358950337100.sql diff --git a/data/sql/updates/pending_db_world/rev_1725714358950337100.sql b/data/sql/updates/pending_db_world/rev_1725714358950337100.sql new file mode 100644 index 000000000..71f969ff3 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1725714358950337100.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `flags_extra` = `flags_extra` |2147483648 WHERE `entry` = 22841; diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index 9852bc345..1f59b410e 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -220,6 +220,7 @@ struct npc_akama_shade : public ScriptedAI DoCastSelf(SPELL_STEALTH, true); me->SetWalk(true); _sayLowHealth = false; + _died = false; scheduler.CancelAll(); } @@ -232,14 +233,14 @@ struct npc_akama_shade : public ScriptedAI case POINT_ENGAGE: me->SetHomePosition(me->GetPosition()); me->SetFaction(FACTION_ENGAGE); - DoCast(me, SPELL_AKAMA_SOUL_CHANNEL, true); + DoCastSelf(SPELL_AKAMA_SOUL_CHANNEL, true); break; case POINT_OUTRO: DoCastSelf(SPELL_AKAMA_SOUL_RETRIEVE, true); ScheduleUniqueTimedEvent(15600ms, [&] { - Talk(SAY_BROKEN_FREE_0); - me->SummonCreatureGroup(SUMMON_GROUP_BROKENS); + Talk(SAY_BROKEN_FREE_0); + me->SummonCreatureGroup(SUMMON_GROUP_BROKENS); }, 1); ScheduleUniqueTimedEvent(26550ms, [&] { @@ -275,6 +276,19 @@ struct npc_akama_shade : public ScriptedAI _sayLowHealth = true; Talk(SAY_LOW_HEALTH); } + else if (damage >= me->GetHealth() && !_died) + { + damage = me->GetHealth() - 1; + Talk(SAY_DEATH); + if (Creature* shade = instance->GetCreature(DATA_SHADE_OF_AKAMA)) + { + shade->SetHomePosition(shade->GetHomePosition()); + shade->AI()->EnterEvadeMode(); + } + + me->DespawnOrUnsummon(); + ScriptedAI::EnterEvadeMode(EvadeReason::EVADE_REASON_OTHER); + } } void DoAction(int32 param) override @@ -298,18 +312,6 @@ struct npc_akama_shade : public ScriptedAI void EnterEvadeMode(EvadeReason /*why*/) override { } - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - if (Creature* shade = instance->GetCreature(DATA_SHADE_OF_AKAMA)) - { - shade->SetHomePosition(shade->GetHomePosition()); - shade->AI()->EnterEvadeMode(); - } - - me->DespawnOrUnsummon(); - } - void JustEngagedWith(Unit* /*who*/) override { ScheduleTimedEvent(2s, [&] @@ -338,6 +340,7 @@ struct npc_akama_shade : public ScriptedAI private: bool _sayLowHealth; + bool _died; }; struct npc_creature_generator_akama : public ScriptedAI @@ -445,27 +448,18 @@ private: struct npc_ashtongue_sorcerer : public NullCreatureAI { - npc_ashtongue_sorcerer(Creature* creature) : NullCreatureAI(creature) - { - instance = creature->GetInstanceScript(); - } + npc_ashtongue_sorcerer(Creature* creature) : NullCreatureAI(creature) { } void MovementInform(uint32 type, uint32 point) override { if (type == POINT_MOTION_TYPE && point == POINT_ENGAGE) me->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true); } - -private: - InstanceScript* instance; }; struct npc_ashtongue_channeler : public NullCreatureAI { - npc_ashtongue_channeler(Creature* creature) : NullCreatureAI(creature) - { - instance = creature->GetInstanceScript(); - } + npc_ashtongue_channeler(Creature* creature) : NullCreatureAI(creature) { } void Reset() override { @@ -484,7 +478,6 @@ struct npc_ashtongue_channeler : public NullCreatureAI } private: - InstanceScript* instance; TaskScheduler scheduler; }; From cbd74ae66365923ecaf5b493c8f9011912a5a46c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 9 Sep 2024 10:46:15 +0000 Subject: [PATCH 09/26] chore(DB): import pending files Referenced commit(s): 56e03c495d15b75f3c9d35c322bbf3b1cdb826de --- .../rev_1725714358950337100.sql => db_world/2024_09_09_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1725714358950337100.sql => db_world/2024_09_09_00.sql} (69%) diff --git a/data/sql/updates/pending_db_world/rev_1725714358950337100.sql b/data/sql/updates/db_world/2024_09_09_00.sql similarity index 69% rename from data/sql/updates/pending_db_world/rev_1725714358950337100.sql rename to data/sql/updates/db_world/2024_09_09_00.sql index 71f969ff3..e27b3f59e 100644 --- a/data/sql/updates/pending_db_world/rev_1725714358950337100.sql +++ b/data/sql/updates/db_world/2024_09_09_00.sql @@ -1,2 +1,3 @@ +-- DB update 2024_09_05_00 -> 2024_09_09_00 -- UPDATE `creature_template` SET `flags_extra` = `flags_extra` |2147483648 WHERE `entry` = 22841; From 00e35a201e0430f5f856eb16ca9125e9e26e53e6 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Wed, 11 Sep 2024 02:25:32 -0400 Subject: [PATCH 10/26] fix(Core/AI): Reduce movement leash extension interval. (#19923) * Init. * Use GetGameTime() instead of system call. Co-Authored-By: Anton Popovichenko * Update leash timer if rooted. * Remove unnecessary checks, add extension for fanning. More parity with VMaNGOS implementation. --------- Co-authored-by: Anton Popovichenko --- .../game/Entities/Creature/Creature.cpp | 4 +-- .../TargetedMovementGenerator.cpp | 34 +++++++++++-------- .../TargetedMovementGenerator.h | 2 +- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 7fe1b532b..d52ea0411 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -3678,7 +3678,7 @@ bool Creature::IsNotReachableAndNeedRegen() const std::shared_ptr const& Creature::GetLastLeashExtensionTimePtr() const { if (m_lastLeashExtensionTime == nullptr) - m_lastLeashExtensionTime = std::make_shared(time(nullptr)); + m_lastLeashExtensionTime = std::make_shared(GameTime::GetGameTime().count()); return m_lastLeashExtensionTime; } @@ -3699,7 +3699,7 @@ time_t Creature::GetLastLeashExtensionTime() const void Creature::UpdateLeashExtensionTime() { - (*GetLastLeashExtensionTimePtr()) = time(nullptr); + (*GetLastLeashExtensionTimePtr()) = GameTime::GetGameTime().count(); } bool Creature::CanPeriodicallyCallForAssistance() const diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index a394c7758..0a58d1450 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -78,8 +78,11 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) { owner->StopMoving(); _lastTargetPosition.reset(); - if (Creature* cOwner2 = owner->ToCreature()) - cOwner2->SetCannotReachTarget(); + if (cOwner) + { + cOwner->UpdateLeashExtensionTime(); + cOwner->SetCannotReachTarget(); + } return true; } @@ -128,8 +131,8 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) { i_recalculateTravel = false; i_path = nullptr; - if (Creature* cOwner2 = owner->ToCreature()) - cOwner2->SetCannotReachTarget(); + if (cOwner) + cOwner->SetCannotReachTarget(); owner->StopMoving(); owner->SetInFront(target); MovementInform(owner); @@ -143,22 +146,25 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) { i_recalculateTravel = false; i_path = nullptr; - if (Creature* cOwner2 = owner->ToCreature()) - cOwner2->SetCannotReachTarget(); + if (cOwner) + cOwner->SetCannotReachTarget(); owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); owner->SetInFront(target); MovementInform(owner); } - // Mobs should chase you infinitely if you stop and wait every few seconds. - i_leashExtensionTimer.Update(time_diff); - if (i_leashExtensionTimer.Passed()) - { - i_leashExtensionTimer.Reset(5000); - if (owner->HasUnitState(UNIT_STATE_CHASE) && owner->movespline->Finalized() && !target->isMoving()) - if (Creature* creature = owner->ToCreature()) - creature->UpdateLeashExtensionTime(); + if (owner->movespline->Finalized()) + { // Mobs should chase you infinitely if you stop and wait every few seconds. + i_leashExtensionTimer.Update(time_diff); + if (i_leashExtensionTimer.Passed()) + { + i_leashExtensionTimer.Reset(1500); + if (cOwner) + cOwner->UpdateLeashExtensionTime(); + } } + else if (i_recalculateTravel) + i_leashExtensionTimer.Reset(1500); // if the target moved, we have to consider whether to adjust if (!_lastTargetPosition || target->GetPosition() != _lastTargetPosition.value() || mutualChase != _mutualChase || !owner->IsWithinLOSInMap(target)) diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 003e967d4..fd3064b51 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -39,7 +39,7 @@ class ChaseMovementGenerator : public MovementGeneratorMedium range = {}, Optional angle = {}) - : TargetedMovementGeneratorBase(target), i_leashExtensionTimer(5000), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {} + : TargetedMovementGeneratorBase(target), i_leashExtensionTimer(1500), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {} ~ChaseMovementGenerator() { } MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; } From eb0cfb79cc4e77dcdbfe42fb0fe7ae5d38f11d33 Mon Sep 17 00:00:00 2001 From: Mattia Date: Wed, 11 Sep 2024 10:43:19 +0200 Subject: [PATCH 11/26] =?UTF-8?q?fix(DB/Creature)=20Black=20Temple=20-=20S?= =?UTF-8?q?hadowmoon=20Blood=20Mages=20dont=20use=20Blood=E2=80=A6=20(#198?= =?UTF-8?q?12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(DB/Creature) Black Temple - Shadowmoon Blood Mages dont use Blood Siphon ability * SQL query refactored * fix: backticks added --- data/sql/updates/pending_db_world/2024_08_31_00.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 data/sql/updates/pending_db_world/2024_08_31_00.sql diff --git a/data/sql/updates/pending_db_world/2024_08_31_00.sql b/data/sql/updates/pending_db_world/2024_08_31_00.sql new file mode 100644 index 000000000..01cff58a1 --- /dev/null +++ b/data/sql/updates/pending_db_world/2024_08_31_00.sql @@ -0,0 +1,5 @@ +UPDATE `smart_scripts` +SET `event_param4` = 6000 +WHERE `entryorguid` = 22945 + AND `source_type` = 0 + AND `id` = 0; From c1296d0b14f043bb133d04e3ea142070c18a35c4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 11 Sep 2024 08:44:17 +0000 Subject: [PATCH 12/26] chore(DB): import pending files Referenced commit(s): eb0cfb79cc4e77dcdbfe42fb0fe7ae5d38f11d33 --- .../2024_08_31_00.sql => db_world/2024_09_11_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/2024_08_31_00.sql => db_world/2024_09_11_00.sql} (72%) diff --git a/data/sql/updates/pending_db_world/2024_08_31_00.sql b/data/sql/updates/db_world/2024_09_11_00.sql similarity index 72% rename from data/sql/updates/pending_db_world/2024_08_31_00.sql rename to data/sql/updates/db_world/2024_09_11_00.sql index 01cff58a1..f5e7b3a93 100644 --- a/data/sql/updates/pending_db_world/2024_08_31_00.sql +++ b/data/sql/updates/db_world/2024_09_11_00.sql @@ -1,3 +1,4 @@ +-- DB update 2024_09_09_00 -> 2024_09_11_00 UPDATE `smart_scripts` SET `event_param4` = 6000 WHERE `entryorguid` = 22945 From c42b3ee258e734c4e93808e13dac397f284a7569 Mon Sep 17 00:00:00 2001 From: Saqra1 <161769195+Saqra1@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:18:13 -0500 Subject: [PATCH 13/26] fix(Core/Pet): Control Infernal without enslave (#19784) Check SummonProperties Category(Control) too to decide the type of controls a Guardian should have. Don't enslave Warlock's Infernal --- .../game/Entities/Creature/TemporarySummon.cpp | 2 +- src/server/game/Spells/SpellEffects.cpp | 17 ----------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp index 86ea77673..9513d1fc9 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.cpp +++ b/src/server/game/Entities/Creature/TemporarySummon.cpp @@ -419,7 +419,7 @@ std::string Minion::GetDebugInfo() const Guardian::Guardian(SummonPropertiesEntry const* properties, ObjectGuid owner, bool isWorldObject) : Minion(properties, owner, isWorldObject) { m_unitTypeMask |= UNIT_MASK_GUARDIAN; - if (properties && properties->Type == SUMMON_TYPE_PET) + if (properties && (properties->Type == SUMMON_TYPE_PET || properties->Category == SUMMON_CATEGORY_PET)) { m_unitTypeMask |= UNIT_MASK_CONTROLABLE_GUARDIAN; InitCharmInfo(); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index aab419f79..5c16b3090 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -6064,23 +6064,6 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* ExecuteLogEffectSummonObject(i, summon); } - - // Summon infernal, cast enslave demon - // xinef: have to do it here because in Pet init stats infernal is not in world, imo this should be changed... - if (summon) - { - switch (m_spellInfo->Id) - { - // Inferno, Warlock summon spell - case 1122: - caster->AddAura(61191, summon); - break; - // Ritual of Doom, Warlock summon spell - case 60478: - caster->AddAura(SPELL_RITUAL_ENSLAVEMENT, summon); - break; - } - } } void Spell::EffectRenamePet(SpellEffIndex /*effIndex*/) From f6e9bd51fd2c316347b34ff1c8184d1bf6de2426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefano=20Borz=C3=AC?= Date: Wed, 11 Sep 2024 16:18:36 +0200 Subject: [PATCH 14/26] feat(ScriptMgr): add OnArenaStart hook (#19922) --- src/server/game/Battlegrounds/Battleground.cpp | 2 ++ src/server/game/Scripting/ScriptDefines/ArenaScript.cpp | 5 +++++ src/server/game/Scripting/ScriptDefines/ArenaScript.h | 3 +++ src/server/game/Scripting/ScriptMgr.h | 1 + 4 files changed, 11 insertions(+) diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index a68c8c643..b9858b350 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -611,6 +611,8 @@ inline void Battleground::_ProcessJoin(uint32 diff) } m_ToBeTeleported.clear(); } + + sScriptMgr->OnArenaStart(this); } else { diff --git a/src/server/game/Scripting/ScriptDefines/ArenaScript.cpp b/src/server/game/Scripting/ScriptDefines/ArenaScript.cpp index 35baeb271..b0869c799 100644 --- a/src/server/game/Scripting/ScriptDefines/ArenaScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/ArenaScript.cpp @@ -39,6 +39,11 @@ bool ScriptMgr::OnBeforeArenaCheckWinConditions(Battleground* const bg) CALL_ENABLED_BOOLEAN_HOOKS(ArenaScript, ARENAHOOK_ON_BEFORE_CHECK_WIN_CONDITION, !script->OnBeforeArenaCheckWinConditions(bg)); } +void ScriptMgr::OnArenaStart(Battleground* bg) +{ + CALL_ENABLED_HOOKS(ArenaScript, ARENAHOOK_ON_ARENA_START, script->OnArenaStart(bg)); +} + ArenaScript::ArenaScript(const char* name, std::vector enabledHooks) : ScriptObject(name, ARENAHOOK_END) { diff --git a/src/server/game/Scripting/ScriptDefines/ArenaScript.h b/src/server/game/Scripting/ScriptDefines/ArenaScript.h index c50a96449..e9a3f1c80 100644 --- a/src/server/game/Scripting/ScriptDefines/ArenaScript.h +++ b/src/server/game/Scripting/ScriptDefines/ArenaScript.h @@ -28,6 +28,7 @@ enum ArenaHook ARENAHOOK_ON_GET_POINTS, ARENAHOOK_CAN_SAVE_TO_DB, ARENAHOOK_ON_BEFORE_CHECK_WIN_CONDITION, + ARENAHOOK_ON_ARENA_START, ARENAHOOK_END }; @@ -48,6 +49,8 @@ public: [[nodiscard]] virtual bool OnBeforeArenaCheckWinConditions(Battleground* const /* bg */) { return true; } [[nodiscard]] virtual bool CanSaveToDB(ArenaTeam* /*team*/) { return true; } + + virtual void OnArenaStart(Battleground* /* bg */) { }; }; #endif diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index f7fe63ae2..c35625b78 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -648,6 +648,7 @@ public: /* ArenaScript */ void OnGetPoints(ArenaTeam* team, uint32 memberRating, float& points); bool CanSaveToDB(ArenaTeam* team); bool OnBeforeArenaCheckWinConditions(Battleground* const bg); + void OnArenaStart(Battleground* const bg); public: /* MiscScript */ From 0ac7ab03bb02c984a0917aefd763cf7ceebd371f Mon Sep 17 00:00:00 2001 From: Mershl Date: Wed, 11 Sep 2024 16:19:14 +0200 Subject: [PATCH 15/26] fix(Scripts/UBRS): increase Drakkisath's conflagrate interval from 10s..13s to 18s..25s, avoiding near infinite CC chains (#19806) fix(Scripts/UBRS): increase Drakkisath's conflagrate interval from 10..13s to 18s..25s, avoids infinite CC chains (conflagrate is a 10s CC) --- .../BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp index 02e619627..3935c78a1 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp @@ -94,7 +94,7 @@ public: _conflagrateThreat = me->GetThreatMgr().GetThreat(me->GetVictim()); me->GetThreatMgr().ModifyThreatByPercent(target, -100); } - events.ScheduleEvent(EVENT_CONFLAGRATION, 10s, 13s); + events.ScheduleEvent(EVENT_CONFLAGRATION, 18s, 25s); events.ScheduleEvent(EVENT_CHECK_CONFLAGRATION_TARGET, 10s); break; case EVENT_THUNDERCLAP: From 06cf2cdf425b3ad1c84486564866a0e651129730 Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:19:51 +0200 Subject: [PATCH 16/26] fix(DB/SAI): Missings spells for few creatures in Blade's Edge Mountains (#19617) *timer estimations done on retail --- .../pending_db_world/rev_1723574442391883600.sql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1723574442391883600.sql diff --git a/data/sql/updates/pending_db_world/rev_1723574442391883600.sql b/data/sql/updates/pending_db_world/rev_1723574442391883600.sql new file mode 100644 index 000000000..f649c5a01 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1723574442391883600.sql @@ -0,0 +1,14 @@ +-- Missing spell (Cleave) for Bladespire Brute +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 19995) AND (`source_type` = 0) AND (`id` IN (0)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(19995, 0, 0, 0, 0, 0, 100, 0, 7000, 12000, 8000, 30000, 0, 0, 11, 15496, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Bladespire Brute - In Combat - Cast Cleave'); + +-- Missing spell (Knockdown) for Bloodmaul Mauler +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 19993) AND (`source_type` = 0) AND (`id` IN (4)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(19993, 0, 4, 0, 0, 0, 100, 0, 15000, 30000, 30000, 60000, 0, 0, 11, 37592, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Bloodmaul Mauler - In Combat - Cast Knockdown'); + +-- Missing spell (Knockdown) for Bloodmaul Taskmaster +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 22160) AND (`source_type` = 0) AND (`id` IN (5)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(22160, 0, 5, 0, 0, 0, 100, 0, 20000, 50000, 60000, 90000, 0, 0, 11, 37592, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Bloodmaul Taskmaster - In Combat - Cast Knockdown'); From 30e77ae8807a5be29d763482d9a01065f040e388 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 11 Sep 2024 14:20:11 +0000 Subject: [PATCH 17/26] chore(DB): import pending files Referenced commit(s): 0ac7ab03bb02c984a0917aefd763cf7ceebd371f --- .../rev_1723574442391883600.sql => db_world/2024_09_11_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1723574442391883600.sql => db_world/2024_09_11_01.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1723574442391883600.sql b/data/sql/updates/db_world/2024_09_11_01.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1723574442391883600.sql rename to data/sql/updates/db_world/2024_09_11_01.sql index f649c5a01..e579b7665 100644 --- a/data/sql/updates/pending_db_world/rev_1723574442391883600.sql +++ b/data/sql/updates/db_world/2024_09_11_01.sql @@ -1,3 +1,4 @@ +-- DB update 2024_09_11_00 -> 2024_09_11_01 -- Missing spell (Cleave) for Bladespire Brute DELETE FROM `smart_scripts` WHERE (`entryorguid` = 19995) AND (`source_type` = 0) AND (`id` IN (0)); INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES From 56d2cc7b4c975448680dfb79ecae91dadcbad22c Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:50:24 +0200 Subject: [PATCH 18/26] refactor(Cote/Unit): cleanup - part2 (#19821) * fix(Core/AI): remove an unused variable * Move variables at the end of each sections * reorder several methods * remove few inline defintions * few codestyle fixes --- src/server/game/Entities/Unit/Unit.cpp | 25 ++ src/server/game/Entities/Unit/Unit.h | 502 +++++++++++++------------ 2 files changed, 284 insertions(+), 243 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 659a42dbf..b9699d13d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -738,6 +738,20 @@ bool Unit::GetRandomContactPoint(Unit const* obj, float& x, float& y, float& z, return true; } +Unit* Unit::getAttackerForHelper() const +{ + if (GetVictim() != nullptr) + return GetVictim(); + + if (!IsEngaged()) + return nullptr; + + if (!m_attackers.empty()) + return *(m_attackers.begin()); + + return nullptr; +} + void Unit::UpdateInterruptMask() { m_interruptMask = 0; @@ -17222,6 +17236,17 @@ void Unit::SetContestedPvP(Player* attackedPlayer, bool lookForNearContestedGuar } } +void Unit::SetCantProc(bool apply) +{ + if (apply) + ++m_procDeep; + else + { + ASSERT(m_procDeep); + --m_procDeep; + } +} + void Unit::AddPetAura(PetAura const* petSpell) { if (!IsPlayer()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 4e7fc51d1..74dae4667 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -653,6 +653,8 @@ public: ~Unit() override; + void Update(uint32 time) override; + UnitAI* GetAI() { return i_AI; } void SetAI(UnitAI* newAI) { i_AI = newAI; } @@ -662,20 +664,101 @@ public: void CleanupBeforeRemoveFromMap(bool finalCleanup); void CleanupsBeforeDelete(bool finalCleanup = true) override; // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) + /*********************************************************/ + /*** UNIT HELPERS ***/ + /*********************************************************/ + void SetUInt32Value(uint16 index, uint32 value); /// @todo: move this in Object class or move GetUInt32value here but keep consistency + + void AddUnitState(uint32 f) { m_state |= f; } + [[nodiscard]] bool HasUnitState(const uint32 f) const { return (m_state & f); } + void ClearUnitState(uint32 f) { m_state &= ~f; } + [[nodiscard]] uint32 GetUnitState() const { return m_state; } + + [[nodiscard]] uint32 HasUnitTypeMask(uint32 mask) const { return mask & m_unitTypeMask; } + void AddUnitTypeMask(uint32 mask) { m_unitTypeMask |= mask; } + [[nodiscard]] uint32 GetUnitTypeMask() const { return m_unitTypeMask; } + + UnitFlags GetUnitFlags() const { return UnitFlags(GetUInt32Value(UNIT_FIELD_FLAGS)); } + bool HasUnitFlag(UnitFlags flags) const { return HasFlag(UNIT_FIELD_FLAGS, flags); } /// @brief UnitFlags available in UnitDefines.h + void SetUnitFlag(UnitFlags flags) { SetFlag(UNIT_FIELD_FLAGS, flags); } /// @brief UnitFlags available in UnitDefines.h + void RemoveUnitFlag(UnitFlags flags) { RemoveFlag(UNIT_FIELD_FLAGS, flags); } /// @brief Remove the Unit flag specify only + void ReplaceAllUnitFlags(UnitFlags flags) { SetUInt32Value(UNIT_FIELD_FLAGS, flags); } /// @brief Remove all UnitFlags and set new ones. UnitFlags available in UnitDefines.h + + UnitFlags2 GetUnitFlags2() const { return UnitFlags2(GetUInt32Value(UNIT_FIELD_FLAGS_2)); } + bool HasUnitFlag2(UnitFlags2 flags) const { return HasFlag(UNIT_FIELD_FLAGS_2, flags); } + void SetUnitFlag2(UnitFlags2 flags) { SetFlag(UNIT_FIELD_FLAGS_2, flags); } + void RemoveUnitFlag2(UnitFlags2 flags) { RemoveFlag(UNIT_FIELD_FLAGS_2, flags); } + void ReplaceAllUnitFlags2(UnitFlags2 flags) { SetUInt32Value(UNIT_FIELD_FLAGS_2, flags); } + + NPCFlags GetNpcFlags() const { return NPCFlags(GetUInt32Value(UNIT_NPC_FLAGS)); } + bool HasNpcFlag(NPCFlags flags) const { return HasFlag(UNIT_NPC_FLAGS, flags) != 0; } + void SetNpcFlag(NPCFlags flags) { SetFlag(UNIT_NPC_FLAGS, flags); } + void RemoveNpcFlag(NPCFlags flags) { RemoveFlag(UNIT_NPC_FLAGS, flags); } + void ReplaceAllNpcFlags(NPCFlags flags) { SetUInt32Value(UNIT_NPC_FLAGS, flags); } + uint32 GetDynamicFlags() const override { return GetUInt32Value(UNIT_DYNAMIC_FLAGS); } void ReplaceAllDynamicFlags(uint32 flag) override { SetUInt32Value(UNIT_DYNAMIC_FLAGS, flag); } - DiminishingLevels GetDiminishing(DiminishingGroup group); - void IncrDiminishing(DiminishingGroup group); - float ApplyDiminishingToDuration(DiminishingGroup group, int32& duration, Unit* caster, DiminishingLevels Level, int32 limitduration); - void ApplyDiminishingAura(DiminishingGroup group, bool apply); - void ClearDiminishings() { m_Diminishing.clear(); } + /*********************************************************/ + /*** UNIT TYPES, CLASSES, RACES... ***/ + /*********************************************************/ - // target dependent range checks - float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; - float GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; + // Unit type methods + [[nodiscard]] bool IsSummon() const { return m_unitTypeMask & UNIT_MASK_SUMMON; } + [[nodiscard]] bool IsGuardian() const { return m_unitTypeMask & UNIT_MASK_GUARDIAN; } + [[nodiscard]] bool IsControllableGuardian() const { return m_unitTypeMask & UNIT_MASK_CONTROLABLE_GUARDIAN; } + [[nodiscard]] bool IsPet() const { return m_unitTypeMask & UNIT_MASK_PET; } + [[nodiscard]] bool IsHunterPet() const { return m_unitTypeMask & UNIT_MASK_HUNTER_PET; } + [[nodiscard]] bool IsTotem() const { return m_unitTypeMask & UNIT_MASK_TOTEM; } + [[nodiscard]] bool IsVehicle() const { return m_unitTypeMask & UNIT_MASK_VEHICLE; } - void Update(uint32 time) override; + // NPC type methods + [[nodiscard]] bool IsVendor() const { return HasNpcFlag(UNIT_NPC_FLAG_VENDOR); } + [[nodiscard]] bool IsTrainer() const { return HasNpcFlag(UNIT_NPC_FLAG_TRAINER); } + [[nodiscard]] bool IsQuestGiver() const { return HasNpcFlag(UNIT_NPC_FLAG_QUESTGIVER); } + [[nodiscard]] bool IsGossip() const { return HasNpcFlag(UNIT_NPC_FLAG_GOSSIP); } + [[nodiscard]] bool IsTaxi() const { return HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER); } + [[nodiscard]] bool IsGuildMaster() const { return HasNpcFlag(UNIT_NPC_FLAG_PETITIONER); } + [[nodiscard]] bool IsBattleMaster() const { return HasNpcFlag(UNIT_NPC_FLAG_BATTLEMASTER); } + [[nodiscard]] bool IsBanker() const { return HasNpcFlag(UNIT_NPC_FLAG_BANKER); } + [[nodiscard]] bool IsInnkeeper() const { return HasNpcFlag(UNIT_NPC_FLAG_INNKEEPER); } + [[nodiscard]] bool IsSpiritHealer() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITHEALER); } + [[nodiscard]] bool IsSpiritGuide() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITGUIDE); } + [[nodiscard]] bool IsTabardDesigner() const { return HasNpcFlag(UNIT_NPC_FLAG_TABARDDESIGNER); } + [[nodiscard]] bool IsAuctioner() const { return HasNpcFlag(UNIT_NPC_FLAG_AUCTIONEER); } + [[nodiscard]] bool IsArmorer() const { return HasNpcFlag(UNIT_NPC_FLAG_REPAIR); } + [[nodiscard]] bool IsServiceProvider() const + { + return HasNpcFlag(UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_FLIGHTMASTER | + UNIT_NPC_FLAG_PETITIONER | UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER | + UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_SPIRITHEALER | + UNIT_NPC_FLAG_SPIRITGUIDE | UNIT_NPC_FLAG_TABARDDESIGNER | UNIT_NPC_FLAG_AUCTIONEER); + } + [[nodiscard]] bool IsSpiritService() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE); } + + // Race methods + [[nodiscard]] uint8 getRace(bool original = false) const; + void setRace(uint8 race); + [[nodiscard]] uint32 getRaceMask() const { return 1 << (getRace(true) - 1); } + [[nodiscard]] DisplayRace GetDisplayRaceFromModelId(uint32 modelId) const; + [[nodiscard]] DisplayRace GetDisplayRace() const { return GetDisplayRaceFromModelId(GetDisplayId()); }; + + // Class methods + [[nodiscard]] uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); } + [[nodiscard]] virtual bool IsClass(Classes unitClass, [[maybe_unused]] ClassContext context = CLASS_CONTEXT_NONE) const { return (getClass() == unitClass); } + [[nodiscard]] uint32 getClassMask() const { return 1 << (getClass() - 1); } + + // Gender methods + [[nodiscard]] uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); } + + // Factions methods + [[nodiscard]] uint32 GetFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); } + void SetFaction(uint32 faction); + [[nodiscard]] FactionTemplateEntry const* GetFactionTemplateEntry() const; + + /*********************************************************/ + /*** METHODS RELATED TO COMBATS ***/ + /*********************************************************/ void setAttackTimer(WeaponAttackType type, int32 time) { m_attackTimer[type] = time; } /// @todo - Look to convert to std::chrono void resetAttackTimer(WeaponAttackType type = BASE_ATTACK); @@ -692,30 +775,9 @@ public: float GetMeleeRange(Unit const* target) const; virtual SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const = 0; bool GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, bool force = false) const; - uint32 m_extraAttacks; - bool m_canDualWield; - void _addAttacker(Unit* pAttacker) // must be called only from Unit::Attack(Unit*) - { - m_attackers.insert(pAttacker); - } - void _removeAttacker(Unit* pAttacker) // must be called only from Unit::AttackStop() - { - m_attackers.erase(pAttacker); - } - [[nodiscard]] Unit* getAttackerForHelper() const // If someone wants to help, who to give them - { - if (GetVictim() != nullptr) - return GetVictim(); + [[nodiscard]] Unit* getAttackerForHelper() const; // If someone wants to help, who to give them - if (!IsEngaged()) - return nullptr; - - if (!m_attackers.empty()) - return *(m_attackers.begin()); - - return nullptr; - } bool Attack(Unit* victim, bool meleeAttack); void CastStop(uint32 except_spellid = 0, bool withInstant = true); @@ -735,39 +797,64 @@ public: void SendMeleeAttackStop(Unit* victim = nullptr); void SendMeleeAttackStart(Unit* victim, Player* sendTo = nullptr); - void AddUnitState(uint32 f) { m_state |= f; } - [[nodiscard]] bool HasUnitState(const uint32 f) const { return (m_state & f); } - void ClearUnitState(uint32 f) { m_state &= ~f; } - [[nodiscard]] uint32 GetUnitState() const { return m_state; } - [[nodiscard]] bool CanFreeMove() const + [[nodiscard]] uint32 GetAttackTime(WeaponAttackType att) const { - return !HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | - UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED) && !GetOwnerGUID(); + float f_BaseAttackTime = GetFloatValue(static_cast(UNIT_FIELD_BASEATTACKTIME) + att) / m_modAttackSpeedPct[att]; + return (uint32)f_BaseAttackTime; } - [[nodiscard]] uint32 HasUnitTypeMask(uint32 mask) const { return mask & m_unitTypeMask; } - void AddUnitTypeMask(uint32 mask) { m_unitTypeMask |= mask; } - [[nodiscard]] uint32 GetUnitTypeMask() const { return m_unitTypeMask; } - [[nodiscard]] bool IsSummon() const { return m_unitTypeMask & UNIT_MASK_SUMMON; } - [[nodiscard]] bool IsGuardian() const { return m_unitTypeMask & UNIT_MASK_GUARDIAN; } - [[nodiscard]] bool IsControllableGuardian() const { return m_unitTypeMask & UNIT_MASK_CONTROLABLE_GUARDIAN; } - [[nodiscard]] bool IsPet() const { return m_unitTypeMask & UNIT_MASK_PET; } - [[nodiscard]] bool IsHunterPet() const { return m_unitTypeMask & UNIT_MASK_HUNTER_PET; } - [[nodiscard]] bool IsTotem() const { return m_unitTypeMask & UNIT_MASK_TOTEM; } - [[nodiscard]] bool IsVehicle() const { return m_unitTypeMask & UNIT_MASK_VEHICLE; } + void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(static_cast(UNIT_FIELD_BASEATTACKTIME) + att, val * m_modAttackSpeedPct[att]); } + void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply); + void ApplyCastTimePercentMod(float val, bool apply); + void SetImmuneToAll(bool apply, bool keepCombat = false) { SetImmuneToPC(apply, keepCombat); SetImmuneToNPC(apply, keepCombat); } + bool IsImmuneToAll() const { return IsImmuneToPC() && IsImmuneToNPC(); } + void SetImmuneToPC(bool apply, bool keepCombat = false); + bool IsImmuneToPC() const { return HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC); } + void SetImmuneToNPC(bool apply, bool keepCombat = false); + bool IsImmuneToNPC() const { return HasUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC); } + + bool IsEngaged() const { return IsInCombat(); } + bool IsEngagedBy(Unit const* who) const { return IsInCombatWith(who); } + + [[nodiscard]] bool IsInCombat() const { return HasUnitFlag(UNIT_FLAG_IN_COMBAT); } + bool IsInCombatWith(Unit const* who) const; + + [[nodiscard]] bool IsPetInCombat() const { return HasUnitFlag(UNIT_FLAG_PET_IN_COMBAT); } + void CombatStart(Unit* target, bool initialAggro = true); + void CombatStartOnCast(Unit* target, bool initialAggro = true, uint32 duration = 0); + void SetInCombatState(bool PvP, Unit* enemy = nullptr, uint32 duration = 0); + void SetInCombatWith(Unit* enemy, uint32 duration = 0); + void ClearInCombat(); + void ClearInPetCombat(); + [[nodiscard]] uint32 GetCombatTimer() const { return m_CombatTimer; } + void SetCombatTimer(uint32 timer) { m_CombatTimer = timer; } + + // Threat related methods + [[nodiscard]] bool CanHaveThreatList() const; + void AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* threatSpell = nullptr); + float ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); + void TauntApply(Unit* victim); + void TauntFadeOut(Unit* taunter); + ThreatMgr& GetThreatMgr() { return m_ThreatMgr; } + ThreatMgr const& GetThreatMgr() const { return m_ThreatMgr; } + void addHatedBy(HostileReference* pHostileReference) { m_HostileRefMgr.insertFirst(pHostileReference); }; + void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ } + HostileRefMgr& getHostileRefMgr() { return m_HostileRefMgr; } + + // Redirect Threat + void SetRedirectThreat(ObjectGuid guid, uint32 pct) { _redirectThreatInfo.Set(guid, pct); } + void ResetRedirectThreat() { SetRedirectThreat(ObjectGuid::Empty, 0); } + void ModifyRedirectThreat(int32 amount) { _redirectThreatInfo.ModifyThreatPct(amount); } + uint32 GetRedirectThreatPercent() { return _redirectThreatInfo.GetThreatPct(); } + [[nodiscard]] Unit* GetRedirectThreatTarget() const; + + /*********************************************************/ + /*** METHODS RELATED TO STATS ***/ + /*********************************************************/ [[nodiscard]] uint8 GetLevel() const { return uint8(GetUInt32Value(UNIT_FIELD_LEVEL)); } uint8 getLevelForTarget(WorldObject const* /*target*/) const override { return GetLevel(); } void SetLevel(uint8 lvl, bool showLevelChange = true); - [[nodiscard]] uint8 getRace(bool original = false) const; - void setRace(uint8 race); - [[nodiscard]] uint32 getRaceMask() const { return 1 << (getRace(true) - 1); } - [[nodiscard]] uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); } - [[nodiscard]] virtual bool IsClass(Classes unitClass, [[maybe_unused]] ClassContext context = CLASS_CONTEXT_NONE) const { return (getClass() == unitClass); } - [[nodiscard]] uint32 getClassMask() const { return 1 << (getClass() - 1); } - [[nodiscard]] uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); } - [[nodiscard]] DisplayRace GetDisplayRaceFromModelId(uint32 modelId) const; - [[nodiscard]] DisplayRace GetDisplayRace() const { return GetDisplayRaceFromModelId(GetDisplayId()); }; [[nodiscard]] float GetStat(Stats stat) const { return float(GetUInt32Value(static_cast(UNIT_FIELD_STAT0) + stat)); } void SetStat(Stats stat, int32 val) { SetStatInt32Value(static_cast(UNIT_FIELD_STAT0) + stat, val); } @@ -805,42 +892,58 @@ public: [[nodiscard]] uint32 GetMaxPower(Powers power) const { return GetUInt32Value(static_cast(UNIT_FIELD_MAXPOWER1) + power); } void SetPower(Powers power, uint32 val, bool withPowerUpdate = true, bool fromRegenerate = false); void SetMaxPower(Powers power, uint32 val); + // returns the change in power int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate = true); int32 ModifyPowerPct(Powers power, float pct, bool apply = true); - [[nodiscard]] uint32 GetAttackTime(WeaponAttackType att) const + // stat system + bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply); + void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; } + [[nodiscard]] float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const; + [[nodiscard]] float GetTotalStatValue(Stats stat, float additionalValue = 0.0f) const; + [[nodiscard]] float GetTotalAuraModValue(UnitMods unitMod) const; + [[nodiscard]] SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const; + [[nodiscard]] Stats GetStatByAuraGroup(UnitMods unitMod) const; + [[nodiscard]] Powers GetPowerTypeByAuraGroup(UnitMods unitMod) const; + [[nodiscard]] bool CanModifyStats() const { return m_canModifyStats; } + void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; } + virtual bool UpdateStats(Stats stat) = 0; + virtual bool UpdateAllStats() = 0; + virtual void UpdateResistances(uint32 school) = 0; + virtual void UpdateAllResistances(); + virtual void UpdateArmor() = 0; + virtual void UpdateMaxHealth() = 0; + virtual void UpdateMaxPower(Powers power) = 0; + virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0; + virtual void UpdateDamagePhysical(WeaponAttackType attType); + float GetTotalAttackPowerValue(WeaponAttackType attType, Unit* pVictim = nullptr) const; + [[nodiscard]] float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type, uint8 damageIndex = 0) const; + void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value, uint8 damageIndex = 0) { m_weaponDamage[attType][damageRange][damageIndex] = value; } + virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex = 0) = 0; + uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, uint8 itemDamagesMask = 0); + float GetAPMultiplier(WeaponAttackType attType, bool normalized); + //------------------------------------------------------// + + DiminishingLevels GetDiminishing(DiminishingGroup group); + void IncrDiminishing(DiminishingGroup group); + float ApplyDiminishingToDuration(DiminishingGroup group, int32& duration, Unit* caster, DiminishingLevels Level, int32 limitduration); + void ApplyDiminishingAura(DiminishingGroup group, bool apply); + void ClearDiminishings() { m_Diminishing.clear(); } + + // target dependent range checks + float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; + float GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; + + [[nodiscard]] bool CanFreeMove() const { - float f_BaseAttackTime = GetFloatValue(static_cast(UNIT_FIELD_BASEATTACKTIME) + att) / m_modAttackSpeedPct[att]; - return (uint32)f_BaseAttackTime; + return !HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | + UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED) && !GetOwnerGUID(); } - void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(static_cast(UNIT_FIELD_BASEATTACKTIME) + att, val * m_modAttackSpeedPct[att]); } - void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply); - void ApplyCastTimePercentMod(float val, bool apply); - - void SetUInt32Value(uint16 index, uint32 value); - - UnitFlags GetUnitFlags() const { return UnitFlags(GetUInt32Value(UNIT_FIELD_FLAGS)); } - bool HasUnitFlag(UnitFlags flags) const { return HasFlag(UNIT_FIELD_FLAGS, flags); } /// @brief UnitFlags available in UnitDefines.h - void SetUnitFlag(UnitFlags flags) { SetFlag(UNIT_FIELD_FLAGS, flags); } /// @brief UnitFlags available in UnitDefines.h - void RemoveUnitFlag(UnitFlags flags) { RemoveFlag(UNIT_FIELD_FLAGS, flags); } /// @brief Remove the Unit flag specify only - void ReplaceAllUnitFlags(UnitFlags flags) { SetUInt32Value(UNIT_FIELD_FLAGS, flags); } /// @brief Remove all UnitFlags and set new ones. UnitFlags available in UnitDefines.h - - UnitFlags2 GetUnitFlags2() const { return UnitFlags2(GetUInt32Value(UNIT_FIELD_FLAGS_2)); } - bool HasUnitFlag2(UnitFlags2 flags) const { return HasFlag(UNIT_FIELD_FLAGS_2, flags); } - void SetUnitFlag2(UnitFlags2 flags) { SetFlag(UNIT_FIELD_FLAGS_2, flags); } - void RemoveUnitFlag2(UnitFlags2 flags) { RemoveFlag(UNIT_FIELD_FLAGS_2, flags); } - void ReplaceAllUnitFlags2(UnitFlags2 flags) { SetUInt32Value(UNIT_FIELD_FLAGS_2, flags); } - [[nodiscard]] SheathState GetSheath() const { return SheathState(GetByteValue(UNIT_FIELD_BYTES_2, 0)); } virtual void SetSheath(SheathState sheathed) { SetByteValue(UNIT_FIELD_BYTES_2, 0, sheathed); } - // faction template id - [[nodiscard]] uint32 GetFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); } - void SetFaction(uint32 faction); - [[nodiscard]] FactionTemplateEntry const* GetFactionTemplateEntry() const; - ReputationRank GetReactionTo(Unit const* target, bool checkOriginalFaction = false) const; ReputationRank GetFactionReactionTo(FactionTemplateEntry const* factionTemplateEntry, Unit const* target) const; @@ -978,6 +1081,7 @@ public: return value; } + uint32 GetUnitMeleeSkill(Unit const* target = nullptr) const { return (target ? getLevelForTarget(target) : GetLevel()) * 5; } uint32 GetDefenseSkillValue(Unit const* target = nullptr) const; uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target = nullptr) const; @@ -987,61 +1091,10 @@ public: MeleeHitOutcome RollMeleeOutcomeAgainst (Unit const* victim, WeaponAttackType attType) const; MeleeHitOutcome RollMeleeOutcomeAgainst (Unit const* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const; - NPCFlags GetNpcFlags() const { return NPCFlags(GetUInt32Value(UNIT_NPC_FLAGS)); } - bool HasNpcFlag(NPCFlags flags) const { return HasFlag(UNIT_NPC_FLAGS, flags) != 0; } - void SetNpcFlag(NPCFlags flags) { SetFlag(UNIT_NPC_FLAGS, flags); } - void RemoveNpcFlag(NPCFlags flags) { RemoveFlag(UNIT_NPC_FLAGS, flags); } - void ReplaceAllNpcFlags(NPCFlags flags) { SetUInt32Value(UNIT_NPC_FLAGS, flags); } - - [[nodiscard]] bool IsVendor() const { return HasNpcFlag(UNIT_NPC_FLAG_VENDOR); } - [[nodiscard]] bool IsTrainer() const { return HasNpcFlag(UNIT_NPC_FLAG_TRAINER); } - [[nodiscard]] bool IsQuestGiver() const { return HasNpcFlag(UNIT_NPC_FLAG_QUESTGIVER); } - [[nodiscard]] bool IsGossip() const { return HasNpcFlag(UNIT_NPC_FLAG_GOSSIP); } - [[nodiscard]] bool IsTaxi() const { return HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER); } - [[nodiscard]] bool IsGuildMaster() const { return HasNpcFlag(UNIT_NPC_FLAG_PETITIONER); } - [[nodiscard]] bool IsBattleMaster() const { return HasNpcFlag(UNIT_NPC_FLAG_BATTLEMASTER); } - [[nodiscard]] bool IsBanker() const { return HasNpcFlag(UNIT_NPC_FLAG_BANKER); } - [[nodiscard]] bool IsInnkeeper() const { return HasNpcFlag(UNIT_NPC_FLAG_INNKEEPER); } - [[nodiscard]] bool IsSpiritHealer() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITHEALER); } - [[nodiscard]] bool IsSpiritGuide() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITGUIDE); } - [[nodiscard]] bool IsTabardDesigner() const { return HasNpcFlag(UNIT_NPC_FLAG_TABARDDESIGNER); } - [[nodiscard]] bool IsAuctioner() const { return HasNpcFlag(UNIT_NPC_FLAG_AUCTIONEER); } - [[nodiscard]] bool IsArmorer() const { return HasNpcFlag(UNIT_NPC_FLAG_REPAIR); } - [[nodiscard]] bool IsServiceProvider() const - { - return HasNpcFlag(UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_FLIGHTMASTER | - UNIT_NPC_FLAG_PETITIONER | UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER | - UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_SPIRITHEALER | - UNIT_NPC_FLAG_SPIRITGUIDE | UNIT_NPC_FLAG_TABARDDESIGNER | UNIT_NPC_FLAG_AUCTIONEER); - } - [[nodiscard]] bool IsSpiritService() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE); } [[nodiscard]] bool IsCritter() const { return GetCreatureType() == CREATURE_TYPE_CRITTER; } [[nodiscard]] bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); } - void SetImmuneToAll(bool apply, bool keepCombat = false) { SetImmuneToPC(apply, keepCombat); SetImmuneToNPC(apply, keepCombat); } - bool IsImmuneToAll() const { return IsImmuneToPC() && IsImmuneToNPC(); } - void SetImmuneToPC(bool apply, bool keepCombat = false); - bool IsImmuneToPC() const { return HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC); } - void SetImmuneToNPC(bool apply, bool keepCombat = false); - bool IsImmuneToNPC() const { return HasUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC); } - - bool IsEngaged() const { return IsInCombat(); } - bool IsEngagedBy(Unit const* who) const { return IsInCombatWith(who); } - - [[nodiscard]] bool IsInCombat() const { return HasUnitFlag(UNIT_FLAG_IN_COMBAT); } - bool IsInCombatWith(Unit const* who) const; - - [[nodiscard]] bool IsPetInCombat() const { return HasUnitFlag(UNIT_FLAG_PET_IN_COMBAT); } - void CombatStart(Unit* target, bool initialAggro = true); - void CombatStartOnCast(Unit* target, bool initialAggro = true, uint32 duration = 0); - void SetInCombatState(bool PvP, Unit* enemy = nullptr, uint32 duration = 0); - void SetInCombatWith(Unit* enemy, uint32 duration = 0); - void ClearInCombat(); - void ClearInPetCombat(); - [[nodiscard]] uint32 GetCombatTimer() const { return m_CombatTimer; } - void SetCombatTimer(uint32 timer) { m_CombatTimer = timer; } - [[nodiscard]] bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const; [[nodiscard]] bool virtual HasSpell(uint32 /*spellID*/) const { return false; } [[nodiscard]] bool HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura = 0) const; @@ -1207,7 +1260,6 @@ public: void RemoveCharmedBy(Unit* charmer); void RestoreFaction(); - ControlSet m_Controlled; [[nodiscard]] Unit* GetFirstControlled() const; void RemoveAllControlled(bool onDeath = false); @@ -1228,7 +1280,7 @@ public: void DeleteCharmInfo(); void UpdateCharmAI(); //Player* GetMoverSource() const; - SafeUnitPointer m_movedByPlayer; + SharedVisionList const& GetSharedVisionList() { return m_sharedVision; } void AddPlayerToVision(Player* player); void RemovePlayerFromVision(Player* player); @@ -1408,9 +1460,6 @@ public: [[nodiscard]] virtual bool IsMovementPreventedByCasting() const; - ObjectGuid m_SummonSlot[MAX_SUMMON_SLOT]; - ObjectGuid m_ObjectSlot[MAX_GAMEOBJECT_SLOT]; - [[nodiscard]] ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, 3)); } void SetShapeshiftForm(ShapeshiftForm form) { @@ -1425,44 +1474,6 @@ public: [[nodiscard]] bool IsInDisallowedMountForm() const; - float m_modMeleeHitChance; - float m_modRangedHitChance; - float m_modSpellHitChance; - int32 m_baseSpellCritChance; - - float m_threatModifier[MAX_SPELL_SCHOOL]; - float m_modAttackSpeedPct[3]; - - // Event handler - EventProcessor m_Events; - - // stat system - bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply); - void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; } - [[nodiscard]] float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const; - [[nodiscard]] float GetTotalStatValue(Stats stat, float additionalValue = 0.0f) const; - [[nodiscard]] float GetTotalAuraModValue(UnitMods unitMod) const; - [[nodiscard]] SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const; - [[nodiscard]] Stats GetStatByAuraGroup(UnitMods unitMod) const; - [[nodiscard]] Powers GetPowerTypeByAuraGroup(UnitMods unitMod) const; - [[nodiscard]] bool CanModifyStats() const { return m_canModifyStats; } - void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; } - virtual bool UpdateStats(Stats stat) = 0; - virtual bool UpdateAllStats() = 0; - virtual void UpdateResistances(uint32 school) = 0; - virtual void UpdateAllResistances(); - virtual void UpdateArmor() = 0; - virtual void UpdateMaxHealth() = 0; - virtual void UpdateMaxPower(Powers power) = 0; - virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0; - virtual void UpdateDamagePhysical(WeaponAttackType attType); - float GetTotalAttackPowerValue(WeaponAttackType attType, Unit* pVictim = nullptr) const; - [[nodiscard]] float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type, uint8 damageIndex = 0) const; - void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value, uint8 damageIndex = 0) { m_weaponDamage[attType][damageRange][damageIndex] = value; } - virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex = 0) = 0; - uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, uint8 itemDamagesMask = 0); - float GetAPMultiplier(WeaponAttackType attType, bool normalized); - bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const; bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const; @@ -1476,21 +1487,6 @@ public: void SetPhaseMask(uint32 newPhaseMask, bool update) override;// overwrite WorldObject::SetPhaseMask void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false) override; - SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; - uint32 m_lastSanctuaryTime; - - // Threat related methods - [[nodiscard]] bool CanHaveThreatList() const; - void AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* threatSpell = nullptr); - float ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); - void TauntApply(Unit* victim); - void TauntFadeOut(Unit* taunter); - ThreatMgr& GetThreatMgr() { return m_ThreatMgr; } - ThreatMgr const& GetThreatMgr() const { return m_ThreatMgr; } - void addHatedBy(HostileReference* pHostileReference) { m_HostileRefMgr.insertFirst(pHostileReference); }; - void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ } - HostileRefMgr& getHostileRefMgr() { return m_HostileRefMgr; } - VisibleAuraMap const* GetVisibleAuras() { return &m_visibleAuras; } AuraApplication* GetVisibleAura(uint8 slot) { @@ -1629,7 +1625,7 @@ public: void DisableSpline(); ///-----------Combo point system------------------- - // This unit having CP on other units + // This unit having CP on other units [[nodiscard]] uint8 GetComboPoints(Unit const* who = nullptr) const { return (who && m_comboTarget != who) ? 0 : m_comboPoints; } [[nodiscard]] uint8 GetComboPoints(ObjectGuid const& guid) const { return (m_comboTarget && m_comboTarget->GetGUID() == guid) ? m_comboPoints : 0; } [[nodiscard]] Unit* GetComboTarget() const { return m_comboTarget; } @@ -1660,21 +1656,9 @@ public: void UpdateAuraForGroup(uint8 slot); // proc trigger system - bool CanProc() {return !m_procDeep;} - void SetCantProc(bool apply) - { - if (apply) - ++m_procDeep; - else - { - ASSERT(m_procDeep); - --m_procDeep; - } - } + bool CanProc() { return !m_procDeep; } + void SetCantProc(bool apply); - // pet auras - typedef std::set PetAuraSet; - PetAuraSet m_petAuras; void AddPetAura(PetAura const* petSpell); void RemovePetAura(PetAura const* petSpell); void CastPetAura(PetAura const* aura); @@ -1683,14 +1667,6 @@ public: [[nodiscard]] uint32 GetModelForForm(ShapeshiftForm form, uint32 spellId) const; uint32 GetModelForTotem(PlayerTotemType totemType); - // Redirect Threat - void SetRedirectThreat(ObjectGuid guid, uint32 pct) { _redirectThreatInfo.Set(guid, pct); } - void ResetRedirectThreat() { SetRedirectThreat(ObjectGuid::Empty, 0); } - void ModifyRedirectThreat(int32 amount) { _redirectThreatInfo.ModifyThreatPct(amount); } - uint32 GetRedirectThreatPercent() { return _redirectThreatInfo.GetThreatPct(); } - [[nodiscard]] Unit* GetRedirectThreatTarget() const; - - bool IsAIEnabled, NeedChangeAI; bool CreateVehicleKit(uint32 id, uint32 creatureEntry); void RemoveVehicleKit(); [[nodiscard]] Vehicle* GetVehicleKit()const { return m_vehicleKit; } @@ -1702,9 +1678,6 @@ public: /// Returns the transport this unit is on directly (if on vehicle and transport, return vehicle) [[nodiscard]] TransportBase* GetDirectTransport() const; - bool m_ControlledByPlayer; - bool m_CreatedByPlayer; - bool HandleSpellClick(Unit* clicker, int8 seatId = -1); void EnterVehicle(Unit* base, int8 seatId = -1); void EnterVehicleUnattackable(Unit* base, int8 seatId = -1); @@ -1743,17 +1716,10 @@ public: TempSummon* ToTempSummon() { if (IsSummon()) return reinterpret_cast(this); else return nullptr; } [[nodiscard]] const TempSummon* ToTempSummon() const { if (IsSummon()) return reinterpret_cast(this); else return nullptr; } - // Safe mover - std::set SafeUnitPointerSet; void AddPointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.insert(sup); } void RemovePointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.erase(sup); } static void HandleSafeUnitPointersOnDelete(Unit* thisUnit); - // Relocation Nofier optimization - Position m_last_notify_position; - uint32 m_last_notify_mstime; - uint16 m_delayed_unit_relocation_timer; - uint16 m_delayed_unit_ai_notify_timer; - bool bRequestForcedVisibilityUpdate; + void ExecuteDelayedUnitRelocationEvent(); void ExecuteDelayedUnitAINotifyEvent(); @@ -1779,9 +1745,6 @@ public: void SetInstantCast(bool set) { _instantCast = set; } [[nodiscard]] bool CanInstantCast() const { return _instantCast; } - // Movement info - Movement::MoveSpline* movespline; - virtual void Talk(std::string_view text, ChatMsg msgType, Language language, float textRange, WorldObject const* target); virtual void Say(std::string_view text, Language language, WorldObject const* target = nullptr); virtual void Yell(std::string_view text, Language language, WorldObject const* target = nullptr); @@ -1806,18 +1769,76 @@ public: [[nodiscard]] uint32 GetOldFactionId() const { return _oldFactionId; } + //----------- Public variables ----------// + uint32 m_extraAttacks; + bool m_canDualWield; + + ControlSet m_Controlled; + + SafeUnitPointer m_movedByPlayer; + + ObjectGuid m_SummonSlot[MAX_SUMMON_SLOT]; + ObjectGuid m_ObjectSlot[MAX_GAMEOBJECT_SLOT]; + + float m_modMeleeHitChance; + float m_modRangedHitChance; + float m_modSpellHitChance; + int32 m_baseSpellCritChance; + + float m_threatModifier[MAX_SPELL_SCHOOL]; + float m_modAttackSpeedPct[3]; + + // Event handler + EventProcessor m_Events; + + SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; + uint32 m_lastSanctuaryTime; + + // pet auras + typedef std::set PetAuraSet; + PetAuraSet m_petAuras; + + bool IsAIEnabled; + bool NeedChangeAI; + + bool m_ControlledByPlayer; + bool m_CreatedByPlayer; + + // Safe mover + std::set SafeUnitPointerSet; + + // Relocation Nofier optimization + Position m_last_notify_position; + uint32 m_last_notify_mstime; + uint16 m_delayed_unit_relocation_timer; + uint16 m_delayed_unit_ai_notify_timer; + bool bRequestForcedVisibilityUpdate; + + // Movement info + Movement::MoveSpline* movespline; + protected: explicit Unit (bool isWorldObject); void BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) override; - UnitAI* i_AI, *i_disabledAI; - void _UpdateSpells(uint32 time); void _DeleteRemovedAuras(); void _UpdateAutoRepeatSpell(); + bool IsAlwaysVisibleFor(WorldObject const* seer) const override; + bool IsAlwaysDetectableFor(WorldObject const* seer) const override; + + 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); + + //----------- Protected variables ----------// + UnitAI* i_AI; + UnitAI* i_disabledAI; + uint8 m_realRace; uint8 m_race; @@ -1851,7 +1872,7 @@ protected: AuraEffectList m_modAuras[TOTAL_AURAS]; AuraList m_scAuras; // casted singlecast auras - AuraApplicationList m_interruptableAuras; // auras which have interrupt mask applied on unit + AuraApplicationList m_interruptableAuras; // auras which have interrupt mask applied on unit AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove uint32 m_interruptMask; @@ -1882,10 +1903,10 @@ protected: // xinef: apply resilience bool m_applyResilience; - bool IsAlwaysVisibleFor(WorldObject const* seer) const override; - bool IsAlwaysDetectableFor(WorldObject const* seer) const override; 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); @@ -1905,15 +1926,12 @@ private: void PatchValuesUpdate(ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPointers& posPointers, Player* target); void InvalidateValuesUpdateCache() { _valuesUpdateCache.clear(); } -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); + [[nodiscard]] float processDummyAuras(float TakenTotalMod) const; - uint32 m_rootTimes; + void _addAttacker(Unit* pAttacker) { m_attackers.insert(pAttacker); } ///@note: Call only in Unit::Attack() + void _removeAttacker(Unit* pAttacker) { m_attackers.erase(pAttacker); } ///@note: Call only in Unit::AttackStop() -private: + //----------- Private variables ----------// uint32 m_state; // Even derived shouldn't modify uint32 m_CombatTimer; uint32 m_lastManaUse; // msecs @@ -1937,8 +1955,6 @@ private: uint32 _oldFactionId; ///< faction before charm bool _isWalkingBeforeCharm; ///< Are we walking before we were charmed? - [[nodiscard]] float processDummyAuras(float TakenTotalMod) const; - uint32 _lastExtraAttackSpell; std::unordered_map extraAttacksTargets; ObjectGuid _lastDamagedTargetGuid; From a971f373a0d697225a16b0b69a2d4ec2fe441d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefano=20Borz=C3=AC?= Date: Wed, 11 Sep 2024 16:50:45 +0200 Subject: [PATCH 19/26] fix: default bgarenas visibility distance default value (#19938) * fix: default bgarenas visibility distance default value * chore: update worldserver.conf.dist --- src/server/apps/worldserver/worldserver.conf.dist | 6 +++--- src/server/game/Entities/Object/ObjectDefines.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index 2b2f58f2e..2fa6d467e 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -1277,17 +1277,17 @@ Visibility.GroupMode = 1 # Visibility.Distance.Instances # Visibility.Distance.BGArenas # Description: Visibility distance to see other players or gameobjects. -# Visibility on continents on retail ~100 yards. In BG/Arenas ~533. +# Visibility on continents on retail ~100 yards. In BG/Arenas ~250. # For instances default ~170. # Max limited by active player zone: ~ 333 # Min limit is max aggro radius (45) * Rate.Creature.Aggro # Default: 100 - (Visibility.Distance.Continents) # 170 - (Visibility.Distance.Instances) -# 533 - (Visibility.Distance.BGArenas) +# 250 - (Visibility.Distance.BGArenas) Visibility.Distance.Continents = 100 Visibility.Distance.Instances = 170 -Visibility.Distance.BGArenas = 533 +Visibility.Distance.BGArenas = 250 # # Visibility.ObjectSparkles diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h index 55c482633..2913e587b 100644 --- a/src/server/game/Entities/Object/ObjectDefines.h +++ b/src/server/game/Entities/Object/ObjectDefines.h @@ -40,7 +40,7 @@ #define DEFAULT_VISIBILITY_DISTANCE 100.0f // default visible distance, 100 yards on continents #define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards #define VISIBILITY_DIST_WINTERGRASP 175.0f -#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards +#define DEFAULT_VISIBILITY_BGARENAS 250.0f // default visible distance in BG/Arenas, roughly 250 yards #define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects #define DEFAULT_COMBAT_REACH 1.5f From d17c179c0345f93dfcc6ced3d22d4a00b6d6b4ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefano=20Borz=C3=AC?= Date: Wed, 11 Sep 2024 16:50:59 +0200 Subject: [PATCH 20/26] chore: remove unused hooks (#19919) --- .../game/Scripting/ScriptDefines/PlayerScript.cpp | 10 ---------- src/server/game/Scripting/ScriptDefines/PlayerScript.h | 6 ------ src/server/game/Scripting/ScriptMgr.h | 2 -- 3 files changed, 18 deletions(-) diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 022914352..9c6769f45 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -359,16 +359,6 @@ void ScriptMgr::OnPlayerJoinArena(Player* player) CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PLAYER_JOIN_ARENA, script->OnPlayerJoinArena(player)); } -void ScriptMgr::GetCustomGetArenaTeamId(Player const* player, uint8 slot, uint32& teamID) const -{ - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_GET_CUSTOM_GET_ARENA_TEAM_ID, script->GetCustomGetArenaTeamId(player, slot, teamID)); -} - -void ScriptMgr::GetCustomArenaPersonalRating(Player const* player, uint8 slot, uint32& rating) const -{ - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_GET_CUSTOM_ARENA_PERSONAL_RATING, script->GetCustomArenaPersonalRating(player, slot, rating)); -} - void ScriptMgr::OnGetMaxPersonalArenaRatingRequirement(Player const* player, uint32 minSlot, uint32& maxArenaRating) const { CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_MAX_PERSONAL_ARENA_RATING_REQUIREMENT, script->OnGetMaxPersonalArenaRatingRequirement(player, minSlot, maxArenaRating)); diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.h b/src/server/game/Scripting/ScriptDefines/PlayerScript.h index dfe68b18c..4b13b96e4 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.h +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.h @@ -404,12 +404,6 @@ public: // After player enters queue for Arena virtual void OnPlayerJoinArena(Player* /*player*/) { } - //Called when trying to get a team ID of a slot > 2 (This is for custom teams created by modules) - virtual void GetCustomGetArenaTeamId(Player const* /*player*/, uint8 /*slot*/, uint32& /*teamID*/) const { } - - //Called when trying to get players personal rating of an arena slot > 2 (This is for custom teams created by modules) - virtual void GetCustomArenaPersonalRating(Player const* /*player*/, uint8 /*slot*/, uint32& /*rating*/) const { } - //Called after the normal slots (0..2) for arena have been evaluated so that custom arena teams could modify it if nececasry virtual void OnGetMaxPersonalArenaRatingRequirement(Player const* /*player*/, uint32 /*minSlot*/, uint32& /*maxArenaRating*/) const {} diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index c35625b78..4dcb3bdfb 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -358,8 +358,6 @@ public: /* PlayerScript */ void OnEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool update); void OnPlayerJoinBG(Player* player); void OnPlayerJoinArena(Player* player); - void GetCustomGetArenaTeamId(Player const* player, uint8 slot, uint32& teamID) const; - void GetCustomArenaPersonalRating(Player const* player, uint8 slot, uint32& rating) const; void OnGetMaxPersonalArenaRatingRequirement(Player const* player, uint32 minSlot, uint32& maxArenaRating) const; void OnLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid); void OnBeforeFillQuestLootItem(Player* player, LootItem& item); From edd7e10dfc7651ed2657a09d5411771831c8ec1e Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:52:15 -0400 Subject: [PATCH 21/26] fix(Core/Spells): Resolve a case of triggered spells prolonging combat. (#19819) * Init. * Expand trigger info check. * Enclose evaluation in parentheses. Maybe workflow will be happy? --- src/server/game/Entities/Unit/Unit.cpp | 12 +++++++----- src/server/game/Spells/Spell.cpp | 3 ++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b9699d13d..705c36e23 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -20225,13 +20225,13 @@ void Unit::OutDebugInfo() const class AuraMunchingQueue : public BasicEvent { public: - AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId) { } + AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId, AuraEffect* aurEff) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId), _aurEff(aurEff) { } bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override { if (_owner.IsInWorld() && _owner.FindMap()) if (Unit* target = ObjectAccessor::GetUnit(_owner, _targetGUID)) - _owner.CastCustomSpell(_spellId, SPELLVALUE_BASE_POINT0, _basePoints, target, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, _owner.GetGUID()); + _owner.CastCustomSpell(_spellId, SPELLVALUE_BASE_POINT0, _basePoints, target, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, _aurEff, _owner.GetGUID()); return true; } @@ -20241,13 +20241,15 @@ private: ObjectGuid _targetGUID; int32 _basePoints; uint32 _spellId; + AuraEffect* _aurEff; }; void Unit::CastDelayedSpellWithPeriodicAmount(Unit* caster, uint32 spellId, AuraType auraType, int32 addAmount, uint8 effectIndex) { + AuraEffect* aurEff = nullptr; for (AuraEffectList::iterator i = m_modAuras[auraType].begin(); i != m_modAuras[auraType].end(); ++i) { - AuraEffect* aurEff = *i; + aurEff = *i; if (aurEff->GetCasterGUID() != caster->GetGUID() || aurEff->GetId() != spellId || aurEff->GetEffIndex() != effectIndex || !aurEff->GetTotalTicks()) continue; @@ -20257,9 +20259,9 @@ void Unit::CastDelayedSpellWithPeriodicAmount(Unit* caster, uint32 spellId, Aura // xinef: delay only for casting on different unit if (this == caster || !sWorld->getBoolConfig(CONFIG_MUNCHING_BLIZZLIKE)) - caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, addAmount, this, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, caster->GetGUID()); + caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, addAmount, this, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, aurEff, caster->GetGUID()); else - caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId), caster->m_Events.CalculateQueueTime(400)); + caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId, aurEff), caster->m_Events.CalculateQueueTime(400)); } void Unit::SendClearTarget() diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 24d07cc94..e26a2a087 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2931,7 +2931,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) { if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(effectUnit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL))) { - m_caster->CombatStart(effectUnit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_SUPRESS_TARGET_PROCS)); + if (!m_triggeredByAuraSpell.spellInfo || (!(m_triggeredByAuraSpell.spellInfo->Effects[m_triggeredByAuraSpell.effectIndex].TriggerSpell == m_spellInfo->Id) && !(m_triggeredByAuraSpell.spellInfo->IsAuraEffectEqual(m_spellInfo)))) + m_caster->CombatStart(effectUnit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_SUPRESS_TARGET_PROCS)); // Patch 3.0.8: All player spells which cause a creature to become aggressive to you will now also immediately cause the creature to be tapped. if (effectUnit->IsInCombatWith(m_caster)) From 4734582e5853acbeeadeeed45f19337374f2b3f1 Mon Sep 17 00:00:00 2001 From: Saqra1 <161769195+Saqra1@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:53:07 -0500 Subject: [PATCH 22/26] fix(Core/Spell): Refreshment Table position (#19704) Refreshment Table game object should be created at the same position its Refreshment Portal was created. --- src/server/game/Spells/SpellInfoCorrections.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index 0e3c9833a..7195b7c97 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4822,6 +4822,13 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AttributesEx3 |= SPELL_ATTR3_SUPRESS_CASTER_PROCS; }); + // Conjure Refreshment Table (Rank 1, Rank 2) + ApplySpellFix({ 43985, 58661 }, [](SpellInfo* spellInfo) + { + spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_CASTER_FRONT); + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_5_YARDS); + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; From 321ac4a8c23ba5e006239fceb89eb8409135bed4 Mon Sep 17 00:00:00 2001 From: Saqra1 <161769195+Saqra1@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:37:56 -0500 Subject: [PATCH 23/26] fix(Core/Spell): Summoning Portal position (#19705) * fix(Core/Spell): Summoning Portal position Summoning Portal is created in front of the caster but it is still too close to them. Move it away a bit. * Cleanup unused SpellInfo correction Spell 61994 was stopped being used for summons in favor of 23598 on: https://github.com/azerothcore/azerothcore-wotlk/commit/67010623a0670b507cbfd2ffc7e9cea7bcfca1a2 --- src/server/game/Spells/SpellInfoCorrections.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index 7195b7c97..f88dfbdc9 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -3954,12 +3954,6 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AttributesEx7 |= SPELL_ATTR7_CAN_CAUSE_INTERRUPT; }); - // Ritual of Summoning - ApplySpellFix({ 61994 }, [](SpellInfo* spellInfo) - { - spellInfo->ManaCostPercentage = 0; // Clicking on Warlock Summoning portal should not require mana - }); - // Shadowmeld ApplySpellFix({ 58984 }, [](SpellInfo* spellInfo) { @@ -4829,6 +4823,14 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_5_YARDS); }); + ApplySpellFix({ + 698, // Ritual of Summoning (portal for clicking) + 61993 // Ritual of Summoning (summons the closet) + }, [](SpellInfo* spellInfo) + { + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; From 5ae1473e3064beb4adf666e33a38b6072639069a Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:11:56 +0200 Subject: [PATCH 24/26] fix(Scripts/BlackTemple): Ajust Judgment timers and pass all the script to std::chrono (#19945) fix(Scripts/BT): ajust Judgment timers and pass all the script to std::chrono --- .../BlackTemple/boss_illidari_council.cpp | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp index 407506228..016cbdba8 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp @@ -262,7 +262,7 @@ struct boss_illidari_council_memberAI : public ScriptedAI if (events.GetNextEventTime(EVENT_KILL_TALK) == 0) { Talk(SAY_COUNCIL_SLAY); - events.ScheduleEvent(EVENT_KILL_TALK, 6000); + events.ScheduleEvent(EVENT_KILL_TALK, 6s); } } @@ -303,12 +303,12 @@ struct boss_gathios_the_shatterer : public boss_illidari_council_memberAI void JustEngagedWith(Unit* who) override { boss_illidari_council_memberAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_SPELL_BLESSING, 10000); - events.ScheduleEvent(EVENT_SPELL_AURA, 0); - events.ScheduleEvent(EVENT_SPELL_SEAL, 2000); - events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 6000); - events.ScheduleEvent(EVENT_SPELL_JUDGEMENT, 8000); - events.ScheduleEvent(EVENT_SPELL_CONSECRATION, 4000); + events.ScheduleEvent(EVENT_SPELL_BLESSING, 10s); + events.ScheduleEvent(EVENT_SPELL_AURA, 0s); + events.ScheduleEvent(EVENT_SPELL_SEAL, 2s); + events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 6s); + events.ScheduleEvent(EVENT_SPELL_JUDGEMENT, 15s); + events.ScheduleEvent(EVENT_SPELL_CONSECRATION, 4s); } void UpdateAI(uint32 diff) override @@ -328,18 +328,18 @@ struct boss_gathios_the_shatterer : public boss_illidari_council_memberAI me->CastSpell(member, _toggleBlessing ? SPELL_BLESSING_OF_PROTECTION : SPELL_BLESSING_OF_SPELL_WARDING); _toggleBlessing = !_toggleBlessing; } - events.ScheduleEvent(EVENT_SPELL_BLESSING, 15000); + events.ScheduleEvent(EVENT_SPELL_BLESSING, 15s); break; case EVENT_SPELL_AURA: me->CastSpell(me, _toggleAura ? SPELL_DEVOTION_AURA : SPELL_CHROMATIC_RESISTANCE_AURA); _toggleAura = !_toggleAura; - events.ScheduleEvent(EVENT_SPELL_AURA, 60000); + events.ScheduleEvent(EVENT_SPELL_AURA, 60s); break; case EVENT_SPELL_CONSECRATION: if (roll_chance_i(50)) Talk(SAY_COUNCIL_SPECIAL); me->CastSpell(me, SPELL_CONSECRATION, false); - events.ScheduleEvent(EVENT_SPELL_AURA, 30000); + events.ScheduleEvent(EVENT_SPELL_AURA, 30s); break; case EVENT_SPELL_HAMMER_OF_JUSTICE: if (Unit* target = me->GetVictim()) @@ -349,16 +349,16 @@ struct boss_gathios_the_shatterer : public boss_illidari_council_memberAI events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 20s); break; } - events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 0); + events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 0s); break; case EVENT_SPELL_SEAL: me->CastSpell(me, _toggleSeal ? SPELL_SEAL_OF_COMMAND : SPELL_SEAL_OF_BLOOD); _toggleSeal = !_toggleSeal; - events.ScheduleEvent(EVENT_SPELL_SEAL, 20000); + events.ScheduleEvent(EVENT_SPELL_SEAL, 20s); break; case EVENT_SPELL_JUDGEMENT: me->CastSpell(me->GetVictim(), SPELL_JUDGEMENT, false); - events.ScheduleEvent(EVENT_SPELL_JUDGEMENT, 20000); + events.ScheduleEvent(EVENT_SPELL_JUDGEMENT, 16s, 20s); break; } @@ -493,10 +493,10 @@ struct boss_lady_malande : public boss_illidari_council_memberAI void JustEngagedWith(Unit* who) override { boss_illidari_council_memberAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_SPELL_REFLECTIVE_SHIELD, 10000); - events.ScheduleEvent(EVENT_SPELL_CIRCLE_OF_HEALING, 20000); - events.ScheduleEvent(EVENT_SPELL_DIVINE_WRATH, 5000); - events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 15000); + events.ScheduleEvent(EVENT_SPELL_REFLECTIVE_SHIELD, 10s); + events.ScheduleEvent(EVENT_SPELL_CIRCLE_OF_HEALING, 20s); + events.ScheduleEvent(EVENT_SPELL_DIVINE_WRATH, 5s); + events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 15s); } void UpdateAI(uint32 diff) override @@ -512,22 +512,22 @@ struct boss_lady_malande : public boss_illidari_council_memberAI { case EVENT_SPELL_CIRCLE_OF_HEALING: me->CastSpell(me, SPELL_CIRCLE_OF_HEALING, false); - events.ScheduleEvent(EVENT_SPELL_CIRCLE_OF_HEALING, 20000); + events.ScheduleEvent(EVENT_SPELL_CIRCLE_OF_HEALING, 20s); break; case EVENT_SPELL_REFLECTIVE_SHIELD: if (roll_chance_i(50)) Talk(SAY_COUNCIL_SPECIAL); me->CastSpell(me, SPELL_REFLECTIVE_SHIELD, false); - events.ScheduleEvent(EVENT_SPELL_REFLECTIVE_SHIELD, 40000); + events.ScheduleEvent(EVENT_SPELL_REFLECTIVE_SHIELD, 40s); break; case EVENT_SPELL_DIVINE_WRATH: if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f)) me->CastSpell(target, SPELL_DIVINE_WRATH, false); - events.ScheduleEvent(EVENT_SPELL_DIVINE_WRATH, 20000); + events.ScheduleEvent(EVENT_SPELL_DIVINE_WRATH, 20s); break; case EVENT_SPELL_EMPOWERED_SMITE: me->CastSpell(me->GetVictim(), SPELL_EMPOWERED_SMITE, false); - events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 3000); + events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 3s); break; } } @@ -541,8 +541,8 @@ struct boss_veras_darkshadow : public boss_illidari_council_memberAI { me->SetCanDualWield(true); boss_illidari_council_memberAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_SPELL_VANISH, 10000); - events.ScheduleEvent(EVENT_SPELL_ENRAGE, 900000); + events.ScheduleEvent(EVENT_SPELL_VANISH, 10s); + events.ScheduleEvent(EVENT_SPELL_ENRAGE, 90s); } void JustSummoned(Creature* summon) override @@ -566,8 +566,8 @@ struct boss_veras_darkshadow : public boss_illidari_council_memberAI Talk(SAY_COUNCIL_SPECIAL); me->CastSpell(me, SPELL_DEADLY_STRIKE, false); me->CastSpell(me, SPELL_VANISH, false); - events.ScheduleEvent(EVENT_SPELL_VANISH, 60000); - events.ScheduleEvent(EVENT_SPELL_VANISH_OUT, 29000); + events.ScheduleEvent(EVENT_SPELL_VANISH, 60s); + events.ScheduleEvent(EVENT_SPELL_VANISH_OUT, 29s); break; case EVENT_SPELL_VANISH_OUT: me->CastSpell(me, SPELL_VANISH_OUT, false); From 20b443e011af4b6df32907c6297989d3a75b434a Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:58:18 +0200 Subject: [PATCH 25/26] refactor(Scripts/TempestKeep): remove an dev residual from Kael'Thas revamp (#19950) refactor(Scripts/TempestKeep): remove an dev rest from my last PR with Keal'Thas --- src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index 23226e225..4f881ff03 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -294,11 +294,6 @@ struct boss_kaelthas : public BossAI BossAI::AttackStart(who); } - void JustReachedHome() override - { - Reset(); - } - void MoveInLineOfSight(Unit* who) override { if (_phase == PHASE_NONE && who->IsPlayer() && me->IsValidAttackTarget(who)) From 4254827b2cadd253c694244b00c458122c96e9d3 Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:05:12 +0200 Subject: [PATCH 26/26] Revert "chore(Debug/Scripting): improve debug errors during the unloading scripts (#19643)" (#19951) This reverts commit db7183a5737646773a2f240f01b5891c1e4a4fe8. *wrongly use to catch sigsegv *null check isn't necessary: https://en.cppreference.com/w/cpp/memory/new/operator_delete --- src/server/game/Scripting/ScriptMgr.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index d97e568bf..9ec3ffeea 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -30,24 +30,9 @@ namespace template inline void SCR_CLEAR() { - for (auto& [scriptID, script] : ScriptRegistry::ScriptPointerList) + for (auto const& [scriptID, script] : ScriptRegistry::ScriptPointerList) { - try - { - if(script) - { - delete script; - script = nullptr; - } - } - catch (const std::exception& e) - { - LOG_ERROR("scripts.unloading", "Failed to unload script {} with ID: {}. Error: {}", script->GetName(), scriptID, e.what()); - } - catch (...) - { - LOG_ERROR("scripts.unloading", "Failed to unload script {} with ID: {}. Unknown error occurred.", script->GetName(), scriptID); - } + delete script; } ScriptRegistry::ScriptPointerList.clear();