diff --git a/data/sql/updates/db_world/2022_05_23_00.sql b/data/sql/updates/db_world/2022_05_23_00.sql new file mode 100644 index 000000000..2eb2f1f3a --- /dev/null +++ b/data/sql/updates/db_world/2022_05_23_00.sql @@ -0,0 +1,3 @@ +-- DB update 2022_05_21_04 -> 2022_05_23_00 +-- +UPDATE `smart_scripts` SET `event_flags`=512 WHERE `entryorguid`=2830800; diff --git a/data/sql/updates/db_world/2022_05_23_01.sql b/data/sql/updates/db_world/2022_05_23_01.sql new file mode 100644 index 000000000..43ba27477 --- /dev/null +++ b/data/sql/updates/db_world/2022_05_23_01.sql @@ -0,0 +1,11 @@ +-- DB update 2022_05_23_00 -> 2022_05_23_01 +/* +Darnassus Temple of the Moon Moonwell spell focus objects +*/ + +DELETE FROM `gameobject` WHERE `guid` IN (2135451,2135452,2135453,2135454); +INSERT INTO `gameobject` VALUES +(2135451, 177281, 1, 0, 0, 1, 1, 9637.86, 2524.03, 1330, 0, -0, -0, 0, 0, 300, 0, 1, '', 0), +(2135452, 177281, 1, 0, 0, 1, 1, 9629.63, 2524.03, 1330, 0, -0, -0, 0, 0, 300, 0, 1, '', 0), +(2135453, 177281, 1, 0, 0, 1, 1, 9634.05, 2519.87, 1330, 0, -0, -0, 0, 0, 300, 0, 1, '', 0), +(2135454, 177281, 1, 0, 0, 1, 1, 9633.71, 2528.07, 1330, 0, -0, -0, 0, 0, 300, 0, 1, '', 0); diff --git a/data/sql/updates/db_world/2022_05_23_02.sql b/data/sql/updates/db_world/2022_05_23_02.sql new file mode 100644 index 000000000..a989eb1a5 --- /dev/null +++ b/data/sql/updates/db_world/2022_05_23_02.sql @@ -0,0 +1,3 @@ +-- DB update 2022_05_23_01 -> 2022_05_23_02 +-- +UPDATE `spell_proc_event` SET `procFlags`=0x1|0x20000 WHERE `entry`=-34914; diff --git a/data/sql/updates/db_world/2022_05_23_03.sql b/data/sql/updates/db_world/2022_05_23_03.sql new file mode 100644 index 000000000..66ca60ad6 --- /dev/null +++ b/data/sql/updates/db_world/2022_05_23_03.sql @@ -0,0 +1,15 @@ +-- DB update 2022_05_23_02 -> 2022_05_23_03 +-- Flamebringer fix flying animation while on ground +UPDATE `creature_template_movement` SET `Flight` = 0 WHERE `CreatureId` = 27292; + +-- Flamebringer remove all auras before mounting +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 27292; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 27292; +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`, `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 +(27292, 0, 0, 1, 62, 0, 100, 512, 9512, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Gossip Option 0 Selected - Remove all auras'), +(27292, 0, 1, 2, 61, 0, 100, 512, 0, 0, 0, 0, 0, 11, 48606, 3, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Gossip Option 0 Selected - Cast \'Flamebringer Summon Cue\''), +(27292, 0, 2, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Gossip Option 0 Selected - Close Gossip'), +(27292, 0, 3, 4, 54, 0, 100, 512, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Just Summoned - Remove Npc Flags Gossip'), +(27292, 0, 4, 5, 61, 0, 100, 512, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Just Summoned - Set Reactstate Passive'), +(27292, 0, 5, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 85, 48600, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Just Summoned - Invoker Cast \'Ride Flamebringer\''), +(27292, 0, 6, 0, 28, 0, 100, 512, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Passenger Removed - Despawn Instant'); diff --git a/data/sql/updates/db_world/2022_05_23_04.sql b/data/sql/updates/db_world/2022_05_23_04.sql new file mode 100644 index 000000000..d56a9e7b3 --- /dev/null +++ b/data/sql/updates/db_world/2022_05_23_04.sql @@ -0,0 +1,12 @@ +-- DB update 2022_05_23_03 -> 2022_05_23_04 +SET @LEADERGUID := 84542; +DELETE FROM `creature_formations` WHERE `memberGUID` IN (@LEADERGUID, 84190, 84194, 84192, 84541, 84543, 84186, 84188); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`) VALUES +(@LEADERGUID, @LEADERGUID, 0, 0, 3), +(@LEADERGUID, 84190, 0, 0, 3), +(@LEADERGUID, 84194, 0, 0, 3), +(@LEADERGUID, 84192, 0, 0, 3), +(@LEADERGUID, 84541, 0, 0, 3), +(@LEADERGUID, 84543, 0, 0, 3), +(@LEADERGUID, 84188, 0, 0, 3), +(@LEADERGUID, 84186, 0, 0, 3); diff --git a/data/sql/updates/db_world/2022_05_23_05.sql b/data/sql/updates/db_world/2022_05_23_05.sql new file mode 100644 index 000000000..9f149b64b --- /dev/null +++ b/data/sql/updates/db_world/2022_05_23_05.sql @@ -0,0 +1,13 @@ +-- DB update 2022_05_23_04 -> 2022_05_23_05 +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 10390; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 10390) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3, 4, 5, 6, 7)); +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`, `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 +(10390, 0, 0, 1, 60, 0, 100, 769, 0, 0, 0, 0, 0, 31, 1, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Guardian - On Update - Set Phase Random Between 1-3 (No Repeat)'), +(10390, 0, 1, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 211, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Guardian - On Update - Flag reset 0 (No Repeat)'), +(10390, 0, 2, 0, 1, 1, 100, 0, 1000, 5000, 600000, 600000, 0, 11, 13787, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Guardian - Out of Combat - Cast \'Demon Armor\' (Phase 1)'), +(10390, 0, 3, 0, 0, 1, 100, 0, 0, 1000, 3000, 4500, 0, 11, 9613, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Guardian - In Combat - Cast \'Shadow Bolt\' (Phase 1)'), +(10390, 0, 4, 0, 0, 2, 100, 0, 5000, 11000, 17000, 24500, 0, 11, 8364, 64, 0, 0, 0, 0, 5, 20, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Guardian - In Combat - Cast \'Blizzard\' (Phase 2)'), +(10390, 0, 5, 0, 0, 2, 100, 0, 0, 1000, 3000, 4500, 0, 11, 9672, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Guardian - In Combat - Cast \'Frostbolt\' (Phase 2)'), +(10390, 0, 6, 0, 0, 4, 100, 0, 4000, 11000, 13000, 24500, 0, 11, 11975, 64, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Guardian - In Combat - Cast \'Arcane Explosion\' (Phase 3)'), +(10390, 0, 7, 0, 0, 4, 100, 0, 0, 1000, 2000, 3500, 0, 11, 37361, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Guardian - In Combat - Cast \'Arcane Bolt\' (Phase 3)'); diff --git a/src/cmake/macros/FindMySQL.cmake b/src/cmake/macros/FindMySQL.cmake index 6ace25bc4..81f6dd18b 100644 --- a/src/cmake/macros/FindMySQL.cmake +++ b/src/cmake/macros/FindMySQL.cmake @@ -40,7 +40,7 @@ endif(WIN32) # Find MariaDB for Windows if (WIN32) # Set know versions MariaDB - set(_MARIADB_KNOWN_VERSIONS "MariaDB 10.8" "MariaDB 10.7" "MariaDB 10.6" "MariaDB 10.5") + set(_MARIADB_KNOWN_VERSIONS "MariaDB 10.9" "MariaDB 10.8" "MariaDB 10.7" "MariaDB 10.6" "MariaDB 10.5") # Set default options set(MARIADB_FOUND_LIB 0) diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp index bc9aca3b7..0253eb007 100644 --- a/src/server/game/AI/CoreAI/GuardAI.cpp +++ b/src/server/game/AI/CoreAI/GuardAI.cpp @@ -43,14 +43,14 @@ void GuardAI::EnterEvadeMode(EvadeReason /*why*/) { me->GetMotionMaster()->MoveIdle(); me->CombatStop(true); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); return; } LOG_DEBUG("entities.unit", "Guard entry: {} enters evade mode.", me->GetEntry()); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); // Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index b71f66729..fe71ffadc 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -563,7 +563,7 @@ void PetAI::HandleReturnMovement() me->GetCharmInfo()->SetForcedTargetGUID(); // xinef: remember that npcs summoned by npcs can also be pets - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->ClearInPetCombat(); } diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 91c2b1af3..78ae7cb46 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -305,7 +305,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) me->ClearComboPointHolders(); // Remove all combo points targeting this unit // sometimes bosses stuck in combat? - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->LoadCreaturesAddon(true); me->SetLootRecipient(nullptr); diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index 614c4e610..648c46d83 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -201,7 +201,7 @@ void npc_escortAI::ReturnToLastPoint() void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/) { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->SetLootRecipient(nullptr); diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index bf7c6d905..5930e0fb4 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -153,7 +153,7 @@ void FollowerAI::JustRespawned() void FollowerAI::EnterEvadeMode(EvadeReason /*why*/) { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->SetLootRecipient(nullptr); diff --git a/src/server/game/Combat/ThreatMgr.cpp b/src/server/game/Combat/ThreatMgr.cpp index ec106e79c..5a9bfcde5 100644 --- a/src/server/game/Combat/ThreatMgr.cpp +++ b/src/server/game/Combat/ThreatMgr.cpp @@ -406,6 +406,13 @@ ThreatMgr::ThreatMgr(Unit* owner) : iCurrentVictim(nullptr), iOwner(owner), iUpd { } +void ThreatMgr::ClearAllThreat() +{ + if (iOwner->CanHaveThreatList() && !isThreatListEmpty()) + iOwner->SendClearThreatListOpcode(); + clearReferences(); +} + //============================================================ void ThreatMgr::clearReferences() diff --git a/src/server/game/Combat/ThreatMgr.h b/src/server/game/Combat/ThreatMgr.h index 92a7f52f2..b6622d8e1 100644 --- a/src/server/game/Combat/ThreatMgr.h +++ b/src/server/game/Combat/ThreatMgr.h @@ -236,6 +236,8 @@ public: // -- compatibility layer for combat rewrite void ResetAllThreat() { resetAllAggro(); } + void ClearAllThreat(); + // Reset all aggro of unit in threadlist satisfying the predicate. template void resetAggro(PREDICATE predicate) { diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp index 4555f83c8..46902575f 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -15,6 +15,7 @@ * with this program. If not, see . */ +#include "SpellAuraEffects.h" #include "GameTime.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -26,7 +27,7 @@ #include "World.h" DynamicObject::DynamicObject(bool isWorldObject) : WorldObject(isWorldObject), MovableMapObject(), - _aura(nullptr), _removedAura(nullptr), _caster(nullptr), _duration(0), _isViewpoint(false) + _aura(nullptr), _removedAura(nullptr), _caster(nullptr), _duration(0), _isViewpoint(false), _updateViewerVisibilityTimer(0) { m_objectType |= TYPEMASK_DYNAMICOBJECT; m_objectTypeId = TYPEID_DYNAMICOBJECT; @@ -125,15 +126,17 @@ bool DynamicObject::CreateDynamicObject(ObjectGuid::LowType guidlow, Unit* caste SetFloatValue(DYNAMICOBJECT_RADIUS, radius); SetUInt32Value(DYNAMICOBJECT_CASTTIME, GameTime::GetGameTimeMS().count()); - if (IsWorldObject()) - setActive(true); //must before add to map to be put in world container - if (!GetMap()->AddToMap(this, true)) { // Returning false will cause the object to be deleted - remove from transport return false; } + if (IsWorldObject()) + { + setActive(true); + } + return true; } @@ -165,7 +168,22 @@ void DynamicObject::Update(uint32 p_time) if (expired) Remove(); else + { + if (_updateViewerVisibilityTimer) + { + if (_updateViewerVisibilityTimer <= p_time) + { + _updateViewerVisibilityTimer = 0; + + if (Player* playerCaster = _caster->ToPlayer()) + playerCaster->UpdateVisibilityForPlayer(); + } + else + _updateViewerVisibilityTimer -= p_time; + } + sScriptMgr->OnDynamicObjectUpdate(this, p_time); + } } void DynamicObject::Remove() @@ -214,13 +232,22 @@ void DynamicObject::RemoveAura() _removedAura->_Remove(AURA_REMOVE_BY_DEFAULT); } -void DynamicObject::SetCasterViewpoint() +void DynamicObject::SetCasterViewpoint(bool updateViewerVisibility) { if (Player* caster = _caster->ToPlayer()) { + // Remove old farsight viewpoint + if (Unit* farsightObject = ObjectAccessor::GetUnit(*caster, caster->GetGuidValue(PLAYER_FARSIGHT))) + { + _oldFarsightGUID = caster->GetGuidValue(PLAYER_FARSIGHT); + caster->SetViewpoint(farsightObject, false); + } + caster->SetViewpoint(this, true); _isViewpoint = true; } + + _updateViewerVisibilityTimer = updateViewerVisibility ? 100 : 0; } void DynamicObject::RemoveCasterViewpoint() @@ -229,6 +256,13 @@ void DynamicObject::RemoveCasterViewpoint() { caster->SetViewpoint(this, false); _isViewpoint = false; + + // Restore prev farsight viewpoint + if (Unit* farsightObject = ObjectAccessor::GetUnit(*caster, _oldFarsightGUID)) + { + caster->SetViewpoint(farsightObject, true); + } + _oldFarsightGUID.Clear(); } } diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h index 90d89c060..f7cef0326 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.h +++ b/src/server/game/Entities/DynamicObject/DynamicObject.h @@ -50,7 +50,7 @@ public: void Delay(int32 delaytime); void SetAura(Aura* aura); void RemoveAura(); - void SetCasterViewpoint(); + void SetCasterViewpoint(bool updateViewerVisibility); void RemoveCasterViewpoint(); [[nodiscard]] Unit* GetCaster() const { return _caster; } void BindToCaster(); @@ -60,11 +60,15 @@ public: [[nodiscard]] float GetRadius() const { return GetFloatValue(DYNAMICOBJECT_RADIUS); } [[nodiscard]] bool IsViewpoint() const { return _isViewpoint; } + ObjectGuid const& GetOldFarsightGUID() const { return _oldFarsightGUID; } + protected: Aura* _aura; Aura* _removedAura; Unit* _caster; int32 _duration; // for non-aura dynobjects bool _isViewpoint; + uint32 _updateViewerVisibilityTimer; + ObjectGuid _oldFarsightGUID; }; #endif diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 5d07919a0..023632c0f 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -65,7 +65,7 @@ constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max VISIBILITY_DISTANCE_SMALL, VISIBILITY_DISTANCE_LARGE, VISIBILITY_DISTANCE_GIGANTIC, - MAX_VISIBILITY_DISTANCE + VISIBILITY_DISTANCE_INFINITE }; Object::Object() : m_PackGUID(sizeof(uint64) + 1) @@ -1631,7 +1631,7 @@ float WorldObject::GetGridActivationRange() const { return ToCreature()->m_SightDistance; } - else if (GetTypeId() == TYPEID_GAMEOBJECT && ToGameObject()->IsTransport() && isActiveObject()) + else if (((GetTypeId() == TYPEID_GAMEOBJECT && ToGameObject()->IsTransport()) || GetTypeId() == TYPEID_DYNAMICOBJECT) && isActiveObject()) { return GetMap()->GetVisibilityRange(); } @@ -1643,7 +1643,7 @@ float WorldObject::GetVisibilityRange() const { if (IsVisibilityOverridden() && GetTypeId() == TYPEID_UNIT) { - return MAX_VISIBILITY_DISTANCE; + return *m_visibilityDistanceOverride; } else if (GetTypeId() == TYPEID_GAMEOBJECT) { @@ -1654,7 +1654,7 @@ float WorldObject::GetVisibilityRange() const } else if (IsVisibilityOverridden()) { - return MAX_VISIBILITY_DISTANCE; + return *m_visibilityDistanceOverride; } else { @@ -1676,7 +1676,7 @@ float WorldObject::GetSightRange(WorldObject const* target) const { if (target->IsVisibilityOverridden() && target->GetTypeId() == TYPEID_UNIT) { - return MAX_VISIBILITY_DISTANCE; + return *target->m_visibilityDistanceOverride; } else if (target->GetTypeId() == TYPEID_GAMEOBJECT) { @@ -1686,7 +1686,7 @@ float WorldObject::GetSightRange(WorldObject const* target) const } else if (target->IsVisibilityOverridden()) { - return MAX_VISIBILITY_DISTANCE; + return *target->m_visibilityDistanceOverride; } else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic()) { diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h index b578b5e6a..2dbd40426 100644 --- a/src/server/game/Entities/Object/ObjectDefines.h +++ b/src/server/game/Entities/Object/ObjectDefines.h @@ -31,6 +31,7 @@ #define MAX_VISIBILITY_DISTANCE 250.0f // max distance for visible objects, experimental #define SIGHT_RANGE_UNIT 50.0f #define MAX_SEARCHER_DISTANCE 150.0f // pussywizard: replace the use of MAX_VISIBILITY_DISTANCE in searchers, because MAX_VISIBILITY_DISTANCE is quite too big for this purpose +#define VISIBILITY_DISTANCE_INFINITE 533.0f #define VISIBILITY_DISTANCE_GIGANTIC 400.0f #define VISIBILITY_DISTANCE_LARGE 200.0f #define VISIBILITY_DISTANCE_NORMAL 100.0f diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 7bee92752..835fca061 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -6967,7 +6967,7 @@ void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change) continue; // Spells that should stay on the caster after removing the item. - constexpr std::array spellExceptions = { /*Electromagnetic Gigaflux Reactivator*/ 11826 }; + constexpr std::array spellExceptions = { /*Electromagnetic Gigaflux Reactivator*/ 11826 }; const auto found = std::find(std::begin(spellExceptions), std::end(spellExceptions), spellData.SpellId); // wrong triggering type @@ -12830,7 +12830,7 @@ void Player::SetViewpoint(WorldObject* target, bool apply) if (!AddGuidValue(PLAYER_FARSIGHT, target->GetGUID())) { - LOG_FATAL("entities.player", "Player::CreateViewpoint: Player {} cannot add new viewpoint!", GetName()); + LOG_DEBUG("entities.player", "Player::CreateViewpoint: Player {} cannot add new viewpoint!", GetName()); return; } @@ -12850,7 +12850,7 @@ void Player::SetViewpoint(WorldObject* target, bool apply) if (!RemoveGuidValue(PLAYER_FARSIGHT, target->GetGUID())) { - LOG_FATAL("entities.player", "Player::CreateViewpoint: Player {} cannot remove current viewpoint!", GetName()); + LOG_DEBUG("entities.player", "Player::CreateViewpoint: Player {} cannot remove current viewpoint!", GetName()); return; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 312e4cb78..67de69654 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1356,6 +1356,7 @@ public: void ApplyEnchantment(Item* item, bool apply); void UpdateSkillEnchantments(uint16 skill_id, uint16 curr_value, uint16 new_value); void SendEnchantmentDurations(); + void UpdateEnchantmentDurations(); void BuildEnchantmentsInfoData(WorldPacket* data); void AddItemDurations(Item* item); void RemoveItemDurations(Item* item); diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index 703ca5304..7e275bd1d 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -4758,6 +4758,14 @@ void Player::SendEnchantmentDurations() } } +void Player::UpdateEnchantmentDurations() +{ + for (EnchantDurationList::iterator itr = m_enchantDuration.begin(); itr != m_enchantDuration.end(); ++itr) + { + itr->item->SetEnchantmentDuration(itr->slot, itr->leftduration, this); + } +} + void Player::SendItemDurations() { for (ItemDurationList::const_iterator itr = m_itemDuration.begin(); itr != m_itemDuration.end(); ++itr) diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index e487c3f50..b41974cc5 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -97,6 +97,10 @@ void Totem::InitSummon() { SetReactState(REACT_AGGRESSIVE); GetOwner()->CastSpell(this, 6277, true); + + // Farsight objects should be active + setActive(true); + SetVisibilityDistanceOverride(VisibilityDistanceType::Infinite); } if (!IsInWater()) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index caa7d172c..7abf36cdc 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -893,7 +893,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage if (attacker && shareDamageTarget->GetTypeId() == TYPEID_PLAYER) attacker->SendSpellNonMeleeDamageLog(shareDamageTarget, spell, shareDamage, damageSchoolMask, shareAbsorb, shareResist, damagetype == DIRECT_DAMAGE, 0, false); - Unit::DealDamage(attacker, shareDamageTarget, shareDamage, cleanDamage, NODAMAGE, damageSchoolMask, spellProto, false); + Unit::DealDamage(attacker, shareDamageTarget, shareDamage, cleanDamage, NODAMAGE, damageSchoolMask, spellProto, false, false, damageSpell); } } @@ -1007,7 +1007,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage //if (attacker && victim->GetTypeId() == TYPEID_PLAYER && victim != attacker) //victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health); // pussywizard: optimization - Unit::Kill(attacker, victim, durabilityLoss, cleanDamage ? cleanDamage->attackType : BASE_ATTACK, spellProto); + Unit::Kill(attacker, victim, durabilityLoss, cleanDamage ? cleanDamage->attackType : BASE_ATTACK, spellProto, damageSpell); } else { @@ -3605,8 +3605,10 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) if (pSpell == m_currentSpells[CSpellType]) // avoid breaking self return; + bool bySelf = m_currentSpells[CSpellType] && m_currentSpells[CSpellType]->m_spellInfo->Id == pSpell->m_spellInfo->Id; + // break same type spell if it is not delayed - InterruptSpell(CSpellType, false); + InterruptSpell(CSpellType, false, true, bySelf); // special breakage effects: switch (CSpellType) @@ -3635,7 +3637,7 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) { // channel spells always break generic non-delayed and any channeled spells InterruptSpell(CURRENT_GENERIC_SPELL, false); - InterruptSpell(CURRENT_CHANNELED_SPELL); + InterruptSpell(CURRENT_CHANNELED_SPELL, true, true, bySelf); // it also does break autorepeat if not Auto Shot if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && @@ -5729,10 +5731,12 @@ DynamicObject* Unit::GetDynObject(uint32 spellId) return nullptr; } -void Unit::RemoveDynObject(uint32 spellId) +bool Unit::RemoveDynObject(uint32 spellId) { if (m_dynObj.empty()) - return; + return false; + + bool result = false; for (DynObjectList::iterator i = m_dynObj.begin(); i != m_dynObj.end();) { DynamicObject* dynObj = *i; @@ -5740,10 +5744,13 @@ void Unit::RemoveDynObject(uint32 spellId) { dynObj->Remove(); i = m_dynObj.begin(); + result = true; } else ++i; } + + return result; } void Unit::RemoveAllDynObjects() @@ -9940,7 +9947,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack) } // switch target - InterruptSpell(CURRENT_MELEE_SPELL); + InterruptSpell(CURRENT_MELEE_SPELL, true, true, true); if (!meleeAttack) ClearUnitState(UNIT_STATE_MELEE_ATTACKING); } @@ -13928,7 +13935,7 @@ void Unit::setDeathState(DeathState s, bool despawn) if (s != ALIVE && s != JUST_RESPAWNED) { CombatStop(); - DeleteThreatList(); + GetThreatMgr().ClearAllThreat(); getHostileRefMgr().deleteReferences(); ClearComboPointHolders(); // any combo points pointed to unit lost at it death @@ -14029,15 +14036,6 @@ void Unit::AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask, Sp //====================================================================== -void Unit::DeleteThreatList() -{ - if (CanHaveThreatList() && !m_ThreatMgr.isThreatListEmpty()) - SendClearThreatListOpcode(); - m_ThreatMgr.clearReferences(); -} - -//====================================================================== - void Unit::TauntApply(Unit* taunter) { ASSERT(GetTypeId() == TYPEID_UNIT); @@ -15108,7 +15106,7 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup) CombatStop(); ClearComboPoints(); ClearComboPointHolders(); - DeleteThreatList(); + GetThreatMgr().ClearAllThreat(); getHostileRefMgr().deleteReferences(); GetMotionMaster()->Clear(false); // remove different non-standard movement generators. } @@ -17233,7 +17231,7 @@ bool Unit::HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura) return true; } -void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackType attackType, SpellInfo const* spellProto) +void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackType attackType, SpellInfo const* spellProto, Spell const* spell /*= nullptr*/) { // Prevent killing unit twice (and giving reward from kill twice) if (!victim->GetHealth()) @@ -17350,15 +17348,15 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp if (killer && (killer->IsPet() || killer->IsTotem())) if (Unit* owner = killer->GetOwner()) { - owner->ProcDamageAndSpell(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto); + owner->ProcDamageAndSpell(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); sScriptMgr->OnCreatureKilledByPet( killer->GetCharmerOrOwnerPlayerOrPlayerItself(), victim->ToCreature()); } if (killer != victim && !victim->IsCritter()) - killer->ProcDamageAndSpell(victim, killer ? PROC_FLAG_KILL : 0, PROC_FLAG_KILLED, PROC_EX_NONE, 0, attackType, spellProto); + killer->ProcDamageAndSpell(victim, killer ? PROC_FLAG_KILL : 0, PROC_FLAG_KILLED, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); // Proc auras on death - must be before aura/combat remove - victim->ProcDamageAndSpell(nullptr, PROC_FLAG_DEATH, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto); + victim->ProcDamageAndSpell(nullptr, PROC_FLAG_DEATH, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); // update get killing blow achievements, must be done before setDeathState to be able to require auras on target // and before Spirit of Redemption as it also removes auras @@ -17457,7 +17455,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp if (!creature->IsPet() && creature->GetLootMode() > 0) { - creature->DeleteThreatList(); + creature->GetThreatMgr().ClearAllThreat(); // must be after setDeathState which resets dynamic flags if (!creature->loot.isLooted()) @@ -17952,14 +17950,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au if (GetTypeId() == TYPEID_UNIT) { - if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE)) - { - movementGenerator->Pause(0); - } - - GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE); - - StopMoving(); + GetMotionMaster()->MoveIdle(); if (charmer->GetTypeId() == TYPEID_PLAYER && charmer->getClass() == CLASS_WARLOCK) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index acf90d019..9ff7c6314 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1518,7 +1518,7 @@ public: uint16 GetMaxSkillValueForLevel(Unit const* target = nullptr) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } static void DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb); static uint32 DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true, bool allowGM = false, Spell const* spell = nullptr); - static void Kill(Unit* killer, Unit* victim, bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr); + static void Kill(Unit* killer, Unit* victim, bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr, Spell const* spell = nullptr); static int32 DealHeal(Unit* healer, Unit* victim, uint32 addhealth); void ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpellInfo = nullptr, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr, uint32 procPhase = 2 /*PROC_SPELL_PHASE_HIT*/); @@ -2107,7 +2107,6 @@ public: [[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 DeleteThreatList(); void TauntApply(Unit* victim); void TauntFadeOut(Unit* taunter); ThreatMgr& GetThreatMgr() { return m_ThreatMgr; } @@ -2142,7 +2141,7 @@ public: void _RegisterDynObject(DynamicObject* dynObj); void _UnregisterDynObject(DynamicObject* dynObj); DynamicObject* GetDynObject(uint32 spellId); - void RemoveDynObject(uint32 spellId); + bool RemoveDynObject(uint32 spellId); void RemoveAllDynObjects(); [[nodiscard]] GameObject* GetGameObject(uint32 spellId) const; diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index 519fa1cb0..e89c2d71c 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -243,6 +243,11 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData) } }); + if (err) + { + err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); + } + if (err <= 0) { grp->DoForAllMembers([err](Player* member) @@ -255,9 +260,6 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData) return; } - ASSERT(err > 0); - err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); - isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam() && bgTypeId != BATTLEGROUND_RB); uint32 avgWaitTime = 0; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 2719d2f88..973cee758 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1225,14 +1225,37 @@ void WorldSession::HandleFarSightOpcode(WorldPacket& recvData) if (WorldObject* target = _player->GetViewpoint()) _player->SetSeer(target); else - { LOG_DEBUG("network.opcode", "Player {} requests non-existing seer {}", _player->GetName(), _player->GetGuidValue(PLAYER_FARSIGHT).ToString()); - } } else { - LOG_DEBUG("network", "Player {} set vision to self", _player->GetGUID().ToString()); - _player->SetSeer(_player); + WorldObject* newFarsightobject = nullptr; + if (WorldObject* viewpoint = _player->GetViewpoint()) + { + if (DynamicObject* viewpointDynamicObject = viewpoint->ToDynObject()) + { + newFarsightobject = ObjectAccessor::GetUnit(*viewpointDynamicObject, viewpointDynamicObject->GetOldFarsightGUID()); + } + else if (DynamicObject* viewpointDynamicObject = _player->GetDynObject(_player->GetUInt32Value(UNIT_CHANNEL_SPELL))) + { + if (viewpointDynamicObject->IsViewpoint() && viewpointDynamicObject->GetCasterGUID() == _player->GetGUID()) + { + newFarsightobject = viewpointDynamicObject; + } + } + } + + if (newFarsightobject) + { + LOG_DEBUG("network", "Player {} set vision to old farsight {}", _player->GetGUID().ToString(), newFarsightobject->GetGUID().ToString()); + _player->SetViewpoint(_player->GetViewpoint(), false); + _player->SetViewpoint(newFarsightobject, true); + } + else + { + LOG_DEBUG("network", "Player {} set vision to self", _player->GetGUID().ToString()); + _player->SetSeer(_player); + } } GetPlayer()->UpdateVisibilityForPlayer(); diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 5f0c3cc97..be3d6c522 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -576,7 +576,7 @@ void WorldSession::HandleCancelChanneling(WorldPacket& recvData) if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) return; - mover->InterruptSpell(CURRENT_CHANNELED_SPELL, true, true, true); + mover->InterruptSpell(CURRENT_CHANNELED_SPELL); } void WorldSession::HandleTotemDestroyed(WorldPackets::Totem::TotemDestroyed& totemDestroyed) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index dbc1db87e..9758eeebc 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3639,8 +3639,15 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const // skip triggered spell (item equip spell casting and other not explicit character casts/item uses) if (!(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS) && m_spellInfo->IsBreakingStealth()) { - m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST, 0, m_spellInfo->Id == 75); - m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK, 0, m_spellInfo->Id == 75); + // Farsight spells exception + uint32 exceptSpellId = 0; + if (m_spellInfo->HasEffect(SPELL_EFFECT_ADD_FARSIGHT)) + { + exceptSpellId = m_spellInfo->Id; + } + + m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST, exceptSpellId, m_spellInfo->Id == 75); + m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK, exceptSpellId, m_spellInfo->Id == 75); } m_caster->SetCurrentCastedSpell(this); @@ -3700,14 +3707,17 @@ void Spell::cancel(bool bySelf) break; case SPELL_STATE_CASTING: - for (std::list::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) - if ((*ihit).missCondition == SPELL_MISS_NONE) - if (Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID)) - unit->RemoveOwnedAura(m_spellInfo->Id, m_originalCasterGUID, 0, AURA_REMOVE_BY_CANCEL); + if (!bySelf) + { + for (std::list::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + if ((*ihit).missCondition == SPELL_MISS_NONE) + if (Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID)) + unit->RemoveOwnedAura(m_spellInfo->Id, m_originalCasterGUID, 0, AURA_REMOVE_BY_CANCEL); - SendChannelUpdate(0); - SendInterrupted(0); - SendCastResult(SPELL_FAILED_INTERRUPTED); + SendChannelUpdate(0); + SendInterrupted(0); + SendCastResult(SPELL_FAILED_INTERRUPTED); + } if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->NeedSendSpectatorData()) ArenaSpectator::SendCommand_Spell(m_caster->FindMap(), m_caster->GetGUID(), "SPE", m_spellInfo->Id, bySelf ? 99998 : 99999); @@ -3718,7 +3728,6 @@ void Spell::cancel(bool bySelf) m_appliedMods.clear(); break; - default: break; } @@ -3727,7 +3736,12 @@ void Spell::cancel(bool bySelf) if (m_selfContainer && *m_selfContainer == this) *m_selfContainer = nullptr; - m_caster->RemoveDynObject(m_spellInfo->Id); + // Do not remove current far sight object (already done in Spell::EffectAddFarsight) to prevent from reset viewpoint to player + if (!(bySelf && m_spellInfo->HasEffect(SPELL_EFFECT_ADD_FARSIGHT))) + { + m_caster->RemoveDynObject(m_spellInfo->Id); + } + if (m_spellInfo->IsChanneled()) // if not channeled then the object for the current cast wasn't summoned yet m_caster->RemoveGameObject(m_spellInfo->Id, true); @@ -8191,7 +8205,6 @@ void Spell::HandleLaunchPhase() PrepareTargetProcessing(); - bool firstTarget = true; for (std::list::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { TargetInfo& target = *ihit; @@ -8225,14 +8238,14 @@ void Spell::HandleLaunchPhase() break; } } - DoAllEffectOnLaunchTarget(target, multiplier, firstTarget); - firstTarget = false; + + DoAllEffectOnLaunchTarget(target, multiplier); } FinishTargetProcessing(); } -void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier, bool firstTarget) +void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) { Unit* unit = nullptr; // In case spell hit target, do all effect on that target @@ -8244,7 +8257,6 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier, if (!unit) return; - uint8 ssEffect = MAX_SPELL_EFFECTS; for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (targetInfo.effectMask & (1 << i)) @@ -8275,18 +8287,6 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier, m_damageMultipliers[i] *= multiplier[i]; } targetInfo.damage += m_damage; - - // Sweeping Strikes - switch (m_spellInfo->Effects[i].Effect) - { - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ssEffect = i; - break; - } } } @@ -8303,31 +8303,6 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier, float critChance = caster->SpellDoneCritChance(unit, m_spellInfo, m_spellSchoolMask, m_attackType, false); critChance = unit->SpellTakenCritChance(caster, m_spellInfo, m_spellSchoolMask, critChance, m_attackType, false); targetInfo.crit = roll_chance_f(std::max(0.0f, critChance)); - - // Sweeping strikes - if (m_caster->getClass() == CLASS_WARRIOR && ssEffect < MAX_SPELL_EFFECTS && m_spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && - ((m_spellInfo->Id != 50622 && m_spellInfo->Id != 44949) || firstTarget)) - { - if (Aura* aur = m_caster->GetAura(12328)) - { - Unit* target = m_caster->SelectNearbyNoTotemTarget(unit); - if (!target || target == unit) - return; // finish - - int32 mdmg = m_damage; - int32 basepoints = 0; - m_damage = 0; - - HandleEffects(target, nullptr, nullptr, ssEffect, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); - - basepoints = (targetInfo.crit ? Unit::SpellCriticalDamageBonus(m_caster, m_spellInfo, m_damage, target) : m_damage); - m_damage = mdmg; - m_caster->CastCustomSpell(target, 26654, &basepoints, nullptr, nullptr, true); - - if (m_spellInfo->Id != 44949) - aur->DropCharge(); - } - } } SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 75cecae7b..65f2d9bf7 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -708,7 +708,7 @@ public: bool UpdateChanneledTargetList(); bool IsValidDeadOrAliveTarget(Unit const* target) const; void HandleLaunchPhase(); - void DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier, bool firstTarget); + void DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier); void PrepareTargetProcessing(); void FinishTargetProcessing(); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index aa16c4026..2fb4afd0b 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2213,6 +2213,9 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex) if (!pNewItem) return; + // Client-side enchantment durations update + player->UpdateEnchantmentDurations(); + for (uint8 j = PERM_ENCHANTMENT_SLOT; j <= TEMP_ENCHANTMENT_SLOT; ++j) if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j))) pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j))); @@ -2719,6 +2722,9 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex) if (!m_caster->IsInWorld()) return; + // Remove old farsight if exist + bool updateViewerVisibility = m_caster->RemoveDynObject(m_spellInfo->Id); + DynamicObject* dynObj = new DynamicObject(true); if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid(), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS)) { @@ -2727,9 +2733,7 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex) } dynObj->SetDuration(duration); - dynObj->SetCasterViewpoint(); - - m_caster->ToPlayer()->UpdateVisibilityForPlayer(); + dynObj->SetCasterViewpoint(updateViewerVisibility); } void Spell::EffectUntrainTalents(SpellEffIndex /*effIndex*/) @@ -3348,13 +3352,6 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), 1) * 30.0f); break; } - // sweeping strikes - case 26654: - { - this->damage = 0; - m_damage = m_spellValue->EffectBasePoints[effIndex]; - return; - } } break; } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp index 8e8547b9c..329b36a9d 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp @@ -203,7 +203,7 @@ public: void EnterEvadeMode(EvadeReason /*why*/) override { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->LoadCreaturesAddon(true); if (me->IsAlive()) diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp index ba9e95003..9b483673a 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp @@ -779,7 +779,7 @@ public: //do not call EnterEvadeMode(), it will create infinit loops boss->Respawn(); boss->RemoveAllAuras(); - boss->DeleteThreatList(); + boss->GetThreatMgr().ClearAllThreat(); boss->CombatStop(true); boss->LoadCreaturesAddon(true); boss->GetMotionMaster()->MoveTargetedHome(); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp index 8078ec984..194f67610 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp @@ -1243,7 +1243,7 @@ public: Julianne->GetMotionMaster()->Clear(); Julianne->setDeathState(JUST_DIED); Julianne->CombatStop(true); - Julianne->DeleteThreatList(); + Julianne->GetThreatMgr().ClearAllThreat(); Julianne->ReplaceAllDynamicFlags(UNIT_DYNFLAG_LOOTABLE); } return; @@ -1546,7 +1546,7 @@ void boss_julianne::boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32& dama Romulo->GetMotionMaster()->Clear(); Romulo->setDeathState(JUST_DIED); Romulo->CombatStop(true); - Romulo->DeleteThreatList(); + Romulo->GetThreatMgr().ClearAllThreat(); Romulo->ReplaceAllDynamicFlags(UNIT_DYNFLAG_LOOTABLE); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp index e3ef5e429..9c15adbdc 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp @@ -242,7 +242,7 @@ public: void EnterEvadeMode(EvadeReason /*why*/) override { - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(false); me->SetLootRecipient(nullptr); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index c10e8543a..408aa1923 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -697,13 +697,13 @@ public: if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr)) { summon->CombatStop(true); - summon->DeleteThreatList(); + summon->GetThreatMgr().ClearAllThreat(); summon->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); summon->SetReactState(REACT_PASSIVE); summon->GetMotionMaster()->Clear(false); } me->CombatStop(true); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); me->SetReactState(REACT_PASSIVE); me->GetMotionMaster()->Clear(false); diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index f9da3901a..418ca14fd 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -329,7 +329,7 @@ public: me->SetTarget(); me->SetReactState(REACT_PASSIVE); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->SetRegeneratingHealth(false); me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->HandleEmoteCommand(EMOTE_ONESHOT_DROWN); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp index 429ba486d..19512ed78 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp @@ -137,31 +137,31 @@ public: if (DoGetThreat(me->GetVictim())) DoModifyThreatPercent(target, -100); Creature* SacrificedTroll; - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX() + 2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX + 2, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX() - 2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX - 2, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX() + 4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX + 4, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX() - 4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX - 4, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX(), target->GetPositionY() + 2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX, TeleportLoc.m_positionY + 2, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX(), target->GetPositionY() - 2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX, TeleportLoc.m_positionY - 2, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX(), target->GetPositionY() + 4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX, TeleportLoc.m_positionY + 4, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX(), target->GetPositionY() - 4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX, TeleportLoc.m_positionY - 4, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); - SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX() + 3, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX + 3, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (SacrificedTroll) SacrificedTroll->AI()->AttackStart(target); } diff --git a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp index 314a0f131..e7756d96e 100644 --- a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp +++ b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp @@ -71,8 +71,8 @@ public: if (player->GetQuestStatus(592) == QUEST_STATUS_INCOMPLETE) //Yenniku's Release { me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); - me->CombatStop(); //stop combat - me->DeleteThreatList(); //unsure of this + me->CombatStop(); //stop combat + me->GetThreatMgr().ClearAllThreat(); //unsure of this me->SetFaction(FACTION_HORDE_GENERIC); bReset = true; @@ -104,7 +104,7 @@ public: if (player->GetTeamId() == TEAM_HORDE) { me->CombatStop(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); } } } diff --git a/src/server/scripts/EasternKingdoms/zone_undercity.cpp b/src/server/scripts/EasternKingdoms/zone_undercity.cpp index 7e870bdfd..0dd04316c 100644 --- a/src/server/scripts/EasternKingdoms/zone_undercity.cpp +++ b/src/server/scripts/EasternKingdoms/zone_undercity.cpp @@ -1013,7 +1013,7 @@ public: void EnterEvadeMode(EvadeReason /*why*/) override { - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->SetLootRecipient(nullptr); @@ -2356,7 +2356,7 @@ public: void EnterEvadeMode(EvadeReason /*why*/) override { me->RemoveAura(SPELL_HEROIC_VANGUARD); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->SetLootRecipient(nullptr); diff --git a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp index 119ef3ec4..d4024d44c 100644 --- a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp @@ -118,7 +118,7 @@ public: me->RestoreFaction(); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); SetRun(false); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp index 3f2d64f50..65ddedf0b 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp @@ -410,7 +410,7 @@ void hyjalAI::EnterEvadeMode(EvadeReason /*why*/) { if (me->GetEntry() != JAINA) me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->LoadCreaturesAddon(true); diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp index 5b968e470..285e794cb 100644 --- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp +++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp @@ -178,7 +178,7 @@ public: void DoFriend() { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->StopMoving(); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp index ff5d0f0ed..096d8cf27 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp @@ -550,7 +550,7 @@ public: me->SetReactState(REACT_PASSIVE); me->RemoveAllAuras(); AddCreatureAddonAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->Clear(); me->StopMoving(); @@ -580,7 +580,7 @@ public: me->SetReactState(REACT_PASSIVE); me->RemoveAllAuras(); AddCreatureAddonAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->Clear(); me->SetRegeneratingHealth(false); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index b87d07929..eb68e0dfd 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -133,7 +133,7 @@ public: { t->RemoveAura(SPELL_CHANGE_VEHICLE); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->SetHealth(me->GetMaxHealth()); if( pInstance ) diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp index e0839ad0b..6ccce9d1b 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp @@ -523,7 +523,7 @@ public: if (TeamIdInInstance == TEAM_ALLIANCE) c->UpdateEntry(NPC_JAINA_PART2); } - c->DeleteThreatList(); + c->GetThreatMgr().ClearAllThreat(); c->CombatStop(true); c->InterruptNonMeleeSpells(true); c->GetMotionMaster()->Clear(); @@ -540,7 +540,7 @@ public: } if (Creature* c = instance->GetCreature(NPC_LichKingGUID)) { - c->DeleteThreatList(); + c->GetThreatMgr().ClearAllThreat(); c->CombatStop(true); c->InterruptNonMeleeSpells(true); c->GetMotionMaster()->Clear(); @@ -915,7 +915,7 @@ public: if (TrashActive[i]) if (Creature* c = instance->GetCreature(NPC_TrashGUID[i])) { - c->DeleteThreatList(); + c->GetThreatMgr().ClearAllThreat(); c->CombatStop(true); c->InterruptNonMeleeSpells(true); c->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE); @@ -1126,7 +1126,7 @@ public: if (Creature* c = instance->GetCreature(NPC_LichKingGUID)) { c->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - c->DeleteThreatList(); + c->GetThreatMgr().ClearAllThreat(); c->CombatStop(true); c->InterruptNonMeleeSpells(true); c->SetVisible(false); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp index 2012e3e2c..fc8354713 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp @@ -1123,7 +1123,7 @@ public: return; me->RemoveEvadeAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->LoadCreaturesAddon(true); me->SetLootRecipient(nullptr); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index 906799647..785cb9386 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -1202,7 +1202,7 @@ public: if (!attacker || attacker == me || attacker == me->GetVictim() || (det != DIRECT_DAMAGE && det != SPELL_DIRECT_DAMAGE)) return; - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->AddThreat(attacker, 500000000.0f); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index f30b7438e..44f572f0f 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -784,7 +784,7 @@ public: { if (!me->IsAlive()) return; - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->MoveTargetedHome(); Reset(); @@ -1120,7 +1120,7 @@ public: { if (!me->IsAlive()) return; - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->MoveTargetedHome(); Reset(); @@ -1496,7 +1496,7 @@ struct gunship_npc_AI : public ScriptedAI { if (!me->IsAlive() || !me->IsInCombat()) return; - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->MoveTargetedHome(); Reset(); @@ -1557,7 +1557,7 @@ struct npc_gunship_boarding_addAI : public ScriptedAI { if (!me->IsAlive() || !me->IsInCombat()) return; - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->MoveTargetedHome(); Reset(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index 8adef8955..e2c600ba0 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -515,7 +515,7 @@ public: { darnavan->RemoveAllAuras(); darnavan->SetFaction(FACTION_FRIENDLY); - darnavan->DeleteThreatList(); + darnavan->GetThreatMgr().ClearAllThreat(); darnavan->CombatStop(true); darnavan->GetMotionMaster()->MoveIdle(); darnavan->StopMoving(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index cec4d51e8..7e31e8550 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -1139,7 +1139,7 @@ public: void StartAttack() { GetCaster()->ClearUnitState(UNIT_STATE_CASTING); - GetCaster()->DeleteThreatList(); + GetCaster()->GetThreatMgr().ClearAllThreat(); GetCaster()->ToCreature()->SetInCombatWithZone(); GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit()); GetCaster()->AddThreat(GetHitUnit(), 500000000.0f); // value seen in sniff diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index ef952ecbb..1b611d389 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -1647,7 +1647,7 @@ public: return; } - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(false); } @@ -3370,7 +3370,7 @@ public: if (!me->IsAlive()) return; - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(false); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 12d723574..1d07f01e6 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -766,7 +766,7 @@ public: _handledWP4 = false; me->CombatStop(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); } } diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 5b14679b1..32ace18ec 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -710,7 +710,7 @@ public: me->SendMeleeAttackStop(me->GetVictim()); me->GetMotionMaster()->MoveTakeoff(MI_POINT_PH_3_FIGHT_POSITION, CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() - 5.0f, me->GetSpeed(MOVE_RUN)); - me->DeleteThreatList(); // players on vehicle are unattackable -> leads to EnterEvadeMode() because target is not acceptable! + me->GetThreatMgr().ClearAllThreat(); // players on vehicle are unattackable -> leads to EnterEvadeMode() because target is not acceptable! // mount players: Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); diff --git a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp index e181b034c..8b355d0ef 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp @@ -239,7 +239,7 @@ public: if (!_allowDeath) { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); damage = 0; diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp index 2707e8e1c..46f205a95 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp @@ -208,7 +208,7 @@ public: void LeaveCombat() { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->LoadCreaturesAddon(true); me->SetLootRecipient(nullptr); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index 2776c66ef..9bf1964e6 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -258,7 +258,7 @@ public: if (param == ACTION_CALLBACK) { me->SetSpeed(MOVE_RUN, 2.5f); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->MoveTargetedHome(); returning = true; diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp index b45e05a45..730c08429 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -384,7 +384,7 @@ struct violet_hold_trashAI : public npc_escortAI me->SetHomePosition(1845.577759f + rand_norm() * 5 - 2.5f, 800.681152f + rand_norm() * 5 - 2.5f, 44.104248f, M_PI); } - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); if (HasEscortState(STATE_ESCORT_ESCORTING)) { diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 7381c070c..b40420795 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -74,7 +74,7 @@ public: Creature* owner = GetOwner()->ToCreature(); owner->RemoveAllAurasExceptType(SPELL_AURA_DUMMY); owner->CombatStop(true); - owner->DeleteThreatList(); + owner->GetThreatMgr().ClearAllThreat(); owner->GetMotionMaster()->Clear(false); owner->GetMotionMaster()->MoveFollow(GetCaster(), 4.0f, M_PI, MOTION_SLOT_ACTIVE); owner->CastSpell(owner, SPELL_SUBDUED, true); diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index 4a6f01797..65ec06932 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -127,7 +127,7 @@ public: me->SetFaction(FACTION_FRIENDLY); me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); Talk(SAY_FREE); return; diff --git a/src/server/scripts/Outland/zone_terokkar_forest.cpp b/src/server/scripts/Outland/zone_terokkar_forest.cpp index 6c16496c0..567072a6c 100644 --- a/src/server/scripts/Outland/zone_terokkar_forest.cpp +++ b/src/server/scripts/Outland/zone_terokkar_forest.cpp @@ -374,7 +374,7 @@ public: me->SetFaction(FACTION_FRIENDLY); me->SetStandState(UNIT_STAND_STATE_SIT); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); UnkorUnfriendly_Timer = 60000; } diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp index ab9abfc60..2533462a5 100644 --- a/src/server/scripts/Pet/pet_hunter.cpp +++ b/src/server/scripts/Pet/pet_hunter.cpp @@ -52,7 +52,7 @@ struct npc_pet_hunter_snake_trap : public ScriptedAI void EnterEvadeMode(EvadeReason /*why*/) override { // _EnterEvadeMode(); - me->DeleteThreatList(); + me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->LoadCreaturesAddon(true); me->SetLootRecipient(nullptr); diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 627c8456d..0e715bf55 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -283,7 +283,7 @@ class spell_hun_taming_the_beast : public AuraScript { if (Creature* creature = target->ToCreature()) { - creature->DeleteThreatList(); + creature->GetThreatMgr().ClearAllThreat(); } } } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index f5b9cfb26..7c92f7ec7 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -841,7 +841,23 @@ class spell_pri_vampiric_touch : public AuraScript bool CheckProc(ProcEventInfo& eventInfo) { - return eventInfo.GetActionTarget() && eventInfo.GetActionTarget()->IsAlive() && GetOwner()->GetGUID() == eventInfo.GetActionTarget()->GetGUID(); + if (!eventInfo.GetActionTarget() || GetOwner()->GetGUID() != eventInfo.GetActionTarget()->GetGUID()) + return false; + + if (eventInfo.GetTypeMask() & PROC_FLAG_KILLED) + { + if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo()) + { + if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (spellInfo->SpellFamilyFlags[0] & 0x00002000)) + { + return true; + } + } + + return false; + } + + return eventInfo.GetActionTarget()->IsAlive(); } void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 8ce91057e..b107256d7 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -50,14 +50,16 @@ enum WarriorSpells SPELL_WARRIOR_RETALIATION_DAMAGE = 22858, SPELL_WARRIOR_SLAM = 50783, SPELL_WARRIOR_SUNDER_ARMOR = 58567, - SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK = 26654, + SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1 = 12723, + SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2 = 26654, SPELL_WARRIOR_TAUNT = 355, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1 = 46859, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_2 = 46860, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_1 = 64849, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_2 = 64850, SPELL_WARRIOR_VIGILANCE_PROC = 50725, - SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT = 59665 + SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT = 59665, + SPELL_WARRIOR_WHIRLWIND_OFF = 44949 }; enum WarriorSpellIcons @@ -613,7 +615,7 @@ class spell_warr_sweeping_strikes : public AuraScript bool Validate(SpellInfo const* /*spellInfo*/) override { - return ValidateSpellInfo({ SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK }); + return ValidateSpellInfo({ SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2 }); } bool Load() override @@ -624,21 +626,27 @@ class spell_warr_sweeping_strikes : public AuraScript bool CheckProc(ProcEventInfo& eventInfo) { - if (!eventInfo.GetActor() || eventInfo.GetProcTarget()) + Unit* actor = eventInfo.GetActor(); + if (!actor) { return false; } + if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo()) + { + switch (spellInfo->Id) + { + case SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1: + case SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2: + case SPELL_WARRIOR_WHIRLWIND_OFF: + return false; + default: + break; + } + } + _procTarget = eventInfo.GetActor()->SelectNearbyNoTotemTarget(eventInfo.GetProcTarget()); - - DamageInfo* damageInfo = eventInfo.GetDamageInfo(); - - if (!damageInfo || !damageInfo->GetSpellInfo()) - { - return false; - } - - return _procTarget && !damageInfo->GetSpellInfo(); + return _procTarget != nullptr; } void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) @@ -646,8 +654,17 @@ class spell_warr_sweeping_strikes : public AuraScript PreventDefaultAction(); if (DamageInfo* damageInfo = eventInfo.GetDamageInfo()) { - int32 damage = damageInfo->GetUnmitigatedDamage(); - GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK, &damage, 0, 0, true, nullptr, aurEff); + SpellInfo const* spellInfo = damageInfo->GetSpellInfo(); + if (spellInfo && spellInfo->Id == SPELL_WARRIOR_EXECUTE && !_procTarget->HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT)) + { + // If triggered by Execute (while target is not under 20% hp) deals normalized weapon damage + GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2, aurEff); + } + else + { + int32 damage = damageInfo->GetUnmitigatedDamage(); + GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, &damage, 0, 0, true, nullptr, aurEff); + } } } @@ -658,7 +675,7 @@ class spell_warr_sweeping_strikes : public AuraScript } private: - Unit* _procTarget; + Unit* _procTarget = nullptr; }; // 50720 - Vigilance diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 38ae3b935..2d3e22751 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -170,7 +170,7 @@ bool ExtractSingleWmo(std::string& fname) break; } - Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, &froot, preciseVectorData); + Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, preciseVectorData); for (uint16 groupReference : fgroup.DoodadReferences) { if (groupReference >= doodads.Spawns.size()) diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index a7b94a24f..e208ff2fa 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -289,7 +289,7 @@ bool WMOGroup::open(WMORoot* rootWMO) return true; } -int WMOGroup::ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool preciseVectorData) +int WMOGroup::ConvertToVMAPGroupWmo(FILE* output, bool preciseVectorData) { fwrite(&mogpFlags, sizeof(uint32), 1, output); fwrite(&groupWMOID, sizeof(uint32), 1, output); diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index d87edf3c8..8967a87a4 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -152,7 +152,7 @@ public: ~WMOGroup(); bool open(WMORoot* rootWMO); - int ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool preciseVectorData); + int ConvertToVMAPGroupWmo(FILE* output, bool preciseVectorData); uint32 GetLiquidTypeId(uint32 liquidTypeId); };