From 0fa38d0ae03e3d301fb1f94c48122ea81f000131 Mon Sep 17 00:00:00 2001 From: xinef1 Date: Sat, 4 Feb 2017 19:38:36 +0100 Subject: Core/Pets: Fixed flashing pet attack button (#18906) --- src/server/game/AI/CoreAI/PetAI.cpp | 17 +++++++++++------ src/server/game/Entities/Unit/Unit.cpp | 20 ++++++++++++++++---- src/server/game/Entities/Unit/Unit.h | 2 ++ src/server/game/Handlers/PetHandler.cpp | 8 +++----- src/server/game/Spells/SpellInfo.cpp | 13 +++---------- 5 files changed, 35 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 3d1216d6247..6662c4d87e9 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -65,13 +65,11 @@ void PetAI::_stopAttack() me->GetMotionMaster()->MoveIdle(); me->CombatStop(); me->getHostileRefManager().deleteReferences(); - return; } me->AttackStop(); me->InterruptNonMeleeSpells(false); - me->SendMeleeAttackStop(); // Should stop pet's attack button from flashing me->GetCharmInfo()->SetIsCommandAttack(false); ClearCharmInfoFlags(); HandleReturnMovement(); @@ -308,7 +306,6 @@ void PetAI::KilledUnit(Unit* victim) // next target selection me->AttackStop(); me->InterruptNonMeleeSpells(false); - me->SendMeleeAttackStop(); // Stops the pet's 'Attack' button from flashing // Before returning to owner, see if there are more things to attack if (Unit* nextTarget = SelectNextTarget(false)) @@ -447,6 +444,8 @@ void PetAI::HandleReturnMovement() me->GetMotionMaster()->MoveFollow(me->GetCharmerOrOwner(), PET_FOLLOW_DIST, me->GetFollowAngle()); } } + + me->ClearInPetCombat(); } void PetAI::DoAttack(Unit* target, bool chase) @@ -456,6 +455,12 @@ void PetAI::DoAttack(Unit* target, bool chase) if (me->Attack(target, true)) { + // properly fix fake combat after pet is sent to attack + if (Unit* owner = me->GetOwner()) + owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); + // 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()) me->SendPetAIReaction(me->GetGUID()); @@ -523,10 +528,10 @@ bool PetAI::CanAttack(Unit* target) if (!target->IsAlive()) { + // if target is invalid, pet should evade automaticly // Clear target to prevent getting stuck on dead targets - me->AttackStop(); - me->InterruptNonMeleeSpells(false); - me->SendMeleeAttackStop(); + //me->AttackStop(); + //me->InterruptNonMeleeSpells(false); return false; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f38e3070579..3407c63aa38 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -5794,6 +5794,10 @@ void Unit::CombatStop(bool includingCast) if (GetTypeId() == TYPEID_PLAYER) ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel ClearInCombat(); + + // just in case + if (IsPetInCombat() && GetTypeId() != TYPEID_PLAYER) + ClearInPetCombat(); } void Unit::CombatStopWithPets(bool includingCast) @@ -8554,10 +8558,12 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy) Dismount(); } - for (Unit::ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) + for (Unit::ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end();) { - (*itr)->SetInCombatState(PvP, enemy); - (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); + Unit* controlled = *itr; + ++itr; + + controlled->SetInCombatState(PvP, enemy); } } @@ -8596,10 +8602,16 @@ void Unit::ClearInCombat() else ToPlayer()->UpdatePotionCooldown(); - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LEAVE_COMBAT); } +void Unit::ClearInPetCombat() +{ + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); + if (Unit* owner = GetOwner()) + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); +} + bool Unit::isTargetableForAttack(bool checkFakeDeath) const { if (!IsAlive()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e81ec55d93d..c2d9b62d902 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1550,11 +1550,13 @@ class TC_GAME_API Unit : public WorldObject bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); } 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; void CombatStart(Unit* target, bool initialAggro = true); void SetInCombatState(bool PvP, Unit* enemy = NULL); void SetInCombatWith(Unit* enemy); void ClearInCombat(); + void ClearInPetCombat(); uint32 GetCombatTimer() const { return m_CombatTimer; } bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const; diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 586f0aa9e6e..89f6e78cc6d 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -138,6 +138,7 @@ void WorldSession::HandlePetStopAttack(WorldPacket &recvData) return; pet->AttackStop(); + pet->ClearInPetCombat(); } void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spellid, uint16 flag, ObjectGuid guid2) @@ -171,6 +172,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe case COMMAND_FOLLOW: //spellid=1792 //FOLLOW pet->AttackStop(); pet->InterruptNonMeleeSpells(false); + pet->ClearInPetCombat(); pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, pet->GetFollowAngle()); charmInfo->SetCommandState(COMMAND_FOLLOW); @@ -227,9 +229,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe } else // charmed player { - if (pet->GetVictim() && pet->GetVictim() != TargetUnit) - pet->AttackStop(); - charmInfo->SetIsCommandAttack(true); charmInfo->SetIsAtStay(false); charmInfo->SetIsFollowing(false); @@ -271,6 +270,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe { case REACT_PASSIVE: //passive pet->AttackStop(); + pet->ClearInPetCombat(); // no break; case REACT_DEFENSIVE: //recovery case REACT_AGGRESSIVE: //activete @@ -361,8 +361,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe // This is true if pet has no target or has target but targets differs. if (pet->GetVictim() != unit_target) { - if (pet->GetVictim()) - pet->AttackStop(); pet->GetMotionMaster()->Clear(); if (pet->ToCreature()->IsAIEnabled) pet->ToCreature()->AI()->AttackStart(unit_target); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index e969c3d35d0..5b766d2426c 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1631,16 +1631,9 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta // creature/player specific target checks if (unitTarget) { - if (HasAttribute(SPELL_ATTR1_CANT_TARGET_IN_COMBAT)) - { - if (unitTarget->IsInCombat()) - return SPELL_FAILED_TARGET_AFFECTING_COMBAT; - // player with active pet counts as a player in combat - else if (Player const* player = unitTarget->ToPlayer()) - if (Pet* pet = player->GetPet()) - if (pet->GetVictim() && !pet->HasUnitState(UNIT_STATE_CONTROLLED)) - return SPELL_FAILED_TARGET_AFFECTING_COMBAT; - } + // spells cannot be cast if player is in fake combat also + if (HasAttribute(SPELL_ATTR1_CANT_TARGET_IN_COMBAT) && (unitTarget->IsInCombat() || unitTarget->IsPetInCombat())) + return SPELL_FAILED_TARGET_AFFECTING_COMBAT; // only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts if (HasAttribute(SPELL_ATTR3_ONLY_TARGET_GHOSTS) != unitTarget->HasAuraType(SPELL_AURA_GHOST)) -- cgit v1.2.3