From e6f049d531c1d5d6d9eb0d391e29c954fbd7a2b0 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 14 Aug 2019 23:35:18 -0400 Subject: [PATCH] Core/Pets: Fixed flashing pet attack button (#18906) Port TrinityCore Commit: https://github.com/TrinityCore/TrinityCore/commit/d1cbd8a837116a0fadae06cf5714a345035eb799 --- Source/Game/AI/CoreAI/PetAI.cs | 17 ++++++++++------- Source/Game/Entities/Unit/Unit.Combat.cs | 24 ++++++++++++++++-------- Source/Game/Handlers/PetHandler.cs | 8 +++----- Source/Game/Spells/SpellInfo.cs | 16 +++------------- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/Source/Game/AI/CoreAI/PetAI.cs b/Source/Game/AI/CoreAI/PetAI.cs index 220de72c9..c12ae9bff 100644 --- a/Source/Game/AI/CoreAI/PetAI.cs +++ b/Source/Game/AI/CoreAI/PetAI.cs @@ -63,7 +63,6 @@ namespace Game.AI me.AttackStop(); me.InterruptNonMeleeSpells(false); - me.SendMeleeAttackStop(); // Should stop pet's attack button from flashing me.GetCharmInfo().SetIsCommandAttack(false); ClearCharmInfoFlags(); HandleReturnMovement(); @@ -299,7 +298,6 @@ namespace Game.AI // 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 Unit nextTarget = SelectNextTarget(false); @@ -445,6 +443,8 @@ namespace Game.AI me.GetMotionMaster().MoveFollow(me.GetCharmerOrOwner(), SharedConst.PetFollowDist, me.GetFollowAngle()); } } + + me.ClearInPetCombat(); } void DoAttack(Unit target, bool chase) @@ -454,9 +454,12 @@ namespace Game.AI if (me.Attack(target, true)) { + // properly fix fake combat after pet is sent to attack Unit owner = me.GetOwner(); - if (owner) - owner.SetInCombatWith(target); + if (owner != null) + owner.AddUnitFlag(UnitFlags.PetInCombat); + + me.AddUnitFlag(UnitFlags.PetInCombat); // Play sound to let the player know the pet is attacking something it picked on its own if (me.HasReactState(ReactStates.Aggressive) && !me.GetCharmInfo().IsCommandAttack()) @@ -525,10 +528,10 @@ namespace Game.AI if (!victim.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/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index 47670be27..01d6d03c8 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -235,6 +235,10 @@ namespace Game.Entities if (IsTypeId(TypeId.Player)) ToPlayer().SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel ClearInCombat(); + + // just in case + if (IsPetInCombat() && GetTypeId() != TypeId.Player) + ClearInPetCombat(); } public void CombatStopWithPets(bool includingCast = false) { @@ -270,10 +274,17 @@ namespace Game.Entities else ToPlayer().OnCombatExit(); - RemoveUnitFlag(UnitFlags.PetInCombat); RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LeaveCombat); } + public void ClearInPetCombat() + { + RemoveUnitFlag(UnitFlags.PetInCombat); + Unit owner = GetOwner(); + if (owner != null) + owner.RemoveUnitFlag(UnitFlags.PetInCombat); + } + void RemoveAllAttackers() { while (!attackerList.Empty()) @@ -327,10 +338,10 @@ namespace Game.Entities { return m_deathState; } - public bool IsInCombat() - { - return HasUnitFlag(UnitFlags.InCombat); - } + + public bool IsInCombat() { return HasUnitFlag(UnitFlags.InCombat); } + public bool IsPetInCombat() { return HasUnitFlag(UnitFlags.PetInCombat); } + public bool Attack(Unit victim, bool meleeAttack) { if (victim == null || victim.GetGUID() == GetGUID()) @@ -1323,10 +1334,7 @@ namespace Game.Entities } foreach (var unit in m_Controlled) - { unit.SetInCombatState(PvP, enemy); - unit.AddUnitFlag(UnitFlags.PetInCombat); - } ProcSkillsAndAuras(enemy, ProcFlags.EnterCombat, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null); } diff --git a/Source/Game/Handlers/PetHandler.cs b/Source/Game/Handlers/PetHandler.cs index 119f4f0c2..dbe4a689f 100644 --- a/Source/Game/Handlers/PetHandler.cs +++ b/Source/Game/Handlers/PetHandler.cs @@ -121,6 +121,7 @@ namespace Game return; pet.AttackStop(); + pet.ClearInPetCombat(); } void HandlePetActionHelper(Unit pet, ObjectGuid guid1, uint spellid, ActiveStates flag, ObjectGuid guid2, float x, float y, float z) @@ -154,6 +155,7 @@ namespace Game case CommandStates.Follow: //spellid=1792 //FOLLOW pet.AttackStop(); pet.InterruptNonMeleeSpells(false); + pet.ClearInPetCombat(); pet.GetMotionMaster().MoveFollow(GetPlayer(), SharedConst.PetFollowDist, pet.GetFollowAngle()); charmInfo.SetCommandState(CommandStates.Follow); @@ -210,9 +212,6 @@ namespace Game } else // charmed player { - if (pet.GetVictim() && pet.GetVictim() != TargetUnit) - pet.AttackStop(); - charmInfo.SetIsCommandAttack(true); charmInfo.SetIsAtStay(false); charmInfo.SetIsFollowing(false); @@ -267,6 +266,7 @@ namespace Game { case ReactStates.Passive: //passive pet.AttackStop(); + pet.ClearInPetCombat(); goto case ReactStates.Defensive; case ReactStates.Defensive: //recovery case ReactStates.Aggressive: //activete @@ -363,8 +363,6 @@ namespace Game // 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().GetAI().AttackStart(unit_target); diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index a55502ff1..e95186cdb 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -1054,19 +1054,9 @@ namespace Game.Spells // creature/player specific target checks if (unitTarget != null) { - if (HasAttribute(SpellAttr1.CantTargetInCombat)) - { - if (unitTarget.IsInCombat()) - return SpellCastResult.TargetAffectingCombat; - // player with active pet counts as a player in combat - else if (unitTarget.IsTypeId(TypeId.Player)) - { - Pet pet = unitTarget.ToPlayer().GetPet(); - if (pet) - if (pet.GetVictim() && !pet.HasUnitState(UnitState.Controlled)) - return SpellCastResult.TargetAffectingCombat; - } - } + // spells cannot be cast if player is in fake combat also + if (HasAttribute(SpellAttr1.CantTargetInCombat) && (unitTarget.IsInCombat() || unitTarget.IsPetInCombat())) + return SpellCastResult.TargetAffectingCombat; // only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts if (HasAttribute(SpellAttr3.OnlyTargetGhosts) != unitTarget.HasAuraType(AuraType.Ghost))