Skip to content

Commit

Permalink
threat rework + power fix
Browse files Browse the repository at this point in the history
threat rework
  • Loading branch information
hatersgit authored Jan 22, 2024
2 parents 2e19639 + c21e42a commit 8324358
Show file tree
Hide file tree
Showing 186 changed files with 3,764 additions and 4,239 deletions.
4 changes: 2 additions & 2 deletions src/server/game/AI/CoreAI/GuardAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ void GuardAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->GetMotionMaster()->MoveIdle();
me->CombatStop(true);
me->GetThreatMgr().ClearAllThreat();
me->GetThreatManager().ClearAllThreat();
return;
}

LOG_DEBUG("entities.unit", "Guard entry: {} enters evade mode.", me->GetEntry());

me->RemoveAllAuras();
me->GetThreatMgr().ClearAllThreat();
me->GetThreatManager().ClearAllThreat();
me->CombatStop(true);

// Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
Expand Down
15 changes: 5 additions & 10 deletions src/server/game/AI/CoreAI/PetAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ void PetAI::_stopAttack()
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->CombatStop();
me->getHostileRefMgr().deleteReferences();
return;
}

Expand Down Expand Up @@ -256,7 +255,7 @@ void PetAI::UpdateAI(uint32 diff)
if (spellInfo->CanBeUsedInCombat())
{
// Check if we're in combat or commanded to attack (exlude auras with infinity duration)
if (!me->IsInCombat() && spellInfo->GetMaxDuration() != -1 && !me->IsPetInCombat())
if (!me->IsInCombat() && spellInfo->GetMaxDuration() != -1)
{
continue;
}
Expand Down Expand Up @@ -489,7 +488,7 @@ Unit* PetAI::SelectNextTarget(bool allowAutoSelect) const
if (!tauntAuras.empty())
for (Unit::AuraEffectList::const_reverse_iterator itr = tauntAuras.rbegin(); itr != tauntAuras.rend(); ++itr)
if (Unit* caster = (*itr)->GetCaster())
if (me->CanCreatureAttack(caster) && !caster->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, me->GetGUID()))
if (me->CanCreatureAttack(caster) && !caster->HasAuraTypeWithCaster(SPELL_AURA_MOD_DETAUNT, me->GetGUID()))
return caster;
}

Expand Down Expand Up @@ -567,8 +566,8 @@ void PetAI::HandleReturnMovement()
me->GetCharmInfo()->SetForcedTargetGUID();

// xinef: remember that npcs summoned by npcs can also be pets
me->GetThreatMgr().ClearAllThreat();
me->ClearInPetCombat();
me->GetThreatManager().ClearAllThreat();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); // on player pets, this flag indicates that we're actively going after a target - we're returning, so remove it
}

void PetAI::SpellHit(Unit* caster, SpellInfo const* spellInfo)
Expand All @@ -594,11 +593,7 @@ void PetAI::DoAttack(Unit* target, bool chase)

if (me->Attack(target, true))
{
// xinef: properly fix fake combat after pet is sent to attack
if (Unit* owner = me->GetOwner())
owner->SetUnitFlag(UNIT_FLAG_PET_IN_COMBAT);

me->SetUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); // on player pets, this flag indicates we're actively going after a target - that's what we're doing, so set it

// Play sound to let the player know the pet is attacking something it picked on its own
if (me->HasReactState(REACT_AGGRESSIVE) && !me->GetCharmInfo()->IsCommandAttack())
Expand Down
18 changes: 9 additions & 9 deletions src/server/game/AI/CoreAI/UnitAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ SpellCastResult UnitAI::DoAddAuraToAllHostilePlayers(uint32 spellid)
{
if (me->IsInCombat())
{
ThreatContainer::StorageType threatlist = me->GetThreatMgr().GetThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
auto list = me->GetThreatManager().GetUnsortedThreatList();
for (auto item : list)
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
if (Unit* unit = ObjectAccessor::GetUnit(*me, item->GetVictim()->GetGUID()))
{
if (unit->GetTypeId() == TYPEID_PLAYER)
{
Expand All @@ -158,10 +158,10 @@ SpellCastResult UnitAI::DoCastToAllHostilePlayers(uint32 spellid, bool triggered
{
if (me->IsInCombat())
{
ThreatContainer::StorageType threatlist = me->GetThreatMgr().GetThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
auto list = me->GetThreatManager().GetUnsortedThreatList();
for (auto item : list)
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
if (Unit* unit = ObjectAccessor::GetUnit(*me, item->GetVictim()->GetGUID()))
{
if (unit->GetTypeId() == TYPEID_PLAYER)
return me->CastSpell(unit, spellid, triggered);
Expand Down Expand Up @@ -337,9 +337,9 @@ void UnitAI::FillAISpellInfo()
}
}

ThreatMgr& UnitAI::GetThreatMgr()
ThreatMgr& UnitAI::GetThreatManager()
{
return me->GetThreatMgr();
return me->GetThreatManager();
}

void UnitAI::SortByDistance(std::list<Unit*>& list, bool ascending)
Expand Down Expand Up @@ -427,7 +427,7 @@ bool NonTankTargetSelector::operator()(Unit const* target) const
if (_playerOnly && target->GetTypeId() != TYPEID_PLAYER)
return false;

if (Unit* currentVictim = _source->GetThreatMgr().GetCurrentVictim())
if (Unit* currentVictim = _source->GetThreatManager().GetCurrentVictim())
return target != currentVictim;

return target != _source->GetVictim();
Expand Down
8 changes: 4 additions & 4 deletions src/server/game/AI/CoreAI/UnitAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct DefaultTargetSelector : public Acore::unary_function<Unit*, bool>
// 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, bool withMainTank, int32 aura) : me(unit), m_dist(dist), except(!withMainTank ? me->GetThreatMgr().GetCurrentVictim() : nullptr), m_playerOnly(playerOnly), m_aura(aura) {}
DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, bool withMainTank, int32 aura) : me(unit), m_dist(dist), except(!withMainTank ? me->GetThreatManager().GetCurrentVictim() : nullptr), m_playerOnly(playerOnly), m_aura(aura) {}

bool operator()(Unit const* target) const
{
Expand Down Expand Up @@ -221,7 +221,7 @@ class UnitAI
template <class PREDICATE>
Unit* SelectTarget(SelectTargetMethod targetType, uint32 position, PREDICATE const& predicate)
{
ThreatMgr& mgr = GetThreatMgr();
ThreatMgr& 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() <= position)
return nullptr;
Expand Down Expand Up @@ -266,7 +266,7 @@ class UnitAI
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType, uint32 position, PREDICATE const& predicate)
{
targetList.clear();
ThreatMgr& mgr = GetThreatMgr();
ThreatMgr& 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() <= position)
return;
Expand Down Expand Up @@ -409,7 +409,7 @@ class UnitAI
virtual std::string GetDebugInfo() const;

private:
ThreatMgr& GetThreatMgr();
ThreatMgr& GetThreatManager();
void SortByDistance(std::list<Unit*>& list, bool ascending = true);
};

Expand Down
62 changes: 44 additions & 18 deletions src/server/game/AI/CreatureAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,37 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
}

Map* map = creature->GetMap();
if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
if (creature->CanHaveThreatList())
{
LOG_ERROR("entities.unit.ai", "DoZoneInCombat call for map {} that isn't a dungeon (creature entry = {})", map->GetId(), creature->GetTypeId() == TYPEID_UNIT ? creature->ToCreature()->GetEntry() : 0);
return;
if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
{
LOG_ERROR("entities.unit.ai", "DoZoneInCombat call for map {} that isn't a dungeon (creature entry = {})", map->GetId(), creature->GetTypeId() == TYPEID_UNIT ? creature->ToCreature()->GetEntry() : 0);
return;
}

if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim())
{
if (Unit* nearTarget = creature->SelectNearestTarget(maxRangeToNearestTarget))
creature->AI()->AttackStart(nearTarget);
else if (creature->IsSummon())
{
if (Unit* summoner = creature->ToTempSummon()->GetSummoner()->ToUnit())
{
Unit* target = summoner->getAttackerForHelper();
if (!target && !summoner->GetThreatManager().IsThreatListEmpty())
target = summoner->GetThreatManager().GetAnyTarget();
if (target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target)))
creature->AI()->AttackStart(target);
}
}
}
// Intended duplicated check, the code above this should select a victim
// If it can't find a suitable attack target then we should error out.
if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim())
{
LOG_ERROR("misc.dozoneincombat", "DoZoneInCombat called for creature that has empty threat list (creature entry = %u)", creature->GetEntry());
return;
}
}

Map::PlayerList const& playerList = map->GetPlayers();
Expand All @@ -121,22 +148,19 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
{
if (Player* player = itr->GetSource())
{
if (!IsValidCombatTarget(creature, player))
if (player->IsAlive())
{
continue;
}
if (!IsValidCombatTarget(creature, player))
{
continue;
}

if (!creature->IsWithinDistInMap(player, maxRangeToNearestTarget))
{
continue;
}

creature->SetInCombatWith(player);
player->SetInCombatWith(creature);
if (!creature->IsWithinDistInMap(player, maxRangeToNearestTarget))
{
continue;
}

if (creature->CanHaveThreatList())
{
creature->AddThreat(player, 0.0f);
creature->SetInCombatWith(player);
}
}
}
Expand Down Expand Up @@ -280,11 +304,13 @@ bool CreatureAI::UpdateVictim()
// xinef: if we have any victim, just return true
else if (me->GetVictim() && me->GetExactDist(me->GetVictim()) < 30.0f)
return true;
else if (me->GetThreatMgr().isThreatListEmpty())
else if (me->GetThreatManager().GetThreatListSize() <= 1)
{
EnterEvadeMode();
return false;
}
else
me->AttackStop();

return true;
}
Expand All @@ -302,7 +328,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)

me->ClearComboPointHolders(); // Remove all combo points targeting this unit
// sometimes bosses stuck in combat?
me->GetThreatMgr().ClearAllThreat();
me->GetThreatManager().ClearAllThreat();
me->CombatStop(true);
me->LoadCreaturesAddon(true);
me->SetLootRecipient(nullptr);
Expand Down
18 changes: 9 additions & 9 deletions src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,42 +416,42 @@ void ScriptedAI::DoAddThreat(Unit* unit, float amount)
if (!unit)
return;

me->GetThreatMgr().AddThreat(unit, amount);
me->GetThreatManager().AddThreat(unit, amount);
}

void ScriptedAI::DoModifyThreatByPercent(Unit* unit, int32 pct)
{
if (!unit)
return;

me->GetThreatMgr().ModifyThreatByPercent(unit, pct);
me->GetThreatManager().ModifyThreatByPercent(unit, pct);
}

void ScriptedAI::DoResetThreat(Unit* unit)
{
if (!unit)
return;

me->GetThreatMgr().ResetThreat(unit);
me->GetThreatManager().ResetThreat(unit);
}

void ScriptedAI::DoResetThreatList()
{
if (!me->CanHaveThreatList() || me->GetThreatMgr().isThreatListEmpty())
if (!me->CanHaveThreatList() || me->GetThreatManager().GetThreatListSize() > 0)
{
LOG_ERROR("entities.unit.ai", "DoResetThreatList called for creature that either cannot have threat list or has empty threat list (me entry = {})", me->GetEntry());
return;
}

me->GetThreatMgr().ResetAllThreat();
me->GetThreatManager().ResetAllThreat();
}

float ScriptedAI::DoGetThreat(Unit* unit)
{
if (!unit)
return 0.0f;

return me->GetThreatMgr().GetThreat(unit);
return me->GetThreatManager().GetThreat(unit);
}

void ScriptedAI::DoTeleportPlayer(Unit* unit, float x, float y, float z, float o)
Expand Down Expand Up @@ -653,9 +653,9 @@ void BossAI::TeleportCheaters()
float x, y, z;
me->GetPosition(x, y, z);

ThreatContainer::StorageType threatList = me->GetThreatMgr().GetThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
if (Unit* target = (*itr)->getTarget())
auto list = me->GetThreatManager().GetUnsortedThreatList();
for (auto item : list)
if (Unit* target = item->GetVictim())
if (target->GetTypeId() == TYPEID_PLAYER && !IsInBoundary(target))
target->NearTeleportTo(x, y, z, 0);
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ void npc_escortAI::ReturnToLastPoint()

void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->GetThreatMgr().ClearAllThreat();
me->GetThreatManager().ClearAllThreat();
me->CombatStop(true);
me->SetLootRecipient(nullptr);

Expand Down
4 changes: 2 additions & 2 deletions src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void FollowerAI::AttackStart(Unit* who)
if (me->Attack(who, true))
{
// This is done in Unit::Attack function which wont bug npcs by not adding threat upon combat start...
//me->AddThreat(who, 0.0f);
//me->GetThreatManager().AddThreat(who, 0.0f);
//me->SetInCombatWith(who);
//who->SetInCombatWith(me);

Expand Down Expand Up @@ -153,7 +153,7 @@ void FollowerAI::JustRespawned()
void FollowerAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->RemoveAllAuras();
me->GetThreatMgr().ClearAllThreat();
me->GetThreatManager().ClearAllThreat();
me->CombatStop(true);
me->SetLootRecipient(nullptr);

Expand Down
Loading

0 comments on commit 8324358

Please sign in to comment.