Fehler #6028
geschlossenFehler #5963: Arena
[Mechanik][Pets] Pet Target positioning fehlerhaft | Pet-Bewegung
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
Von karn vor etwa 11 Jahren aktualisiert
- Status wurde von Bestätigt zu Testbereit geändert
Von karn vor etwa 11 Jahren aktualisiert
http://www.youtube.com/watch?v=dPPJBX8CiRQ
so soll es nicht sein xD
Von Ajolkus vor etwa 11 Jahren aktualisiert
- Status wurde von Testbereit zu Bestätigt geändert
Von 2danger vor fast 11 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.
Von 2danger vor mehr als 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
Von karn vor etwa 10 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
Von Corrius vor fast 10 Jahren aktualisiert
- Status wurde von Testbereit zu Neu geändert
Kein Fixcommit, also Neu.
Von sniffy vor fast 10 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.
Von Rushor vor etwa 9 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.
Von Rushor vor fast 9 Jahren aktualisiert
- Thema wurde von [Pets] Pet Target positioning fehlerhaft | Pet-Bewegung zu [Mechanik][Pets] Pet Target positioning fehlerhaft | Pet-Bewegung geändert
Von ediurdsettog vor fast 9 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.
Von Rushor vor fast 9 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()); }
Von Rushor vor fast 9 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
Von Rushor vor mehr als 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
Von Rushor vor mehr als 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
Von Rushor vor mehr als 8 Jahren aktualisiert
/push wäre schön wenn es nächsten mittwoch live geht :)
Von Anonym vor mehr als 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.