From 2358b256f2d9d39ba5e9e7476b2e3126076478bd Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 13 Sep 2024 17:13:32 +0800 Subject: [PATCH] Revert "Merge branch 'master' into Playerbot" This reverts commit 9973151927437582e1b0e90a2e126273c116e795, reversing changes made to 6f5b504e4cfa46f54442b9b4c7f4b3294800214e. --- data/sql/updates/db_world/2024_09_09_00.sql | 3 - data/sql/updates/db_world/2024_09_11_00.sql | 6 - data/sql/updates/db_world/2024_09_11_01.sql | 15 - .../apps/worldserver/worldserver.conf.dist | 6 +- src/server/game/Battlegrounds/ArenaTeam.cpp | 5 +- .../game/Battlegrounds/Battleground.cpp | 2 - .../game/Battlegrounds/BattlegroundQueue.cpp | 4 - .../game/Entities/Creature/Creature.cpp | 4 +- .../Entities/Creature/TemporarySummon.cpp | 2 +- .../game/Entities/Object/ObjectDefines.h | 2 +- src/server/game/Entities/Unit/Unit.cpp | 40 +- src/server/game/Entities/Unit/Unit.h | 500 +++++++++--------- .../TargetedMovementGenerator.cpp | 27 +- .../TargetedMovementGenerator.h | 2 +- .../ScriptDefines/AllBattlegroundScript.cpp | 5 - .../ScriptDefines/AllBattlegroundScript.h | 3 - .../Scripting/ScriptDefines/ArenaScript.cpp | 5 - .../Scripting/ScriptDefines/ArenaScript.h | 3 - .../Scripting/ScriptDefines/PlayerScript.cpp | 10 + .../Scripting/ScriptDefines/PlayerScript.h | 6 + src/server/game/Scripting/ScriptMgr.cpp | 19 +- src/server/game/Scripting/ScriptMgr.h | 4 +- src/server/game/Spells/Spell.cpp | 3 +- src/server/game/Spells/SpellEffects.cpp | 17 + .../game/Spells/SpellInfoCorrections.cpp | 21 +- .../BlackrockSpire/boss_drakkisath.cpp | 2 +- .../EasternKingdoms/ZulAman/boss_nalorakk.cpp | 1 - .../Outland/BlackTemple/boss_bloodboil.cpp | 183 ++++--- .../Outland/BlackTemple/boss_illidan.cpp | 16 +- .../BlackTemple/boss_illidari_council.cpp | 50 +- .../BlackTemple/boss_shade_of_akama.cpp | 47 +- .../Outland/TempestKeep/Eye/boss_kaelthas.cpp | 5 + 32 files changed, 489 insertions(+), 529 deletions(-) delete mode 100644 data/sql/updates/db_world/2024_09_09_00.sql delete mode 100644 data/sql/updates/db_world/2024_09_11_00.sql delete mode 100644 data/sql/updates/db_world/2024_09_11_01.sql diff --git a/data/sql/updates/db_world/2024_09_09_00.sql b/data/sql/updates/db_world/2024_09_09_00.sql deleted file mode 100644 index e27b3f59ec4791..00000000000000 --- a/data/sql/updates/db_world/2024_09_09_00.sql +++ /dev/null @@ -1,3 +0,0 @@ --- DB update 2024_09_05_00 -> 2024_09_09_00 --- -UPDATE `creature_template` SET `flags_extra` = `flags_extra` |2147483648 WHERE `entry` = 22841; diff --git a/data/sql/updates/db_world/2024_09_11_00.sql b/data/sql/updates/db_world/2024_09_11_00.sql deleted file mode 100644 index f5e7b3a93bb435..00000000000000 --- a/data/sql/updates/db_world/2024_09_11_00.sql +++ /dev/null @@ -1,6 +0,0 @@ --- DB update 2024_09_09_00 -> 2024_09_11_00 -UPDATE `smart_scripts` -SET `event_param4` = 6000 -WHERE `entryorguid` = 22945 - AND `source_type` = 0 - AND `id` = 0; diff --git a/data/sql/updates/db_world/2024_09_11_01.sql b/data/sql/updates/db_world/2024_09_11_01.sql deleted file mode 100644 index e579b766523090..00000000000000 --- a/data/sql/updates/db_world/2024_09_11_01.sql +++ /dev/null @@ -1,15 +0,0 @@ --- 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 -(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'); diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index ad24a70179f9fa..c2c35da7eb3a5c 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 ~250. +# Visibility on continents on retail ~100 yards. In BG/Arenas ~533. # 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) -# 250 - (Visibility.Distance.BGArenas) +# 533 - (Visibility.Distance.BGArenas) Visibility.Distance.Continents = 100 Visibility.Distance.Instances = 170 -Visibility.Distance.BGArenas = 250 +Visibility.Distance.BGArenas = 533 # # Visibility.ObjectSparkles diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index f0532ee5b445e5..9f5ca8fa59fe8f 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -1034,10 +1034,7 @@ void ArenaTeam::CreateTempArenaTeam(std::vector playerList, uint8 type, { auto playerCountInTeam = static_cast(playerList.size()); - 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)); + ASSERT(playerCountInTeam == GetReqPlayersForType(type)); // Generate new arena team id TeamId = sArenaTeamMgr->GenerateTempArenaTeamId(); diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index b9858b3506106f..a68c8c643509c8 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -611,8 +611,6 @@ inline void Battleground::_ProcessJoin(uint32 diff) } m_ToBeTeleported.clear(); } - - sScriptMgr->OnArenaStart(this); } else { diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index 395a62a16d2e94..1d602967d8bbb7 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -773,10 +773,6 @@ 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/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 3ac41b1086acb0..961d55c1975da0 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -3679,7 +3679,7 @@ bool Creature::IsNotReachableAndNeedRegen() const std::shared_ptr const& Creature::GetLastLeashExtensionTimePtr() const { if (m_lastLeashExtensionTime == nullptr) - m_lastLeashExtensionTime = std::make_shared(GameTime::GetGameTime().count()); + m_lastLeashExtensionTime = std::make_shared(time(nullptr)); return m_lastLeashExtensionTime; } @@ -3700,7 +3700,7 @@ time_t Creature::GetLastLeashExtensionTime() const void Creature::UpdateLeashExtensionTime() { - (*GetLastLeashExtensionTimePtr()) = GameTime::GetGameTime().count(); + (*GetLastLeashExtensionTimePtr()) = time(nullptr); } bool Creature::CanPeriodicallyCallForAssistance() const diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp index 9513d1fc9877c7..86ea77673995d6 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 || properties->Category == SUMMON_CATEGORY_PET)) + if (properties && properties->Type == SUMMON_TYPE_PET) { m_unitTypeMask |= UNIT_MASK_CONTROLABLE_GUARDIAN; InitCharmInfo(); diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h index 2913e587b6d002..55c4826339ab93 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 250.0f // default visible distance in BG/Arenas, roughly 250 yards +#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 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 diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index d01fc681daeeb9..525ef48c0a1f6f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -738,20 +738,6 @@ 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; @@ -13573,9 +13559,6 @@ void Unit::SetInCombatWith(Unit* enemy, uint32 duration) } } - if (Creature* pCreature = ToCreature()) - pCreature->UpdateLeashExtensionTime(); - SetInCombatState(false, enemy, duration); } @@ -17253,17 +17236,6 @@ 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()) @@ -20256,13 +20228,13 @@ void Unit::OutDebugInfo() const class AuraMunchingQueue : public BasicEvent { public: - AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId, AuraEffect* aurEff) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId), _aurEff(aurEff) { } + AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId) { } 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, _aurEff, _owner.GetGUID()); + _owner.CastCustomSpell(_spellId, SPELLVALUE_BASE_POINT0, _basePoints, target, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, _owner.GetGUID()); return true; } @@ -20272,15 +20244,13 @@ class AuraMunchingQueue : public BasicEvent 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) { - aurEff = *i; + AuraEffect* aurEff = *i; if (aurEff->GetCasterGUID() != caster->GetGUID() || aurEff->GetId() != spellId || aurEff->GetEffIndex() != effectIndex || !aurEff->GetTotalTicks()) continue; @@ -20290,9 +20260,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, aurEff, caster->GetGUID()); + caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, addAmount, this, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, caster->GetGUID()); else - caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId, aurEff), caster->m_Events.CalculateQueueTime(400)); + caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId), caster->m_Events.CalculateQueueTime(400)); } void Unit::SendClearTarget() diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index ebf827fd3dab74..634a84226fcab3 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -653,8 +653,6 @@ class Unit : public WorldObject ~Unit() override; - void Update(uint32 time) override; - UnitAI* GetAI() { return i_AI; } void SetAI(UnitAI* newAI) { i_AI = newAI; } @@ -664,101 +662,20 @@ class Unit : public WorldObject 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); } - /*********************************************************/ - /*** UNIT TYPES, CLASSES, RACES... ***/ - /*********************************************************/ - - // 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; } - - // 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); } + 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(); } - // Factions methods - [[nodiscard]] uint32 GetFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); } - void SetFaction(uint32 faction); - [[nodiscard]] FactionTemplateEntry const* GetFactionTemplateEntry() const; + // target dependent range checks + float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; + float GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; - /*********************************************************/ - /*** METHODS RELATED TO COMBATS ***/ - /*********************************************************/ + void Update(uint32 time) override; void setAttackTimer(WeaponAttackType type, int32 time) { m_attackTimer[type] = time; } /// @todo - Look to convert to std::chrono void resetAttackTimer(WeaponAttackType type = BASE_ATTACK); @@ -775,9 +692,30 @@ class Unit : public WorldObject 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); @@ -797,64 +735,39 @@ class Unit : public WorldObject void SendMeleeAttackStop(Unit* victim = nullptr); void SendMeleeAttackStart(Unit* victim, Player* sendTo = nullptr); - [[nodiscard]] uint32 GetAttackTime(WeaponAttackType att) const + 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 { - 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 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; + [[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; } - /*********************************************************/ - /*** 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); } @@ -892,58 +805,42 @@ class Unit : public WorldObject [[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); - // 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); - //------------------------------------------------------// + [[nodiscard]] uint32 GetAttackTime(WeaponAttackType att) const + { + float f_BaseAttackTime = GetFloatValue(static_cast(UNIT_FIELD_BASEATTACKTIME) + att) / m_modAttackSpeedPct[att]; + return (uint32)f_BaseAttackTime; + } - 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(); } + 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); - // target dependent range checks - float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; - float GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; + void SetUInt32Value(uint16 index, uint32 value); - [[nodiscard]] bool CanFreeMove() const - { - return !HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | - UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED) && !GetOwnerGUID(); - } + 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; static ReputationRank GetFactionReactionTo(FactionTemplateEntry const* factionTemplateEntry, FactionTemplateEntry const* targetFactionTemplateEntry); @@ -1082,7 +979,6 @@ class Unit : public WorldObject 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; @@ -1092,10 +988,61 @@ class Unit : public WorldObject 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; @@ -1262,6 +1209,7 @@ class Unit : public WorldObject void RemoveCharmedBy(Unit* charmer); void RestoreFaction(); + ControlSet m_Controlled; [[nodiscard]] Unit* GetFirstControlled() const; void RemoveAllControlled(bool onDeath = false); @@ -1282,7 +1230,7 @@ class Unit : public WorldObject void DeleteCharmInfo(); void UpdateCharmAI(); //Player* GetMoverSource() const; - + SafeUnitPointer m_movedByPlayer; SharedVisionList const& GetSharedVisionList() { return m_sharedVision; } void AddPlayerToVision(Player* player); void RemovePlayerFromVision(Player* player); @@ -1462,6 +1410,9 @@ class Unit : public WorldObject [[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) { @@ -1476,6 +1427,44 @@ class Unit : public WorldObject [[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; @@ -1489,6 +1478,21 @@ class Unit : public WorldObject 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) { @@ -1627,7 +1631,7 @@ class Unit : public WorldObject 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; } @@ -1658,9 +1662,21 @@ class Unit : public WorldObject void UpdateAuraForGroup(uint8 slot); // proc trigger system - bool CanProc() { return !m_procDeep; } - void SetCantProc(bool apply); + bool CanProc() {return !m_procDeep;} + void SetCantProc(bool apply) + { + if (apply) + ++m_procDeep; + else + { + ASSERT(m_procDeep); + --m_procDeep; + } + } + // pet auras + typedef std::set PetAuraSet; + PetAuraSet m_petAuras; void AddPetAura(PetAura const* petSpell); void RemovePetAura(PetAura const* petSpell); void CastPetAura(PetAura const* aura); @@ -1669,6 +1685,14 @@ class Unit : public WorldObject [[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; } @@ -1680,6 +1704,9 @@ class Unit : public WorldObject /// 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); @@ -1718,10 +1745,17 @@ class Unit : public WorldObject 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(); @@ -1747,6 +1781,9 @@ class Unit : public WorldObject 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); @@ -1775,76 +1812,18 @@ class Unit : public WorldObject [[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; @@ -1878,7 +1857,7 @@ class Unit : public WorldObject 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; @@ -1909,10 +1888,10 @@ class Unit : public WorldObject // 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); @@ -1932,12 +1911,15 @@ class Unit : public WorldObject void PatchValuesUpdate(ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPointers& posPointers, Player* target); void InvalidateValuesUpdateCache() { _valuesUpdateCache.clear(); } - [[nodiscard]] float processDummyAuras(float TakenTotalMod) const; +protected: + void SetFeared(bool apply, Unit* fearedBy = nullptr, bool isFear = false); + void SetConfused(bool apply); + void SetStunned(bool apply); + void SetRooted(bool apply, bool isStun = false); - void _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() + uint32 m_rootTimes; - //----------- Private variables ----------// +private: uint32 m_state; // Even derived shouldn't modify uint32 m_CombatTimer; uint32 m_lastManaUse; // msecs @@ -1961,6 +1943,8 @@ class Unit : public WorldObject 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; diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 0a58d145088cd3..4dc2f55bd28243 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -78,11 +78,8 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) { owner->StopMoving(); _lastTargetPosition.reset(); - if (cOwner) - { - cOwner->UpdateLeashExtensionTime(); - cOwner->SetCannotReachTarget(); - } + if (Creature* cOwner2 = owner->ToCreature()) + cOwner2->SetCannotReachTarget(); return true; } @@ -131,8 +128,8 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) { i_recalculateTravel = false; i_path = nullptr; - if (cOwner) - cOwner->SetCannotReachTarget(); + if (Creature* cOwner2 = owner->ToCreature()) + cOwner2->SetCannotReachTarget(); owner->StopMoving(); owner->SetInFront(target); MovementInform(owner); @@ -146,25 +143,21 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) { i_recalculateTravel = false; i_path = nullptr; - if (cOwner) - cOwner->SetCannotReachTarget(); + if (Creature* cOwner2 = owner->ToCreature()) + cOwner2->SetCannotReachTarget(); owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); owner->SetInFront(target); MovementInform(owner); - } - if (owner->movespline->Finalized()) - { // Mobs should chase you infinitely if you stop and wait every few seconds. + // 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(); + i_leashExtensionTimer.Reset(5000); + if (Creature* creature = owner->ToCreature()) + creature->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 fd3064b5138ce4..4e7df89db811e1 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(1500), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {} + : TargetedMovementGeneratorBase(target), i_leashExtensionTimer(0), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {} ~ChaseMovementGenerator() { } MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; } diff --git a/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.cpp b/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.cpp index af617ddba39076..9367a748b5df7e 100644 --- a/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.cpp @@ -54,11 +54,6 @@ 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 9e8baba15103fe..880518b5dc548e 100644 --- a/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.h +++ b/src/server/game/Scripting/ScriptDefines/AllBattlegroundScript.h @@ -30,7 +30,6 @@ 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, @@ -79,8 +78,6 @@ class AllBattlegroundScript : public ScriptObject 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/ScriptDefines/ArenaScript.cpp b/src/server/game/Scripting/ScriptDefines/ArenaScript.cpp index b0869c79963afe..35baeb271a44cc 100644 --- a/src/server/game/Scripting/ScriptDefines/ArenaScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/ArenaScript.cpp @@ -39,11 +39,6 @@ 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 e9a3f1c800bc75..c50a964498a812 100644 --- a/src/server/game/Scripting/ScriptDefines/ArenaScript.h +++ b/src/server/game/Scripting/ScriptDefines/ArenaScript.h @@ -28,7 +28,6 @@ enum ArenaHook ARENAHOOK_ON_GET_POINTS, ARENAHOOK_CAN_SAVE_TO_DB, ARENAHOOK_ON_BEFORE_CHECK_WIN_CONDITION, - ARENAHOOK_ON_ARENA_START, ARENAHOOK_END }; @@ -49,8 +48,6 @@ class ArenaScript : public ScriptObject [[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/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 883b9eaf9b2891..3e4713adbd1c38 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -367,6 +367,16 @@ 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 59575562ae003a..0afa8081dd178b 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.h +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.h @@ -405,6 +405,12 @@ class PlayerScript : public ScriptObject // 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.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 22738ea997c45a..265a39c799edae 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -30,9 +30,24 @@ namespace template inline void SCR_CLEAR() { - for (auto const& [scriptID, script] : ScriptRegistry::ScriptPointerList) + for (auto& [scriptID, script] : ScriptRegistry::ScriptPointerList) { - delete script; + 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); + } } ScriptRegistry::ScriptPointerList.clear(); diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 888262995b7672..47a6c8669528d8 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -391,6 +391,8 @@ class ScriptMgr 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); @@ -615,7 +617,6 @@ class ScriptMgr 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); @@ -679,7 +680,6 @@ class ScriptMgr void OnGetPoints(ArenaTeam* team, uint32 memberRating, float& points); bool CanSaveToDB(ArenaTeam* team); bool OnBeforeArenaCheckWinConditions(Battleground* const bg); - void OnArenaStart(Battleground* const bg); public: /* MiscScript */ diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f8c26a2e7399dd..56b58548749f7a 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2931,8 +2931,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) { if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(effectUnit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL))) { - 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)); + 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)) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 5c16b3090d1e3b..aab419f79df4f9 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -6064,6 +6064,23 @@ 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*/) diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index f88dfbdc93c989..0e3c9833a7e18a 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -3954,6 +3954,12 @@ 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) { @@ -4816,21 +4822,6 @@ 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); - }); - - 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]; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp index 3935c78a129b0a..02e6196276aae8 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 @@ class boss_drakkisath : public CreatureScript _conflagrateThreat = me->GetThreatMgr().GetThreat(me->GetVictim()); me->GetThreatMgr().ModifyThreatByPercent(target, -100); } - events.ScheduleEvent(EVENT_CONFLAGRATION, 18s, 25s); + events.ScheduleEvent(EVENT_CONFLAGRATION, 10s, 13s); events.ScheduleEvent(EVENT_CHECK_CONFLAGRATION_TARGET, 10s); break; case EVENT_THUNDERCLAP: diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index 4a290c25311446..af0e1e19d30fe3 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -89,7 +89,6 @@ 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); diff --git a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp index af5189dad91f57..97c2a096d4df13 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp @@ -65,110 +65,127 @@ enum Misc GROUP_DELAY = 1 }; -struct boss_gurtogg_bloodboil : public BossAI +class boss_gurtogg_bloodboil : public CreatureScript { - boss_gurtogg_bloodboil(Creature* creature) : BossAI(creature, DATA_GURTOGG_BLOODBOIL), _recentlySpoken(false) { } +public: + boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { } - void Reset() override + CreatureAI* GetAI(Creature* creature) const override { - BossAI::Reset(); - _recentlySpoken = false; + return GetBlackTempleAI(creature); } - void JustEngagedWith(Unit* who) override + struct boss_gurtogg_bloodboilAI : public BossAI { - BossAI::JustEngagedWith(who); - Talk(SAY_AGGRO); + boss_gurtogg_bloodboilAI(Creature* creature) : BossAI(creature, DATA_GURTOGG_BLOODBOIL), _recentlySpoken(false) { } - DoCastSelf(SPELL_ACIDIC_WOUND, true); - - ScheduleTimedEvent(10s, [&] { - if (!me->HasAura(SPELL_FEL_RAGE_SELF)) - me->CastCustomSpell(SPELL_BLOODBOIL, SPELLVALUE_MAX_TARGETS, 5, me, false); - }, 10s); + void Reset() override + { + BossAI::Reset(); + _recentlySpoken = false; + } - ScheduleTimedEvent(38s, [&] { - DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_FEL_ACID_BREATH2 : SPELL_FEL_ACID_BREATH1); - }, 30s); + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); - ScheduleTimedEvent(14s, [&] { - DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_EJECT2 : SPELL_EJECT1); - }, 20s); + DoCastSelf(SPELL_ACIDIC_WOUND, true); - ScheduleTimedEvent(5s, [&] { - DoCastVictim(me->HasAura(SPELL_FEL_RAGE_SELF) ? SPELL_ARCING_SMASH2 : SPELL_ARCING_SMASH1); - }, 15s); + ScheduleTimedEvent(10s, [&] { + me->CastCustomSpell(SPELL_BLOODBOIL, SPELLVALUE_MAX_TARGETS, 5, me, false); + }, 10s); + + 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(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); + }); + } - ScheduleTimedEvent(1min, [&] { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 40.0f, true)) + void KilledUnit(Unit* /*victim*/) override + { + if (!_recentlySpoken) { - 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); - + Talk(SAY_SLAY); me->m_Events.AddEventAtOffset([&] { - DoCastVictim(SPELL_CHARGE); - }, 2s); - - scheduler.DelayGroup(GROUP_DELAY, 30s); + _recentlySpoken = false; + }, 6s); } - }, 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); - }); - } + } - bool CanAIAttack(Unit const* who) const override - { - return !who->IsImmunedToDamage(SPELL_SCHOOL_MASK_ALL); - } + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + summon->CastSpell(summon, SPELL_FEL_GEYSER_DAMAGE, false); + } - void KilledUnit(Unit* /*victim*/) override - { - if (!_recentlySpoken) + void JustDied(Unit* killer) override { - Talk(SAY_SLAY); - me->m_Events.AddEventAtOffset([&] { - _recentlySpoken = false; - }, 6s); + 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 @@ -214,7 +231,7 @@ class spell_gurtogg_eject : public SpellScript void AddSC_boss_gurtogg_bloodboil() { - RegisterBlackTempleCreatureAI(boss_gurtogg_bloodboil); + new boss_gurtogg_bloodboil(); RegisterSpellScript(spell_gurtogg_bloodboil); RegisterSpellScript(spell_gurtogg_eject); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index e4de895c3511dd..a07fc810d31c6b 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -1209,10 +1209,7 @@ enum WarbladeTear struct npc_blade_of_azzinoth : public ScriptedAI { - npc_blade_of_azzinoth(Creature* creature) : ScriptedAI(creature) - { - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - } + npc_blade_of_azzinoth(Creature* creature) : ScriptedAI(creature) { } void IsSummonedBy(WorldObject* /*summoner*/) override { @@ -1260,13 +1257,12 @@ enum FlameAzzinoth struct npc_flame_of_azzinoth : public ScriptedAI { - npc_flame_of_azzinoth(Creature* creature) : ScriptedAI(creature) { } + npc_flame_of_azzinoth(Creature* creature) : ScriptedAI(creature), _bladeSummoner(nullptr) { } void IsSummonedBy(WorldObject* /*summoner*/) override { // Flame is set to be Illidan's summon, so we check for nearest blade - if (Creature* _blade = me->FindNearestCreature(NPC_BLADE_OF_AZZINOTH, 15.0f)) - _bladeGUID = _blade->GetGUID(); + _bladeSummoner = me->FindNearestCreature(NPC_BLADE_OF_AZZINOTH, 15.0f); me->SetCorpseDelay(2); me->SetReactState(REACT_DEFENSIVE); @@ -1289,8 +1285,8 @@ struct npc_flame_of_azzinoth : public ScriptedAI void JustEngagedWith(Unit* /*who*/) override { ScheduleTimedEvent(10s, [&] { - if (Creature* _blade = ObjectAccessor::GetCreature(*me, _bladeGUID)) - if (Unit* target = _blade->AI()->SelectTarget(SelectTargetMethod::Random, 0, 30.0f, true)) + if (_bladeSummoner) + if (Unit* target = _bladeSummoner->AI()->SelectTarget(SelectTargetMethod::Random, 0, 30.f, true)) DoCast(target, SPELL_CHARGE); }, 5s, 20s); @@ -1305,7 +1301,7 @@ struct npc_flame_of_azzinoth : public ScriptedAI } private: - ObjectGuid _bladeGUID; + Creature* _bladeSummoner; }; class spell_illidan_draw_soul : public SpellScript diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp index 016cbdba89d090..407506228f2747 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, 6s); + events.ScheduleEvent(EVENT_KILL_TALK, 6000); } } @@ -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, 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); + 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); } 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, 15s); + events.ScheduleEvent(EVENT_SPELL_BLESSING, 15000); break; case EVENT_SPELL_AURA: me->CastSpell(me, _toggleAura ? SPELL_DEVOTION_AURA : SPELL_CHROMATIC_RESISTANCE_AURA); _toggleAura = !_toggleAura; - events.ScheduleEvent(EVENT_SPELL_AURA, 60s); + events.ScheduleEvent(EVENT_SPELL_AURA, 60000); 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, 30s); + events.ScheduleEvent(EVENT_SPELL_AURA, 30000); 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, 0s); + events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 0); break; case EVENT_SPELL_SEAL: me->CastSpell(me, _toggleSeal ? SPELL_SEAL_OF_COMMAND : SPELL_SEAL_OF_BLOOD); _toggleSeal = !_toggleSeal; - events.ScheduleEvent(EVENT_SPELL_SEAL, 20s); + events.ScheduleEvent(EVENT_SPELL_SEAL, 20000); break; case EVENT_SPELL_JUDGEMENT: me->CastSpell(me->GetVictim(), SPELL_JUDGEMENT, false); - events.ScheduleEvent(EVENT_SPELL_JUDGEMENT, 16s, 20s); + events.ScheduleEvent(EVENT_SPELL_JUDGEMENT, 20000); 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, 10s); - events.ScheduleEvent(EVENT_SPELL_CIRCLE_OF_HEALING, 20s); - events.ScheduleEvent(EVENT_SPELL_DIVINE_WRATH, 5s); - events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 15s); + 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); } 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, 20s); + events.ScheduleEvent(EVENT_SPELL_CIRCLE_OF_HEALING, 20000); 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, 40s); + events.ScheduleEvent(EVENT_SPELL_REFLECTIVE_SHIELD, 40000); 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, 20s); + events.ScheduleEvent(EVENT_SPELL_DIVINE_WRATH, 20000); break; case EVENT_SPELL_EMPOWERED_SMITE: me->CastSpell(me->GetVictim(), SPELL_EMPOWERED_SMITE, false); - events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 3s); + events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 3000); 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, 10s); - events.ScheduleEvent(EVENT_SPELL_ENRAGE, 90s); + events.ScheduleEvent(EVENT_SPELL_VANISH, 10000); + events.ScheduleEvent(EVENT_SPELL_ENRAGE, 900000); } 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, 60s); - events.ScheduleEvent(EVENT_SPELL_VANISH_OUT, 29s); + events.ScheduleEvent(EVENT_SPELL_VANISH, 60000); + events.ScheduleEvent(EVENT_SPELL_VANISH_OUT, 29000); break; case EVENT_SPELL_VANISH_OUT: me->CastSpell(me, SPELL_VANISH_OUT, false); 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 1f59b410e08492..9852bc345ea1ac 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -220,7 +220,6 @@ struct npc_akama_shade : public ScriptedAI DoCastSelf(SPELL_STEALTH, true); me->SetWalk(true); _sayLowHealth = false; - _died = false; scheduler.CancelAll(); } @@ -233,14 +232,14 @@ struct npc_akama_shade : public ScriptedAI case POINT_ENGAGE: me->SetHomePosition(me->GetPosition()); me->SetFaction(FACTION_ENGAGE); - DoCastSelf(SPELL_AKAMA_SOUL_CHANNEL, true); + DoCast(me, 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, [&] { @@ -276,19 +275,6 @@ 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 @@ -312,6 +298,18 @@ 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, [&] @@ -340,7 +338,6 @@ struct npc_akama_shade : public ScriptedAI private: bool _sayLowHealth; - bool _died; }; struct npc_creature_generator_akama : public ScriptedAI @@ -448,18 +445,27 @@ struct npc_creature_generator_akama : public ScriptedAI struct npc_ashtongue_sorcerer : public NullCreatureAI { - npc_ashtongue_sorcerer(Creature* creature) : NullCreatureAI(creature) { } + npc_ashtongue_sorcerer(Creature* creature) : NullCreatureAI(creature) + { + instance = creature->GetInstanceScript(); + } 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) { } + npc_ashtongue_channeler(Creature* creature) : NullCreatureAI(creature) + { + instance = creature->GetInstanceScript(); + } void Reset() override { @@ -478,6 +484,7 @@ struct npc_ashtongue_channeler : public NullCreatureAI } private: + InstanceScript* instance; TaskScheduler scheduler; }; diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index 4f881ff03bbbee..23226e22555a15 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -294,6 +294,11 @@ 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))