mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-19 06:29:50 -04:00
[3.3.5] Combat/Threat rewrite - prep & refactor (#19966)
* Combat/Threat rewrite (PR #19930) prep work. Mostly refactors, and a compatibility layer on ThreatManager/HostileReference that allows scripts to be changed already.
(cherry picked from commit e2a1ccd118)
This commit is contained in:
@@ -33,6 +33,7 @@ namespace Trinity
|
||||
{
|
||||
public:
|
||||
IteratorPair() : _iterators() { }
|
||||
IteratorPair(iterator first, iterator second) : _iterators(first, second) { }
|
||||
IteratorPair(std::pair<iterator, iterator> iterators) : _iterators(iterators) { }
|
||||
|
||||
iterator begin() const { return _iterators.first; }
|
||||
|
||||
@@ -44,14 +44,9 @@ void GuardAI::UpdateAI(uint32 /*diff*/)
|
||||
|
||||
bool GuardAI::CanSeeAlways(WorldObject const* obj)
|
||||
{
|
||||
if (!obj->isType(TYPEMASK_UNIT))
|
||||
return false;
|
||||
|
||||
ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
|
||||
if ((*itr)->getUnitGuid() == obj->GetGUID())
|
||||
if (Unit const* unit = obj->ToUnit())
|
||||
if (unit->IsControlledByPlayer() && me->IsEngagedBy(unit))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -61,14 +56,14 @@ void GuardAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
{
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->CombatStop(true);
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
return;
|
||||
}
|
||||
|
||||
TC_LOG_DEBUG("entities.unit", "Guard entry: %u enters evade mode.", me->GetEntry());
|
||||
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
|
||||
// Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
|
||||
|
||||
@@ -104,14 +104,14 @@ bool UnitAI::DoSpellAttackIfReady(uint32 spellId)
|
||||
return false;
|
||||
}
|
||||
|
||||
Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, int32 aura)
|
||||
Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, bool withTank, int32 aura)
|
||||
{
|
||||
return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, aura));
|
||||
return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, withTank, aura));
|
||||
}
|
||||
|
||||
void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly, int32 aura)
|
||||
void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, uint32 offset, float dist, bool playerOnly, bool withTank, int32 aura)
|
||||
{
|
||||
SelectTargetList(targetList, DefaultTargetSelector(me, dist, playerOnly, aura), num, targetType);
|
||||
SelectTargetList(targetList, num, targetType, offset, DefaultTargetSelector(me, dist, playerOnly, withTank, aura));
|
||||
}
|
||||
|
||||
void UnitAI::DoCast(uint32 spellId)
|
||||
@@ -152,7 +152,7 @@ void UnitAI::DoCast(uint32 spellId)
|
||||
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS);
|
||||
float range = spellInfo->GetMaxRange(false);
|
||||
|
||||
DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId);
|
||||
DefaultTargetSelector targetSelector(me, range, playerOnly, true, -(int32)spellId);
|
||||
if (!spellInfo->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_NOT_VICTIM) && targetSelector(me->GetVictim()))
|
||||
target = me->GetVictim();
|
||||
else
|
||||
@@ -319,7 +319,17 @@ uint32 UnitAI::GetDialogStatus(Player* /*player*/)
|
||||
|
||||
ThreatManager& UnitAI::GetThreatManager()
|
||||
{
|
||||
return me->getThreatManager();
|
||||
return me->GetThreatManager();
|
||||
}
|
||||
|
||||
void UnitAI::SortByDistance(std::list<Unit*> list, bool ascending)
|
||||
{
|
||||
list.sort(Trinity::ObjectDistanceOrderPred(me, ascending));
|
||||
}
|
||||
|
||||
DefaultTargetSelector::DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, bool withMainTank, int32 aura)
|
||||
: me(unit), m_dist(dist), m_playerOnly(playerOnly), except(withMainTank ? me->GetThreatManager().GetCurrentVictim() : nullptr), m_aura(aura)
|
||||
{
|
||||
}
|
||||
|
||||
bool DefaultTargetSelector::operator()(Unit const* target) const
|
||||
@@ -330,6 +340,9 @@ bool DefaultTargetSelector::operator()(Unit const* target) const
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
if (target == except)
|
||||
return false;
|
||||
|
||||
if (m_playerOnly && (target->GetTypeId() != TYPEID_PLAYER))
|
||||
return false;
|
||||
|
||||
@@ -434,8 +447,8 @@ bool NonTankTargetSelector::operator()(Unit const* target) const
|
||||
if (_playerOnly && target->GetTypeId() != TYPEID_PLAYER)
|
||||
return false;
|
||||
|
||||
if (HostileReference* currentVictim = _source->getThreatManager().getCurrentVictim())
|
||||
return target->GetGUID() != currentVictim->getUnitGuid();
|
||||
if (Unit* currentVictim = _source->GetThreatManager().GetCurrentVictim())
|
||||
return target != currentVictim;
|
||||
|
||||
return target != _source->GetVictim();
|
||||
}
|
||||
@@ -476,8 +489,3 @@ bool FarthestTargetSelector::operator()(Unit const* target) const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SortByDistanceTo(Unit* reference, std::list<Unit*>& targets)
|
||||
{
|
||||
targets.sort(Trinity::ObjectDistanceOrderPred(reference));
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ enum SpellEffIndex : uint8;
|
||||
//Selection method used by SelectTarget
|
||||
enum SelectAggroTarget
|
||||
{
|
||||
SELECT_TARGET_RANDOM = 0, //Just selects a random target
|
||||
SELECT_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom
|
||||
SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top
|
||||
SELECT_TARGET_NEAREST,
|
||||
SELECT_TARGET_FARTHEST
|
||||
SELECT_TARGET_RANDOM = 0, // just pick a random target
|
||||
SELECT_TARGET_MAXTHREAT, // prefer targets higher in the threat list
|
||||
SELECT_TARGET_MINTHREAT, // prefer targets lower in the threat list
|
||||
SELECT_TARGET_MAXDISTANCE, // prefer targets further from us
|
||||
SELECT_TARGET_MINDISTANCE // prefer targets closer to us
|
||||
};
|
||||
|
||||
// default predicate function to select target based on distance, player and/or aura criteria
|
||||
@@ -60,14 +60,15 @@ struct TC_GAME_API DefaultTargetSelector
|
||||
Unit const* me;
|
||||
float m_dist;
|
||||
bool m_playerOnly;
|
||||
Unit const* except;
|
||||
int32 m_aura;
|
||||
|
||||
// unit: the reference unit
|
||||
// dist: if 0: ignored, if > 0: maximum distance to the reference unit, if < 0: minimum distance to the reference unit
|
||||
// playerOnly: self explaining
|
||||
// withMainTank: allow current tank to be selected
|
||||
// aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura
|
||||
DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, int32 aura) : me(unit), m_dist(dist), m_playerOnly(playerOnly), m_aura(aura) { }
|
||||
|
||||
DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, bool withMainTank, int32 aura);
|
||||
bool operator()(Unit const* target) const;
|
||||
};
|
||||
|
||||
@@ -125,8 +126,6 @@ private:
|
||||
bool _inLos;
|
||||
};
|
||||
|
||||
TC_GAME_API void SortByDistanceTo(Unit* reference, std::list<Unit*>& targets);
|
||||
|
||||
class TC_GAME_API UnitAI
|
||||
{
|
||||
protected:
|
||||
@@ -153,92 +152,174 @@ class TC_GAME_API UnitAI
|
||||
virtual void SetGUID(ObjectGuid /*guid*/, int32 /*id*/ = 0) { }
|
||||
virtual ObjectGuid GetGUID(int32 /*id*/ = 0) const { return ObjectGuid::Empty; }
|
||||
|
||||
Unit* SelectTarget(SelectAggroTarget targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
|
||||
// Select the targets satisfying the predicate.
|
||||
// Select the best target (in <targetType> order) from the threat list that fulfill the following:
|
||||
// - Not among the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM).
|
||||
// - Within at most <dist> yards (if dist > 0.0f)
|
||||
// - At least -<dist> yards away (if dist < 0.0f)
|
||||
// - Is a player (if playerOnly = true)
|
||||
// - Not the current tank (if withTank = false)
|
||||
// - Has aura with ID <aura> (if aura > 0)
|
||||
// - Does not have aura with ID -<aura> (if aura < 0)
|
||||
Unit* SelectTarget(SelectAggroTarget targetType, uint32 offset = 0, float dist = 0.0f, bool playerOnly = false, bool withTank = true, int32 aura = 0);
|
||||
// Select the best target (in <targetType> order) satisfying <predicate> from the threat list.
|
||||
// If <offset> is nonzero, the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM) are skipped.
|
||||
template<class PREDICATE>
|
||||
Unit* SelectTarget(SelectAggroTarget targetType, uint32 position, PREDICATE const& predicate)
|
||||
Unit* SelectTarget(SelectAggroTarget targetType, uint32 offset, PREDICATE const& predicate)
|
||||
{
|
||||
ThreatContainer::StorageType const& threatlist = GetThreatManager().getThreatList();
|
||||
if (position >= threatlist.size())
|
||||
ThreatManager& mgr = GetThreatManager();
|
||||
// shortcut: if we ignore the first <offset> elements, and there are at most <offset> elements, then we ignore ALL elements
|
||||
if (mgr.GetThreatListSize() <= offset)
|
||||
return nullptr;
|
||||
|
||||
std::list<Unit*> targetList;
|
||||
Unit* currentVictim = nullptr;
|
||||
if (auto currentVictimReference = GetThreatManager().getCurrentVictim())
|
||||
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
|
||||
{
|
||||
currentVictim = currentVictimReference->getTarget();
|
||||
for (ThreatReference* ref : mgr.GetUnsortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
// Current victim always goes first
|
||||
if (currentVictim && predicate(currentVictim))
|
||||
targetList.push_back(ref->GetVictim());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* currentVictim = mgr.GetCurrentVictim();
|
||||
if (currentVictim)
|
||||
targetList.push_back(currentVictim);
|
||||
|
||||
for (ThreatReference* ref : mgr.GetSortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
Unit* thisTarget = ref->GetVictim();
|
||||
if (thisTarget != currentVictim)
|
||||
targetList.push_back(thisTarget);
|
||||
}
|
||||
}
|
||||
|
||||
for (HostileReference* hostileRef : threatlist)
|
||||
{
|
||||
if (currentVictim != nullptr && hostileRef->getTarget() != currentVictim && predicate(hostileRef->getTarget()))
|
||||
targetList.push_back(hostileRef->getTarget());
|
||||
else if (currentVictim == nullptr && predicate(hostileRef->getTarget()))
|
||||
targetList.push_back(hostileRef->getTarget());
|
||||
}
|
||||
// filter by predicate
|
||||
targetList.remove_if([&predicate](Unit* target) { return !predicate(target); });
|
||||
|
||||
if (position >= targetList.size())
|
||||
// shortcut: the list certainly isn't gonna get any larger after this point
|
||||
if (targetList.size() <= offset)
|
||||
return nullptr;
|
||||
|
||||
if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
|
||||
SortByDistanceTo(me, targetList);
|
||||
// right now, list is unsorted for DISTANCE types - re-sort by MAXDISTANCE
|
||||
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
|
||||
SortByDistance(targetList, targetType == SELECT_TARGET_MINDISTANCE);
|
||||
|
||||
// then reverse the sorting for MIN sortings
|
||||
if (targetType == SELECT_TARGET_MINTHREAT)
|
||||
targetList.reverse();
|
||||
|
||||
// now pop the first <offset> elements
|
||||
while (offset)
|
||||
{
|
||||
targetList.pop_front();
|
||||
--offset;
|
||||
}
|
||||
|
||||
// maybe nothing fulfills the predicate
|
||||
if (targetList.empty())
|
||||
return nullptr;
|
||||
|
||||
switch (targetType)
|
||||
{
|
||||
case SELECT_TARGET_NEAREST:
|
||||
case SELECT_TARGET_TOPAGGRO:
|
||||
{
|
||||
auto itr = targetList.begin();
|
||||
std::advance(itr, position);
|
||||
return *itr;
|
||||
}
|
||||
case SELECT_TARGET_FARTHEST:
|
||||
case SELECT_TARGET_BOTTOMAGGRO:
|
||||
{
|
||||
auto ritr = targetList.rbegin();
|
||||
std::advance(ritr, position);
|
||||
return *ritr;
|
||||
}
|
||||
case SELECT_TARGET_MAXTHREAT:
|
||||
case SELECT_TARGET_MINTHREAT:
|
||||
case SELECT_TARGET_MAXDISTANCE:
|
||||
case SELECT_TARGET_MINDISTANCE:
|
||||
return targetList.front();
|
||||
case SELECT_TARGET_RANDOM:
|
||||
return Trinity::Containers::SelectRandomContainerElement(targetList);
|
||||
default:
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
|
||||
// Select the best (up to) <num> targets (in <targetType> order) from the threat list that fulfill the following:
|
||||
// - Not among the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM).
|
||||
// - Within at most <dist> yards (if dist > 0.0f)
|
||||
// - At least -<dist> yards away (if dist < 0.0f)
|
||||
// - Is a player (if playerOnly = true)
|
||||
// - Not the current tank (if withTank = false)
|
||||
// - Has aura with ID <aura> (if aura > 0)
|
||||
// - Does not have aura with ID -<aura> (if aura < 0)
|
||||
// The resulting targets are stored in <targetList> (which is cleared first).
|
||||
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, uint32 offset = 0, float dist = 0.0f, bool playerOnly = false, bool withTank = true, int32 aura = 0);
|
||||
|
||||
// Select the targets satifying the predicate.
|
||||
// Select the best (up to) <num> targets (in <targetType> order) satisfying <predicate> from the threat list and stores them in <targetList> (which is cleared first).
|
||||
// If <offset> is nonzero, the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM) are skipped.
|
||||
template <class PREDICATE>
|
||||
void SelectTargetList(std::list<Unit*>& targetList, PREDICATE const& predicate, uint32 maxTargets, SelectAggroTarget targetType)
|
||||
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, uint32 offset, PREDICATE const& predicate)
|
||||
{
|
||||
ThreatContainer::StorageType const& threatlist = GetThreatManager().getThreatList();
|
||||
if (threatlist.empty())
|
||||
targetList.clear();
|
||||
ThreatManager& mgr = GetThreatManager();
|
||||
// shortcut: we're gonna ignore the first <offset> elements, and there's at most <offset> elements, so we ignore them all - nothing to do here
|
||||
if (mgr.GetThreatListSize() <= offset)
|
||||
return;
|
||||
|
||||
for (HostileReference* hostileRef : threatlist)
|
||||
if (predicate(hostileRef->getTarget()))
|
||||
targetList.push_back(hostileRef->getTarget());
|
||||
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
|
||||
{
|
||||
for (ThreatReference* ref : mgr.GetUnsortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
if (targetList.size() < maxTargets)
|
||||
targetList.push_back(ref->GetVictim());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* currentVictim = mgr.GetCurrentVictim();
|
||||
if (currentVictim)
|
||||
targetList.push_back(currentVictim);
|
||||
|
||||
for (ThreatReference* ref : mgr.GetSortedThreatList())
|
||||
{
|
||||
if (ref->IsOffline())
|
||||
continue;
|
||||
|
||||
Unit* thisTarget = ref->GetVictim();
|
||||
if (thisTarget != currentVictim)
|
||||
targetList.push_back(thisTarget);
|
||||
}
|
||||
}
|
||||
|
||||
// filter by predicate
|
||||
targetList.remove_if([&predicate](Unit* target) { return !predicate(target); });
|
||||
|
||||
// shortcut: the list isn't gonna get any larger
|
||||
if (targetList.size() <= offset)
|
||||
{
|
||||
targetList.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
|
||||
SortByDistanceTo(me, targetList);
|
||||
// right now, list is unsorted for DISTANCE types - re-sort by MAXDISTANCE
|
||||
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
|
||||
SortByDistance(targetList, targetType == SELECT_TARGET_MINDISTANCE);
|
||||
|
||||
if (targetType == SELECT_TARGET_FARTHEST || targetType == SELECT_TARGET_BOTTOMAGGRO)
|
||||
// now the list is MAX sorted, reverse for MIN types
|
||||
if (targetType == SELECT_TARGET_MINTHREAT)
|
||||
targetList.reverse();
|
||||
|
||||
// ignore the first <offset> elements
|
||||
while (offset)
|
||||
{
|
||||
targetList.pop_front();
|
||||
--offset;
|
||||
}
|
||||
|
||||
if (targetList.size() <= num)
|
||||
return;
|
||||
|
||||
if (targetType == SELECT_TARGET_RANDOM)
|
||||
Trinity::Containers::RandomResize(targetList, maxTargets);
|
||||
Trinity::Containers::RandomResize(targetList, num);
|
||||
else
|
||||
targetList.resize(maxTargets);
|
||||
targetList.resize(num);
|
||||
}
|
||||
|
||||
// Called at any Damage to any victim (before damage apply)
|
||||
@@ -300,6 +381,7 @@ class TC_GAME_API UnitAI
|
||||
UnitAI& operator=(UnitAI const& right) = delete;
|
||||
|
||||
ThreatManager& GetThreatManager();
|
||||
void SortByDistance(std::list<Unit*> list, bool ascending = true);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -85,8 +85,8 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
|
||||
if (Unit* summoner = creature->ToTempSummon()->GetSummoner())
|
||||
{
|
||||
Unit* target = summoner->getAttackerForHelper();
|
||||
if (!target && summoner->CanHaveThreatList() && !summoner->getThreatManager().isThreatListEmpty())
|
||||
target = summoner->getThreatManager().getHostilTarget();
|
||||
if (!target && summoner->CanHaveThreatList() && !summoner->GetThreatManager().IsThreatListEmpty())
|
||||
target = summoner->GetThreatManager().GetAnyTarget();
|
||||
if (target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target)))
|
||||
creature->AI()->AttackStart(target);
|
||||
}
|
||||
@@ -117,16 +117,8 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
|
||||
{
|
||||
creature->SetInCombatWith(player);
|
||||
player->SetInCombatWith(creature);
|
||||
creature->AddThreat(player, 0.0f);
|
||||
creature->GetThreatManager().AddThreat(player, 0.0f, nullptr, true, true);
|
||||
}
|
||||
|
||||
/* Causes certain things to never leave the threat list (Priest Lightwell, etc):
|
||||
for (Unit::ControlList::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr)
|
||||
{
|
||||
creature->SetInCombatWith(*itr);
|
||||
(*itr)->SetInCombatWith(creature);
|
||||
creature->AddThreat(*itr, 0.0f);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,11 +136,11 @@ void CreatureAI::MoveInLineOfSight_Safe(Unit* who)
|
||||
|
||||
void CreatureAI::MoveInLineOfSight(Unit* who)
|
||||
{
|
||||
if (me->GetVictim())
|
||||
if (me->IsEngaged())
|
||||
return;
|
||||
|
||||
if (me->HasReactState(REACT_AGGRESSIVE) && me->CanStartAttack(who, false))
|
||||
AttackStart(who);
|
||||
me->EngageWithTarget(who);
|
||||
}
|
||||
|
||||
void CreatureAI::_OnOwnerCombatInteraction(Unit* target)
|
||||
@@ -157,12 +149,7 @@ void CreatureAI::_OnOwnerCombatInteraction(Unit* target)
|
||||
return;
|
||||
|
||||
if (!me->HasReactState(REACT_PASSIVE) && me->CanStartAttack(target, true))
|
||||
{
|
||||
if (me->IsInCombat())
|
||||
me->AddThreat(target, 0.0f);
|
||||
else
|
||||
AttackStart(target);
|
||||
}
|
||||
me->EngageWithTarget(target);
|
||||
}
|
||||
|
||||
// Distract creature, if player gets too close while stealthed/prowling
|
||||
@@ -172,8 +159,8 @@ void CreatureAI::TriggerAlert(Unit const* who) const
|
||||
if (!who || who->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
// If this unit isn't an NPC, is already distracted, is in combat, is confused, stunned or fleeing, do nothing
|
||||
if (me->GetTypeId() != TYPEID_UNIT || me->IsInCombat() || me->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED))
|
||||
// If this unit isn't an NPC, is already distracted, is fighting, is confused, stunned or fleeing, do nothing
|
||||
if (me->GetTypeId() != TYPEID_UNIT || me->IsEngaged() || me->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED))
|
||||
return;
|
||||
|
||||
// Only alert for hostiles!
|
||||
@@ -230,7 +217,7 @@ void CreatureAI::SetGazeOn(Unit* target)
|
||||
|
||||
bool CreatureAI::UpdateVictimWithGaze()
|
||||
{
|
||||
if (!me->IsInCombat())
|
||||
if (!me->IsEngaged())
|
||||
return false;
|
||||
|
||||
if (me->HasReactState(REACT_PASSIVE))
|
||||
@@ -250,7 +237,7 @@ bool CreatureAI::UpdateVictimWithGaze()
|
||||
|
||||
bool CreatureAI::UpdateVictim()
|
||||
{
|
||||
if (!me->IsInCombat())
|
||||
if (!me->IsEngaged())
|
||||
return false;
|
||||
|
||||
if (!me->HasReactState(REACT_PASSIVE))
|
||||
@@ -261,7 +248,7 @@ bool CreatureAI::UpdateVictim()
|
||||
|
||||
return me->GetVictim() != nullptr;
|
||||
}
|
||||
else if (me->getThreatManager().isThreatListEmpty())
|
||||
else if (me->GetThreatManager().IsThreatListEmpty())
|
||||
{
|
||||
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
|
||||
return false;
|
||||
@@ -278,7 +265,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
|
||||
me->RemoveAurasOnEvade();
|
||||
|
||||
// sometimes bosses stuck in combat?
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
me->SetLootRecipient(nullptr);
|
||||
me->ResetPlayerDamageReq();
|
||||
|
||||
@@ -85,7 +85,7 @@ class TC_GAME_API CreatureAI : public UnitAI
|
||||
// Called for reaction at stopping attack at no attackers or targets
|
||||
virtual void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER);
|
||||
|
||||
// Called for reaction at enter to combat if not in combat yet (enemy can be nullptr)
|
||||
// Called for reaction when initially engaged
|
||||
virtual void EnterCombat(Unit* /*victim*/) { }
|
||||
|
||||
// Called when the creature is killed
|
||||
|
||||
@@ -1216,7 +1216,7 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
if (charmer->IsInCombat())
|
||||
if (charmer->IsEngaged())
|
||||
{
|
||||
Unit* target = me->GetVictim();
|
||||
if (!target || !charmer->IsValidAttackTarget(target) || target->HasBreakableByDamageCrowdControlAura())
|
||||
|
||||
@@ -193,6 +193,49 @@ void ScriptedAI::DoPlaySoundToSet(WorldObject* source, uint32 soundId)
|
||||
source->PlayDirectSound(soundId);
|
||||
}
|
||||
|
||||
void ScriptedAI::AddThreat(Unit* victim, float amount, Unit* who)
|
||||
{
|
||||
if (!victim)
|
||||
return;
|
||||
if (!who)
|
||||
who = me;
|
||||
who->GetThreatManager().AddThreat(victim, amount, nullptr, true, true);
|
||||
}
|
||||
|
||||
void ScriptedAI::ModifyThreatByPercent(Unit* victim, int32 pct, Unit* who)
|
||||
{
|
||||
if (!victim)
|
||||
return;
|
||||
if (!who)
|
||||
who = me;
|
||||
who->GetThreatManager().ModifyThreatByPercent(victim, pct);
|
||||
}
|
||||
|
||||
void ScriptedAI::ResetThreat(Unit* victim, Unit* who)
|
||||
{
|
||||
if (!victim)
|
||||
return;
|
||||
if (!who)
|
||||
who = me;
|
||||
who->GetThreatManager().ResetThreat(victim);
|
||||
}
|
||||
|
||||
void ScriptedAI::ResetThreatList(Unit* who)
|
||||
{
|
||||
if (!who)
|
||||
who = me;
|
||||
who->GetThreatManager().ResetAllThreat();
|
||||
}
|
||||
|
||||
float ScriptedAI::GetThreat(Unit const* victim, Unit const* who)
|
||||
{
|
||||
if (!victim)
|
||||
return 0.0f;
|
||||
if (!who)
|
||||
who = me;
|
||||
return who->GetThreatManager().GetThreat(victim);
|
||||
}
|
||||
|
||||
Creature* ScriptedAI::DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, uint32 despawntime)
|
||||
{
|
||||
return me->SummonCreature(entry, me->GetPositionX() + offsetX, me->GetPositionY() + offsetY, me->GetPositionZ() + offsetZ, angle, TempSummonType(type), despawntime);
|
||||
@@ -276,38 +319,6 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec
|
||||
return apSpell[urand(0, spellCount - 1)];
|
||||
}
|
||||
|
||||
void ScriptedAI::DoResetThreat()
|
||||
{
|
||||
if (!me->CanHaveThreatList() || me->getThreatManager().isThreatListEmpty())
|
||||
{
|
||||
TC_LOG_ERROR("scripts", "DoResetThreat called for creature that either cannot have threat list or has empty threat list (me entry = %d)", me->GetEntry());
|
||||
return;
|
||||
}
|
||||
|
||||
ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
|
||||
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
|
||||
{
|
||||
Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
|
||||
if (unit && DoGetThreat(unit))
|
||||
DoModifyThreatPercent(unit, -100);
|
||||
}
|
||||
}
|
||||
|
||||
float ScriptedAI::DoGetThreat(Unit* unit)
|
||||
{
|
||||
if (!unit)
|
||||
return 0.0f;
|
||||
return me->getThreatManager().getThreat(unit);
|
||||
}
|
||||
|
||||
void ScriptedAI::DoModifyThreatPercent(Unit* unit, int32 pct)
|
||||
{
|
||||
if (!unit)
|
||||
return;
|
||||
me->getThreatManager().modifyThreatPercent(unit, pct);
|
||||
}
|
||||
|
||||
void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time)
|
||||
{
|
||||
me->Relocate(x, y, z);
|
||||
@@ -493,7 +504,7 @@ void BossAI::TeleportCheaters()
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType threatList = me->GetThreatManager().getThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
|
||||
if (Unit* target = (*itr)->getTarget())
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && !CheckBoundary(target))
|
||||
@@ -503,7 +514,7 @@ void BossAI::TeleportCheaters()
|
||||
void BossAI::JustSummoned(Creature* summon)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (me->IsInCombat())
|
||||
if (me->IsEngaged())
|
||||
DoZoneInCombat(summon);
|
||||
}
|
||||
|
||||
|
||||
@@ -208,11 +208,16 @@ struct TC_GAME_API ScriptedAI : public CreatureAI
|
||||
//Plays a sound to all nearby players
|
||||
void DoPlaySoundToSet(WorldObject* source, uint32 soundId);
|
||||
|
||||
//Drops all threat to 0%. Does not remove players from the threat list
|
||||
void DoResetThreat();
|
||||
|
||||
float DoGetThreat(Unit* unit);
|
||||
void DoModifyThreatPercent(Unit* unit, int32 pct);
|
||||
// Add specified amount of threat directly to victim (ignores redirection effects) - also puts victim in combat and engages them if necessary
|
||||
void AddThreat(Unit* victim, float amount, Unit* who = nullptr);
|
||||
// Adds/removes the specified percentage from the specified victim's threat (to who, or me if not specified)
|
||||
void ModifyThreatByPercent(Unit* victim, int32 pct, Unit* who = nullptr);
|
||||
// Resets the victim's threat level to who (or me if not specified) to zero
|
||||
void ResetThreat(Unit* victim, Unit* who = nullptr);
|
||||
// Resets the specified unit's threat list (me if not specified) - does not delete entries, just sets their threat to zero
|
||||
void ResetThreatList(Unit* who = nullptr);
|
||||
// Returns the threat level of victim towards who (or me if not specified)
|
||||
float GetThreat(Unit const* victim, Unit const* who = nullptr);
|
||||
|
||||
void DoTeleportTo(float x, float y, float z, uint32 time = 0);
|
||||
void DoTeleportTo(float const pos[4]);
|
||||
|
||||
@@ -102,8 +102,7 @@ bool npc_escortAI::AssistPlayerInCombatAgainst(Unit* who)
|
||||
}
|
||||
else
|
||||
{
|
||||
who->SetInCombatWith(me);
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->EngageWithTarget(who);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -125,24 +124,7 @@ void npc_escortAI::MoveInLineOfSight(Unit* who)
|
||||
{
|
||||
float fAttackRadius = me->GetAttackDistance(who);
|
||||
if (me->IsWithinDistInMap(who, fAttackRadius) && me->IsWithinLOSInMap(who))
|
||||
{
|
||||
if (!me->GetVictim())
|
||||
{
|
||||
// Clear distracted state on combat
|
||||
if (me->HasUnitState(UNIT_STATE_DISTRACTED))
|
||||
{
|
||||
me->ClearUnitState(UNIT_STATE_DISTRACTED);
|
||||
me->GetMotionMaster()->Clear();
|
||||
}
|
||||
|
||||
AttackStart(who);
|
||||
}
|
||||
else if (me->GetMap()->IsDungeon())
|
||||
{
|
||||
who->SetInCombatWith(me);
|
||||
me->AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
me->EngageWithTarget(who);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,7 +174,7 @@ void npc_escortAI::ReturnToLastPoint()
|
||||
void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
me->SetLootRecipient(NULL);
|
||||
|
||||
|
||||
@@ -51,9 +51,7 @@ void FollowerAI::AttackStart(Unit* who)
|
||||
|
||||
if (me->Attack(who, true))
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
me->EngageWithTarget(who); // in case it doesn't have threat+combat yet
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_FOLLOW))
|
||||
me->ClearUnitState(UNIT_STATE_FOLLOW);
|
||||
@@ -86,18 +84,8 @@ bool FollowerAI::AssistPlayerInCombatAgainst(Unit* who)
|
||||
//too far away and no free sight?
|
||||
if (me->IsWithinDistInMap(who, MAX_PLAYER_DISTANCE) && me->IsWithinLOSInMap(who))
|
||||
{
|
||||
//already fighting someone?
|
||||
if (!me->GetVictim())
|
||||
{
|
||||
AttackStart(who);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
who->SetInCombatWith(me);
|
||||
me->AddThreat(who, 0.0f);
|
||||
return true;
|
||||
}
|
||||
me->EngageWithTarget(who);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -130,10 +118,7 @@ void FollowerAI::MoveInLineOfSight(Unit* who)
|
||||
AttackStart(who);
|
||||
}
|
||||
else if (me->GetMap()->IsDungeon())
|
||||
{
|
||||
who->SetInCombatWith(me);
|
||||
me->AddThreat(who, 0.0f);
|
||||
}
|
||||
me->EngageWithTarget(who);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,7 +160,7 @@ void FollowerAI::JustRespawned()
|
||||
void FollowerAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
me->SetLootRecipient(NULL);
|
||||
|
||||
|
||||
@@ -558,18 +558,8 @@ bool SmartAI::AssistPlayerInCombatAgainst(Unit* who)
|
||||
//too far away and no free sight?
|
||||
if (me->IsWithinDistInMap(who, SMART_MAX_AID_DIST) && me->IsWithinLOSInMap(who))
|
||||
{
|
||||
//already fighting someone?
|
||||
if (!me->GetVictim())
|
||||
{
|
||||
AttackStart(who);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
who->SetInCombatWith(me);
|
||||
me->AddThreat(who, 0.0f);
|
||||
return true;
|
||||
}
|
||||
me->EngageWithTarget(who);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -445,16 +445,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (!me)
|
||||
break;
|
||||
|
||||
ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList();
|
||||
for (auto i = threatList.begin(); i != threatList.end(); ++i)
|
||||
for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
|
||||
{
|
||||
me->getThreatManager().modifyThreatPercent(target, e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature %s modify threat for %s, value %i",
|
||||
me->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str(),
|
||||
e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
|
||||
}
|
||||
ref->ModifyThreatByPercent(std::max<int32>(-100,int32(e.action.threatPCT.threatINC) - int32(e.action.threatPCT.threatDEC)));
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature %s modify threat for %s, value %i",
|
||||
me->GetGUID().ToString().c_str(), ref->GetVictim()->GetGUID().ToString().c_str(), int32(e.action.threatPCT.threatINC)-int32(e.action.threatPCT.threatDEC));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -467,10 +462,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
{
|
||||
if (IsUnit(target))
|
||||
{
|
||||
me->getThreatManager().modifyThreatPercent(target->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
|
||||
me->GetThreatManager().ModifyThreatByPercent(target->ToUnit(), std::max<int32>(-100, int32(e.action.threatPCT.threatINC) - int32(e.action.threatPCT.threatDEC)));
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature %s modify threat for %s, value %i",
|
||||
me->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str(),
|
||||
e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
|
||||
me->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), int32(e.action.threatPCT.threatINC) - int32(e.action.threatPCT.threatDEC));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2148,7 +2142,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
{
|
||||
for (WorldObject* const target : targets)
|
||||
if (IsUnit(target))
|
||||
me->AddThreat(target->ToUnit(), float(e.action.threatPCT.threatINC) - float(e.action.threatPCT.threatDEC));
|
||||
me->GetThreatManager().AddThreat(target->ToUnit(), float(e.action.threatPCT.threatINC) - float(e.action.threatPCT.threatDEC), nullptr, true, true);
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_LOAD_EQUIPMENT:
|
||||
@@ -2421,10 +2415,10 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
||||
{
|
||||
if (e.target.hostilRandom.powerType)
|
||||
{
|
||||
if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)))
|
||||
if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MAXTHREAT, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)))
|
||||
targets.push_back(u);
|
||||
}
|
||||
else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))
|
||||
else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MAXTHREAT, 1, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))
|
||||
targets.push_back(u);
|
||||
}
|
||||
break;
|
||||
@@ -2433,10 +2427,10 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
||||
{
|
||||
if (e.target.hostilRandom.powerType)
|
||||
{
|
||||
if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)))
|
||||
if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MINTHREAT, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)))
|
||||
targets.push_back(u);
|
||||
}
|
||||
else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))
|
||||
else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MINTHREAT, 0, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))
|
||||
targets.push_back(u);
|
||||
}
|
||||
break;
|
||||
@@ -2467,7 +2461,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
||||
case SMART_TARGET_FARTHEST:
|
||||
if (me)
|
||||
{
|
||||
if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_FARTHEST, 0, FarthestTargetSelector(me, float(e.target.farthest.maxDist), e.target.farthest.playerOnly != 0, e.target.farthest.isInLos != 0)))
|
||||
if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MAXDISTANCE, 0, FarthestTargetSelector(me, float(e.target.farthest.maxDist), e.target.farthest.playerOnly != 0, e.target.farthest.isInLos != 0)))
|
||||
targets.push_back(u);
|
||||
}
|
||||
break;
|
||||
@@ -2684,14 +2678,10 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
||||
}
|
||||
case SMART_TARGET_THREAT_LIST:
|
||||
{
|
||||
if (me)
|
||||
{
|
||||
ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList();
|
||||
for (HostileReference const* ref : threatList)
|
||||
if (Unit* temp = ObjectAccessor::GetUnit(*me, ref->getUnitGuid()))
|
||||
if (e.target.hostilRandom.maxDist == 0 || me->IsWithinCombatRange(temp, float(e.target.hostilRandom.maxDist)))
|
||||
targets.push_back(temp);
|
||||
}
|
||||
if (me && me->CanHaveThreatList())
|
||||
for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
|
||||
if (!e.target.hostilRandom.maxDist || me->IsWithinCombatRange(ref->GetVictim(), float(e.target.hostilRandom.maxDist)))
|
||||
targets.push_back(ref->GetVictim());
|
||||
break;
|
||||
}
|
||||
case SMART_TARGET_CLOSEST_ENEMY:
|
||||
@@ -2775,18 +2765,18 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
|
||||
break;
|
||||
case SMART_EVENT_UPDATE_OOC:
|
||||
if (me && me->IsInCombat())
|
||||
if (me && me->IsEngaged())
|
||||
return;
|
||||
ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
|
||||
break;
|
||||
case SMART_EVENT_UPDATE_IC:
|
||||
if (!me || !me->IsInCombat())
|
||||
if (!me || !me->IsEngaged())
|
||||
return;
|
||||
ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
|
||||
break;
|
||||
case SMART_EVENT_HEALT_PCT:
|
||||
{
|
||||
if (!me || !me->IsInCombat() || !me->GetMaxHealth())
|
||||
if (!me || !me->IsEngaged() || !me->GetMaxHealth())
|
||||
return;
|
||||
uint32 perc = (uint32)me->GetHealthPct();
|
||||
if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
|
||||
@@ -2796,7 +2786,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_TARGET_HEALTH_PCT:
|
||||
{
|
||||
if (!me || !me->IsInCombat() || !me->GetVictim() || !me->EnsureVictim()->GetMaxHealth())
|
||||
if (!me || !me->IsEngaged() || !me->GetVictim() || !me->EnsureVictim()->GetMaxHealth())
|
||||
return;
|
||||
uint32 perc = (uint32)me->EnsureVictim()->GetHealthPct();
|
||||
if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
|
||||
@@ -2806,7 +2796,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_MANA_PCT:
|
||||
{
|
||||
if (!me || !me->IsInCombat() || !me->GetMaxPower(POWER_MANA))
|
||||
if (!me || !me->IsEngaged() || !me->GetMaxPower(POWER_MANA))
|
||||
return;
|
||||
uint32 perc = uint32(me->GetPowerPct(POWER_MANA));
|
||||
if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
|
||||
@@ -2816,7 +2806,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_TARGET_MANA_PCT:
|
||||
{
|
||||
if (!me || !me->IsInCombat() || !me->GetVictim() || !me->EnsureVictim()->GetMaxPower(POWER_MANA))
|
||||
if (!me || !me->IsEngaged() || !me->GetVictim() || !me->EnsureVictim()->GetMaxPower(POWER_MANA))
|
||||
return;
|
||||
uint32 perc = uint32(me->EnsureVictim()->GetPowerPct(POWER_MANA));
|
||||
if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
|
||||
@@ -2826,7 +2816,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_RANGE:
|
||||
{
|
||||
if (!me || !me->IsInCombat() || !me->GetVictim())
|
||||
if (!me || !me->IsEngaged() || !me->GetVictim())
|
||||
return;
|
||||
|
||||
if (me->IsInRange(me->GetVictim(), (float)e.event.minMaxRepeat.min, (float)e.event.minMaxRepeat.max))
|
||||
@@ -2837,7 +2827,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_VICTIM_CASTING:
|
||||
{
|
||||
if (!me || !me->IsInCombat())
|
||||
if (!me || !me->IsEngaged())
|
||||
return;
|
||||
|
||||
Unit* victim = me->GetVictim();
|
||||
@@ -2855,7 +2845,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_FRIENDLY_HEALTH:
|
||||
{
|
||||
if (!me || !me->IsInCombat())
|
||||
if (!me || !me->IsEngaged())
|
||||
return;
|
||||
|
||||
Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealth.radius, e.event.friendlyHealth.hpDeficit);
|
||||
@@ -2871,7 +2861,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_FRIENDLY_IS_CC:
|
||||
{
|
||||
if (!me || !me->IsInCombat())
|
||||
if (!me || !me->IsEngaged())
|
||||
return;
|
||||
|
||||
std::vector<Creature*> creatures;
|
||||
@@ -2994,7 +2984,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_OOC_LOS:
|
||||
{
|
||||
if (!me || me->IsInCombat())
|
||||
if (!me || me->IsEngaged())
|
||||
return;
|
||||
//can trigger if closer than fMaxAllowedRange
|
||||
float range = (float)e.event.los.maxDist;
|
||||
@@ -3014,7 +3004,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_IC_LOS:
|
||||
{
|
||||
if (!me || !me->IsInCombat())
|
||||
if (!me || !me->IsEngaged())
|
||||
return;
|
||||
//can trigger if closer than fMaxAllowedRange
|
||||
float range = (float)e.event.los.maxDist;
|
||||
@@ -3204,7 +3194,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
case SMART_EVENT_FRIENDLY_HEALTH_PCT:
|
||||
{
|
||||
if (!me || !me->IsInCombat())
|
||||
if (!me || !me->IsEngaged())
|
||||
return;
|
||||
|
||||
ObjectVector targets;
|
||||
@@ -3364,10 +3354,10 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
if (e.event.event_phase_mask && !IsInPhase(e.event.event_phase_mask))
|
||||
return;
|
||||
|
||||
if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsInCombat()))
|
||||
if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsEngaged()))
|
||||
return;
|
||||
|
||||
if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->IsInCombat())) //can be used with me=nullptr (go script)
|
||||
if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->IsEngaged())) //can be used with me=nullptr (go script)
|
||||
return;
|
||||
|
||||
if (e.timer < diff)
|
||||
@@ -3719,7 +3709,7 @@ void SmartScript::OnMoveInLineOfSight(Unit* who)
|
||||
if (!me)
|
||||
return;
|
||||
|
||||
ProcessEventsFor(me->IsInCombat() ? SMART_EVENT_IC_LOS : SMART_EVENT_OOC_LOS, who);
|
||||
ProcessEventsFor(me->IsEngaged() ? SMART_EVENT_IC_LOS : SMART_EVENT_OOC_LOS, who);
|
||||
}
|
||||
// SmartScript end
|
||||
|
||||
|
||||
@@ -131,6 +131,9 @@ void HostileReference::fireStatusChanged(ThreatRefStatusChangeEvent& threatRefSt
|
||||
GetSource()->processThreatEvent(&threatRefStatusChangeEvent);
|
||||
}
|
||||
|
||||
// -- compatibility layer for combat rewrite (PR #19930)
|
||||
Unit* HostileReference::GetOwner() const { return GetSource()->GetOwner(); }
|
||||
|
||||
//============================================================
|
||||
|
||||
void HostileReference::addThreat(float modThreat)
|
||||
@@ -264,7 +267,7 @@ void ThreatContainer::clearReferences()
|
||||
|
||||
//============================================================
|
||||
// Return the HostileReference of NULL, if not found
|
||||
HostileReference* ThreatContainer::getReferenceByTarget(Unit* victim) const
|
||||
HostileReference* ThreatContainer::getReferenceByTarget(Unit const* victim) const
|
||||
{
|
||||
if (!victim)
|
||||
return NULL;
|
||||
@@ -293,7 +296,7 @@ HostileReference* ThreatContainer::addThreat(Unit* victim, float threat)
|
||||
|
||||
//============================================================
|
||||
|
||||
void ThreatContainer::modifyThreatPercent(Unit* victim, int32 percent)
|
||||
void ThreatContainer::ModifyThreatByPercent(Unit* victim, int32 percent)
|
||||
{
|
||||
if (HostileReference* ref = getReferenceByTarget(victim))
|
||||
ref->addThreatPercent(percent);
|
||||
@@ -392,6 +395,30 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* attacker, HostileR
|
||||
|
||||
ThreatManager::ThreatManager(Unit* owner) : iCurrentVictim(NULL), iOwner(owner), iUpdateTimer(THREAT_UPDATE_INTERVAL) { }
|
||||
|
||||
// -- compatibility layer for combat rewrite (PR #19930)
|
||||
void ThreatManager::ForwardThreatForAssistingMe(Unit* victim, float amount, SpellInfo const* spell, bool ignoreModifiers, bool ignoreRedirection)
|
||||
{
|
||||
(void)ignoreModifiers; (void)ignoreRedirection;
|
||||
GetOwner()->getHostileRefManager().threatAssist(victim, amount, spell);
|
||||
}
|
||||
|
||||
void ThreatManager::AddThreat(Unit* victim, float amount, SpellInfo const* spell, bool ignoreModifiers, bool ignoreRedirection)
|
||||
{
|
||||
(void)ignoreModifiers; (void)ignoreRedirection;
|
||||
if (!iOwner->CanHaveThreatList() || iOwner->HasUnitState(UNIT_STATE_EVADE))
|
||||
return;
|
||||
iOwner->SetInCombatWith(victim);
|
||||
victim->SetInCombatWith(iOwner);
|
||||
addThreat(victim, amount, spell ? spell->GetSchoolMask() : victim->GetMeleeDamageSchoolMask(), spell);
|
||||
}
|
||||
|
||||
void ThreatManager::ClearAllThreat()
|
||||
{
|
||||
if (iOwner->CanHaveThreatList(true) && !isThreatListEmpty())
|
||||
iOwner->SendClearThreatListOpcode();
|
||||
clearReferences();
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
||||
void ThreatManager::clearReferences()
|
||||
@@ -471,9 +498,9 @@ void ThreatManager::_addThreat(Unit* victim, float threat)
|
||||
|
||||
//============================================================
|
||||
|
||||
void ThreatManager::modifyThreatPercent(Unit* victim, int32 percent)
|
||||
void ThreatManager::ModifyThreatByPercent(Unit* victim, int32 percent)
|
||||
{
|
||||
iThreatContainer.modifyThreatPercent(victim, percent);
|
||||
iThreatContainer.ModifyThreatByPercent(victim, percent);
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "LinkedReference/Reference.h"
|
||||
#include "UnitEvents.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "IteratorPair.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
@@ -50,6 +51,19 @@ class TC_GAME_API HostileReference : public Reference<Unit, ThreatManager>
|
||||
public:
|
||||
HostileReference(Unit* refUnit, ThreatManager* threatManager, float threat);
|
||||
|
||||
// -- compatibility layer for combat rewrite (PR #19930)
|
||||
Unit* GetOwner() const;
|
||||
Unit* GetVictim() const { return getTarget(); }
|
||||
void AddThreat(float amt) { addThreat(amt); }
|
||||
void SetThreat(float amt) { setThreat(amt); }
|
||||
void ModifyThreatByPercent(int32 pct) { addThreatPercent(pct); }
|
||||
void ScaleThreat(float factor) { setThreat(iThreat*factor); }
|
||||
bool IsOnline() const { return iOnline; }
|
||||
bool IsAvailable() const { return iOnline; }
|
||||
bool IsOffline() const { return !iOnline; }
|
||||
float GetThreat() const { return getThreat(); }
|
||||
void ClearThreat() { removeReference(); }
|
||||
|
||||
//=================================================
|
||||
void addThreat(float modThreat);
|
||||
|
||||
@@ -156,7 +170,7 @@ class TC_GAME_API ThreatContainer
|
||||
|
||||
HostileReference* addThreat(Unit* victim, float threat);
|
||||
|
||||
void modifyThreatPercent(Unit* victim, int32 percent);
|
||||
void ModifyThreatByPercent(Unit* victim, int32 percent);
|
||||
|
||||
HostileReference* selectNextVictim(Creature* attacker, HostileReference* currentVictim) const;
|
||||
|
||||
@@ -174,7 +188,7 @@ class TC_GAME_API ThreatContainer
|
||||
return iThreatList.empty() ? nullptr : iThreatList.front();
|
||||
}
|
||||
|
||||
HostileReference* getReferenceByTarget(Unit* victim) const;
|
||||
HostileReference* getReferenceByTarget(Unit const* victim) const;
|
||||
|
||||
StorageType const & getThreatList() const { return iThreatList; }
|
||||
|
||||
@@ -200,9 +214,31 @@ class TC_GAME_API ThreatContainer
|
||||
|
||||
//=================================================
|
||||
|
||||
typedef HostileReference ThreatReference;
|
||||
class TC_GAME_API ThreatManager
|
||||
{
|
||||
public:
|
||||
// -- compatibility layer for combat rewrite (PR #19930)
|
||||
Trinity::IteratorPair<std::list<ThreatReference*>::const_iterator> GetSortedThreatList() const { auto& list = iThreatContainer.getThreatList(); return { list.cbegin(), list.cend() }; }
|
||||
Trinity::IteratorPair<std::list<ThreatReference*>::const_iterator> GetUnsortedThreatList() const { return GetSortedThreatList(); }
|
||||
Unit* SelectVictim() { return getHostilTarget(); }
|
||||
Unit* GetCurrentVictim() const { if (ThreatReference* ref = getCurrentVictim()) return ref->GetVictim(); else return nullptr; }
|
||||
bool IsThreatListEmpty(bool includeOffline = false) const { return includeOffline ? areThreatListsEmpty() : isThreatListEmpty(); }
|
||||
bool IsThreatenedBy(Unit const* who, bool includeOffline = false) const { return (FindReference(who, includeOffline) != nullptr); }
|
||||
size_t GetThreatListSize() const { return iThreatContainer.iThreatList.size(); }
|
||||
void ForwardThreatForAssistingMe(Unit* victim, float amount, SpellInfo const* spell, bool ignoreModifiers = false, bool ignoreRedirection = false);
|
||||
Unit* GetAnyTarget() const { auto const& list = getThreatList(); if (!list.empty()) return list.front()->getTarget(); return nullptr; }
|
||||
void ResetThreat(Unit const* who) { if (auto* ref = FindReference(who, true)) ref->setThreat(0.0f); }
|
||||
void ResetAllThreat() { resetAllAggro(); }
|
||||
float GetThreat(Unit const* who, bool includeOffline = false) const { if (auto* ref = FindReference(who, includeOffline)) return ref->GetThreat(); return 0.0f; }
|
||||
void ClearThreat(Unit const* who) { if (auto* ref = FindReference(who, true)) ref->removeReference(); }
|
||||
void ClearAllThreat();
|
||||
void AddThreat(Unit* victim, float amount, SpellInfo const* spell = nullptr, bool ignoreModifiers = false, bool ignoreRedirection = false);
|
||||
private:
|
||||
HostileReference* FindReference(Unit const* who, bool includeOffline) const { if (auto* ref = iThreatContainer.getReferenceByTarget(who)) return ref; if (includeOffline) if (auto* ref = iThreatOfflineContainer.getReferenceByTarget(who)) return ref; return nullptr; }
|
||||
|
||||
public:
|
||||
|
||||
friend class HostileReference;
|
||||
|
||||
explicit ThreatManager(Unit* owner);
|
||||
@@ -215,7 +251,7 @@ class TC_GAME_API ThreatManager
|
||||
|
||||
void doAddThreat(Unit* victim, float threat);
|
||||
|
||||
void modifyThreatPercent(Unit* victim, int32 percent);
|
||||
void ModifyThreatByPercent(Unit* victim, int32 percent);
|
||||
|
||||
float getThreat(Unit* victim, bool alsoSearchOfflineList = false);
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ class TC_GAME_API ThreatRefStatusChangeEvent : public UnitBaseEvent
|
||||
|
||||
void setThreatManager(ThreatManager* pThreatManager) { iThreatManager = pThreatManager; }
|
||||
|
||||
ThreatManager* getThreatManager() const { return iThreatManager; }
|
||||
ThreatManager* GetThreatManager() const { return iThreatManager; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -263,9 +263,7 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
if (assistant && assistant->CanAssistTo(&m_owner, victim))
|
||||
{
|
||||
assistant->SetNoCallAssistance(true);
|
||||
assistant->CombatStart(victim);
|
||||
if (assistant->IsAIEnabled)
|
||||
assistant->AI()->AttackStart(victim);
|
||||
assistant->EngageWithTarget(victim);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -739,7 +737,7 @@ void Creature::Update(uint32 diff)
|
||||
}
|
||||
|
||||
// periodic check to see if the creature has passed an evade boundary
|
||||
if (IsAIEnabled && !IsInEvadeMode() && IsInCombat())
|
||||
if (IsAIEnabled && !IsInEvadeMode() && IsEngaged())
|
||||
{
|
||||
if (diff >= m_boundaryCheckTime)
|
||||
{
|
||||
@@ -750,7 +748,7 @@ void Creature::Update(uint32 diff)
|
||||
}
|
||||
|
||||
// if periodic combat pulse is enabled and we are both in combat and in a dungeon, do this now
|
||||
if (m_combatPulseDelay > 0 && IsInCombat() && GetMap()->IsDungeon())
|
||||
if (m_combatPulseDelay > 0 && IsEngaged() && GetMap()->IsDungeon())
|
||||
{
|
||||
if (diff > m_combatPulseTime)
|
||||
m_combatPulseTime = 0;
|
||||
@@ -768,13 +766,8 @@ void Creature::Update(uint32 diff)
|
||||
if (player->IsGameMaster())
|
||||
continue;
|
||||
|
||||
if (player->IsAlive() && this->IsHostileTo(player))
|
||||
{
|
||||
if (CanHaveThreatList())
|
||||
AddThreat(player, 0.0f);
|
||||
this->SetInCombatWith(player);
|
||||
player->SetInCombatWith(this);
|
||||
}
|
||||
if (player->IsAlive() && IsHostileTo(player))
|
||||
EngageWithTarget(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1817,7 +1810,7 @@ bool Creature::CanStartAttack(Unit const* who, bool force) const
|
||||
if (!_IsTargetAcceptable(who))
|
||||
return false;
|
||||
|
||||
if (who->IsInCombat() && IsWithinDist(who, ATTACK_DISTANCE))
|
||||
if (who->IsEngaged() && IsWithinDist(who, ATTACK_DISTANCE))
|
||||
if (Unit* victim = who->getAttackerForHelper())
|
||||
if (IsWithinDistInMap(victim, sWorld->getFloatConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS)))
|
||||
force = true;
|
||||
@@ -2375,7 +2368,7 @@ bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction /
|
||||
return false;
|
||||
|
||||
// skip fighting creature
|
||||
if (IsInCombat())
|
||||
if (IsEngaged())
|
||||
return false;
|
||||
|
||||
// only free creature
|
||||
@@ -2425,7 +2418,7 @@ bool Creature::_IsTargetAcceptable(Unit const* target) const
|
||||
Unit const* targetVictim = target->getAttackerForHelper();
|
||||
|
||||
// if I'm already fighting target, or I'm hostile towards the target, the target is acceptable
|
||||
if (IsInCombatWith(target) || IsHostileTo(target))
|
||||
if (IsEngagedBy(target) || IsHostileTo(target))
|
||||
return true;
|
||||
|
||||
// if the target's victim is friendly, and the target is neutral, the target is acceptable
|
||||
@@ -2626,11 +2619,7 @@ void Creature::SetInCombatWithZone()
|
||||
continue;
|
||||
|
||||
if (player->IsAlive())
|
||||
{
|
||||
this->SetInCombatWith(player);
|
||||
player->SetInCombatWith(this);
|
||||
AddThreat(player, 0.0f);
|
||||
}
|
||||
EngageWithTarget(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ void CreatureGroup::RemoveMember(Creature* member)
|
||||
member->SetFormation(NULL);
|
||||
}
|
||||
|
||||
void CreatureGroup::MemberAttackStart(Creature* member, Unit* target)
|
||||
void CreatureGroup::MemberEngagingTarget(Creature* member, Unit* target)
|
||||
{
|
||||
uint8 groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()]->groupAI;
|
||||
if (!groupAI)
|
||||
@@ -188,11 +188,7 @@ void CreatureGroup::MemberAttackStart(Creature* member, Unit* target)
|
||||
|
||||
for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
if (m_leader) // avoid crash if leader was killed and reset.
|
||||
TC_LOG_DEBUG("entities.unit", "GROUP ATTACK: group instance id %u calls member instid %u", m_leader->GetInstanceId(), member->GetInstanceId());
|
||||
|
||||
Creature* other = itr->first;
|
||||
|
||||
// Skip self
|
||||
if (other == member)
|
||||
continue;
|
||||
@@ -200,11 +196,8 @@ void CreatureGroup::MemberAttackStart(Creature* member, Unit* target)
|
||||
if (!other->IsAlive())
|
||||
continue;
|
||||
|
||||
if (other->GetVictim())
|
||||
continue;
|
||||
|
||||
if (((other != m_leader && (groupAI & FLAG_MEMBERS_ASSIST_LEADER)) || (other == m_leader && (groupAI & FLAG_LEADER_ASSISTS_MEMBER))) && other->IsValidAttackTarget(target))
|
||||
other->AI()->AttackStart(target);
|
||||
other->EngageWithTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ class TC_GAME_API CreatureGroup
|
||||
void FormationReset(bool dismiss);
|
||||
|
||||
void LeaderMoveTo(Position destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false);
|
||||
void MemberAttackStart(Creature* member, Unit* target);
|
||||
void MemberEngagingTarget(Creature* member, Unit* target);
|
||||
};
|
||||
|
||||
#define sFormationMgr FormationMgr::instance()
|
||||
|
||||
@@ -844,7 +844,7 @@ void MovementInfo::OutDebug()
|
||||
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0),
|
||||
m_name(""), m_isActive(false), m_isWorldObject(isWorldObject), m_zoneScript(NULL),
|
||||
m_transport(NULL), m_zoneId(0), m_areaId(0), m_staticFloorZ(VMAP_INVALID_HEIGHT), m_currMap(NULL), m_InstanceId(0),
|
||||
_dbPhase(0), m_notifyflags(0), m_executed_notifies(0)
|
||||
_dbPhase(0), m_notifyflags(0)
|
||||
{
|
||||
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST);
|
||||
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
|
||||
|
||||
@@ -539,9 +539,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
|
||||
void AddToNotify(uint16 f) { m_notifyflags |= f;}
|
||||
bool isNeedNotify(uint16 f) const { return (m_notifyflags & f) != 0; }
|
||||
uint16 GetNotifyFlags() const { return m_notifyflags; }
|
||||
bool NotifyExecuted(uint16 f) const { return (m_executed_notifies & f) != 0; }
|
||||
void SetNotified(uint16 f) { m_executed_notifies |= f;}
|
||||
void ResetAllNotifies() { m_notifyflags = 0; m_executed_notifies = 0; }
|
||||
void ResetAllNotifies() { m_notifyflags = 0; }
|
||||
|
||||
bool isActiveObject() const { return m_isActive; }
|
||||
void setActive(bool isActiveObject);
|
||||
@@ -614,7 +612,6 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
|
||||
int32 _dbPhase;
|
||||
|
||||
uint16 m_notifyflags;
|
||||
uint16 m_executed_notifies;
|
||||
virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius = true, bool incTargetRadius = true) const;
|
||||
|
||||
bool CanNeverSee(WorldObject const* obj) const;
|
||||
|
||||
@@ -21591,14 +21591,38 @@ void Player::UpdateAfkReport(time_t currTime)
|
||||
}
|
||||
}
|
||||
|
||||
void Player::SetContestedPvP(Player* attackedPlayer)
|
||||
{
|
||||
if (attackedPlayer && (attackedPlayer == this || (duel && duel->opponent == attackedPlayer)))
|
||||
return;
|
||||
|
||||
SetContestedPvPTimer(30000);
|
||||
if (!HasUnitState(UNIT_STATE_ATTACK_PLAYER))
|
||||
{
|
||||
AddUnitState(UNIT_STATE_ATTACK_PLAYER);
|
||||
AddPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP);
|
||||
// call MoveInLineOfSight for nearby contested guards
|
||||
Trinity::AIRelocationNotifier notifier(*this);
|
||||
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
|
||||
}
|
||||
for (Unit* unit : m_Controlled)
|
||||
{
|
||||
if (!unit->HasUnitState(UNIT_STATE_ATTACK_PLAYER))
|
||||
{
|
||||
unit->AddUnitState(UNIT_STATE_ATTACK_PLAYER);
|
||||
Trinity::AIRelocationNotifier notifier(*unit);
|
||||
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::UpdateContestedPvP(uint32 diff)
|
||||
{
|
||||
if (!m_contestedPvPTimer||IsInCombat())
|
||||
if (!m_contestedPvPTimer || IsInCombat())
|
||||
return;
|
||||
|
||||
if (m_contestedPvPTimer <= diff)
|
||||
{
|
||||
ResetContestedPvP();
|
||||
}
|
||||
else
|
||||
m_contestedPvPTimer -= diff;
|
||||
}
|
||||
|
||||
@@ -1703,6 +1703,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
|
||||
void UpdateAfkReport(time_t currTime);
|
||||
void UpdatePvPFlag(time_t currTime);
|
||||
void SetContestedPvP(Player* attackedPlayer = nullptr);
|
||||
void UpdateContestedPvP(uint32 currTime);
|
||||
void SetContestedPvPTimer(uint32 newTime) {m_contestedPvPTimer = newTime;}
|
||||
void ResetContestedPvP();
|
||||
|
||||
@@ -468,7 +468,7 @@ void Unit::Update(uint32 p_time)
|
||||
// Having this would prevent spells from being proced, so let's crash
|
||||
ASSERT(!m_procDeep);
|
||||
|
||||
if (CanHaveThreatList() && getThreatManager().isNeedUpdateToClient(p_time))
|
||||
if (CanHaveThreatList() && GetThreatManager().isNeedUpdateToClient(p_time))
|
||||
SendThreatListUpdate();
|
||||
|
||||
// update combat timer only for players and pets (only pets with PetAI)
|
||||
@@ -883,7 +883,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
|
||||
if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(SPELL_AURA_DAMAGE_SHIELD)))
|
||||
victim->ToCreature()->SetLastDamagedTime(GameTime::GetGameTime() + MAX_AGGRO_RESET_TIME);
|
||||
|
||||
victim->AddThreat(this, float(damage), damageSchoolMask, spellProto);
|
||||
victim->GetThreatManager().AddThreat(this, float(damage), spellProto);
|
||||
}
|
||||
else // victim is a player
|
||||
{
|
||||
@@ -5617,6 +5617,9 @@ void Unit::_removeAttacker(Unit* pAttacker)
|
||||
|
||||
Unit* Unit::getAttackerForHelper() const // If someone wants to help, who to give them
|
||||
{
|
||||
if (!IsEngaged())
|
||||
return nullptr;
|
||||
|
||||
if (Unit* victim = GetVictim())
|
||||
if ((!IsPet() && !GetPlayerMovingMe()) || IsInCombatWith(victim) || victim->IsInCombatWith(this))
|
||||
return victim;
|
||||
@@ -5720,14 +5723,14 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||
if (creature && !IsPet())
|
||||
{
|
||||
// should not let player enter combat by right clicking target - doesn't helps
|
||||
AddThreat(victim, 0.0f);
|
||||
GetThreatManager().AddThreat(victim, 0.0f);
|
||||
SetInCombatWith(victim);
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
victim->SetInCombatWith(this);
|
||||
|
||||
if (Unit* owner = victim->GetOwner())
|
||||
{
|
||||
AddThreat(owner, 0.0f);
|
||||
GetThreatManager().AddThreat(owner, 0.0f);
|
||||
SetInCombatWith(owner);
|
||||
if (owner->GetTypeId() == TYPEID_PLAYER)
|
||||
owner->SetInCombatWith(this);
|
||||
@@ -6635,14 +6638,17 @@ void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, int3
|
||||
}
|
||||
|
||||
void Unit::EnergizeBySpell(Unit* victim, uint32 spellId, int32 damage, Powers powerType)
|
||||
{
|
||||
if (SpellInfo const* info = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID()))
|
||||
EnergizeBySpell(victim, info, damage, powerType);
|
||||
}
|
||||
|
||||
void Unit::EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damage, Powers powerType)
|
||||
{
|
||||
int32 gain = victim->ModifyPower(powerType, damage);
|
||||
int32 overEnergize = damage - gain;
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
|
||||
victim->getHostileRefManager().threatAssist(this, float(damage) * 0.5f, spellInfo);
|
||||
|
||||
SendEnergizeSpellLog(victim, spellId, damage, overEnergize, powerType);
|
||||
victim->GetThreatManager().ForwardThreatForAssistingMe(this, float(damage)/2, spellInfo, true);
|
||||
SendEnergizeSpellLog(victim, spellInfo->Id, damage, overEnergize, powerType);
|
||||
}
|
||||
|
||||
uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, SpellEffectInfo const* effect, uint32 stack) const
|
||||
@@ -7995,11 +8001,11 @@ void Unit::CombatStart(Unit* target, bool initialAggro)
|
||||
SetInCombatWith(target);
|
||||
target->SetInCombatWith(this);
|
||||
}
|
||||
Unit* who = target->GetCharmerOrOwnerOrSelf();
|
||||
if (who->GetTypeId() == TYPEID_PLAYER)
|
||||
SetContestedPvP(who->ToPlayer());
|
||||
|
||||
Player* me = GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
Unit* who = target->GetCharmerOrOwnerOrSelf();
|
||||
if (me && who->GetTypeId() == TYPEID_PLAYER)
|
||||
me->SetContestedPvP(who->ToPlayer());
|
||||
if (me && who->IsPvP()
|
||||
&& (who->GetTypeId() != TYPEID_PLAYER
|
||||
|| !me->duel || me->duel->opponent != who))
|
||||
@@ -8041,7 +8047,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
|
||||
creature->AI()->EnterCombat(enemy);
|
||||
|
||||
if (creature->GetFormation())
|
||||
creature->GetFormation()->MemberAttackStart(creature, enemy);
|
||||
creature->GetFormation()->MemberEngagingTarget(creature, enemy);
|
||||
}
|
||||
|
||||
if (IsPet())
|
||||
@@ -8726,7 +8732,7 @@ void Unit::setDeathState(DeathState s)
|
||||
if (s != ALIVE && s != JUST_RESPAWNED)
|
||||
{
|
||||
CombatStop();
|
||||
DeleteThreatList();
|
||||
GetThreatManager().ClearAllThreat();
|
||||
getHostileRefManager().deleteReferences();
|
||||
|
||||
if (IsNonMeleeSpellCast(false))
|
||||
@@ -8795,7 +8801,7 @@ bool Unit::CanHaveThreatList(bool skipAliveCheck) const
|
||||
// return false;
|
||||
|
||||
// summons can not have a threat list, unless they are controlled by a creature
|
||||
if (HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Pet*)this)->GetOwnerGUID().IsPlayer())
|
||||
if (HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && GetOwnerGUID().IsPlayer())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -8815,24 +8821,6 @@ float Unit::ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask)
|
||||
|
||||
//======================================================================
|
||||
|
||||
void Unit::AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask, SpellInfo const* threatSpell)
|
||||
{
|
||||
// Only mobs can manage threat lists
|
||||
if (CanHaveThreatList() && !HasUnitState(UNIT_STATE_EVADE))
|
||||
m_ThreatManager.addThreat(victim, fThreat, schoolMask, threatSpell);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
void Unit::DeleteThreatList()
|
||||
{
|
||||
if (CanHaveThreatList(true) && !m_ThreatManager.isThreatListEmpty())
|
||||
SendClearThreatListOpcode();
|
||||
m_ThreatManager.clearReferences();
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
void Unit::TauntApply(Unit* taunter)
|
||||
{
|
||||
ASSERT(GetTypeId() == TYPEID_UNIT);
|
||||
@@ -9987,7 +9975,7 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup)
|
||||
|
||||
m_Events.KillAllEvents(false); // non-delatable (currently cast spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
|
||||
CombatStop();
|
||||
DeleteThreatList();
|
||||
GetThreatManager().ClearAllThreat();
|
||||
getHostileRefManager().deleteReferences();
|
||||
}
|
||||
|
||||
@@ -10633,8 +10621,7 @@ Player* Unit::GetSpellModOwner() const
|
||||
if (HasUnitTypeMask(UNIT_MASK_PET | UNIT_MASK_TOTEM | UNIT_MASK_GUARDIAN))
|
||||
{
|
||||
if (Unit* owner = GetOwner())
|
||||
if (Player* player = owner->ToPlayer())
|
||||
return player;
|
||||
return owner->ToPlayer();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -11153,29 +11140,6 @@ float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) const
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::SetContestedPvP(Player* attackedPlayer)
|
||||
{
|
||||
Player* player = GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
|
||||
if (!player || (attackedPlayer && (attackedPlayer == player || (player->duel && player->duel->opponent == attackedPlayer))))
|
||||
return;
|
||||
|
||||
player->SetContestedPvPTimer(30000);
|
||||
if (!player->HasUnitState(UNIT_STATE_ATTACK_PLAYER))
|
||||
{
|
||||
player->AddUnitState(UNIT_STATE_ATTACK_PLAYER);
|
||||
player->AddPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP);
|
||||
// call MoveInLineOfSight for nearby contested guards
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
if (!HasUnitState(UNIT_STATE_ATTACK_PLAYER))
|
||||
{
|
||||
AddUnitState(UNIT_STATE_ATTACK_PLAYER);
|
||||
// call MoveInLineOfSight for nearby contested guards
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget, uint32 spell_id)
|
||||
{
|
||||
if (GetTypeId() != TYPEID_PLAYER)
|
||||
@@ -11475,7 +11439,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
|
||||
|
||||
if (!creature->IsPet())
|
||||
{
|
||||
creature->DeleteThreatList();
|
||||
creature->GetThreatManager().ClearAllThreat();
|
||||
|
||||
// must be after setDeathState which resets dynamic flags
|
||||
if (!creature->loot.isLooted())
|
||||
@@ -11845,7 +11809,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
|
||||
CastStop();
|
||||
CombatStop(); /// @todo CombatStop(true) may cause crash (interrupt spells)
|
||||
DeleteThreatList();
|
||||
GetThreatManager().ClearAllThreat();
|
||||
|
||||
Player* playerCharmer = charmer->ToPlayer();
|
||||
|
||||
@@ -11988,7 +11952,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
||||
CastStop();
|
||||
CombatStop(); /// @todo CombatStop(true) may cause crash (interrupt spells)
|
||||
getHostileRefManager().deleteReferences();
|
||||
DeleteThreatList();
|
||||
GetThreatManager().ClearAllThreat();
|
||||
|
||||
if (_oldFactionId)
|
||||
{
|
||||
@@ -12471,8 +12435,8 @@ void Unit::OnPhaseChange()
|
||||
// modify threat lists for new phasemask
|
||||
if (GetTypeId() != TYPEID_PLAYER)
|
||||
{
|
||||
std::list<HostileReference*> threatList = getThreatManager().getThreatList();
|
||||
std::list<HostileReference*> offlineThreatList = getThreatManager().getOfflineThreatList();
|
||||
std::list<HostileReference*> threatList = GetThreatManager().getThreatList();
|
||||
std::list<HostileReference*> offlineThreatList = GetThreatManager().getOfflineThreatList();
|
||||
|
||||
// merge expects sorted lists
|
||||
threatList.sort();
|
||||
@@ -13385,11 +13349,11 @@ void Unit::UpdateHeight(float newZ)
|
||||
|
||||
void Unit::SendThreatListUpdate()
|
||||
{
|
||||
if (!getThreatManager().isThreatListEmpty())
|
||||
if (!GetThreatManager().isThreatListEmpty())
|
||||
{
|
||||
WorldPackets::Combat::ThreatUpdate packet;
|
||||
packet.UnitGUID = GetGUID();
|
||||
ThreatContainer::StorageType const &tlist = getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType const& tlist = GetThreatManager().getThreatList();
|
||||
packet.ThreatList.reserve(tlist.size());
|
||||
for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
|
||||
{
|
||||
@@ -13404,12 +13368,12 @@ void Unit::SendThreatListUpdate()
|
||||
|
||||
void Unit::SendChangeCurrentVictimOpcode(HostileReference* pHostileReference)
|
||||
{
|
||||
if (!getThreatManager().isThreatListEmpty())
|
||||
if (!GetThreatManager().isThreatListEmpty())
|
||||
{
|
||||
WorldPackets::Combat::HighestThreatUpdate packet;
|
||||
packet.UnitGUID = GetGUID();
|
||||
packet.HighestThreatGUID = pHostileReference->getUnitGuid();
|
||||
ThreatContainer::StorageType const &tlist = getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType const& tlist = GetThreatManager().getThreatList();
|
||||
packet.ThreatList.reserve(tlist.size());
|
||||
for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
|
||||
{
|
||||
|
||||
@@ -976,8 +976,9 @@ class TC_GAME_API Unit : public WorldObject
|
||||
bool IsWithinCombatRange(const Unit* obj, float dist2compare) const;
|
||||
bool IsWithinMeleeRange(Unit const* obj) const;
|
||||
float GetMeleeRange(Unit const* target) const;
|
||||
virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
|
||||
bool IsWithinBoundaryRadius(const Unit* obj) const;
|
||||
void GetRandomContactPoint(const Unit* target, float &x, float &y, float &z, float distance2dMin, float distance2dMax) const;
|
||||
void GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, float distance2dMin, float distance2dMax) const;
|
||||
uint32 m_extraAttacks;
|
||||
bool m_canDualWield;
|
||||
|
||||
@@ -1267,6 +1268,12 @@ class TC_GAME_API Unit : public WorldObject
|
||||
|
||||
bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); }
|
||||
|
||||
bool IsEngaged() const { return IsInCombat(); }
|
||||
bool IsEngagedBy(Unit const* who) const { return IsInCombatWith(who); }
|
||||
void EngageWithTarget(Unit* who) { SetInCombatWith(who); who->SetInCombatWith(this); GetThreatManager().AddThreat(who, 0.0f); }
|
||||
bool IsThreatened() const { return CanHaveThreatList() && !GetThreatManager().IsThreatListEmpty(); }
|
||||
bool IsThreatenedBy(Unit const* who) const { return who && CanHaveThreatList() && GetThreatManager().IsThreatenedBy(who); }
|
||||
|
||||
bool IsInCombat() const { return HasUnitFlag(UNIT_FLAG_IN_COMBAT); }
|
||||
bool IsPetInCombat() const { return HasUnitFlag(UNIT_FLAG_PET_IN_COMBAT); }
|
||||
bool IsInCombatWith(Unit const* who) const;
|
||||
@@ -1303,8 +1310,9 @@ class TC_GAME_API Unit : public WorldObject
|
||||
|
||||
void SendHealSpellLog(HealInfo& healInfo, bool critical = false);
|
||||
int32 HealBySpell(HealInfo& healInfo, bool critical = false);
|
||||
void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, int32 overEnergize, Powers powerType);
|
||||
void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype);
|
||||
void SendEnergizeSpellLog(Unit* victim, uint32 spellId, int32 damage, int32 overEnergize, Powers powerType);
|
||||
void EnergizeBySpell(Unit* victim, uint32 spellId, int32 damage, Powers powerType);
|
||||
void EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damage, Powers powerType);
|
||||
|
||||
void CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
|
||||
void CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
|
||||
@@ -1761,12 +1769,11 @@ class TC_GAME_API Unit : public WorldObject
|
||||
|
||||
// Threat related methods
|
||||
bool CanHaveThreatList(bool skipAliveCheck = false) const;
|
||||
void AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* threatSpell = NULL);
|
||||
float ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL);
|
||||
void DeleteThreatList();
|
||||
void TauntApply(Unit* victim);
|
||||
void TauntFadeOut(Unit* taunter);
|
||||
ThreatManager& getThreatManager() { return m_ThreatManager; }
|
||||
ThreatManager& GetThreatManager() { return m_ThreatManager; }
|
||||
ThreatManager const& GetThreatManager() const { return m_ThreatManager; }
|
||||
void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); }
|
||||
void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ }
|
||||
HostileRefManager& getHostileRefManager() { return m_HostileRefManager; }
|
||||
@@ -2094,8 +2101,6 @@ class TC_GAME_API Unit : public WorldObject
|
||||
CharmInfo* m_charmInfo;
|
||||
SharedVisionList m_sharedVision;
|
||||
|
||||
virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
|
||||
|
||||
MotionMaster* i_motionMaster;
|
||||
|
||||
uint32 m_reactiveTimer[MAX_REACTIVE];
|
||||
|
||||
@@ -219,11 +219,10 @@ void ObjectGridStoper::Visit(CreatureMapType &m)
|
||||
{
|
||||
iter->GetSource()->RemoveAllDynObjects();
|
||||
iter->GetSource()->RemoveAllAreaTriggers();
|
||||
|
||||
if (iter->GetSource()->IsInCombat() || !iter->GetSource()->getThreatManager().areThreatListsEmpty())
|
||||
if (iter->GetSource()->IsInCombat() || !iter->GetSource()->GetThreatManager().areThreatListsEmpty())
|
||||
{
|
||||
iter->GetSource()->CombatStop();
|
||||
iter->GetSource()->DeleteThreatList();
|
||||
iter->GetSource()->GetThreatManager().ClearAllThreat();
|
||||
iter->GetSource()->AI()->EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "Spell.h"
|
||||
#include "SpellHistory.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "ThreatManager.h"
|
||||
#include "Unit.h"
|
||||
#include "Util.h"
|
||||
#include "Vehicle.h"
|
||||
@@ -4498,7 +4499,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
|
||||
case 1515: // Tame beast
|
||||
// FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
|
||||
if (caster && target->CanHaveThreatList())
|
||||
target->AddThreat(caster, 10.0f);
|
||||
target->GetThreatManager().AddThreat(caster, 10.0f);
|
||||
break;
|
||||
case 13139: // net-o-matic
|
||||
// root to self part of (root_target->charge->root_self sequence
|
||||
@@ -5794,7 +5795,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
|
||||
HealInfo healInfo(caster, caster, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
|
||||
caster->HealBySpell(healInfo);
|
||||
|
||||
caster->getHostileRefManager().threatAssist(caster, healInfo.GetEffectiveHeal() * 0.5f, GetSpellInfo());
|
||||
caster->GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal()*0.5f, GetSpellInfo());
|
||||
caster->ProcSkillsAndAuras(caster, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo);
|
||||
}
|
||||
|
||||
@@ -5904,7 +5905,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
|
||||
SpellPeriodicAuraLogInfo pInfo(this, heal, damage, heal - healInfo.GetEffectiveHeal(), healInfo.GetAbsorb(), 0, 0.0f, crit);
|
||||
target->SendPeriodicAuraLog(&pInfo);
|
||||
|
||||
target->getHostileRefManager().threatAssist(caster, float(healInfo.GetEffectiveHeal()) * 0.5f, GetSpellInfo());
|
||||
target->GetThreatManager().ForwardThreatForAssistingMe(caster, float(healInfo.GetEffectiveHeal())*0.5f, GetSpellInfo());
|
||||
|
||||
// %-based heal - does not proc auras
|
||||
if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH)
|
||||
@@ -5952,7 +5953,8 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
|
||||
if (gainAmount)
|
||||
{
|
||||
gainedAmount = caster->ModifyPower(powerType, gainAmount);
|
||||
target->AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo()->GetSchoolMask(), GetSpellInfo());
|
||||
// energize is not modified by threat modifiers
|
||||
target->GetThreatManager().AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo(), true);
|
||||
}
|
||||
|
||||
// Drain Mana
|
||||
@@ -6003,7 +6005,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const
|
||||
int32 gain = target->ModifyPower(powerType, amount);
|
||||
|
||||
if (caster)
|
||||
target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellInfo());
|
||||
target->GetThreatManager().ForwardThreatForAssistingMe(caster, float(gain)*0.5f, GetSpellInfo(), true);
|
||||
|
||||
target->SendPeriodicAuraLog(&pInfo);
|
||||
}
|
||||
@@ -6036,7 +6038,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons
|
||||
target->SendPeriodicAuraLog(&pInfo);
|
||||
|
||||
if (caster)
|
||||
target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellInfo());
|
||||
target->GetThreatManager().ForwardThreatForAssistingMe(caster, float(gain)*0.5f, GetSpellInfo(), true);
|
||||
}
|
||||
|
||||
void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) const
|
||||
|
||||
@@ -2453,7 +2453,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
|
||||
HealInfo healInfo(caster, unitTarget, addhealth, m_spellInfo, m_spellInfo->GetSchoolMask());
|
||||
caster->HealBySpell(healInfo, crit);
|
||||
unitTarget->getHostileRefManager().threatAssist(caster, float(healInfo.GetEffectiveHeal()) * 0.5f, m_spellInfo);
|
||||
unitTarget->GetThreatManager().ForwardThreatForAssistingMe(caster, float(healInfo.GetEffectiveHeal())*0.5f, m_spellInfo);
|
||||
m_healing = healInfo.GetEffectiveHeal();
|
||||
|
||||
// Do triggers for unit
|
||||
@@ -2523,8 +2523,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
if (missInfo == SPELL_MISS_RESIST && m_spellInfo->HasAttribute(SPELL_ATTR0_CU_PICKPOCKET) && unitTarget->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
|
||||
if (unitTarget->ToCreature()->IsAIEnabled)
|
||||
unitTarget->ToCreature()->AI()->AttackStart(m_caster);
|
||||
unitTarget->ToCreature()->EngageWithTarget(m_caster);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2620,14 +2619,16 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
|
||||
// assisting case, healing and resurrection
|
||||
if (unit->HasUnitState(UNIT_STATE_ATTACK_PLAYER))
|
||||
{
|
||||
m_caster->SetContestedPvP();
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
m_caster->ToPlayer()->UpdatePvP(true);
|
||||
if (Player* playerOwner = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
{
|
||||
playerOwner->SetContestedPvP();
|
||||
playerOwner->UpdatePvP(true);
|
||||
}
|
||||
}
|
||||
if (unit->IsInCombat() && m_spellInfo->HasInitialAggro())
|
||||
{
|
||||
m_caster->SetInCombatState(unit->GetCombatTimer() > 0, unit);
|
||||
unit->getHostileRefManager().threatAssist(m_caster, 0.0f);
|
||||
unit->GetThreatManager().ForwardThreatForAssistingMe(m_caster, 0.0f, nullptr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4838,14 +4839,14 @@ void Spell::HandleThreatSpells()
|
||||
|
||||
// positive spells distribute threat among all units that are in combat with target, like healing
|
||||
if (m_spellInfo->IsPositive())
|
||||
target->getHostileRefManager().threatAssist(m_caster, threatToAdd, m_spellInfo);
|
||||
target->GetThreatManager().ForwardThreatForAssistingMe(m_caster, threatToAdd, m_spellInfo);
|
||||
// for negative spells threat gets distributed among affected targets
|
||||
else
|
||||
{
|
||||
if (!target->CanHaveThreatList())
|
||||
continue;
|
||||
|
||||
target->AddThreat(m_caster, threatToAdd, m_spellInfo->GetSchoolMask(), m_spellInfo);
|
||||
target->GetThreatManager().AddThreat(m_caster, threatToAdd, m_spellInfo, true);
|
||||
}
|
||||
}
|
||||
TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->IsPositive() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
|
||||
@@ -7937,7 +7938,7 @@ bool WorldObjectSpellTargetCheck::operator()(WorldObject* target)
|
||||
return false;
|
||||
break;
|
||||
case TARGET_CHECK_THREAT:
|
||||
if (_referer->getThreatManager().getThreat(unitTarget, true) <= 0.0f)
|
||||
if (_referer->GetThreatManager().getThreat(unitTarget, true) <= 0.0f)
|
||||
return false;
|
||||
break;
|
||||
case TARGET_CHECK_TAP:
|
||||
|
||||
@@ -2214,7 +2214,7 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/)
|
||||
return;
|
||||
|
||||
// Check for possible target
|
||||
if (!unitTarget || unitTarget->IsInCombat())
|
||||
if (!unitTarget || unitTarget->IsEngaged())
|
||||
return;
|
||||
|
||||
// target must be OK to do this
|
||||
@@ -2730,17 +2730,17 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!unitTarget->getThreatManager().getOnlineContainer().empty())
|
||||
if (!unitTarget->GetThreatManager().getOnlineContainer().empty())
|
||||
{
|
||||
// Also use this effect to set the taunter's threat to the taunted creature's highest value
|
||||
float myThreat = unitTarget->getThreatManager().getThreat(m_caster);
|
||||
float topThreat = unitTarget->getThreatManager().getOnlineContainer().getMostHated()->getThreat();
|
||||
float myThreat = unitTarget->GetThreatManager().getThreat(m_caster);
|
||||
float topThreat = unitTarget->GetThreatManager().getOnlineContainer().getMostHated()->getThreat();
|
||||
if (topThreat > myThreat)
|
||||
unitTarget->getThreatManager().doAddThreat(m_caster, topThreat - myThreat);
|
||||
unitTarget->GetThreatManager().doAddThreat(m_caster, topThreat - myThreat);
|
||||
|
||||
//Set aggro victim to caster
|
||||
if (HostileReference* forcedVictim = unitTarget->getThreatManager().getOnlineContainer().getReferenceByTarget(m_caster))
|
||||
unitTarget->getThreatManager().setCurrentVictim(forcedVictim);
|
||||
if (HostileReference* forcedVictim = unitTarget->GetThreatManager().getOnlineContainer().getReferenceByTarget(m_caster))
|
||||
unitTarget->GetThreatManager().setCurrentVictim(forcedVictim);
|
||||
}
|
||||
|
||||
if (unitTarget->ToCreature()->IsAIEnabled && !unitTarget->ToCreature()->HasReactState(REACT_PASSIVE))
|
||||
@@ -2950,7 +2950,7 @@ void Spell::EffectThreat(SpellEffIndex /*effIndex*/)
|
||||
if (!unitTarget->CanHaveThreatList())
|
||||
return;
|
||||
|
||||
unitTarget->AddThreat(m_caster, float(damage));
|
||||
unitTarget->GetThreatManager().AddThreat(m_caster, float(damage));
|
||||
}
|
||||
|
||||
void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
|
||||
@@ -4589,7 +4589,7 @@ void Spell::EffectModifyThreatPercent(SpellEffIndex /*effIndex*/)
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
|
||||
unitTarget->GetThreatManager().ModifyThreatByPercent(m_caster, damage);
|
||||
}
|
||||
|
||||
void Spell::EffectTransmitted(SpellEffIndex effIndex)
|
||||
|
||||
@@ -843,7 +843,7 @@ public:
|
||||
if (!target || target->IsTotem() || target->IsPet())
|
||||
return false;
|
||||
|
||||
ThreatContainer::StorageType const &threatList = target->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType const& threatList = target->GetThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType::const_iterator itr;
|
||||
uint32 count = 0;
|
||||
handler->PSendSysMessage("Threat list of %s (%s)", target->GetName().c_str(), target->GetGUID().ToString().c_str());
|
||||
|
||||
@@ -161,7 +161,7 @@ class boss_alizabal : public CreatureScript
|
||||
case 0:
|
||||
if (!_skewer)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0))
|
||||
{
|
||||
DoCast(target, SPELL_SKEWER, true);
|
||||
Talk(SAY_SKEWER);
|
||||
@@ -203,7 +203,7 @@ class boss_alizabal : public CreatureScript
|
||||
}
|
||||
else if (!_skewer)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0))
|
||||
{
|
||||
DoCast(target, SPELL_SKEWER, true);
|
||||
Talk(SAY_SKEWER);
|
||||
|
||||
@@ -212,7 +212,7 @@ class FocusedFireTargetSelector : public std::unary_function<Unit *, bool>
|
||||
|
||||
bool operator() (WorldObject* target)
|
||||
{
|
||||
if (target == _victim && _me->getThreatManager().getThreatList().size() > 1)
|
||||
if (target == _victim && _me->GetThreatManager().getThreatList().size() > 1)
|
||||
return true;
|
||||
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
|
||||
+1
-1
@@ -321,7 +321,7 @@ public:
|
||||
})
|
||||
.Schedule(Seconds(2), [this](TaskContext mugChuck)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, -SPELL_HAS_DARK_BREWMAIDENS_BREW))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, true, -SPELL_HAS_DARK_BREWMAIDENS_BREW))
|
||||
DoCast(target, SPELL_CHUCK_MUG);
|
||||
mugChuck.Repeat(Seconds(4));
|
||||
});
|
||||
|
||||
+1
-1
@@ -374,7 +374,7 @@ public:
|
||||
{//do not call EnterEvadeMode(), it will create infinit loops
|
||||
boss->Respawn();
|
||||
boss->RemoveAllAuras();
|
||||
boss->DeleteThreatList();
|
||||
boss->GetThreatManager().ClearAllThreat();
|
||||
boss->CombatStop(true);
|
||||
boss->LoadCreaturesAddon();
|
||||
boss->GetMotionMaster()->MoveTargetedHome();
|
||||
|
||||
+2
-2
@@ -88,8 +88,8 @@ public:
|
||||
break;
|
||||
case EVENT_KNOCKBACK:
|
||||
DoCastVictim(SPELL_KNOCKBACK);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatPercent(me->GetVictim(), -50);
|
||||
if (GetThreat(me->GetVictim()))
|
||||
ModifyThreatByPercent(me->GetVictim(), -50);
|
||||
events.ScheduleEvent(EVENT_KNOCKBACK, urand(15000, 30000));
|
||||
break;
|
||||
case EVENT_CHECK:
|
||||
|
||||
@@ -71,8 +71,8 @@ public:
|
||||
break;
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatPercent(me->GetVictim(), -75);
|
||||
if (GetThreat(me->GetVictim()))
|
||||
ModifyThreatByPercent(me->GetVictim(), -75);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30000);
|
||||
break;
|
||||
case EVENT_FLAMEBUFFET:
|
||||
|
||||
+2
-2
@@ -76,8 +76,8 @@ public:
|
||||
break;
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatPercent(me->GetVictim(), -75);
|
||||
if (GetThreat(me->GetVictim()))
|
||||
ModifyThreatByPercent(me->GetVictim(), -75);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30000);
|
||||
break;
|
||||
case EVENT_FRENZY:
|
||||
|
||||
+1
-1
@@ -319,7 +319,7 @@ public:
|
||||
DoCast(target, SPELL_SHADOWBOLT);
|
||||
break;
|
||||
}
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(3000, 10000));
|
||||
break;
|
||||
case EVENT_FEAR:
|
||||
|
||||
@@ -150,10 +150,6 @@ public:
|
||||
break;
|
||||
case EVENT_CONFLAGRATION:
|
||||
DoCastVictim(SPELL_CONFLAGRATION);
|
||||
// @todo is this even necessary? pretty sure AI ignores targets with disorient by default
|
||||
if (me->GetVictim() && me->EnsureVictim()->HasAura(SPELL_CONFLAGRATION))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true))
|
||||
me->TauntApply(target);
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 30000);
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ class boss_baron_geddon : public CreatureScript
|
||||
events.ScheduleEvent(EVENT_INFERNO, 45000);
|
||||
break;
|
||||
case EVENT_IGNITE_MANA:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IGNITE_MANA))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_IGNITE_MANA))
|
||||
DoCast(target, SPELL_IGNITE_MANA);
|
||||
events.ScheduleEvent(EVENT_IGNITE_MANA, 30000);
|
||||
break;
|
||||
|
||||
@@ -95,7 +95,7 @@ class boss_magmadar : public CreatureScript
|
||||
events.ScheduleEvent(EVENT_PANIC, 35000);
|
||||
break;
|
||||
case EVENT_LAVA_BOMB:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_LAVA_BOMB))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_LAVA_BOMB))
|
||||
DoCast(target, SPELL_LAVA_BOMB);
|
||||
events.ScheduleEvent(EVENT_LAVA_BOMB, 12000);
|
||||
break;
|
||||
|
||||
@@ -248,7 +248,7 @@ class boss_ragnaros : public CreatureScript
|
||||
//is not very well supported in the core //no it really isnt
|
||||
//so added normaly spawning and banish workaround and attack again after 90 secs.
|
||||
me->AttackStop();
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
//Root self
|
||||
|
||||
@@ -82,7 +82,7 @@ class boss_shazzrah : public CreatureScript
|
||||
DoCastVictim(SPELL_ARCANE_EXPLOSION);
|
||||
break;
|
||||
case EVENT_SHAZZRAH_CURSE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHAZZRAH_CURSE))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_SHAZZRAH_CURSE))
|
||||
DoCast(target, SPELL_SHAZZRAH_CURSE);
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, urand(25000, 30000));
|
||||
break;
|
||||
@@ -95,7 +95,7 @@ class boss_shazzrah : public CreatureScript
|
||||
events.ScheduleEvent(EVENT_COUNTERSPELL, urand(16000, 20000));
|
||||
break;
|
||||
case EVENT_SHAZZRAH_GATE:
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY);
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION_TRIGGERED, 2000);
|
||||
events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, urand(3000, 6000));
|
||||
|
||||
+2
-2
@@ -184,12 +184,12 @@ class npc_flamewaker_priest : public CreatureScript
|
||||
events.ScheduleEvent(EVENT_HEAL, urand(15000, 20000));
|
||||
break;
|
||||
case EVENT_SHADOW_WORD_PAIN:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHADOWWORDPAIN))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_SHADOWWORDPAIN))
|
||||
DoCast(target, SPELL_SHADOWWORDPAIN);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(18000, 26000));
|
||||
break;
|
||||
case EVENT_IMMOLATE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IMMOLATE))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_IMMOLATE))
|
||||
DoCast(target, SPELL_IMMOLATE);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, urand(15000, 25000));
|
||||
break;
|
||||
|
||||
@@ -213,11 +213,7 @@ public:
|
||||
continue;
|
||||
|
||||
if (player->IsAlive())
|
||||
{
|
||||
temp->SetInCombatWith(player);
|
||||
player->SetInCombatWith(temp);
|
||||
temp->AddThreat(player, 0.0f);
|
||||
}
|
||||
AddThreat(player, 0.0f, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_HATEFUL_BOLT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 1))
|
||||
DoCast(target, SPELL_HATEFUL_BOLT);
|
||||
events.Repeat(Seconds(7), Seconds(15));
|
||||
break;
|
||||
|
||||
@@ -172,12 +172,11 @@ public:
|
||||
scheduler.Schedule(Seconds(10), Seconds(25), [this](TaskContext task)
|
||||
{
|
||||
Unit* target = nullptr;
|
||||
ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList();
|
||||
std::vector<Unit*> target_list;
|
||||
|
||||
for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr)
|
||||
for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
|
||||
{
|
||||
target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
|
||||
target = ref->GetVictim();
|
||||
if (target && !target->IsWithinDist(me, 8.00f, false) && target->IsWithinDist(me, 25.0f, false))
|
||||
target_list.push_back(target);
|
||||
|
||||
|
||||
@@ -299,14 +299,8 @@ public:
|
||||
|
||||
if (Blind_Timer <= diff)
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetCombatReach()*5, true);
|
||||
for (std::list<Unit*>::const_iterator i = targets.begin(); i != targets.end(); ++i)
|
||||
if (!me->IsWithinMeleeRange(*i))
|
||||
{
|
||||
DoCast(*i, SPELL_BLIND);
|
||||
break;
|
||||
}
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 0.0f, true, false))
|
||||
DoCast(target, SPELL_BLIND);
|
||||
Blind_Timer = 40000;
|
||||
} else Blind_Timer -= diff;
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ public:
|
||||
}
|
||||
// aggro target if Red Beam
|
||||
if (j == RED_PORTAL && me->GetVictim() != target && target->GetTypeId() == TYPEID_PLAYER)
|
||||
me->getThreatManager().addThreat(target, 100000.0f+DoGetThreat(me->GetVictim()));
|
||||
AddThreat(target, 100000.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ public:
|
||||
me->GetMotionMaster()->MoveAlongSplineChain(POINT_INTRO_END, SPLINE_CHAIN_INTRO_END, false);
|
||||
break;
|
||||
case EVENT_RAIN_OF_BONES:
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
me->SetFacingToObject(target);
|
||||
|
||||
@@ -315,19 +315,18 @@ public:
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
ThreatContainer::StorageType const& t_list = me->getThreatManager().getThreatList();
|
||||
Unit* tank = me->GetThreatManager().GetCurrentVictim();
|
||||
std::vector<Unit*> targets;
|
||||
|
||||
if (t_list.empty())
|
||||
return;
|
||||
for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList())
|
||||
{
|
||||
Unit* target = ref->GetVictim();
|
||||
if (target != tank && target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER)
|
||||
targets.push_back(target);
|
||||
}
|
||||
|
||||
//begin + 1, so we don't target the one with the highest threat
|
||||
ThreatContainer::StorageType::const_iterator itr = t_list.begin();
|
||||
std::advance(itr, 1);
|
||||
for (; itr != t_list.end(); ++itr) //store the threat list in a different container
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
|
||||
if (target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER)
|
||||
targets.push_back(target);
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
//cut down to size if we have more than 5 targets
|
||||
while (targets.size() > 5)
|
||||
@@ -454,9 +453,7 @@ public:
|
||||
if (target)
|
||||
{
|
||||
axe->AI()->AttackStart(target);
|
||||
//axe->getThreatManager().tauntApply(target); //Taunt Apply and fade out does not work properly
|
||||
// So we'll use a hack to add a lot of threat to our target
|
||||
axe->AddThreat(target, 10000000.0f);
|
||||
AddThreat(target, 10000000.0f, axe);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -492,11 +489,9 @@ public:
|
||||
if (Unit* axe = ObjectAccessor::GetUnit(*me, axes[i]))
|
||||
{
|
||||
if (axe->GetVictim())
|
||||
DoModifyThreatPercent(axe->GetVictim(), -100);
|
||||
ResetThreat(axe->GetVictim(), axe);
|
||||
if (target)
|
||||
axe->AddThreat(target, 1000000.0f);
|
||||
//axe->getThreatManager().tauntFadeOut(axe->GetVictim());
|
||||
//axe->getThreatManager().tauntApply(target);
|
||||
AddThreat(target, 1000000.0f, axe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,18 +205,12 @@ public:
|
||||
void FlameWreathEffect()
|
||||
{
|
||||
std::vector<Unit*> targets;
|
||||
ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList();
|
||||
|
||||
if (t_list.empty())
|
||||
return;
|
||||
|
||||
//store the threat list in a different container
|
||||
for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
|
||||
for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
|
||||
//only on alive players
|
||||
if (target && target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER)
|
||||
targets.push_back(target);
|
||||
Unit* target = ref->GetVictim();
|
||||
if (ref->GetVictim()->GetTypeId() == TYPEID_PLAYER && ref->GetVictim()->IsAlive())
|
||||
targets.push_back(target);
|
||||
}
|
||||
|
||||
//cut down to size if we have more than 3 targets
|
||||
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
events.Repeat(Seconds(42));
|
||||
break;
|
||||
case EVENT_SHADOWBOLT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0))
|
||||
DoCast(target, SPELL_SHADOW_BOLT);
|
||||
events.Repeat(Seconds(4), Seconds(10));
|
||||
break;
|
||||
|
||||
@@ -923,11 +923,11 @@ public:
|
||||
{
|
||||
Talk(SAY_WOLF_HOOD);
|
||||
DoCast(target, SPELL_LITTLE_RED_RIDING_HOOD, true);
|
||||
TempThreat = DoGetThreat(target);
|
||||
TempThreat = GetThreat(target);
|
||||
if (TempThreat)
|
||||
DoModifyThreatPercent(target, -100);
|
||||
ModifyThreatByPercent(target, -100);
|
||||
HoodGUID = target->GetGUID();
|
||||
me->AddThreat(target, 1000000.0f);
|
||||
AddThreat(target, 1000000.0f);
|
||||
ChaseTimer = 20000;
|
||||
IsChasing = true;
|
||||
}
|
||||
@@ -939,9 +939,9 @@ public:
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, HoodGUID))
|
||||
{
|
||||
HoodGUID.Clear();
|
||||
if (DoGetThreat(target))
|
||||
DoModifyThreatPercent(target, -100);
|
||||
me->AddThreat(target, TempThreat);
|
||||
if (GetThreat(target))
|
||||
ModifyThreatByPercent(target, -100);
|
||||
AddThreat(target, TempThreat);
|
||||
TempThreat = 0;
|
||||
}
|
||||
|
||||
@@ -1256,7 +1256,7 @@ public:
|
||||
Julianne->GetMotionMaster()->Clear();
|
||||
Julianne->setDeathState(JUST_DIED);
|
||||
Julianne->CombatStop(true);
|
||||
Julianne->DeleteThreatList();
|
||||
Julianne->GetThreatManager().ClearAllThreat();
|
||||
Julianne->SetDynamicFlags(UNIT_DYNFLAG_LOOTABLE);
|
||||
}
|
||||
return;
|
||||
@@ -1284,7 +1284,7 @@ public:
|
||||
Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID));
|
||||
if (Julianne && Julianne->GetVictim())
|
||||
{
|
||||
me->AddThreat(Julianne->GetVictim(), 1.0f);
|
||||
AddThreat(Julianne->GetVictim(), 1.0f);
|
||||
AttackStart(Julianne->GetVictim());
|
||||
}
|
||||
}
|
||||
@@ -1526,7 +1526,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->GetThreatManager().ClearAllThreat();
|
||||
Romulo->SetDynamicFlags(UNIT_DYNFLAG_LOOTABLE);
|
||||
}
|
||||
|
||||
|
||||
@@ -200,15 +200,15 @@ public:
|
||||
if (!summonedUnit)
|
||||
return;
|
||||
|
||||
ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType const& threatlist = me->GetThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType::const_iterator i = threatlist.begin();
|
||||
for (i = threatlist.begin(); i != threatlist.end(); ++i)
|
||||
{
|
||||
Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid());
|
||||
if (unit && unit->IsAlive())
|
||||
{
|
||||
float threat = me->getThreatManager().getThreat(unit);
|
||||
summonedUnit->AddThreat(unit, threat);
|
||||
float threat = me->GetThreatManager().getThreat(unit);
|
||||
AddThreat(unit, threat, summonedUnit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
float x = KaelLocations[0][0];
|
||||
float y = KaelLocations[0][1];
|
||||
me->UpdatePosition(x, y, LOCATION_Z, 0.0f);
|
||||
ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType::const_iterator i = threatlist.begin();
|
||||
for (i = threatlist.begin(); i != threatlist.end(); ++i)
|
||||
{
|
||||
@@ -231,7 +231,7 @@ public:
|
||||
|
||||
void CastGravityLapseKnockUp()
|
||||
{
|
||||
ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType::const_iterator i = threatlist.begin();
|
||||
for (i = threatlist.begin(); i != threatlist.end(); ++i)
|
||||
{
|
||||
@@ -244,7 +244,7 @@ public:
|
||||
|
||||
void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air...
|
||||
{
|
||||
ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType::const_iterator i = threatlist.begin();
|
||||
for (i = threatlist.begin(); i != threatlist.end(); ++i)
|
||||
{
|
||||
@@ -260,7 +260,7 @@ public:
|
||||
|
||||
void RemoveGravityLapse()
|
||||
{
|
||||
ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType::const_iterator i = threatlist.begin();
|
||||
for (i = threatlist.begin(); i != threatlist.end(); ++i)
|
||||
{
|
||||
@@ -400,7 +400,7 @@ public:
|
||||
if (Orb && target)
|
||||
{
|
||||
Orb->SetSpeedRate(MOVE_RUN, 0.5f);
|
||||
Orb->AddThreat(target, 1000000.0f);
|
||||
AddThreat(target, 1000000.0f, Orb);
|
||||
Orb->AI()->AttackStart(target);
|
||||
}
|
||||
}
|
||||
@@ -680,7 +680,7 @@ public:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AttackStart(target);
|
||||
}
|
||||
|
||||
@@ -168,16 +168,9 @@ public:
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i)
|
||||
{
|
||||
if (Unit* pAdd = ObjectAccessor::GetUnit(*me, m_auiLackeyGUID[i]))
|
||||
{
|
||||
if (!pAdd->GetVictim())
|
||||
{
|
||||
who->SetInCombatWith(pAdd);
|
||||
pAdd->AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pAdd->IsEngaged())
|
||||
AddThreat(who, 0.0f, pAdd);
|
||||
|
||||
instance->SetBossState(DATA_DELRISSA, IN_PROGRESS);
|
||||
}
|
||||
@@ -398,25 +391,13 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI
|
||||
return;
|
||||
|
||||
for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i)
|
||||
{
|
||||
if (Unit* pAdd = ObjectAccessor::GetUnit(*me, m_auiLackeyGUIDs[i]))
|
||||
{
|
||||
if (!pAdd->GetVictim() && pAdd != me)
|
||||
{
|
||||
who->SetInCombatWith(pAdd);
|
||||
pAdd->AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pAdd->IsEngaged() && pAdd != me)
|
||||
AddThreat(who, 0.0f, pAdd);
|
||||
|
||||
if (Creature* pDelrissa = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_DELRISSA)))
|
||||
{
|
||||
if (pDelrissa->IsAlive() && !pDelrissa->GetVictim())
|
||||
{
|
||||
who->SetInCombatWith(pDelrissa);
|
||||
pDelrissa->AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
if (pDelrissa->IsAlive() && !pDelrissa->IsEngaged())
|
||||
AddThreat(who, 0.0f, pDelrissa);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -472,7 +453,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI
|
||||
|
||||
if (ResetThreatTimer <= diff)
|
||||
{
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
ResetThreatTimer = urand(5000, 20000);
|
||||
} else ResetThreatTimer -= diff;
|
||||
}
|
||||
@@ -544,10 +525,10 @@ public:
|
||||
|
||||
Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0);
|
||||
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
|
||||
if (unit)
|
||||
me->AddThreat(unit, 1000.0f);
|
||||
AddThreat(unit, 1000.0f);
|
||||
|
||||
InVanish = true;
|
||||
Vanish_Timer = 30000;
|
||||
@@ -869,7 +850,7 @@ public:
|
||||
if (Blink_Timer <= diff)
|
||||
{
|
||||
bool InMeleeRange = false;
|
||||
ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType const& t_list = me->GetThreatManager().getThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
|
||||
@@ -963,7 +944,7 @@ public:
|
||||
if (Intercept_Stun_Timer <= diff)
|
||||
{
|
||||
bool InMeleeRange = false;
|
||||
ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType const& t_list = me->GetThreatManager().getThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
|
||||
|
||||
@@ -430,7 +430,7 @@ public:
|
||||
|
||||
if (me->Attack(who, true))
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
DoStartMovement(who);
|
||||
@@ -1384,7 +1384,7 @@ public:
|
||||
if (me->HasAura(SPELL_THE_MIGHT_OF_MOGRAINE))
|
||||
me->RemoveAurasDueToSpell(SPELL_THE_MIGHT_OF_MOGRAINE);
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->SetWalk(false);
|
||||
@@ -1405,7 +1405,7 @@ public:
|
||||
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiKorfaxGUID))
|
||||
{
|
||||
temp->RemoveAllAuras();
|
||||
temp->DeleteThreatList();
|
||||
temp->GetThreatManager().ClearAllThreat();
|
||||
temp->CombatStop(true);
|
||||
temp->AttackStop();
|
||||
temp->SetFaction(me->GetFaction());
|
||||
@@ -1416,7 +1416,7 @@ public:
|
||||
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiMaxwellGUID))
|
||||
{
|
||||
temp->RemoveAllAuras();
|
||||
temp->DeleteThreatList();
|
||||
temp->GetThreatManager().ClearAllThreat();
|
||||
temp->CombatStop(true);
|
||||
temp->AttackStop();
|
||||
temp->SetFaction(me->GetFaction());
|
||||
@@ -1427,7 +1427,7 @@ public:
|
||||
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiEligorGUID))
|
||||
{
|
||||
temp->RemoveAllAuras();
|
||||
temp->DeleteThreatList();
|
||||
temp->GetThreatManager().ClearAllThreat();
|
||||
temp->CombatStop(true);
|
||||
temp->AttackStop();
|
||||
temp->SetFaction(me->GetFaction());
|
||||
@@ -1439,7 +1439,7 @@ public:
|
||||
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiKoltiraGUID))
|
||||
{
|
||||
temp->RemoveAllAuras();
|
||||
temp->DeleteThreatList();
|
||||
temp->GetThreatManager().ClearAllThreat();
|
||||
temp->CombatStop(true);
|
||||
temp->AttackStop();
|
||||
temp->SetFaction(me->GetFaction());
|
||||
@@ -1454,7 +1454,7 @@ public:
|
||||
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiThassarianGUID))
|
||||
{
|
||||
temp->RemoveAllAuras();
|
||||
temp->DeleteThreatList();
|
||||
temp->GetThreatManager().ClearAllThreat();
|
||||
temp->CombatStop(true);
|
||||
temp->AttackStop();
|
||||
temp->SetFaction(me->GetFaction());
|
||||
@@ -1484,15 +1484,11 @@ public:
|
||||
{
|
||||
if (Creature* temp = ObjectAccessor::GetCreature(*me, ui_GUID))
|
||||
if (temp->IsAlive())
|
||||
if (Unit* pTarger = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
if (pTarger->IsAlive())
|
||||
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
if (pTarget->IsAlive())
|
||||
{
|
||||
// temp->DeleteThreatList();
|
||||
temp->AddThreat(pTarger, 0.0f);
|
||||
temp->AI()->AttackStart(pTarger);
|
||||
temp->SetInCombatWith(pTarger);
|
||||
pTarger->SetInCombatWith(temp);
|
||||
// temp->GetMotionMaster()->MoveChase(pTarger, 20.0f);
|
||||
AddThreat(pTarget, 0.0f, temp);
|
||||
temp->AI()->AttackStart(pTarget);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1550,7 +1546,7 @@ public:
|
||||
{
|
||||
temp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000);
|
||||
temp->SetFaction(FACTION_SCARLET_CRUSADE);
|
||||
me->AddThreat(temp, 0.0f);
|
||||
AddThreat(temp, 0.0f);
|
||||
uiDefenderGUID[i] = temp->GetGUID();
|
||||
}
|
||||
}
|
||||
@@ -1561,7 +1557,7 @@ public:
|
||||
{
|
||||
temp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000);
|
||||
temp->SetFaction(FACTION_SCARLET_CRUSADE);
|
||||
me->AddThreat(temp, 0.0f);
|
||||
AddThreat(temp, 0.0f);
|
||||
uiEarthshatterGUID[i] = temp->GetGUID();
|
||||
}
|
||||
}
|
||||
@@ -1570,7 +1566,7 @@ public:
|
||||
{
|
||||
temp = me->SummonCreature(NPC_KORFAX_CHAMPION_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000);
|
||||
temp->SetFaction(FACTION_SCARLET_CRUSADE);
|
||||
me->AddThreat(temp, 0.0f);
|
||||
AddThreat(temp, 0.0f);
|
||||
uiKorfaxGUID = temp->GetGUID();
|
||||
}
|
||||
temp = ObjectAccessor::GetCreature(*me, uiMaxwellGUID);
|
||||
@@ -1578,7 +1574,7 @@ public:
|
||||
{
|
||||
temp = me->SummonCreature(NPC_LORD_MAXWELL_TYROSUS, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000);
|
||||
temp->SetFaction(FACTION_SCARLET_CRUSADE);
|
||||
me->AddThreat(temp, 0.0f);
|
||||
AddThreat(temp, 0.0f);
|
||||
uiMaxwellGUID = temp->GetGUID();
|
||||
}
|
||||
temp = ObjectAccessor::GetCreature(*me, uiEligorGUID);
|
||||
@@ -1586,7 +1582,7 @@ public:
|
||||
{
|
||||
temp = me->SummonCreature(NPC_COMMANDER_ELIGOR_DAWNBRINGER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000);
|
||||
temp->SetFaction(FACTION_SCARLET_CRUSADE);
|
||||
me->AddThreat(temp, 0.0f);
|
||||
AddThreat(temp, 0.0f);
|
||||
uiEligorGUID = temp->GetGUID();
|
||||
}
|
||||
temp = ObjectAccessor::GetCreature(*me, uiRayneGUID);
|
||||
@@ -1594,7 +1590,7 @@ public:
|
||||
{
|
||||
temp = me->SummonCreature(NPC_RAYNE, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000);
|
||||
temp->SetFaction(FACTION_SCARLET_CRUSADE);
|
||||
me->AddThreat(temp, 0.0f);
|
||||
AddThreat(temp, 0.0f);
|
||||
uiRayneGUID = temp->GetGUID();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,14 +604,6 @@ public:
|
||||
DoCast(me, SPELL_HEAD);
|
||||
caster->GetMotionMaster()->Clear(false);
|
||||
caster->GetMotionMaster()->MoveFollow(me, 6, float(urand(0, 5)));
|
||||
//DoResetThreat();//not sure if need
|
||||
ThreatContainer::StorageType threatlist = caster->getThreatManager().getThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
|
||||
{
|
||||
Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
|
||||
if (unit && unit->IsAlive() && unit != caster)
|
||||
me->AddThreat(unit, caster->getThreatManager().getThreat(unit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -861,7 +853,7 @@ public:
|
||||
if (!who || !me->IsValidAttackTarget(who) || me->GetVictim())
|
||||
return;
|
||||
|
||||
me->AddThreat(who, 0.0f);
|
||||
AddThreat(who, 0.0f);
|
||||
if (sprouted)
|
||||
DoStartMovement(who);
|
||||
}
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ public:
|
||||
//Sleep_Timer
|
||||
if (Sleep_Timer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0))
|
||||
DoCast(target, SPELL_SLEEP);
|
||||
|
||||
Sleep_Timer = 30000;
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
DoCast(SPELL_ILLUSION);
|
||||
me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetDisplayId(11686); // Invisible Model
|
||||
DoModifyThreatPercent(me->GetVictim(), -99);
|
||||
ModifyThreatByPercent(me->GetVictim(), -99);
|
||||
events.ScheduleEvent(EVENT_SET_VISIBILITY, 3000);
|
||||
events.ScheduleEvent(EVENT_ILLUSION, 25000);
|
||||
break;
|
||||
|
||||
@@ -321,14 +321,8 @@ public:
|
||||
|
||||
if (BurnTimer <= diff)
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, 10, SELECT_TARGET_RANDOM, 100, true);
|
||||
for (std::list<Unit*>::const_iterator i = targets.begin(); i != targets.end(); ++i)
|
||||
if (!(*i)->HasAura(SPELL_BURN))
|
||||
{
|
||||
(*i)->CastSpell((*i), SPELL_BURN, true);
|
||||
break;
|
||||
}
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_BURN))
|
||||
target->CastSpell(target, SPELL_BURN, true);
|
||||
BurnTimer = urand(60000, 180000);
|
||||
} else BurnTimer -= diff;
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
if (temp->isDead())
|
||||
temp->Respawn();
|
||||
else if (temp->GetVictim())
|
||||
me->getThreatManager().addThreat(temp->GetVictim(), 0.0f);
|
||||
AddThreat(temp->GetVictim(), 0.0f);
|
||||
}
|
||||
|
||||
if (!me->IsInCombat())
|
||||
@@ -276,7 +276,7 @@ public:
|
||||
temp = DoSpawnCreature(NPC_SHADOW_IMAGE, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 10000);
|
||||
if (temp && target)
|
||||
{
|
||||
temp->AddThreat(target, 1000000); //don't change target(healers)
|
||||
AddThreat(target, 1000000.0f, temp); //don't change target(healers)
|
||||
temp->AI()->AttackStart(target);
|
||||
}
|
||||
}
|
||||
@@ -373,7 +373,7 @@ public:
|
||||
if (temp->isDead())
|
||||
temp->Respawn();
|
||||
else if (temp->GetVictim())
|
||||
me->getThreatManager().addThreat(temp->GetVictim(), 0.0f);
|
||||
AddThreat(temp->GetVictim(), 0.0f);
|
||||
}
|
||||
|
||||
if (!me->IsInCombat())
|
||||
@@ -551,7 +551,7 @@ public:
|
||||
Creature* sisiter = instance->GetCreature(DATA_SACROLASH);
|
||||
if (sisiter && !sisiter->isDead() && sisiter->GetVictim())
|
||||
{
|
||||
me->AddThreat(sisiter->GetVictim(), 0.0f);
|
||||
AddThreat(sisiter->GetVictim(), 0.0f);
|
||||
DoStartNoMovement(sisiter->GetVictim());
|
||||
me->Attack(sisiter->GetVictim(), false);
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ public:
|
||||
uiFlightCount = 4;
|
||||
break;
|
||||
case 9:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT))
|
||||
DoStartMovement(target);
|
||||
else
|
||||
{
|
||||
@@ -397,7 +397,7 @@ public:
|
||||
me->SetDisableGravity(false);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||
EnterPhase(PHASE_GROUND);
|
||||
AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO));
|
||||
AttackStart(SelectTarget(SELECT_TARGET_MAXTHREAT));
|
||||
break;
|
||||
}
|
||||
++uiFlightCount;
|
||||
|
||||
@@ -209,7 +209,7 @@ public:
|
||||
me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop();
|
||||
++TalkSequence;
|
||||
}
|
||||
@@ -302,7 +302,7 @@ public:
|
||||
|
||||
if (SpectralBlastTimer <= diff)
|
||||
{
|
||||
ThreatContainer::StorageType const& m_threatlist = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType const& m_threatlist = me->GetThreatManager().getThreatList();
|
||||
std::list<Unit*> targetList;
|
||||
for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr)
|
||||
{
|
||||
@@ -649,7 +649,7 @@ public:
|
||||
{
|
||||
KalecGUID = Kalec->GetGUID();
|
||||
me->CombatStart(Kalec);
|
||||
me->AddThreat(Kalec, 100.0f);
|
||||
AddThreat(Kalec, 100.0f);
|
||||
Kalec->setActive(true);
|
||||
}
|
||||
Talk(SAY_SATH_AGGRO);
|
||||
@@ -776,12 +776,12 @@ public:
|
||||
|
||||
if (ResetThreat <= diff)
|
||||
{
|
||||
ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
|
||||
ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
|
||||
{
|
||||
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
|
||||
if (unit->GetPositionZ() > me->GetPositionZ() + 5)
|
||||
me->getThreatManager().modifyThreatPercent(unit, -100);
|
||||
me->GetThreatManager().ModifyThreatByPercent(unit, -100);
|
||||
}
|
||||
ResetThreat = 1000;
|
||||
} else ResetThreat -= diff;
|
||||
|
||||
@@ -470,7 +470,7 @@ public:
|
||||
break;
|
||||
case NPC_KILJAEDEN:
|
||||
summoned->CastSpell(summoned, SPELL_REBIRTH, false);
|
||||
summoned->AddThreat(me->GetVictim(), 1.0f);
|
||||
AddThreat(me->GetVictim(), 1.0f, summoned);
|
||||
break;
|
||||
}
|
||||
summons.Summon(summoned);
|
||||
@@ -671,7 +671,7 @@ public:
|
||||
Talk(SAY_KJ_REFLECTION);
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true, -SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true, true, -SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT))
|
||||
{
|
||||
float x, y, z;
|
||||
target->GetPosition(x, y, z);
|
||||
@@ -956,7 +956,7 @@ public:
|
||||
{
|
||||
instance->SetBossState(DATA_KILJAEDEN, IN_PROGRESS);
|
||||
if (Creature* pControl = instance->GetCreature(DATA_KILJAEDEN_CONTROLLER))
|
||||
pControl->AddThreat(who, 1.0f);
|
||||
AddThreat(who, 1.0f, pControl);
|
||||
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
}
|
||||
@@ -992,15 +992,8 @@ public:
|
||||
if (FelfirePortalTimer <= diff)
|
||||
{
|
||||
if (Creature* pPortal = DoSpawnCreature(NPC_FELFIRE_PORTAL, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 20000))
|
||||
{
|
||||
ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
|
||||
{
|
||||
Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
|
||||
if (unit)
|
||||
pPortal->AddThreat(unit, 1.0f);
|
||||
}
|
||||
}
|
||||
for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList())
|
||||
AddThreat(ref->GetVictim(), 1.0f, pPortal);
|
||||
FelfirePortalTimer = 20000;
|
||||
} else FelfirePortalTimer -= diff;
|
||||
|
||||
@@ -1060,7 +1053,7 @@ public:
|
||||
if (uiSpawnFiendTimer <= diff)
|
||||
{
|
||||
if (Creature* pFiend = DoSpawnCreature(NPC_VOLATILE_FELFIRE_FIEND, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000))
|
||||
pFiend->AddThreat(SelectTarget(SELECT_TARGET_RANDOM, 0), 100000.0f);
|
||||
AddThreat(SelectTarget(SELECT_TARGET_RANDOM, 0), 100000.0f, pFiend);
|
||||
uiSpawnFiendTimer = urand(4000, 8000);
|
||||
} else uiSpawnFiendTimer -= diff;
|
||||
}
|
||||
@@ -1113,7 +1106,7 @@ public:
|
||||
|
||||
if (!bLockedTarget)
|
||||
{
|
||||
me->AddThreat(me->GetVictim(), 10000000.0f);
|
||||
AddThreat(me->GetVictim(), 10000000.0f);
|
||||
bLockedTarget = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,18 +74,10 @@ class boss_ironaya : public CreatureScript
|
||||
return;
|
||||
|
||||
//If we are <50% hp do knockaway ONCE
|
||||
if (!bHasCastKnockaway && HealthBelowPct(50))
|
||||
if (!bHasCastKnockaway && HealthBelowPct(50) && me->GetVictim())
|
||||
{
|
||||
DoCastVictim(SPELL_KNOCKAWAY, true);
|
||||
|
||||
// current aggro target is knocked away pick new target
|
||||
Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0);
|
||||
|
||||
if (!target || target == me->GetVictim())
|
||||
target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1);
|
||||
|
||||
if (target)
|
||||
me->TauntApply(target);
|
||||
me->GetThreatManager().ResetThreat(me->EnsureVictim());
|
||||
|
||||
//Shouldn't cast this agian
|
||||
bHasCastKnockaway = true;
|
||||
|
||||
@@ -92,13 +92,7 @@ class npc_jadespine_basilisk : public CreatureScript
|
||||
//Stop attacking target thast asleep and pick new target
|
||||
uiCslumberTimer = 28000;
|
||||
|
||||
Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0);
|
||||
|
||||
if (!target || target == me->GetVictim())
|
||||
target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
|
||||
if (target)
|
||||
me->TauntApply(target);
|
||||
me->GetThreatManager().ResetThreat(me->GetVictim());
|
||||
|
||||
} else uiCslumberTimer -= uiDiff;
|
||||
|
||||
|
||||
@@ -553,7 +553,7 @@ class DevastatingSlamTargetSelector : public std::unary_function<Unit *, bool>
|
||||
|
||||
bool operator() (WorldObject* target)
|
||||
{
|
||||
if (target == _victim && _me->getThreatManager().getThreatList().size() > 1)
|
||||
if (target == _victim && _me->GetThreatManager().getThreatList().size() > 1)
|
||||
return true;
|
||||
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
@@ -680,8 +680,8 @@ class spell_mandokir_ohgan_orders_trigger : public SpellScriptLoader
|
||||
// HACK: research better way
|
||||
caster->ClearUnitState(UNIT_STATE_CASTING);
|
||||
caster->GetMotionMaster()->Clear();
|
||||
caster->DeleteThreatList();
|
||||
caster->AddThreat(target, 50000000.0f);
|
||||
caster->GetThreatManager().ClearAllThreat();
|
||||
caster->GetThreatManager().AddThreat(target, 50000000.0f);
|
||||
caster->TauntApply(target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
|
||||
if (Creature* Myrmidon = me->FindNearestCreature(NPC_DARKSPINE_MYRIDON, 70))
|
||||
{
|
||||
me->AddThreat(Myrmidon, 100000.0f);
|
||||
AddThreat(Myrmidon, 100000.0f);
|
||||
AttackStart(Myrmidon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ public:
|
||||
if (player->GetQuestStatus(QUEST_SAVING_YENNIKU) == QUEST_STATUS_INCOMPLETE) // Yenniku's Release
|
||||
{
|
||||
me->SetEmoteState(EMOTE_STATE_STUN);
|
||||
me->CombatStop(); // stop combat
|
||||
me->DeleteThreatList(); // unsure of this
|
||||
me->SetFaction(FACTION_HORDE_GENERIC); // horde generic
|
||||
me->CombatStop(); //stop combat
|
||||
me->GetThreatManager().ClearAllThreat(); //unsure of this
|
||||
me->SetFaction(FACTION_HORDE_GENERIC);
|
||||
|
||||
bReset = true;
|
||||
Reset_Timer = 60000;
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
if (player->GetTeam() == HORDE)
|
||||
{
|
||||
me->CombatStop();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
|
||||
me->RestoreFaction();
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
|
||||
SetRun(false);
|
||||
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -421,7 +421,7 @@ void hyjalAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
{
|
||||
if (me->GetEntry() != JAINA)
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
me->LoadCreaturesAddon();
|
||||
|
||||
|
||||
@@ -451,7 +451,7 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -487,7 +487,7 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
} else if (instance->GetData(DATA_ALLIANCE_RETREAT) && instance->GetData(DATA_HORDE_RETREAT)){
|
||||
//do overrun
|
||||
}
|
||||
@@ -564,13 +564,13 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
if (waypointId == LastOverronPos && IsOverrun)
|
||||
@@ -662,13 +662,13 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
if (waypointId == LastOverronPos && IsOverrun)
|
||||
@@ -772,13 +772,13 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -885,13 +885,13 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -981,13 +981,13 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1067,13 +1067,13 @@ public:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE));
|
||||
if (target && target->IsAlive())
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1160,7 +1160,7 @@ public:
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
{
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
DoCast(target, SPELL_FROST_BREATH, true);
|
||||
}
|
||||
}
|
||||
@@ -1281,7 +1281,7 @@ public:
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THRALL));
|
||||
if (target && target->IsAlive())
|
||||
{
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
DoCast(target, SPELL_GARGOYLE_STRIKE, true);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -304,10 +304,10 @@ public:
|
||||
if (Creature* boss = SummonedPortalBoss(temp))
|
||||
{
|
||||
if (boss->GetEntry() == NPC_AEONUS)
|
||||
boss->AddThreat(medivh, 0.0f);
|
||||
boss->GetThreatManager().AddThreat(medivh, 0.0f);
|
||||
else
|
||||
{
|
||||
boss->AddThreat(temp, 0.0f);
|
||||
boss->GetThreatManager().AddThreat(temp, 0.0f);
|
||||
temp->CastSpell(boss, SPELL_RIFT_CHANNEL, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ public:
|
||||
|
||||
if (Unit* Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT))
|
||||
if (Unit* temp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MEDIVH)))
|
||||
Summon->AddThreat(temp, 0.0f);
|
||||
AddThreat(temp, 0.0f, Summon);
|
||||
}
|
||||
|
||||
void DoSelectSummon()
|
||||
|
||||
@@ -227,7 +227,7 @@ class npc_harbinger_of_flame : public CreatureScript
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FIEROBLAST:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, -SPELL_RIDE_MONSTROSITY))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, true, -SPELL_RIDE_MONSTROSITY))
|
||||
DoCast(target, SPELL_FIEROBLAST_TRASH);
|
||||
_events.RescheduleEvent(EVENT_FIEROBLAST, 500); // cast time is longer, but thanks to UNIT_STATE_CASTING check it won't trigger more often (need this because this creature gets a stacking haste aura)
|
||||
break;
|
||||
@@ -330,7 +330,7 @@ class npc_blazing_monstrosity : public CreatureScript
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_START_SPITTING:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, -SPELL_RIDE_MONSTROSITY))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, true, -SPELL_RIDE_MONSTROSITY))
|
||||
DoCast(target, SPELL_MOLTEN_BARRAGE);
|
||||
break;
|
||||
case EVENT_CONTINUE_SPITTING:
|
||||
@@ -635,8 +635,8 @@ class spell_alysrazor_aggro_closest : public SpellScriptLoader
|
||||
void HandleEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
float curThreat = GetCaster()->getThreatManager().getThreat(GetHitUnit(), true);
|
||||
GetCaster()->getThreatManager().addThreat(GetHitUnit(), -curThreat + 50000.0f / std::min(1.0f, GetCaster()->GetDistance(GetHitUnit())));
|
||||
float curThreat = GetCaster()->GetThreatManager().getThreat(GetHitUnit(), true);
|
||||
GetCaster()->GetThreatManager().AddThreat(GetHitUnit(), -curThreat + 50000.0f / std::min(1.0f, GetCaster()->GetDistance(GetHitUnit())));
|
||||
}
|
||||
|
||||
void UpdateThreat()
|
||||
|
||||
@@ -464,11 +464,7 @@ class spell_baleroc_countdown_aoe_dummy : public SpellScript
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
Creature* caster = GetCaster()->ToCreature();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
if (WorldObject* tank = caster->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO))
|
||||
if (WorldObject* tank = GetCaster()->GetVictim())
|
||||
targets.remove(tank);
|
||||
|
||||
if (targets.size() < 2)
|
||||
@@ -583,11 +579,8 @@ class spell_baleroc_shards_of_torment_target_search : public SpellScript
|
||||
return;
|
||||
}
|
||||
|
||||
Creature* caster = GetCaster()->ToCreature();
|
||||
if (!caster || !caster->IsAIEnabled)
|
||||
return;
|
||||
|
||||
if (WorldObject* tank = caster->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO))
|
||||
Unit* caster = GetCaster();
|
||||
if (WorldObject* tank = caster->GetVictim())
|
||||
targets.remove(tank);
|
||||
|
||||
std::list<WorldObject*> melee, ranged;
|
||||
|
||||
@@ -232,7 +232,7 @@ struct npc_firelands_magmakin : public ScriptedAI
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
me->AddThreat(target, 50000000.0f);
|
||||
AddThreat(target, 50000000.0f);
|
||||
me->TauntApply(target);
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ public:
|
||||
// tank selection based on phase one. If tank is not there i take nearest one
|
||||
if (Unit* tank = ObjectAccessor::GetUnit(*me, tankGUID))
|
||||
me->GetMotionMaster()->MoveChase(tank);
|
||||
else if (Unit* newtarget = SelectTarget(SELECT_TARGET_NEAREST, 0))
|
||||
else if (Unit* newtarget = SelectTarget(SELECT_TARGET_MINDISTANCE, 0))
|
||||
me->GetMotionMaster()->MoveChase(newtarget);
|
||||
events.ScheduleEvent(EVENT_BELLOWING_ROAR, 5000);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, urand(10000, 20000));
|
||||
|
||||
@@ -169,7 +169,7 @@ class boss_ayamiss : public CreatureScript
|
||||
Position VictimPos = me->EnsureVictim()->GetPosition();
|
||||
me->GetMotionMaster()->MovePoint(POINT_GROUND, VictimPos);
|
||||
}
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
events.ScheduleEvent(EVENT_LASH, urand(5000, 8000));
|
||||
events.ScheduleEvent(EVENT_TRASH, urand(3000, 6000));
|
||||
events.CancelEvent(EVENT_POISON_STINGER);
|
||||
|
||||
@@ -122,7 +122,7 @@ class boss_buru : public CreatureScript
|
||||
|
||||
if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
AttackStart(victim);
|
||||
Talk(EMOTE_TARGET, victim);
|
||||
}
|
||||
|
||||
@@ -148,10 +148,9 @@ class boss_moam : public CreatureScript
|
||||
{
|
||||
std::list<Unit*> targetList;
|
||||
{
|
||||
const std::list<HostileReference*>& threatlist = me->getThreatManager().getThreatList();
|
||||
for (std::list<HostileReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
|
||||
if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->GetPowerType() == POWER_MANA)
|
||||
targetList.push_back((*itr)->getTarget());
|
||||
for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList())
|
||||
if (ref->GetVictim()->GetTypeId() == TYPEID_PLAYER && ref->GetVictim()->GetPowerType() == POWER_MANA)
|
||||
targetList.push_back(ref->GetVictim());
|
||||
}
|
||||
|
||||
Trinity::Containers::RandomResize(targetList, 5);
|
||||
|
||||
@@ -219,8 +219,8 @@ public:
|
||||
if (KnockBack_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_KNOCKBACK);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatPercent(me->GetVictim(), -80);
|
||||
if (GetThreat(me->GetVictim()))
|
||||
ModifyThreatByPercent(me->GetVictim(), -80);
|
||||
KnockBack_Timer = urand(15000, 25000);
|
||||
} else KnockBack_Timer -= diff;
|
||||
|
||||
@@ -307,7 +307,7 @@ public:
|
||||
if (Fear_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_FEAR);
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
Fear_Timer = 20000;
|
||||
} else Fear_Timer -= diff;
|
||||
|
||||
|
||||
@@ -649,8 +649,8 @@ public:
|
||||
//Place all units in threat list on outside of stomach
|
||||
Stomach_Map.clear();
|
||||
|
||||
for (std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i)
|
||||
Stomach_Map[(*i)->getUnitGuid()] = false; //Outside stomach
|
||||
for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList())
|
||||
Stomach_Map[ref->GetVictim()->GetGUID()] = false; //Outside stomach
|
||||
|
||||
//Spawn 2 flesh tentacles
|
||||
FleshTentaclesKilled = 0;
|
||||
|
||||
@@ -150,8 +150,8 @@ public:
|
||||
{
|
||||
DoCast(target, SPELL_ROOT);
|
||||
|
||||
if (DoGetThreat(target))
|
||||
DoModifyThreatPercent(target, -100);
|
||||
if (GetThreat(target))
|
||||
ModifyThreatByPercent(target, -100);
|
||||
|
||||
Creature* Hatchling = nullptr;
|
||||
switch (urand(0, 2))
|
||||
|
||||
@@ -118,8 +118,7 @@ public:
|
||||
//Attack random Gamers
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AddThreat(target, 1.0f);
|
||||
AttackStart(target);
|
||||
}
|
||||
WhirlWindRandom_Timer = urand(3000, 7000);
|
||||
@@ -146,8 +145,7 @@ public:
|
||||
//Attack random Gamers
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AddThreat(target, 1.0f);
|
||||
AttackStart(target);
|
||||
}
|
||||
AggroReset = true;
|
||||
@@ -261,8 +259,7 @@ public:
|
||||
//Attack random Gamers
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AddThreat(target, 1.0f);
|
||||
AttackStart(target);
|
||||
}
|
||||
|
||||
@@ -282,8 +279,7 @@ public:
|
||||
//Attack random Gamers
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AddThreat(target, 1.0f);
|
||||
AttackStart(target);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ class boss_skeram : public CreatureScript
|
||||
break;
|
||||
case EVENT_BLINK:
|
||||
DoCast(me, BlinkSpells[urand(0, 2)]);
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
me->SetVisible(true);
|
||||
events.ScheduleEvent(EVENT_BLINK, urand(10000, 30000));
|
||||
break;
|
||||
|
||||
@@ -239,7 +239,7 @@ struct boss_twinemperorsAI : public ScriptedAI
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoStopAttack();
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
DoCast(me, SPELL_TWIN_TELEPORT_VISUAL);
|
||||
me->AddUnitState(UNIT_STATE_STUNNED);
|
||||
AfterTeleport = true;
|
||||
@@ -268,7 +268,7 @@ struct boss_twinemperorsAI : public ScriptedAI
|
||||
{
|
||||
//DoYell(nearu->GetName(), LANG_UNIVERSAL, 0);
|
||||
AttackStart(nearu);
|
||||
me->AddThreat(nearu, 10000);
|
||||
AddThreat(nearu, 10000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -428,7 +428,7 @@ public:
|
||||
void CastSpellOnBug(Creature* target) override
|
||||
{
|
||||
target->SetFaction(FACTION_MONSTER);
|
||||
target->AI()->AttackStart(me->getThreatManager().getHostilTarget());
|
||||
target->AI()->AttackStart(me->GetThreatManager().GetCurrentVictim());
|
||||
target->AddAura(SPELL_MUTATE_BUG, target);
|
||||
target->SetFullHealth();
|
||||
}
|
||||
@@ -559,7 +559,7 @@ public:
|
||||
|
||||
if (ArcaneBurst_Timer <= diff)
|
||||
{
|
||||
if (Unit* mvic = SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true))
|
||||
if (Unit* mvic = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, NOMINAL_MELEE_RANGE, true))
|
||||
{
|
||||
DoCast(mvic, SPELL_ARCANEBURST);
|
||||
ArcaneBurst_Timer = 5000;
|
||||
@@ -594,7 +594,7 @@ public:
|
||||
if (me->Attack(who, false))
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0);
|
||||
me->AddThreat(who, 0.0f);
|
||||
AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ class boss_viscidus : public CreatureScript
|
||||
|
||||
if (_phase == PHASE_GLOB && summons.empty())
|
||||
{
|
||||
DoResetThreat();
|
||||
ResetThreatList();
|
||||
me->NearTeleportTo(ViscidusCoord.GetPositionX(),
|
||||
ViscidusCoord.GetPositionY(),
|
||||
ViscidusCoord.GetPositionZ(),
|
||||
|
||||
@@ -662,7 +662,7 @@ public:
|
||||
if (!target)
|
||||
target = me;
|
||||
|
||||
target->AddThreat(sironas, 0.001f);
|
||||
AddThreat(sironas, 0.001f, target);
|
||||
sironas->Attack(target, true);
|
||||
sironas->GetMotionMaster()->MoveChase(target);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
|
||||
me->UpdateEntry(NPC_TAMED_KODO);
|
||||
me->CombatStop();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->SetSpeedRate(MOVE_RUN, 0.6f);
|
||||
me->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, me->GetFollowAngle());
|
||||
me->setActive(true);
|
||||
|
||||
@@ -1234,8 +1234,7 @@ class go_wind_stone : public GameObjectScript
|
||||
break;
|
||||
}
|
||||
summons->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
summons->SendMeleeAttackStart(player);
|
||||
summons->CombatStart(player);
|
||||
summons->EngageWithTarget(player);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
void DoFriend()
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
|
||||
me->StopMoving();
|
||||
|
||||
@@ -323,7 +323,7 @@ public:
|
||||
|
||||
if (Unit* target = me->SelectNearestPlayer(200.0f))
|
||||
{
|
||||
me->AddThreat(target, 0.0f);
|
||||
AddThreat(target, 0.0f);
|
||||
me->SetInCombatWith(target);
|
||||
target->SetInCombatWith(me);
|
||||
DoStartMovement(target);
|
||||
|
||||
@@ -173,7 +173,7 @@ class npc_sc_millhouse_manastorm : public CreatureScript
|
||||
|
||||
me->RemoveAllAuras();
|
||||
me->CombatStop(true);
|
||||
me->DeleteThreatList();
|
||||
me->GetThreatManager().ClearAllThreat();
|
||||
|
||||
switch (pointId)
|
||||
{
|
||||
|
||||
@@ -192,7 +192,7 @@ public:
|
||||
else
|
||||
{
|
||||
who->SetInCombatWith(me);
|
||||
me->AddThreat(who, 0.0f);
|
||||
AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user