diff options
| author | trickerer <onlysuffering@gmail.com> | 2021-10-01 21:40:20 +0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-01 16:40:20 +0200 |
| commit | 084f8f3ded45150a57eabd3ad117f1152d4d046d (patch) | |
| tree | 5fd3fb733d8618c043704bc373c3a19a40a3969f /src/server/game/Entities/Unit | |
| parent | e317beb449fb36b9f13c3bda192f86dc72d07581 (diff) | |
Core/Combat Improve extra attacks handling (#26859)
* Core/Combat Improve extra attacks handling
* Remove unnecessary _lastDamagedTargetGuid check
* Add missing initialization of _lastExtraAttackSpell. Do not use hardcoded spell ids.
* Partially revert 9f90b835019b
Diffstat (limited to 'src/server/game/Entities/Unit')
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 48 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 13 |
2 files changed, 54 insertions, 7 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e515a048830..2daf345215c 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -314,7 +314,6 @@ Unit::Unit(bool isWorldObject) : m_modAttackSpeedPct[OFF_ATTACK] = 1.0f; m_modAttackSpeedPct[RANGED_ATTACK] = 1.0f; - m_extraAttacks = 0; m_canDualWield = false; m_movementCounter = 0; @@ -389,6 +388,8 @@ Unit::Unit(bool isWorldObject) : _isWalkingBeforeCharm = false; _instantCast = false; _isCombatDisallowed = false; + + _lastExtraAttackSpell = 0; } //////////////////////////////////////////////////////////// @@ -445,6 +446,21 @@ void Unit::Update(uint32 p_time) m_combatManager.Update(p_time); + _lastDamagedTargetGuid = ObjectGuid::Empty; + if (_lastExtraAttackSpell) + { + while (!extraAttacksTargets.empty()) + { + auto itr = extraAttacksTargets.begin(); + ObjectGuid targetGuid = itr->first; + uint32 count = itr->second; + extraAttacksTargets.erase(itr); + if (Unit* victim = ObjectAccessor::GetUnit(*this, targetGuid)) + HandleProcExtraAttackFor(victim, count); + } + _lastExtraAttackSpell = 0; + } + // not implemented before 3.0.2 if (uint32 base_att = getAttackTimer(BASE_ATTACK)) setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time)); @@ -2056,7 +2072,10 @@ void Unit::HandleEmoteCommand(Emote emoteId) void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra) { - if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) + if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) + return; + + if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) && !extra) return; if (!victim->IsAlive()) @@ -2071,6 +2090,9 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr if (attType != BASE_ATTACK && attType != OFF_ATTACK) return; // ignore ranged case + if (!extra && _lastExtraAttackSpell) + _lastExtraAttackSpell = 0; + if (GetTypeId() == TYPEID_UNIT && !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED) && !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_CANNOT_TURN)) SetFacingToObject(victim, false); // update client side facing to face the target (prevents visual glitches when casting untargeted spells) @@ -2090,6 +2112,8 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr Unit::DealDamageMods(victim, damageInfo.Damages[i].Damage, &damageInfo.Damages[i].Absorb); SendAttackStateUpdate(&damageInfo); + _lastDamagedTargetGuid = victim->GetGUID(); + DealMeleeDamage(&damageInfo, true); DamageInfo dmgInfo(damageInfo); @@ -2104,15 +2128,29 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr } } -void Unit::HandleProcExtraAttackFor(Unit* victim) +void Unit::HandleProcExtraAttackFor(Unit* victim, uint32 count) { - while (m_extraAttacks) + while (count) { + --count; AttackerStateUpdate(victim, BASE_ATTACK, true); - --m_extraAttacks; } } +void Unit::AddExtraAttacks(uint32 count) +{ + ObjectGuid targetGUID = _lastDamagedTargetGuid; + if (!targetGUID) + { + if (ObjectGuid selection = GetTarget()) + targetGUID = selection; // Spell was cast directly (not triggered by aura) + else + return; + } + + extraAttacksTargets[targetGUID] += count; +} + MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackType attType) const { if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index cffd683d28e..ea63c22ea3a 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -834,7 +834,6 @@ class TC_GAME_API Unit : public WorldObject bool IsWithinMeleeRangeAt(Position const& pos, Unit const* obj) const; float GetMeleeRange(Unit const* target) const; virtual SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const = 0; - uint32 m_extraAttacks; bool m_canDualWield; void _addAttacker(Unit* pAttacker); // must be called only from Unit::Attack(Unit*) @@ -991,7 +990,13 @@ class TC_GAME_API Unit : public WorldObject void CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK); void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss); - void HandleProcExtraAttackFor(Unit* victim); + void HandleProcExtraAttackFor(Unit* victim, uint32 count); + + void SetLastExtraAttackSpell(uint32 spellId) { _lastExtraAttackSpell = spellId; } + uint32 GetLastExtraAttackSpell() const { return _lastExtraAttackSpell; } + void AddExtraAttacks(uint32 count); + void SetLastDamagedTargetGuid(ObjectGuid guid) { _lastDamagedTargetGuid = guid; } + ObjectGuid GetLastDamagedTargetGuid() const { return _lastDamagedTargetGuid; } void CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = BASE_ATTACK, bool crit = false, Spell* spell = nullptr); void DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss); @@ -1884,6 +1889,10 @@ class TC_GAME_API Unit : public WorldObject int8 m_comboPoints; std::unordered_set<Unit*> m_ComboPointHolders; + uint32 _lastExtraAttackSpell; + std::unordered_map<ObjectGuid /*guid*/, uint32 /*count*/> extraAttacksTargets; + ObjectGuid _lastDamagedTargetGuid; + bool m_cleanupDone; // lock made to not add stuff after cleanup before delete bool m_duringRemoveFromWorld; // lock made to not add stuff after begining removing from world bool _instantCast; |
