Core/Threat: Fix taunt behavior in some edge cases

This commit is contained in:
Treeston
2018-05-04 10:36:56 +02:00
parent 081eab3cf5
commit 1b7ec4bc84
2 changed files with 34 additions and 32 deletions

View File

@@ -108,26 +108,28 @@ ThreatReference::OnlineState ThreatReference::SelectOnlineState()
return ONLINE_STATE_ONLINE; return ONLINE_STATE_ONLINE;
} }
void ThreatReference::UpdateTauntState(bool victimIsTaunting) void ThreatReference::UpdateTauntState(TauntState state)
{ {
if (victimIsTaunting) if (state < TAUNT_STATE_TAUNT) // not taunting
{ {
_taunted = TAUNT_STATE_TAUNT; // Check for SPELL_AURA_MOD_DETAUNT (applied from owner to victim)
HeapNotifyIncreased(); for (AuraEffect const* eff : _victim->GetAuraEffectsByType(SPELL_AURA_MOD_DETAUNT))
return; if (eff->GetCasterGUID() == _owner->GetGUID())
{
state = TAUNT_STATE_DETAUNT;
break;
}
} }
// Check for SPELL_AURA_MOD_DETAUNT (applied from owner to victim) if (state == _taunted)
for (AuraEffect const* eff : _victim->GetAuraEffectsByType(SPELL_AURA_MOD_DETAUNT)) return;
if (eff->GetCasterGUID() == _owner->GetGUID())
{
_taunted = TAUNT_STATE_DETAUNT;
HeapNotifyDecreased();
return;
}
_taunted = TAUNT_STATE_NONE; std::swap(state, _taunted);
HeapNotifyChanged();
if (_taunted < state)
HeapNotifyDecreased();
else
HeapNotifyIncreased();
} }
void ThreatReference::ClearThreat(bool sendRemove) void ThreatReference::ClearThreat(bool sendRemove)
@@ -414,21 +416,21 @@ void ThreatManager::MatchUnitThreatToHighestThreat(Unit* target)
void ThreatManager::TauntUpdate() void ThreatManager::TauntUpdate()
{ {
std::list<AuraEffect*> const& tauntEffects = _owner->GetAuraEffectsByType(SPELL_AURA_MOD_TAUNT); std::list<AuraEffect*> const& tauntEffects = _owner->GetAuraEffectsByType(SPELL_AURA_MOD_TAUNT);
auto threatEnd = _myThreatListEntries.end();
ThreatReference* tauntRef = nullptr; uint32 state = ThreatReference::TAUNT_STATE_TAUNT;
std::unordered_map<ObjectGuid, ThreatReference::TauntState> tauntStates;
// Only the last taunt effect applied by something still on our threat list is considered // Only the last taunt effect applied by something still on our threat list is considered
for (auto it = tauntEffects.rbegin(), end = tauntEffects.rend(); it != end; ++it) for (auto it = tauntEffects.begin(), end = tauntEffects.end(); it != end; ++it)
{ tauntStates[(*it)->GetCasterGUID()] = ThreatReference::TauntState(state++);
auto threatIt = _myThreatListEntries.find((*it)->GetCasterGUID());
if (threatIt == threatEnd)
continue;
if (!threatIt->second->IsAvailable())
continue;
tauntRef = threatIt->second;
break;
}
for (auto const& pair : _myThreatListEntries) for (auto const& pair : _myThreatListEntries)
pair.second->UpdateTauntState(pair.second == tauntRef); {
auto it = tauntStates.find(pair.first);
if (it != tauntStates.end())
pair.second->UpdateTauntState(it->second);
else
pair.second->UpdateTauntState();
}
} }
void ThreatManager::ResetAllThreat() void ThreatManager::ResetAllThreat()

View File

@@ -244,7 +244,7 @@ class TC_GAME_API ThreatManager
class TC_GAME_API ThreatReference class TC_GAME_API ThreatReference
{ {
public: public:
enum TauntState { TAUNT_STATE_DETAUNT = -1, TAUNT_STATE_NONE = 0, TAUNT_STATE_TAUNT = 1 }; enum TauntState : uint32 { TAUNT_STATE_DETAUNT = 0, TAUNT_STATE_NONE = 1, TAUNT_STATE_TAUNT = 2 };
enum OnlineState { ONLINE_STATE_ONLINE = 2, ONLINE_STATE_SUPPRESSED = 1, ONLINE_STATE_OFFLINE = 0 }; enum OnlineState { ONLINE_STATE_ONLINE = 2, ONLINE_STATE_SUPPRESSED = 1, ONLINE_STATE_OFFLINE = 0 };
Unit* GetOwner() const { return _owner; } Unit* GetOwner() const { return _owner; }
@@ -254,8 +254,8 @@ class TC_GAME_API ThreatReference
bool IsOnline() const { return (_online >= ONLINE_STATE_ONLINE); } bool IsOnline() const { return (_online >= ONLINE_STATE_ONLINE); }
bool IsAvailable() const { return (_online > ONLINE_STATE_OFFLINE); } bool IsAvailable() const { return (_online > ONLINE_STATE_OFFLINE); }
bool IsOffline() const { return (_online <= ONLINE_STATE_OFFLINE); } bool IsOffline() const { return (_online <= ONLINE_STATE_OFFLINE); }
TauntState GetTauntState() const { return _taunted; } TauntState GetTauntState() const { return IsTaunting() ? TAUNT_STATE_TAUNT : _taunted; }
bool IsTaunting() const { return _taunted == TAUNT_STATE_TAUNT; } bool IsTaunting() const { return _taunted >= TAUNT_STATE_TAUNT; }
bool IsDetaunted() const { return _taunted == TAUNT_STATE_DETAUNT; } bool IsDetaunted() const { return _taunted == TAUNT_STATE_DETAUNT; }
void SetThreat(float amount) { _baseAmount = amount; HeapNotifyChanged(); } void SetThreat(float amount) { _baseAmount = amount; HeapNotifyChanged(); }
@@ -270,7 +270,7 @@ class TC_GAME_API ThreatReference
ThreatReference(ThreatManager* mgr, Unit* victim, float amount) : _owner(mgr->_owner), _mgr(mgr), _victim(victim), _baseAmount(amount), _tempModifier(0), _online(SelectOnlineState()), _taunted(TAUNT_STATE_NONE) { } ThreatReference(ThreatManager* mgr, Unit* victim, float amount) : _owner(mgr->_owner), _mgr(mgr), _victim(victim), _baseAmount(amount), _tempModifier(0), _online(SelectOnlineState()), _taunted(TAUNT_STATE_NONE) { }
static bool FlagsAllowFighting(Unit const* a, Unit const* b); static bool FlagsAllowFighting(Unit const* a, Unit const* b);
OnlineState SelectOnlineState(); OnlineState SelectOnlineState();
void UpdateTauntState(bool victimIsTaunting); void UpdateTauntState(TauntState state = TAUNT_STATE_NONE);
Unit* const _owner; Unit* const _owner;
ThreatManager* const _mgr; ThreatManager* const _mgr;
void HeapNotifyIncreased() { _mgr->_sortedThreatList.increase(_handle); } void HeapNotifyIncreased() { _mgr->_sortedThreatList.increase(_handle); }