diff --git a/src/common/Containers/ListUtils.h b/src/common/Containers/ListUtils.h
new file mode 100644
index 0000000000..f5de0d42ec
--- /dev/null
+++ b/src/common/Containers/ListUtils.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#ifndef TRINITYCORE_LIST_UTILS_H
+#define TRINITYCORE_LIST_UTILS_H
+
+#include
+#include
+
+namespace Trinity::Containers::Lists
+{
+template>
+inline typename std::list::iterator RemoveUnique(std::list& list, T const& value)
+{
+ auto itr = std::find(list.begin(), list.end(), value);
+ if (itr != list.end())
+ return list.erase(itr);
+
+ return list.end();
+}
+
+template>
+inline typename std::forward_list::iterator RemoveUnique(std::forward_list& list, T const& value)
+{
+ auto itr = list.before_begin();
+ auto toErase = std::next(itr);
+ while (toErase != list.end())
+ {
+ if (*toErase == value)
+ return list.erase_after(itr);
+
+ itr = toErase++;
+ }
+
+ return list.end();
+}
+}
+
+#endif // TRINITYCORE_LIST_UTILS_H
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp
index 454537e7b5..54453b495c 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.cpp
+++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp
@@ -687,7 +687,7 @@ void PlayerAI::DoAutoAttackIfReady()
void PlayerAI::CancelAllShapeshifts()
{
- std::list const& shapeshiftAuras = me->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
+ Unit::AuraEffectList const& shapeshiftAuras = me->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
std::set removableShapeshifts;
for (AuraEffect* auraEff : shapeshiftAuras)
{
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index 5f83c58f8e..265dc8cd41 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -503,19 +503,19 @@ void ThreatManager::MatchUnitThreatToHighestThreat(Unit* target)
void ThreatManager::TauntUpdate()
{
- std::list const& tauntEffects = _owner->GetAuraEffectsByType(SPELL_AURA_MOD_TAUNT);
+ Unit::AuraEffectList const& tauntEffects = _owner->GetAuraEffectsByType(SPELL_AURA_MOD_TAUNT);
- uint32 state = ThreatReference::TAUNT_STATE_TAUNT;
- std::unordered_map tauntStates;
+ uint32 tauntPriority = 0; // lowest is highest
+ std::unordered_map tauntStates;
// Only the last taunt effect applied by something still on our threat list is considered
- for (auto it = tauntEffects.begin(), end = tauntEffects.end(); it != end; ++it)
- tauntStates[(*it)->GetCasterGUID()] = ThreatReference::TauntState(state++);
+ for (AuraEffect const* tauntEffect : tauntEffects)
+ tauntStates[tauntEffect->GetCasterGUID()] = ++tauntPriority;
for (auto const& pair : _myThreatListEntries)
{
auto it = tauntStates.find(pair.first);
if (it != tauntStates.end())
- pair.second->UpdateTauntState(it->second);
+ pair.second->UpdateTauntState(ThreatReference::TauntState(ThreatReference::TAUNT_STATE_TAUNT + tauntStates.size() - it->second));
else
pair.second->UpdateTauntState();
}
@@ -523,7 +523,6 @@ void ThreatManager::TauntUpdate()
// taunt aura update also re-evaluates all suppressed states (retail behavior)
EvaluateSuppressed(true);
}
-
void ThreatManager::ResetAllThreat()
{
for (auto const& pair : _myThreatListEntries)
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 5bf1feb93d..a11ba0931f 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -43,6 +43,7 @@
#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
#include "Item.h"
+#include "ListUtils.h"
#include "Log.h"
#include "LootMgr.h"
#include "LootPackets.h"
@@ -3098,20 +3099,20 @@ void Unit::_AddAura(UnitAura* aura, Unit* caster)
* but may be created as a result of aura links.
*/
- // register single target aura
- caster->GetSingleCastAuras().push_back(aura);
-
- std::queue aurasSharingLimit;
+ std::vector aurasSharingLimit;
// remove other single target auras
for (Aura* scAura : caster->GetSingleCastAuras())
- if (scAura != aura && scAura->IsSingleTargetWith(aura))
- aurasSharingLimit.push(scAura);
+ if (scAura->IsSingleTargetWith(aura))
+ aurasSharingLimit.push_back(scAura);
+
+ // register single target aura
+ caster->GetSingleCastAuras().push_front(aura);
uint32 maxOtherAuras = aura->GetSpellInfo()->MaxAffectedTargets - 1;
while (aurasSharingLimit.size() > maxOtherAuras)
{
- aurasSharingLimit.front()->Remove();
- aurasSharingLimit.pop();
+ aurasSharingLimit.back()->Remove();
+ aurasSharingLimit.pop_back();
}
}
}
@@ -3149,7 +3150,7 @@ AuraApplication* Unit::_CreateAuraApplication(Aura* aura, uint8 effMask)
if (aurSpellInfo->HasAnyAuraInterruptFlag())
{
- m_interruptableAuras.push_back(aurApp);
+ m_interruptableAuras.push_front(aurApp);
AddInterruptMask(aurSpellInfo->AuraInterruptFlags, aurSpellInfo->AuraInterruptFlags2);
}
@@ -3243,7 +3244,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveFlags removeM
if (aura->GetSpellInfo()->HasAnyAuraInterruptFlag())
{
- m_interruptableAuras.remove(aurApp);
+ Trinity::Containers::Lists::RemoveUnique(m_interruptableAuras, aurApp);
UpdateInterruptMask();
}
@@ -3349,7 +3350,7 @@ void Unit::_RegisterAuraEffect(AuraEffect* aurEff, bool apply)
{
if (apply)
{
- m_modAuras[aurEff->GetAuraType()].push_back(aurEff);
+ m_modAuras[aurEff->GetAuraType()].push_front(aurEff);
if (Player* player = ToPlayer())
{
player->StartAchievementCriteria(AchievementCriteriaStartEvent::GainAuraEffect, aurEff->GetAuraType());
@@ -3357,7 +3358,7 @@ void Unit::_RegisterAuraEffect(AuraEffect* aurEff, bool apply)
}
}
else
- m_modAuras[aurEff->GetAuraType()].remove(aurEff);
+ Trinity::Containers::Lists::RemoveUnique(m_modAuras[aurEff->GetAuraType()], aurEff);
}
// All aura base removes should go through this function!
@@ -3371,7 +3372,7 @@ void Unit::RemoveOwnedAura(AuraMap::iterator& i, AuraRemoveFlags removeMode)
++m_auraUpdateIterator;
m_ownedAuras.erase(i);
- m_removedAuras.push_back(aura);
+ m_removedAuras.push_front(aura);
// Unregister single target aura
if (aura->IsSingleTarget())
@@ -3704,7 +3705,7 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, W
newAura->UnregisterSingleTarget();
// bring back single target aura status to the old aura
aura->SetIsSingleTarget(true);
- caster->GetSingleCastAuras().push_back(aura);
+ caster->GetSingleCastAuras().push_front(aura);
}
// FIXME: using aura->GetMaxDuration() maybe not blizzlike but it fixes stealing of spells like Innervate
newAura->SetLoadedState(aura->GetMaxDuration(), int32(dur), stealCharge ? stolenCharges : aura->GetCharges(), stolenCharges, recalculateMask, aura->GetCritChance(), aura->CanApplyResilience(), &damage[0]);
@@ -10207,7 +10208,7 @@ void Unit::TriggerAurasProcOnEvent(Unit* actionTarget, uint32 typeMaskActor, uin
for (auto itr = modOwner->GetAppliedAuras().begin(); itr != modOwner->GetAppliedAuras().end(); ++itr)
{
if (spell->m_appliedMods.count(itr->second->GetBase()) != 0)
- modAuras.push_back(itr->second);
+ modAuras.push_front(itr->second);
}
modOwner->GetProcAurasTriggeredOnEvent(myAurasTriggeringProc, &modAuras, myProcEventInfo);
}
@@ -10408,7 +10409,7 @@ void Unit::RestoreDisplayId()
if (!transforms.empty())
{
// iterate over already applied transform auras - from newest to oldest
- for (auto i = transforms.rbegin(); i != transforms.rend(); ++i)
+ for (auto i = transforms.begin(); i != transforms.end(); ++i)
{
if (AuraApplication const* aurApp = (*i)->GetBase()->GetApplicationOfTarget(GetGUID()))
{
@@ -11795,6 +11796,12 @@ void Unit::RemoveCharmedBy(Unit* charmer)
void Unit::RestoreFaction()
{
+ if (HasAuraType(SPELL_AURA_MOD_FACTION))
+ {
+ SetFaction(GetAuraEffectsByType(SPELL_AURA_MOD_FACTION).front()->GetMiscValue());
+ return;
+ }
+
if (GetTypeId() == TYPEID_PLAYER)
ToPlayer()->SetFactionForRace(getRace());
else
@@ -14302,10 +14309,8 @@ float Unit::GetCollisionHeight() const
SpellInfo const* Unit::GetCastSpellInfo(SpellInfo const* spellInfo, TriggerCastFlags& triggerFlag) const
{
- Unit::AuraEffectList swaps = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS);
+ Unit::AuraEffectList const& swaps = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS);
Unit::AuraEffectList const& swaps2 = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_TRIGGERED);
- if (!swaps2.empty())
- swaps.insert(swaps.end(), swaps2.begin(), swaps2.end());
for (AuraEffect const* auraEffect : swaps)
{
@@ -14321,6 +14326,20 @@ SpellInfo const* Unit::GetCastSpellInfo(SpellInfo const* spellInfo, TriggerCastF
}
}
+ for (AuraEffect const* auraEffect : swaps2)
+ {
+ if (uint32(auraEffect->GetMiscValue()) == spellInfo->Id || auraEffect->IsAffectingSpell(spellInfo))
+ {
+ if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo(auraEffect->GetAmount()))
+ {
+ if (auraEffect->GetSpellInfo()->HasAttribute(SPELL_ATTR8_IGNORE_SPELLCAST_OVERRIDE_COST))
+ triggerFlag |= TRIGGERED_IGNORE_POWER_AND_REAGENT_COST;
+
+ return newInfo;
+ }
+ }
+ }
+
return spellInfo;
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 969895a31a..68b6878468 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -27,6 +27,7 @@
#include "UnitDefines.h"
#include "Util.h"
#include
+#include
#include