refactor(Core/Unit): minor changes for the combat system (#11904)

Cherry-pick from TC: https://github.com/TrinityCore/TrinityCore/pull/19966

Co-authored-by: Treeston <treeston.nmoc@gmail.com>
This commit is contained in:
Maelthyr
2022-06-14 00:40:29 +02:00
committed by GitHub
parent bf04f280d2
commit 32334f5f14
11 changed files with 39 additions and 42 deletions
+4 -12
View File
@@ -134,14 +134,6 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
{ {
creature->AddThreat(player, 0.0f); creature->AddThreat(player, 0.0f);
} }
/* Causes certain things to never leave the threat list (Priest Lightwell, etc):
for (Unit::ControlSet::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr)
{
creature->SetInCombatWith(*itr);
(*itr)->SetInCombatWith(creature);
creature->AddThreat(*itr, 0.0f);
}*/
} }
} }
} }
@@ -161,7 +153,7 @@ void CreatureAI::MoveInLineOfSight_Safe(Unit* who)
void CreatureAI::MoveInLineOfSight(Unit* who) void CreatureAI::MoveInLineOfSight(Unit* who)
{ {
if (me->GetVictim()) if (me->IsEngaged())
return; return;
// pussywizard: civilian, non-combat pet or any other NOT HOSTILE TO ANYONE (!) // pussywizard: civilian, non-combat pet or any other NOT HOSTILE TO ANYONE (!)
@@ -182,7 +174,7 @@ void CreatureAI::TriggerAlert(Unit const* who) const
if (!who || who->GetTypeId() != TYPEID_PLAYER) if (!who || who->GetTypeId() != TYPEID_PLAYER)
return; return;
// If this unit isn't an NPC, is already distracted, is in combat, is confused, stunned or fleeing, do nothing // 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 (me->GetTypeId() != TYPEID_UNIT || me->IsEngaged() || me->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED))
return; return;
// Only alert for hostiles! // Only alert for hostiles!
if (me->IsCivilian() || me->HasReactState(REACT_PASSIVE) || !me->IsHostileTo(who) || !me->_IsTargetAcceptable(who)) if (me->IsCivilian() || me->HasReactState(REACT_PASSIVE) || !me->IsHostileTo(who) || !me->_IsTargetAcceptable(who))
@@ -253,7 +245,7 @@ void CreatureAI::SetGazeOn(Unit* target)
bool CreatureAI::UpdateVictimWithGaze() bool CreatureAI::UpdateVictimWithGaze()
{ {
if (!me->IsInCombat()) if (!me->IsEngaged())
return false; return false;
if (me->HasReactState(REACT_PASSIVE)) if (me->HasReactState(REACT_PASSIVE))
@@ -271,7 +263,7 @@ bool CreatureAI::UpdateVictimWithGaze()
bool CreatureAI::UpdateVictim() bool CreatureAI::UpdateVictim()
{ {
if (!me->IsInCombat()) if (!me->IsEngaged())
return false; return false;
if (!me->HasReactState(REACT_PASSIVE)) if (!me->HasReactState(REACT_PASSIVE))
+1 -1
View File
@@ -114,7 +114,7 @@ public:
// Called for reaction at stopping attack at no attackers or targets // Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER); 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*/) {} virtual void EnterCombat(Unit* /*victim*/) {}
// Called when the creature is killed // Called when the creature is killed
@@ -574,7 +574,7 @@ void BossAI::TeleportCheaters()
void BossAI::JustSummoned(Creature* summon) void BossAI::JustSummoned(Creature* summon)
{ {
summons.Summon(summon); summons.Summon(summon);
if (me->IsInCombat()) if (me->IsEngaged())
DoZoneInCombat(summon); DoZoneInCombat(summon);
} }
+16 -16
View File
@@ -4044,18 +4044,18 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
break; break;
case SMART_EVENT_UPDATE_OOC: case SMART_EVENT_UPDATE_OOC:
if (me && me->IsInCombat()) if (me && me->IsEngaged())
return; return;
ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
break; break;
case SMART_EVENT_UPDATE_IC: case SMART_EVENT_UPDATE_IC:
if (!me || !me->IsInCombat()) if (!me || !me->IsEngaged())
return; return;
ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
break; break;
case SMART_EVENT_HEALTH_PCT: case SMART_EVENT_HEALTH_PCT:
{ {
if (!me || !me->IsInCombat() || !me->GetMaxHealth()) if (!me || !me->IsEngaged() || !me->GetMaxHealth())
return; return;
uint32 perc = (uint32)me->GetHealthPct(); uint32 perc = (uint32)me->GetHealthPct();
if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
@@ -4065,7 +4065,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_TARGET_HEALTH_PCT: case SMART_EVENT_TARGET_HEALTH_PCT:
{ {
if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxHealth()) if (!me || !me->IsEngaged() || !me->GetVictim() || !me->GetVictim()->GetMaxHealth())
return; return;
uint32 perc = (uint32)me->GetVictim()->GetHealthPct(); uint32 perc = (uint32)me->GetVictim()->GetHealthPct();
if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
@@ -4075,7 +4075,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_MANA_PCT: case SMART_EVENT_MANA_PCT:
{ {
if (!me || !me->IsInCombat() || !me->GetMaxPower(POWER_MANA)) if (!me || !me->IsEngaged() || !me->GetMaxPower(POWER_MANA))
return; return;
uint32 perc = uint32(me->GetPowerPct(POWER_MANA)); uint32 perc = uint32(me->GetPowerPct(POWER_MANA));
if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
@@ -4085,7 +4085,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_TARGET_MANA_PCT: case SMART_EVENT_TARGET_MANA_PCT:
{ {
if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxPower(POWER_MANA)) if (!me || !me->IsEngaged() || !me->GetVictim() || !me->GetVictim()->GetMaxPower(POWER_MANA))
return; return;
uint32 perc = uint32(me->GetVictim()->GetPowerPct(POWER_MANA)); uint32 perc = uint32(me->GetVictim()->GetPowerPct(POWER_MANA));
if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
@@ -4095,7 +4095,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_RANGE: case SMART_EVENT_RANGE:
{ {
if (!me || !me->IsInCombat() || !me->GetVictim()) if (!me || !me->IsEngaged() || !me->GetVictim())
return; return;
if (me->IsInRange(me->GetVictim(), (float)e.event.minMaxRepeat.min, (float)e.event.minMaxRepeat.max)) if (me->IsInRange(me->GetVictim(), (float)e.event.minMaxRepeat.min, (float)e.event.minMaxRepeat.max))
@@ -4106,7 +4106,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_VICTIM_CASTING: case SMART_EVENT_VICTIM_CASTING:
{ {
if (!me || !me->IsInCombat()) if (!me || !me->IsEngaged())
return; return;
Unit* victim = me->GetVictim(); Unit* victim = me->GetVictim();
@@ -4124,7 +4124,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_FRIENDLY_HEALTH: case SMART_EVENT_FRIENDLY_HEALTH:
{ {
if (!me || !me->IsInCombat()) if (!me || !me->IsEngaged())
return; return;
Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealth.radius, e.event.friendlyHealth.hpDeficit); Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealth.radius, e.event.friendlyHealth.hpDeficit);
@@ -4139,7 +4139,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_FRIENDLY_IS_CC: case SMART_EVENT_FRIENDLY_IS_CC:
{ {
if (!me || !me->IsInCombat()) if (!me || !me->IsEngaged())
return; return;
std::list<Creature*> pList; std::list<Creature*> pList;
@@ -4285,7 +4285,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_OOC_LOS: case SMART_EVENT_OOC_LOS:
{ {
if (!me || me->IsInCombat()) if (!me || me->IsEngaged())
return; return;
//can trigger if closer than fMaxAllowedRange //can trigger if closer than fMaxAllowedRange
float range = (float)e.event.los.maxDist; float range = (float)e.event.los.maxDist;
@@ -4309,7 +4309,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_IC_LOS: case SMART_EVENT_IC_LOS:
{ {
if (!me || !me->IsInCombat()) if (!me || !me->IsEngaged())
return; return;
//can trigger if closer than fMaxAllowedRange //can trigger if closer than fMaxAllowedRange
float range = (float)e.event.los.maxDist; float range = (float)e.event.los.maxDist;
@@ -4507,7 +4507,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_EVENT_FRIENDLY_HEALTH_PCT: case SMART_EVENT_FRIENDLY_HEALTH_PCT:
{ {
if (!me || !me->IsInCombat()) if (!me || !me->IsEngaged())
return; return;
Unit* target = nullptr; Unit* target = nullptr;
@@ -4701,10 +4701,10 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
if (e.event.event_phase_mask && !IsInPhase(e.event.event_phase_mask)) if (e.event.event_phase_mask && !IsInPhase(e.event.event_phase_mask))
return; return;
if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsInCombat())) if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsEngaged()))
return; 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; return;
if (e.timer < diff) if (e.timer < diff)
@@ -4982,7 +4982,7 @@ void SmartScript::OnMoveInLineOfSight(Unit* who)
if (!me) if (!me)
return; 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);
} }
/* /*
@@ -704,7 +704,7 @@ void Creature::Update(uint32 diff)
} }
// periodic check to see if the creature has passed an evade boundary // periodic check to see if the creature has passed an evade boundary
if (IsAIEnabled && !IsInEvadeMode() && IsInCombat()) if (IsAIEnabled && !IsInEvadeMode() && IsEngaged())
{ {
if (diff >= m_boundaryCheckTime) if (diff >= m_boundaryCheckTime)
{ {
@@ -1838,7 +1838,7 @@ bool Creature::CanStartAttack(Unit const* who) const
// pussywizard: at this point we are either hostile to who or friendly to who->getAttackerForHelper() // pussywizard: at this point we are either hostile to who or friendly to who->getAttackerForHelper()
// pussywizard: if who is in combat and has an attacker, help him if the distance is right (help because who is hostile or help because attacker is friendly) // pussywizard: if who is in combat and has an attacker, help him if the distance is right (help because who is hostile or help because attacker is friendly)
bool assist = false; bool assist = false;
if (who->IsInCombat() && IsWithinDist(who, ATTACK_DISTANCE)) if (who->IsEngaged() && IsWithinDist(who, ATTACK_DISTANCE))
if (Unit* victim = who->getAttackerForHelper()) if (Unit* victim = who->getAttackerForHelper())
if (IsWithinDistInMap(victim, sWorld->getFloatConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS))) if (IsWithinDistInMap(victim, sWorld->getFloatConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS)))
assist = true; assist = true;
@@ -2357,7 +2357,7 @@ bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction /
return false; return false;
// skip fighting creature // skip fighting creature
if (IsInCombat()) if (IsEngaged())
return false; return false;
// only free creature // only free creature
@@ -2408,11 +2408,10 @@ bool Creature::_IsTargetAcceptable(Unit const* target) const
return false; return false;
} }
Unit const* myVictim = getAttackerForHelper();
Unit const* targetVictim = target->getAttackerForHelper(); Unit const* targetVictim = target->getAttackerForHelper();
// if I'm already fighting target, or I'm hostile towards the target, the target is acceptable // if I'm already fighting target, or I'm hostile towards the target, the target is acceptable
if (myVictim == target || targetVictim == this || IsHostileTo(target)) if (IsEngagedBy(target) || IsHostileTo(target))
return true; return true;
// if the target's victim is friendly, and the target is neutral, the target is acceptable // if the target's victim is friendly, and the target is neutral, the target is acceptable
@@ -190,7 +190,7 @@ void CreatureGroup::RemoveMember(Creature* member)
member->SetFormation(nullptr); member->SetFormation(nullptr);
} }
void CreatureGroup::MemberAttackStart(Creature* member, Unit* target) void CreatureGroup::MemberEngagingTarget(Creature* member, Unit* target)
{ {
uint8 const groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()].groupAI; uint8 const groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()].groupAI;
if (member == m_leader) if (member == m_leader)
@@ -106,7 +106,7 @@ public:
void FormationReset(bool dismiss, bool initMotionMaster); void FormationReset(bool dismiss, bool initMotionMaster);
void LeaderMoveTo(float x, float y, float z, bool run); void LeaderMoveTo(float x, float y, float z, bool run);
void MemberAttackStart(Creature* member, Unit* target); void MemberEngagingTarget(Creature* member, Unit* target);
void MemberEvaded(Creature* member); void MemberEvaded(Creature* member);
private: private:
+1 -1
View File
@@ -13150,7 +13150,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy, uint32 duration)
creature->AI()->EnterCombat(enemy); creature->AI()->EnterCombat(enemy);
if (creature->GetFormation()) if (creature->GetFormation())
creature->GetFormation()->MemberAttackStart(creature, enemy); creature->GetFormation()->MemberEngagingTarget(creature, enemy);
} }
creature->RefreshSwimmingFlag(); creature->RefreshSwimmingFlag();
+8 -2
View File
@@ -1326,6 +1326,7 @@ public:
bool IsWithinCombatRange(Unit const* obj, float dist2compare) const; bool IsWithinCombatRange(Unit const* obj, float dist2compare) const;
bool IsWithinMeleeRange(Unit const* obj, float dist = 0.f) const; bool IsWithinMeleeRange(Unit const* obj, float dist = 0.f) const;
float GetMeleeRange(Unit const* target) const; float GetMeleeRange(Unit const* target) const;
[[nodiscard]] virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
bool GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, bool force = false) const; bool GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, bool force = false) const;
uint32 m_extraAttacks; uint32 m_extraAttacks;
bool m_canDualWield; bool m_canDualWield;
@@ -1343,6 +1344,9 @@ public:
if (GetVictim() != nullptr) if (GetVictim() != nullptr)
return GetVictim(); return GetVictim();
if (!IsEngaged())
return nullptr;
if (!m_attackers.empty()) if (!m_attackers.empty())
return *(m_attackers.begin()); return *(m_attackers.begin());
@@ -1643,6 +1647,9 @@ public:
[[nodiscard]] bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); } [[nodiscard]] bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); }
bool IsEngaged() const { return IsInCombat(); }
bool IsEngagedBy(Unit const* who) const { return IsInCombatWith(who); }
[[nodiscard]] bool IsInCombat() const { return HasUnitFlag(UNIT_FLAG_IN_COMBAT); } [[nodiscard]] bool IsInCombat() const { return HasUnitFlag(UNIT_FLAG_IN_COMBAT); }
bool IsInCombatWith(Unit const* who) const; bool IsInCombatWith(Unit const* who) const;
@@ -2103,6 +2110,7 @@ public:
void TauntApply(Unit* victim); void TauntApply(Unit* victim);
void TauntFadeOut(Unit* taunter); void TauntFadeOut(Unit* taunter);
ThreatMgr& GetThreatMgr() { return m_ThreatMgr; } ThreatMgr& GetThreatMgr() { return m_ThreatMgr; }
ThreatMgr const& GetThreatMgr() const { return m_ThreatMgr; }
void addHatedBy(HostileReference* pHostileReference) { m_HostileRefMgr.insertFirst(pHostileReference); }; void addHatedBy(HostileReference* pHostileReference) { m_HostileRefMgr.insertFirst(pHostileReference); };
void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ } void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ }
HostileRefMgr& getHostileRefMgr() { return m_HostileRefMgr; } HostileRefMgr& getHostileRefMgr() { return m_HostileRefMgr; }
@@ -2473,8 +2481,6 @@ protected:
CharmInfo* m_charmInfo; CharmInfo* m_charmInfo;
SharedVisionList m_sharedVision; SharedVisionList m_sharedVision;
[[nodiscard]] virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
MotionMaster* i_motionMaster; MotionMaster* i_motionMaster;
uint32 m_reactiveTimer[MAX_REACTIVE]; uint32 m_reactiveTimer[MAX_REACTIVE];
+1 -1
View File
@@ -2677,7 +2677,7 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/)
return; return;
// Check for possible target // Check for possible target
if (!unitTarget || unitTarget->IsInCombat()) if (!unitTarget || unitTarget->IsEngaged())
return; return;
// target must be OK to do this // target must be OK to do this
@@ -339,7 +339,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
if (Creature* delrissa = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_DELRISSA))) if (Creature* delrissa = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_DELRISSA)))
if (delrissa->IsAlive() && !delrissa->IsInCombat()) if (delrissa->IsAlive() && !delrissa->IsEngaged())
delrissa->AI()->AttackStart(who); delrissa->AI()->AttackStart(who);
events.ScheduleEvent(EVENT_SPELL_HELPER_HEALING_POTION, 1000); events.ScheduleEvent(EVENT_SPELL_HELPER_HEALING_POTION, 1000);