-
-
Save Keader/0b2ad7dec23fdc2b8191 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment