diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp index a0a79b949..c5dd44fe2 100644 --- a/src/server/scripts/Pet/pet_dk.cpp +++ b/src/server/scripts/Pet/pet_dk.cpp @@ -49,292 +49,228 @@ enum DeathKnightSpells SPELL_GHOUL_FRENZY = 62218, }; -class npc_pet_dk_ebon_gargoyle : public CreatureScript +struct npc_pet_dk_ebon_gargoyle : ScriptedAI { -public: - npc_pet_dk_ebon_gargoyle() : CreatureScript("npc_pet_dk_ebon_gargoyle") { } - - struct npc_pet_dk_ebon_gargoyleAI : ScriptedAI + npc_pet_dk_ebon_gargoyle(Creature* creature) : ScriptedAI(creature) { - npc_pet_dk_ebon_gargoyleAI(Creature* creature) : ScriptedAI(creature) - { - _despawnTimer = 36000; // 30 secs + 4 fly out + 2 initial attack timer - _despawning = false; - _initialSelection = true; - _targetGUID.Clear(); - } + _despawnTimer = 36000; // 30 secs + 4 fly out + 2 initial attack timer + _despawning = false; + _initialSelection = true; + _targetGUID.Clear(); + } - void MovementInform(uint32 type, uint32 point) override + void MovementInform(uint32 type, uint32 point) override + { + if (type == POINT_MOTION_TYPE && point == 1) { - if (type == POINT_MOTION_TYPE && point == 1) + me->SetCanFly(false); + me->SetDisableGravity(false); + } + } + + void InitializeAI() override + { + ScriptedAI::InitializeAI(); + Unit* owner = me->GetOwner(); + if (!owner) + return; + + // Xinef: Night of the Dead avoidance + if (Aura* aur = me->GetAura(SPELL_DK_NIGHT_OF_THE_DEAD)) + if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_DEATHKNIGHT, 2718, 0)) + if (aur->GetEffect(0)) + aur->GetEffect(0)->SetAmount(-aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue()); + + me->SetCanFly(true); + me->SetDisableGravity(true); + + float tz = me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), true, MAX_FALL_DISTANCE); + me->GetMotionMaster()->MoveCharge(me->GetPositionX(), me->GetPositionY(), tz, 7.0f, 1); + me->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD); + _selectionTimer = 2000; + _initialCastTimer = 0; + } + + void MySelectNextTarget() + { + Unit* owner = me->GetOwner(); + if (owner && owner->IsPlayer() && (!me->GetVictim() || me->GetVictim()->IsImmunedToSpell(sSpellMgr->GetSpellInfo(51963)) || !me->IsValidAttackTarget(me->GetVictim()) || !owner->CanSeeOrDetect(me->GetVictim()))) + { + Unit* selection = owner->ToPlayer()->GetSelectedUnit(); + if (selection && selection != me->GetVictim() && me->IsValidAttackTarget(selection)) { - me->SetCanFly(false); - me->SetDisableGravity(false); + me->GetMotionMaster()->Clear(false); + SetGazeOn(selection); + } + + else if (!me->GetVictim() || !owner->CanSeeOrDetect(me->GetVictim())) + { + me->CombatStop(true); + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, 0.0f); + RemoveTargetAura(); } } + } - void InitializeAI() override + void AttackStart(Unit* who) override + { + RemoveTargetAura(); + _targetGUID = who->GetGUID(); + me->AddAura(SPELL_DK_SUMMON_GARGOYLE_1, who); + ScriptedAI::AttackStart(who); + } + + void RemoveTargetAura() + { + if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID)) + target->RemoveAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetGUID()); + } + + void Reset() override + { + _selectionTimer = 0; + me->SetReactState(REACT_PASSIVE); + MySelectNextTarget(); + } + + // Fly away when dismissed + void FlyAway() + { + RemoveTargetAura(); + + // Stop Fighting + me->CombatStop(true); + me->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, true); + + // Sanctuary + me->CastSpell(me, SPELL_DK_SANCTUARY, true); + me->SetReactState(REACT_PASSIVE); + + me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + me->SetSpeed(MOVE_RUN, 1.0f, true); + float x = me->GetPositionX() + 20 * cos(me->GetOrientation()); + float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation()); + float z = me->GetPositionZ() + 40; + me->DisableSpline(); + me->GetMotionMaster()->Clear(false); + + me->GetMotionMaster()->MoveCharge(x, y, z, 7.0f, 1); + me->SetCanFly(true); + me->SetDisableGravity(true); + + _despawning = true; + } + + void UpdateAI(uint32 diff) override + { + if (_initialSelection) { - ScriptedAI::InitializeAI(); - Unit* owner = me->GetOwner(); - if (!owner) + _initialSelection = false; + // Find victim of Summon Gargoyle spell + std::list targets; + Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 50.0f); + Acore::UnitListSearcher searcher(me, targets, u_check); + Cell::VisitAllObjects(me, searcher, 50.0f); + for (auto const& target : targets) + if (target->GetAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID())) + { + target->RemoveAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID()); + SetGazeOn(target); + _targetGUID = target->GetGUID(); + break; + } + } + if (_despawnTimer > 4000) + { + _despawnTimer -= diff; + if (!UpdateVictimWithGaze()) + { + MySelectNextTarget(); return; - - // Xinef: Night of the Dead avoidance - if (Aura* aur = me->GetAura(SPELL_DK_NIGHT_OF_THE_DEAD)) - if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_DEATHKNIGHT, 2718, 0)) - { - if (aur->GetEffect(0)) - { - aur->GetEffect(0)->SetAmount(-aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue()); - } - } - - me->SetCanFly(true); - me->SetDisableGravity(true); - - float tz = me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), true, MAX_FALL_DISTANCE); - me->GetMotionMaster()->MoveCharge(me->GetPositionX(), me->GetPositionY(), tz, 7.0f, 1); - me->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD); - _selectionTimer = 2000; - _initialCastTimer = 0; - } - - void MySelectNextTarget() - { - Unit* owner = me->GetOwner(); - if (owner && owner->IsPlayer() && (!me->GetVictim() || me->GetVictim()->IsImmunedToSpell(sSpellMgr->GetSpellInfo(51963)) || !me->IsValidAttackTarget(me->GetVictim()) || !owner->CanSeeOrDetect(me->GetVictim()))) - { - Unit* selection = owner->ToPlayer()->GetSelectedUnit(); - if (selection && selection != me->GetVictim() && me->IsValidAttackTarget(selection)) - { - me->GetMotionMaster()->Clear(false); - SetGazeOn(selection); - } - - else if (!me->GetVictim() || !owner->CanSeeOrDetect(me->GetVictim())) - { - me->CombatStop(true); - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, 0.0f); - RemoveTargetAura(); - } } - } - void AttackStart(Unit* who) override - { - RemoveTargetAura(); - _targetGUID = who->GetGUID(); - me->AddAura(SPELL_DK_SUMMON_GARGOYLE_1, who); - ScriptedAI::AttackStart(who); - } - - void RemoveTargetAura() - { - if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID)) - target->RemoveAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetGUID()); - } - - void Reset() override - { - _selectionTimer = 0; - me->SetReactState(REACT_PASSIVE); - MySelectNextTarget(); - } - - // Fly away when dismissed - void FlyAway() - { - RemoveTargetAura(); - - // Stop Fighting - me->CombatStop(true); - me->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, true); - - // Sanctuary - me->CastSpell(me, SPELL_DK_SANCTUARY, true); - me->SetReactState(REACT_PASSIVE); - - me->SetSpeed(MOVE_FLIGHT, 1.0f, true); - me->SetSpeed(MOVE_RUN, 1.0f, true); - float x = me->GetPositionX() + 20 * cos(me->GetOrientation()); - float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation()); - float z = me->GetPositionZ() + 40; - me->DisableSpline(); - me->GetMotionMaster()->Clear(false); - - me->GetMotionMaster()->MoveCharge(x, y, z, 7.0f, 1); - me->SetCanFly(true); - me->SetDisableGravity(true); - - _despawning = true; - } - - void UpdateAI(uint32 diff) override - { - if (_initialSelection) + _initialCastTimer += diff; + _selectionTimer += diff; + if (_selectionTimer >= 1000) { - _initialSelection = false; - // Find victim of Summon Gargoyle spell - std::list targets; - Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 50.0f); - Acore::UnitListSearcher searcher(me, targets, u_check); - Cell::VisitAllObjects(me, searcher, 50.0f); - for (std::list::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) - if ((*iter)->GetAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID())) - { - (*iter)->RemoveAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID()); - SetGazeOn(*iter); - _targetGUID = (*iter)->GetGUID(); - break; - } + MySelectNextTarget(); + _selectionTimer = 0; } - if (_despawnTimer > 4000) - { + if (_initialCastTimer >= 2000 && !me->HasUnitState(UNIT_STATE_CASTING | UNIT_STATE_LOST_CONTROL) && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE) + me->CastSpell(me->GetVictim(), 51963, false); + } + else + { + if (!_despawning) + FlyAway(); + + if (_despawnTimer > diff) _despawnTimer -= diff; - if (!UpdateVictimWithGaze()) - { - MySelectNextTarget(); - return; - } - - _initialCastTimer += diff; - _selectionTimer += diff; - if (_selectionTimer >= 1000) - { - MySelectNextTarget(); - _selectionTimer = 0; - } - if (_initialCastTimer >= 2000 && !me->HasUnitState(UNIT_STATE_CASTING | UNIT_STATE_LOST_CONTROL) && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE) - me->CastSpell(me->GetVictim(), 51963, false); - } else - { - if (!_despawning) - FlyAway(); - - if (_despawnTimer > diff) - _despawnTimer -= diff; - else - me->DespawnOrUnsummon(); - } + me->DespawnOrUnsummon(); } + } - private: - ObjectGuid _targetGUID; - uint32 _despawnTimer; - uint32 _selectionTimer; - uint32 _initialCastTimer; - bool _despawning; - bool _initialSelection; - }; +private: + ObjectGuid _targetGUID; + uint32 _despawnTimer; + uint32 _selectionTimer; + uint32 _initialCastTimer; + bool _despawning; + bool _initialSelection; +}; - CreatureAI* GetAI(Creature* creature) const override +struct npc_pet_dk_ghoul : public CombatAI +{ + npc_pet_dk_ghoul(Creature* c) : CombatAI(c) { } + + void JustDied(Unit* /*who*/) override { - return new npc_pet_dk_ebon_gargoyleAI(creature); + if (me->IsGuardian() || me->IsSummon()) + me->ToTempSummon()->UnSummon(); } }; -class npc_pet_dk_ghoul : public CreatureScript +struct npc_pet_dk_risen_ally : public PossessedAI { -public: - npc_pet_dk_ghoul() : CreatureScript("npc_pet_dk_ghoul") { } + npc_pet_dk_risen_ally(Creature* c) : PossessedAI(c) { } - struct npc_pet_dk_ghoulAI : public CombatAI + void OnCharmed(bool apply) override { - npc_pet_dk_ghoulAI(Creature* c) : CombatAI(c) { } - - void JustDied(Unit* /*who*/) override - { - if (me->IsGuardian() || me->IsSummon()) - me->ToTempSummon()->UnSummon(); - } - }; - - CreatureAI* GetAI(Creature* pCreature) const override - { - return new npc_pet_dk_ghoulAI (pCreature); - } -}; - -class npc_pet_dk_risen_ally : public CreatureScript -{ -public: - npc_pet_dk_risen_ally() : CreatureScript("npc_pet_dk_risen_ally") { } - - struct npc_pet_dk_risen_allyAI : public PossessedAI - { - npc_pet_dk_risen_allyAI(Creature* c) : PossessedAI(c) { } - - void OnCharmed(bool apply) override - { - if (!apply) - { - if (Unit* owner = me->GetCharmerOrOwner()) + if (!apply) + if (Unit* owner = me->GetCharmerOrOwner()) + if (Player* player = owner->ToPlayer()) { - if (Player* player = owner->ToPlayer()) - { - player->RemoveAurasDueToSpell(SPELL_DK_RAISE_ALLY); // Remove Raise Ally aura - player->RemoveAurasDueToSpell(SPELL_GHOUL_FRENZY); // Remove Frenzy aura - //player->ClearResurrectRequestData(); - } + player->RemoveAurasDueToSpell(SPELL_DK_RAISE_ALLY); // Remove Raise Ally aura + player->RemoveAurasDueToSpell(SPELL_GHOUL_FRENZY); // Remove Frenzy aura + //player->ClearResurrectRequestData(); } - } - } - }; - - CreatureAI* GetAI(Creature* pCreature) const override - { - return new npc_pet_dk_risen_allyAI (pCreature); } }; -class npc_pet_dk_army_of_the_dead : public CreatureScript +struct npc_pet_dk_army_of_the_dead : public CombatAI { -public: - npc_pet_dk_army_of_the_dead() : CreatureScript("npc_pet_dk_army_of_the_dead") { } + npc_pet_dk_army_of_the_dead(Creature* creature) : CombatAI(creature) { } - struct npc_pet_dk_army_of_the_deadAI : public CombatAI + void InitializeAI() override { - npc_pet_dk_army_of_the_deadAI(Creature* creature) : CombatAI(creature) { } - - void InitializeAI() override - { - CombatAI::InitializeAI(); - ((Minion*)me)->SetFollowAngle(rand_norm() * 2 * M_PI); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_pet_dk_army_of_the_deadAI (creature); + CombatAI::InitializeAI(); + ((Minion*)me)->SetFollowAngle(rand_norm() * 2 * M_PI); } }; -class npc_pet_dk_dancing_rune_weapon : public CreatureScript +struct npc_pet_dk_dancing_rune_weapon : public NullCreatureAI { -public: - npc_pet_dk_dancing_rune_weapon() : CreatureScript("npc_pet_dk_dancing_rune_weapon") { } + npc_pet_dk_dancing_rune_weapon(Creature* creature) : NullCreatureAI(creature) { } - struct npc_pet_dk_dancing_rune_weaponAI : public NullCreatureAI + void InitializeAI() override { - npc_pet_dk_dancing_rune_weaponAI(Creature* creature) : NullCreatureAI(creature) { } + me->AddAura(SPELL_HUNTER_PET_SCALING_04, me); + if (Unit* owner = me->GetOwner()) + me->GetMotionMaster()->MoveFollow(owner, 0.01f, me->GetFollowAngle(), MOTION_SLOT_CONTROLLED); - void InitializeAI() override - { - // Xinef: Hit / Expertise scaling - me->AddAura(61017, me); - if (Unit* owner = me->GetOwner()) - me->GetMotionMaster()->MoveFollow(owner, 0.01f, me->GetFollowAngle(), MOTION_SLOT_CONTROLLED); - - NullCreatureAI::InitializeAI(); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_pet_dk_dancing_rune_weaponAI (creature); + NullCreatureAI::InitializeAI(); } }; @@ -346,12 +282,8 @@ class spell_pet_dk_gargoyle_strike : public SpellScript { int32 damage = 60; if (Unit* caster = GetCaster()) - { if (caster->GetLevel() >= 60) - { damage += (caster->GetLevel() - 60) * 4; - } - } SetEffectValue(damage); } @@ -364,10 +296,10 @@ class spell_pet_dk_gargoyle_strike : public SpellScript void AddSC_deathknight_pet_scripts() { - new npc_pet_dk_ebon_gargoyle(); - new npc_pet_dk_ghoul(); - new npc_pet_dk_risen_ally(); - new npc_pet_dk_army_of_the_dead(); - new npc_pet_dk_dancing_rune_weapon(); + RegisterCreatureAI(npc_pet_dk_ebon_gargoyle); + RegisterCreatureAI(npc_pet_dk_ghoul); + RegisterCreatureAI(npc_pet_dk_risen_ally); + RegisterCreatureAI(npc_pet_dk_army_of_the_dead); + RegisterCreatureAI(npc_pet_dk_dancing_rune_weapon); RegisterSpellScript(spell_pet_dk_gargoyle_strike); }