Projekt

Allgemein

Profil

Aktionen

Fehler #6028

geschlossen

Fehler #5963: Arena

[Mechanik][Pets] Pet Target positioning fehlerhaft | Pet-Bewegung

Von Murloc vor etwa 11 Jahren hinzugefügt. Vor fast 6 Jahren aktualisiert.

Status:
Live
Priorität:
Dringend
Zugewiesen an:
-
Kategorie:
Kreaturen
Zielversion:
Beginn:
06.04.2013
Update Text Deutsch:

Begleiter sollten sich nun nicht mehr an einer Kante verbuggen lassen. Desweiteren wirken Begleiter nun Fähigkeiten auch wenn sie außer Reichweite sind, indem sie automatisch an das Ziel heranlaufen.


Beschreibung

Das Ziel des Pets bspw. in der Arena kann sihc so an einen Pfosten oder an der Wand postieren, dass das Pet das Target nicht angreifen kann. Auch wenn ich den Befehl gebe, dass mein Pet ihn angreifen soll passiert nichts. Das Pet läuft zwar zu ihm hin, kann ihn aber nicht angreifen. Pets werden damit in der Arena so gut wie unbrauchbar!


Zugehörige Tickets

Beziehung mit RG Live WotLK 3.3.5a - Fehler #4074: [Jäger][Pet]Bleiben in der Wand steckenLive25.07.2012Aktionen
Aktionen #1

Von karn vor mehr als 10 Jahren aktualisiert

  • Status wurde von Bestätigt zu Testbereit geändert
Aktionen #2

Von karn vor mehr als 10 Jahren aktualisiert

Aktionen #3

Von Ajolkus vor mehr als 10 Jahren aktualisiert

  • Status wurde von Testbereit zu Bestätigt geändert
Aktionen #4

Von 2danger vor mehr als 10 Jahren aktualisiert

Betrifft logischerweise auch andere Pets wie Ghul, fellhunter etc., diese bleiben einfach vor der Ecke der Pillar stehen, während das Target sich dahinter befindet.

Aktionen #5

Von 2danger vor etwa 10 Jahren aktualisiert

  • Thema wurde von [Jäger] Ziel vom Begleiter kann sich so an Wänden postieren, das Pet ihn nicht angreifen kann zu [Pets] Pet Target positioning fehlerhaft geändert
Aktionen #6

Von karn vor mehr als 9 Jahren aktualisiert

  • Status wurde von Bestätigt zu Testbereit geändert

atm wird doch los ignoriert. wollen wir das noch "besser" oder passt es so

Aktionen #7

Von Sioni vor mehr als 9 Jahren aktualisiert

  • Zugewiesen an wurde auf 2403 gesetzt
Aktionen #8

Von Corrius vor mehr als 9 Jahren aktualisiert

  • Status wurde von Testbereit zu Neu geändert

Kein Fixcommit, also Neu.

Aktionen #9

Von sniffy vor mehr als 9 Jahren aktualisiert

  • Status wurde von Neu zu Bestätigt geändert
Aktionen #10

Von sniffy vor mehr als 9 Jahren aktualisiert

  • Zugewiesen an 2403 wurde gelöscht
Aktionen #11

Von sniffy vor mehr als 9 Jahren aktualisiert

Pets sollten zu Gegnern / Freundlichen Zielen hinlaufen, wenn man Spells auf sie castet. Zb. bei Magie bannen vom Teufelsjäger. Der Spell wird benutzt und das Pet läuft dann zu seinem Ziel und sobald es in LoS zu seinem Ziel ist, sollte es gewirkt werden.

Aktionen #14

Von Rushor vor mehr als 8 Jahren aktualisiert

  • Thema wurde von [Pets] Pet Target positioning fehlerhaft zu [Pets] Pet Target positioning fehlerhaft | Pet-Bewegung geändert

Insbesondere beim Felhunter ist mir aufgefallen, dass es Ziele mit Autoattack hinter Hindernissen angreift.(korrekt)
Ist das Ziel aber freundlich und der Felhunter soll ihn dispellen, sollte es korrekterweiße genauso ablaufen wie bei einem normalen Angriff auf einen Gegner.
Das Pet läuft um das Hindernis herum, dispellt und läuft zurück. Das trifft leider nicht zu. Zurzeit ist es so, dass das Pet stehen bleibt und nichts macht.
Das selbe sollte mit Zaubersperre sein. Da sollte das Pet um das Hindernis herumm rennen, dann Zaubersperre casten und wider zurück laufen. Auch hier passiert nichts, weil der Gegner nich in LoS ist.
Kenne das nur von AT und hab keine Links gefunden, wo man es gut sieht.

Aktionen #15

Von Rushor vor mehr als 8 Jahren aktualisiert

  • Thema wurde von [Pets] Pet Target positioning fehlerhaft | Pet-Bewegung zu [Mechanik][Pets] Pet Target positioning fehlerhaft | Pet-Bewegung geändert
Aktionen #16

Von ediurdsettog vor etwa 8 Jahren aktualisiert

Gleiches auch bei Succubus. Wenn ich Verführung auf ein Target caste, das nicht in LoS ist, sollte es automatisch hinlaufen(wie petattack) und sobald es in LoS ist verführen.

Aktionen #17

Von Rushor vor etwa 8 Jahren aktualisiert

  • Übergeordnetes Ticket wurde auf #5963 gesetzt

https://github.com/TrinityCore/TrinityCore/pull/16492

diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 8acf6b9..afe7ae0 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -134,8 +134,7 @@ void PetAI::UpdateAI(uint32 diff)
     // Autocast (cast only in combat or persistent spells in any state)
     if (!me->HasUnitState(UNIT_STATE_CASTING))
     {
-        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
-        TargetSpellList targetSpellStore;
+        targetSpellStore.clear();

         for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
         {
@@ -222,7 +221,7 @@ void PetAI::UpdateAI(uint32 diff)
             }
         }

-        //found units to cast on to
+        // found units to cast on to
         if (!targetSpellStore.empty())
         {
             uint32 index = urand(0, targetSpellStore.size() - 1);
@@ -471,7 +470,7 @@ void PetAI::DoAttack(Unit* target, bool chase)
             ClearCharmInfoFlags();
             me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
             me->GetMotionMaster()->Clear();
-            me->GetMotionMaster()->MoveChase(target);
+            me->GetMotionMaster()->MoveChase(target, me->GetPetChaseDistance());
         }
         else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
         {
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index 9c33baa..19ded2b 100644
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -25,6 +25,8 @@
 class Creature;
 class Spell;

+typedef std::vector<std::pair<Unit*, Spell*>> TargetSpellList;
+
 class PetAI : public CreatureAI
 {
     public:
@@ -65,6 +67,8 @@ class PetAI : public CreatureAI
         void DoAttack(Unit* target, bool chase);
         bool CanAttack(Unit* target);
         void ClearCharmInfoFlags();
+
+        TargetSpellList targetSpellStore;
 };
 #endif

diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 8711cd1..8b82ba6 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -2500,6 +2500,28 @@ uint32 Creature::GetPetAutoSpellOnPos(uint8 pos) const
         return m_charmInfo->GetCharmSpell(pos)->GetAction();
 }

+float Creature::GetPetChaseDistance() const
+{
+    float range = MELEE_RANGE;
+
+    for (uint8 i = 0; i < GetPetAutoSpellSize(); ++i)
+    {
+        uint32 spellID = GetPetAutoSpellOnPos(i);
+        if (!spellID)
+            continue;
+
+        if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID))
+        {
+            if (spellInfo->GetRecoveryTime() == 0 &&  // No cooldown
+                    spellInfo->RangeEntry->ID != 1 /*Self*/ && spellInfo->RangeEntry->ID != 2 /*Combat Range*/ &&  // Range bigger than melee
+                        range < spellInfo->GetMaxRange(true))  // Bigger than previous
+                range = spellInfo->RangeEntry->minRangeHostile;
+        }
+    }
+
+    return range;
+}
+
 void Creature::SetPosition(float x, float y, float z, float o)
 {
     // prevent crash when a bad coord is sent by the client
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 49bd854..b70a56d 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -630,6 +630,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
         void setRegeneratingHealth(bool regenHealth) { m_regenHealth = regenHealth; }
         virtual uint8 GetPetAutoSpellSize() const { return MAX_SPELL_CHARM; }
         virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const;
+        float GetPetChaseDistance() const;

         void SetPosition(float x, float y, float z, float o);
         void SetPosition(const Position &pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); }

Aktionen #18

Von Rushor vor etwa 8 Jahren aktualisiert

https://github.com/healthstone/RE/commit/55e6f6f2340b016a2167e95a13ff5714fdc2757a

diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 0da63c5..9e2c50a 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -37,7 +37,7 @@
 Pet::Pet(Player* owner, PetType type) :
     Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false),
     m_happinessTimer(7500), m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
-    m_declinedname(NULL)
+    m_declinedname(NULL), tempspell(0), temptarget(NULL)
 {
     ASSERT(GetOwner());

@@ -621,6 +621,29 @@ void Pet::Update(uint32 diff)
                 }
             }

+            if (temptarget && tempspell != 0)
+            {
+                if (GetVictim() == temptarget && EnsureVictim()->IsAlive())
+                {
+                    if (IsWithinLOSInMap(temptarget))
+                    {
+                        SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(tempspell);
+
+                        if (GetVictim() && !GetSpellHistory()->HasGlobalCooldown(spellInfo) && !GetSpellHistory()->HasCooldown(tempspell))
+                        {
+                            CastSpell(GetVictim(), tempspell, true);
+                            tempspell = 0;
+                            temptarget = nullptr;
+                        }
+                    }
+                }
+                else
+                {
+                    tempspell = 0;
+                    temptarget = nullptr;
+                }
+            }
+
             if (getPetType() != HUNTER_PET)
                 break;

@@ -1918,6 +1941,24 @@ void Pet::CastPetAura(PetAura const* aura)
         CastSpell(this, auraId, true);
 }

+void Pet::CastWhenWillAvailable(Unit* target, uint32 spellid)
+{
+    if (!spellid)
+        return;
+
+    if (!target)
+        return;
+
+    temptarget = target;
+    tempspell = spellid;
+}
+
+void Pet::ClearCastWhenWillAvailable()
+{
+    temptarget = nullptr;
+    tempspell = 0;
+}
+
 bool Pet::IsPetAura(Aura const* aura)
 {
     Player* owner = GetOwner();
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index b0863a3..ec5922b 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -107,6 +107,9 @@ class Pet : public Guardian
         void CastPetAura(PetAura const* aura);
         bool IsPetAura(Aura const* aura);

+        void CastWhenWillAvailable(Unit* target, uint32 spellid);
+        void ClearCastWhenWillAvailable();
+
         void _LoadSpellCooldowns();
         void _LoadAuras(uint32 timediff);
         void _SaveAuras(SQLTransaction& trans);
@@ -147,6 +150,8 @@ class Pet : public Guardian
         Player* GetOwner() const;

     protected:
+        Unit*  temptarget;
+        uint32  tempspell;
         uint32  m_happinessTimer;
         PetType m_petType;
         int32   m_duration;                                 // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 8bfb007..77da6d9 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -167,11 +167,13 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
                     charmInfo->SetIsFollowing(false);
                     charmInfo->SetIsReturning(false);
                     charmInfo->SaveStayPosition();
+                    pet->ToPet()->ClearCastWhenWillAvailable();
                     break;
                 case COMMAND_FOLLOW:                        //spellid=1792  //FOLLOW
                     pet->AttackStop();
                     pet->InterruptNonMeleeSpells(false);
                     pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, pet->GetFollowAngle());
+                    pet->ToPet()->ClearCastWhenWillAvailable();
                     charmInfo->SetCommandState(COMMAND_FOLLOW);

                     charmInfo->SetIsCommandAttack(false);
@@ -271,6 +273,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
             {
                 case REACT_PASSIVE:                         //passive
                     pet->AttackStop();
+                    pet->ToPet()->ClearCastWhenWillAvailable();
                     // no break;
                 case REACT_DEFENSIVE:                       //recovery
                 case REACT_AGGRESSIVE:                      //activete
@@ -371,6 +374,82 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe

                 spell->prepare(&(spell->m_targets));
             }
+            else if (result == SPELL_FAILED_LINE_OF_SIGHT)
+            {
+                if (pet->isPossessed() || pet->IsVehicle()) /// @todo: confirm this check
+                    Spell::SendCastResult(GetPlayer(), spellInfo, 0, result);
+                else
+                    spell->SendPetCastResult(SPELL_FAILED_DONT_REPORT);
+
+                unit_target = spell->m_targets.GetUnitTarget();
+
+                if (!pet->GetSpellHistory()->HasCooldown(spellid))
+                    pet->GetSpellHistory()->ResetCooldown(spellid, true);
+
+                spell->finish(false);
+                delete spell;                
+
+                // Can't attack if owner is pacified
+                if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY))
+                {
+                    //pet->SendPetCastFail(spellid, SPELL_FAILED_PACIFIED);
+                    /// @todo Send proper error message to client
+                    return;
+                }
+
+                // only place where pet can be player
+                Unit* TargetUnit = ObjectAccessor::GetUnit(*_player, guid2);
+                if (!TargetUnit)
+                    return;
+
+                if (Unit* owner = pet->GetOwner())
+                    if (!owner->IsValidAttackTarget(TargetUnit))
+                        return;
+
+                pet->ClearUnitState(UNIT_STATE_FOLLOW);
+                // This is true if pet has no target or has target but targets differs.
+                if (pet->GetVictim() != TargetUnit || (pet->GetVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack()))
+                {
+                    if (pet->GetVictim())
+                        pet->AttackStop();
+
+                    if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature()->IsAIEnabled)
+                    {
+                        charmInfo->SetIsCommandAttack(true);
+                        charmInfo->SetIsAtStay(false);
+                        charmInfo->SetIsFollowing(false);
+                        charmInfo->SetIsCommandFollow(false);
+                        charmInfo->SetIsReturning(false);
+
+                        pet->ToCreature()->AI()->AttackStart(TargetUnit);
+
+                        //10% chance to play special pet attack talk, else growl
+                        if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
+                            pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
+                        else
+                        {
+                            // 90% chance for pet and 100% chance for charmed creature
+                            pet->SendPetAIReaction(guid1);
+                        }
+                    }
+                    else                                // charmed player
+                    {
+                        if (pet->GetVictim() && pet->GetVictim() != TargetUnit)
+                            pet->AttackStop();
+
+                        charmInfo->SetIsCommandAttack(true);
+                        charmInfo->SetIsAtStay(false);
+                        charmInfo->SetIsFollowing(false);
+                        charmInfo->SetIsCommandFollow(false);
+                        charmInfo->SetIsReturning(false);
+
+                        pet->Attack(TargetUnit, true);
+                        pet->SendPetAIReaction(guid1);
+                    }
+
+                    pet->ToPet()->CastWhenWillAvailable(unit_target, spellid);
+                }
+            }
             else
             {
                 if (pet->isPossessed() || pet->IsVehicle()) /// @todo: confirm this check

Aktionen #20

Von Rushor vor etwa 8 Jahren aktualisiert

https://gist.github.com/Keader/0b2ad7dec23fdc2b8191

diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 0da63c5..0de39d4 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -31,13 +31,14 @@
 #include "Util.h" 
 #include "Group.h" 
 #include "WorldSession.h" 
+#include "CreatureAI.h" 

 #define PET_XP_FACTOR 0.05f

 Pet::Pet(Player* owner, PetType type) :
     Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false),
     m_happinessTimer(7500), m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
-    m_declinedname(NULL)
+    m_declinedname(NULL), m_tempspell(0), m_tempspellTarget(NULL), m_tempoldTarget(NULL), m_tempspellIsPositive(false)
 {
     ASSERT(GetOwner());

@@ -621,6 +622,112 @@ void Pet::Update(uint32 diff)
                 }
             }

+            if (m_tempspell != 0)
+            {
+                Unit* tempspellTarget = m_tempspellTarget;
+                Unit* tempoldTarget = m_tempoldTarget;
+                bool tempspellIsPositive = m_tempspellIsPositive;
+                uint32 tempspell = m_tempspell;
+                Unit* charmer = GetCharmerOrOwner();
+                if (!charmer)
+                    return;
+
+                if (tempspellTarget && tempspellTarget->IsAlive())
+                {
+                    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(tempspell);
+                    if (!spellInfo)
+                        return;
+                    float max_range = GetSpellMaxRangeForTarget(tempspellTarget, spellInfo);
+
+                    if (IsWithinLOSInMap(tempspellTarget) && GetDistance(tempspellTarget) < max_range)
+                    {
+                        if (tempspellTarget && !GetSpellHistory()->HasGlobalCooldown(spellInfo) && !GetSpellHistory()->HasCooldown(tempspell))
+                        {
+                            StopMoving();
+                            GetMotionMaster()->Clear(false);
+                            GetMotionMaster()->MoveIdle();
+
+                            GetCharmInfo()->SetIsCommandAttack(false);
+                            GetCharmInfo()->SetIsAtStay(true);
+                            GetCharmInfo()->SetIsCommandFollow(false);
+                            GetCharmInfo()->SetIsFollowing(false);
+                            GetCharmInfo()->SetIsReturning(false);
+                            GetCharmInfo()->SaveStayPosition();
+
+                            CastSpell(tempspellTarget, tempspell, true);
+                            m_tempspell = 0;
+                            m_tempspellTarget = NULL;
+
+                            if (tempspellIsPositive)
+                            {
+                                if (tempoldTarget && tempoldTarget->IsAlive())
+                                {
+                                    GetCharmInfo()->SetIsCommandAttack(true);
+                                    GetCharmInfo()->SetIsAtStay(false);
+                                    GetCharmInfo()->SetIsFollowing(false);
+                                    GetCharmInfo()->SetIsCommandFollow(false);
+                                    GetCharmInfo()->SetIsReturning(false);
+
+                                    if (ToCreature() && ToCreature()->IsAIEnabled)
+                                        ToCreature()->AI()->AttackStart(tempoldTarget);
+                                }
+                                else
+                                {
+                                    GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
+                                    GetCharmInfo()->SetIsCommandAttack(false);
+                                    GetCharmInfo()->SetIsAtStay(false);
+                                    GetCharmInfo()->SetIsReturning(true);
+                                    GetCharmInfo()->SetIsCommandFollow(true);
+                                    GetCharmInfo()->SetIsFollowing(false);
+                                    GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, GetFollowAngle());
+                                }
+
+                                m_tempoldTarget = NULL;
+                                m_tempspellIsPositive = false;
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    m_tempspell = 0;
+                    m_tempspellTarget = NULL;
+                    m_tempoldTarget = NULL;
+                    m_tempspellIsPositive = false;
+
+                    Unit* victim = charmer->GetVictim();
+                    if (victim && victim->IsAlive())
+                    {
+                        StopMoving();
+                        GetMotionMaster()->Clear(false);
+                        GetMotionMaster()->MoveIdle();
+
+                        GetCharmInfo()->SetIsCommandAttack(true);
+                        GetCharmInfo()->SetIsAtStay(false);
+                        GetCharmInfo()->SetIsFollowing(false);
+                        GetCharmInfo()->SetIsCommandFollow(false);
+                        GetCharmInfo()->SetIsReturning(false);
+
+                        if (ToCreature() && ToCreature()->IsAIEnabled)
+                            ToCreature()->AI()->AttackStart(victim);
+                    }
+                    else
+                    {
+                        StopMoving();
+                        GetMotionMaster()->Clear(false);
+                        GetMotionMaster()->MoveIdle();
+
+                        GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
+                        GetCharmInfo()->SetIsCommandAttack(false);
+                        GetCharmInfo()->SetIsAtStay(false);
+                        GetCharmInfo()->SetIsReturning(true);
+                        GetCharmInfo()->SetIsCommandFollow(true);
+                        GetCharmInfo()->SetIsFollowing(false);
+                        GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, GetFollowAngle());
+                    }
+                }
+            }
+
             if (getPetType() != HUNTER_PET)
                 break;

@@ -1918,6 +2025,30 @@ void Pet::CastPetAura(PetAura const* aura)
         CastSpell(this, auraId, true);
 }

+void Pet::CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarget, bool spellIsPositive)
+{
+    if (!spellid)
+        return;
+
+    if (!spellTarget)
+        return;
+
+    m_tempspellTarget = spellTarget;
+    m_tempspell = spellid;
+    m_tempspellIsPositive = spellIsPositive;
+
+    if (oldTarget)
+        m_tempoldTarget = oldTarget;
+}
+
+void Pet::ClearCastWhenWillAvailable()
+{
+    m_tempspellIsPositive = false;
+    m_tempspell = 0;
+    m_tempspellTarget = NULL;
+    m_tempoldTarget = NULL;
+}
+
 bool Pet::IsPetAura(Aura const* aura)
 {
     Player* owner = GetOwner();
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index b0863a3..40aa963 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -106,6 +106,9 @@ class Pet : public Guardian
         void CastPetAuras(bool current);
         void CastPetAura(PetAura const* aura);
         bool IsPetAura(Aura const* aura);
+       
+        void CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarget, bool spellIsPositive = false);
+        void ClearCastWhenWillAvailable();

         void _LoadSpellCooldowns();
         void _LoadAuras(uint32 timediff);
@@ -155,6 +158,10 @@ class Pet : public Guardian
         uint32  m_focusRegenTimer;

         DeclinedName *m_declinedname;
+        Unit*   m_tempspellTarget;
+        Unit*   m_tempoldTarget;
+        bool    m_tempspellIsPositive;
+        uint32  m_tempspell;

     private:
         void SaveToDB(uint32, uint8, uint32) override                // override of Creature::SaveToDB     - must not be called
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 8bfb007..efcbbba 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -167,11 +167,15 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
                     charmInfo->SetIsFollowing(false);
                     charmInfo->SetIsReturning(false);
                     charmInfo->SaveStayPosition();
+                    if (pet->ToPet())
+                        pet->ToPet()->ClearCastWhenWillAvailable();
                     break;
                 case COMMAND_FOLLOW:                        //spellid=1792  //FOLLOW
                     pet->AttackStop();
                     pet->InterruptNonMeleeSpells(false);
                     pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, pet->GetFollowAngle());
+                    if (pet->ToPet())
+                        pet->ToPet()->ClearCastWhenWillAvailable();
                     charmInfo->SetCommandState(COMMAND_FOLLOW);

                     charmInfo->SetIsCommandAttack(false);
@@ -271,6 +275,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
             {
                 case REACT_PASSIVE:                         //passive
                     pet->AttackStop();
+                    if (pet->ToPet())
+                        pet->ToPet()->ClearCastWhenWillAvailable();
                     // no break;
                 case REACT_DEFENSIVE:                       //recovery
                 case REACT_AGGRESSIVE:                      //activete
@@ -371,6 +377,130 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe

                 spell->prepare(&(spell->m_targets));
             }
+            else if (pet->ToPet() && (result == SPELL_FAILED_LINE_OF_SIGHT || result == SPELL_FAILED_OUT_OF_RANGE))
+            {
+                unit_target = spell->m_targets.GetUnitTarget();
+                bool haspositiveeffect = false;
+
+                if (!unit_target)
+                    return;
+
+                // search positive effects for spell
+                for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+                {
+                    if (spellInfo->_IsPositiveEffect(i, true))
+                    {
+                        haspositiveeffect = true;
+                        break;
+                    }
+                }
+
+                if (pet->isPossessed() || pet->IsVehicle())
+                    Spell::SendCastResult(GetPlayer(), spellInfo, 0, result);
+                else if (GetPlayer()->IsFriendlyTo(unit_target) && !haspositiveeffect)
+                    spell->SendPetCastResult(SPELL_FAILED_TARGET_FRIENDLY);
+                else
+                    spell->SendPetCastResult(SPELL_FAILED_DONT_REPORT);
+
+                if (!pet->GetSpellHistory()->HasCooldown(spellid))
+                    pet->GetSpellHistory()->ResetCooldown(spellid, true);
+
+                spell->finish(false);
+                delete spell;
+
+                if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY))
+                    return;
+
+                bool tempspellIsPositive = false;
+
+                if (!GetPlayer()->IsFriendlyTo(unit_target))
+                {
+                    // only place where pet can be player
+                    Unit* TargetUnit = ObjectAccessor::GetUnit(*_player, guid2);
+                    if (!TargetUnit)
+                        return;
+
+                    if (Unit* owner = pet->GetOwner())
+                        if (!owner->IsValidAttackTarget(TargetUnit))
+                            return;
+
+                    pet->ClearUnitState(UNIT_STATE_FOLLOW);
+                    // This is true if pet has no target or has target but targets differs.
+                    if (pet->GetVictim() != TargetUnit || (pet->GetVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack()))
+                    {
+                        if (pet->GetVictim())
+                            pet->AttackStop();
+
+                        if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature() && pet->ToCreature()->IsAIEnabled)
+                        {
+                            charmInfo->SetIsCommandAttack(true);
+                            charmInfo->SetIsAtStay(false);
+                            charmInfo->SetIsFollowing(false);
+                            charmInfo->SetIsCommandFollow(false);
+                            charmInfo->SetIsReturning(false);
+
+                            pet->ToCreature()->AI()->AttackStart(TargetUnit);
+
+                            if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
+                                pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
+                            else
+                                pet->SendPetAIReaction(guid1);
+                        }
+                        else // charmed player
+                        {
+                            if (pet->GetVictim() && pet->GetVictim() != TargetUnit)
+                                pet->AttackStop();
+
+                            charmInfo->SetIsCommandAttack(true);
+                            charmInfo->SetIsAtStay(false);
+                            charmInfo->SetIsFollowing(false);
+                            charmInfo->SetIsCommandFollow(false);
+                            charmInfo->SetIsReturning(false);
+
+                            pet->Attack(TargetUnit, true);
+                            pet->SendPetAIReaction(guid1);
+                        }
+
+                        pet->ToPet()->CastWhenWillAvailable(spellid, unit_target, NULL, tempspellIsPositive);
+                    }
+                }
+                else if (haspositiveeffect)
+                {
+                    bool tempspellIsPositive = true;
+                    pet->ClearUnitState(UNIT_STATE_FOLLOW);
+                    // This is true if pet has no target or has target but targets differs.
+                    Unit* victim = pet->GetVictim();
+                    if (victim)
+                    {
+                        pet->AttackStop();
+                    }
+                    else
+                        victim = NULL;
+
+                    if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature() && pet->ToCreature()->IsAIEnabled)
+                    {
+                        pet->StopMoving();
+                        pet->GetMotionMaster()->Clear();
+
+                        charmInfo->SetIsCommandAttack(false);
+                        charmInfo->SetIsAtStay(false);
+                        charmInfo->SetIsFollowing(false);
+                        charmInfo->SetIsCommandFollow(false);
+                        charmInfo->SetIsReturning(false);
+
+                        pet->GetMotionMaster()->MoveChase(unit_target);
+
+                        if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && urand(0, 100) < 10)
+                            pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
+                        else
+                        {
+                            pet->SendPetAIReaction(guid1);
+                        }
+
+                        pet->ToPet()->CastWhenWillAvailable(spellid, unit_target, victim, tempspellIsPositive);
+                    }
+                }
+            }
             else
             {
                 if (pet->isPossessed() || pet->IsVehicle()) /// @todo: confirm this check

Aktionen #21

Von Rushor vor etwa 8 Jahren aktualisiert

  • Status wurde von Bestätigt zu Testbereit geändert
  • Zugewiesen an wurde auf 2403 gesetzt

drin - sollte es eine verbesserung sein mit mehr vorteilen als neuen nachteilen > ready

Aktionen #22

Von Rushor vor etwa 8 Jahren aktualisiert

crashfix

Aktionen #23

Von Rushor vor etwa 8 Jahren aktualisiert

/push wäre schön wenn es nächsten mittwoch live geht :)

Aktionen #24

Von Anonym vor etwa 8 Jahren aktualisiert

  • Status wurde von Testbereit zu Ready geändert
  • Update Text Deutsch aktualisiert (Vergleich)

In allen Arenas mit verschiedenen Pets getestet. Pets laufen jetzt an das Ziel ran, um Fähigkeiten zu casten und lassen sich auch nicht mehr verbuggen.

Aktionen #25

Von Daejiv vor etwa 8 Jahren aktualisiert

  • Status wurde von Ready zu Live geändert
Aktionen #27

Von Left4Info vor fast 6 Jahren aktualisiert

  • Tags wurde auf Classes gesetzt
Aktionen

Auch abrufbar als: Atom PDF