diff options
| author | Treeston <treeston.mmoc@gmail.com> | 2017-07-01 20:18:02 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2017-07-01 20:18:02 +0200 |
| commit | e2a1ccd118d129b96e09ff1a15ed0adb1d4a3897 (patch) | |
| tree | bbe6600c4066078bb7c64a117df457dce0d00b26 /src/server/game/Entities/Unit | |
| parent | 5879eb2198fdb976b9fff136757bf8187adb6cf0 (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.cpp | 103 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 19 |
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]; |
