Skip to content

Instantly share code, notes, and snippets.

@Keader
Last active March 12, 2016 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Keader/0b2ad7dec23fdc2b8191 to your computer and use it in GitHub Desktop.
Save Keader/0b2ad7dec23fdc2b8191 to your computer and use it in GitHub Desktop.
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