aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorxinef1 <w.szyszko2@gmail.com>2017-02-04 19:38:36 +0100
committerShauren <shauren.trinity@gmail.com>2019-06-15 18:41:09 +0200
commitd1cbd8a837116a0fadae06cf5714a345035eb799 (patch)
tree261991af0f578858f15bb8ce15d115b60c40f3b3 /src
parent2dcc2d0f058bc2e1d5a66352ec76db18bee189dc (diff)
Core/Pets: Fixed flashing pet attack button (#18906)
(cherrypicked from 0fa38d0ae03e3d301fb1f94c48122ea81f000131)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp16
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp20
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Handlers/PetHandler.cpp8
-rw-r--r--src/server/game/Spells/SpellInfo.cpp13
5 files changed, 35 insertions, 24 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 24d4ee96f3c..bd9a0fdf5d5 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -72,7 +72,6 @@ void PetAI::_stopAttack()
me->AttackStop();
me->InterruptNonMeleeSpells(false);
- me->SendMeleeAttackStop(); // Should stop pet's attack button from flashing
me->GetCharmInfo()->SetIsCommandAttack(false);
ClearCharmInfoFlags();
HandleReturnMovement();
@@ -309,7 +308,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))
@@ -448,6 +446,8 @@ void PetAI::HandleReturnMovement()
me->GetMotionMaster()->MoveFollow(me->GetCharmerOrOwner(), PET_FOLLOW_DIST, me->GetFollowAngle());
}
}
+
+ me->ClearInPetCombat();
}
void PetAI::DoAttack(Unit* target, bool chase)
@@ -457,6 +457,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->AddUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
+
+ me->AddUnitFlag(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());
@@ -524,10 +530,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 5b83470dc4e..f5a0412d7f1 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -5605,6 +5605,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)
@@ -7804,10 +7808,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)->AddUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
+ Unit* controlled = *itr;
+ ++itr;
+
+ controlled->SetInCombatState(PvP, enemy);
}
ProcSkillsAndAuras(enemy, PROC_FLAG_ENTER_COMBAT, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
@@ -7838,10 +7844,16 @@ void Unit::ClearInCombat()
else
ToPlayer()->OnCombatExit();
- RemoveUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LEAVE_COMBAT);
}
+void Unit::ClearInPetCombat()
+{
+ RemoveUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
+ if (Unit* owner = GetOwner())
+ owner->RemoveUnitFlag(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 9f0e19ea0d8..e56dc09df42 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1277,11 +1277,13 @@ class TC_GAME_API Unit : public WorldObject
bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); }
bool IsInCombat() const { return HasUnitFlag(UNIT_FLAG_IN_COMBAT); }
+ bool IsPetInCombat() const { return HasUnitFlag(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 18b69ac2d0b..0a765ffec1c 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -133,6 +133,7 @@ void WorldSession::HandlePetStopAttack(WorldPackets::Pet::PetStopAttack& packet)
return;
pet->AttackStop();
+ pet->ClearInPetCombat();
}
void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spellid, uint16 flag, ObjectGuid guid2, Position const& pos)
@@ -166,6 +167,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);
@@ -222,9 +224,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);
@@ -278,6 +277,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
@@ -368,8 +368,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 bbd597b9096..90ca90f9740 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -2046,16 +2046,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))