aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities/Unit
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2017-07-01 20:18:02 +0200
committerShauren <shauren.trinity@gmail.com>2017-07-01 20:18:02 +0200
commite2a1ccd118d129b96e09ff1a15ed0adb1d4a3897 (patch)
treebbe6600c4066078bb7c64a117df457dce0d00b26 /src/server/game/Entities/Unit
parent5879eb2198fdb976b9fff136757bf8187adb6cf0 (diff)
[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.
Diffstat (limited to 'src/server/game/Entities/Unit')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp103
-rw-r--r--src/server/game/Entities/Unit/Unit.h19
2 files changed, 46 insertions, 76 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index bb43c34182a..daa9d5bdefa 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -445,7 +445,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)
@@ -880,7 +880,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
{
@@ -5763,6 +5763,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;
@@ -5866,14 +5869,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);
@@ -6768,12 +6771,16 @@ void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellId, int32 damage, Powe
void Unit::EnergizeBySpell(Unit* victim, uint32 spellId, int32 damage, Powers powerType)
{
- SendEnergizeSpellLog(victim, spellId, damage, powerType);
+ if (SpellInfo const* info = sSpellMgr->GetSpellInfo(spellId))
+ EnergizeBySpell(victim, info, damage, powerType);
+}
+
+void Unit::EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damage, Powers powerType)
+{
+ SendEnergizeSpellLog(victim, spellInfo->Id, damage, powerType);
// needs to be called after sending spell log
victim->ModifyPower(powerType, damage);
-
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
- victim->getHostileRefManager().threatAssist(this, float(damage) * 0.5f, spellInfo);
+ victim->GetThreatManager().ForwardThreatForAssistingMe(this, float(damage)/2, spellInfo, true);
}
uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) const
@@ -8690,11 +8697,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))
@@ -8732,7 +8739,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())
@@ -9419,7 +9426,7 @@ void Unit::setDeathState(DeathState s)
if (s != ALIVE && s != JUST_RESPAWNED)
{
CombatStop();
- DeleteThreatList();
+ GetThreatManager().ClearAllThreat();
getHostileRefManager().deleteReferences();
ClearComboPointHolders(); // any combo points pointed to unit lost at it death
@@ -9489,7 +9496,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;
@@ -9509,24 +9516,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);
@@ -10678,7 +10667,7 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup)
CombatStop();
ClearComboPoints();
ClearComboPointHolders();
- DeleteThreatList();
+ GetThreatManager().ClearAllThreat();
getHostileRefManager().deleteReferences();
}
@@ -11338,8 +11327,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;
}
@@ -11904,29 +11892,6 @@ bool Unit::IsUnderLastManaUseEffect() const
return getMSTimeDiff(m_lastManaUse, GameTime::GetGameTimeMS()) < 5000;
}
-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->SetFlag(PLAYER_FLAGS, 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)
@@ -12184,7 +12149,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())
@@ -12576,7 +12541,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();
@@ -12719,7 +12684,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
CastStop();
CombatStop(); /// @todo CombatStop(true) may cause crash (interrupt spells)
getHostileRefManager().deleteReferences();
- DeleteThreatList();
+ GetThreatManager().ClearAllThreat();
if (_oldFactionId)
{
@@ -13177,8 +13142,8 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
// 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();
@@ -14027,15 +13992,15 @@ void Unit::UpdateHeight(float newZ)
void Unit::SendThreatListUpdate()
{
- if (!getThreatManager().isThreatListEmpty())
+ if (!GetThreatManager().isThreatListEmpty())
{
- uint32 count = getThreatManager().getThreatList().size();
+ uint32 count = GetThreatManager().getThreatList().size();
//TC_LOG_DEBUG("entities.unit", "WORLD: Send SMSG_THREAT_UPDATE Message");
WorldPacket data(SMSG_THREAT_UPDATE, 8 + count * 8);
data << GetPackGUID();
data << uint32(count);
- ThreatContainer::StorageType const& tlist = getThreatManager().getThreatList();
+ ThreatContainer::StorageType const& tlist = GetThreatManager().getThreatList();
for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
{
data << (*itr)->getUnitGuid().WriteAsPacked();
@@ -14047,16 +14012,16 @@ void Unit::SendThreatListUpdate()
void Unit::SendChangeCurrentVictimOpcode(HostileReference* pHostileReference)
{
- if (!getThreatManager().isThreatListEmpty())
+ if (!GetThreatManager().isThreatListEmpty())
{
- uint32 count = getThreatManager().getThreatList().size();
+ uint32 count = GetThreatManager().getThreatList().size();
TC_LOG_DEBUG("entities.unit", "WORLD: Send SMSG_HIGHEST_THREAT_UPDATE Message");
WorldPacket data(SMSG_HIGHEST_THREAT_UPDATE, 8 + 8 + count * 8);
data << GetPackGUID();
data << pHostileReference->getUnitGuid().WriteAsPacked();
data << uint32(count);
- ThreatContainer::StorageType const& tlist = getThreatManager().getThreatList();
+ ThreatContainer::StorageType const& tlist = GetThreatManager().getThreatList();
for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
{
data << (*itr)->getUnitGuid().WriteAsPacked();
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 73ca8add151..1a32512a01b 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1000,6 +1000,7 @@ class TC_GAME_API Unit : public WorldObject
bool IsWithinCombatRange(Unit const* obj, float dist2compare) const;
bool IsWithinMeleeRange(Unit const* obj) const;
float GetMeleeRange(Unit const* target) const;
+ virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
void GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, float distance2dMin, float distance2dMax) const;
uint32 m_extraAttacks;
bool m_canDualWield;
@@ -1222,6 +1223,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 HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); }
bool IsPetInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); }
bool IsInCombatWith(Unit const* who) const;
@@ -1259,8 +1266,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, Powers powerType);
- void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype);
+ void SendEnergizeSpellLog(Unit* victim, uint32 spellId, int32 damage, 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);
@@ -1661,12 +1669,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 = nullptr);
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; }
@@ -1974,8 +1981,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];