TrinityCore
Loading...
Searching...
No Matches
spell_hunter.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Scripts for spells with SPELLFAMILY_HUNTER, SPELLFAMILY_PET and SPELLFAMILY_GENERIC spells used by hunter players.
20 * Ordered alphabetically using scriptname.
21 * Scriptnames of files in this file should be prefixed with "spell_hun_".
22 */
23
24#include "ScriptMgr.h"
25#include "AreaTriggerAI.h"
26#include "CellImpl.h"
27#include "GridNotifiersImpl.h"
28#include "ObjectAccessor.h"
29#include "Pet.h"
30#include "SpellAuraEffects.h"
31#include "SpellHistory.h"
32#include "SpellMgr.h"
33#include "SpellScript.h"
34#include "TaskScheduler.h"
35
37{
106
111
112// 131894 - A Murder of Crows
114{
125
126 void HandleDummyTick(AuraEffect const* /*aurEff*/)
127 {
128 Unit* target = GetTarget();
129
130 if (Unit* caster = GetCaster())
131 caster->CastSpell(target, SPELL_HUNTER_A_MURDER_OF_CROWS_DAMAGE, true);
132
136 target->CastSpell(target, SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_3, true); // not a mistake, it is intended to cast twice
137 }
138
139 void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
140 {
141 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
142 if (Unit* caster = GetCaster())
143 caster->GetSpellHistory()->ResetCooldown(GetId(), true);
144 }
145
151};
152
153// 186257 - Aspect of the Cheetah
175
176// 1219162 - Aspect of the Fox (attached to 186257 - Aspect of the Cheetah)
178{
179 bool Validate(SpellInfo const* spellInfo) override
180 {
182 && ValidateSpellEffect({ { spellInfo->Id, EFFECT_2 } })
184 }
185
186 bool Load() override
187 {
189 }
190
191 static void HandleCastWhileWalking(SpellScript const&, WorldObject*& target)
192 {
193 target = nullptr;
194 }
195
200};
201
202// 186265 - Aspect of the Turtle
226
227// 109248 - Binding Shot
245
246// 109248 - Binding Shot
247// Id - 1524
249{
251
252 void OnInitialize() override
253 {
254 if (Unit* caster = at->GetCaster())
255 for (AreaTrigger* other : caster->GetAreaTriggers(SPELL_HUNTER_BINDING_SHOT))
256 other->SetDuration(0);
257 }
258
259 void OnCreate(Spell const* /*creatingSpell*/) override
260 {
261 _scheduler.Schedule(1s, [this](TaskContext& task)
262 {
263 for (ObjectGuid const& guid : at->GetInsideUnits())
264 {
265 Unit* unit = ObjectAccessor::GetUnit(*at, guid);
267 continue;
268
270 }
271
272 task.Repeat(1s);
273 });
274 }
275
276 void OnUnitEnter(Unit* unit) override
277 {
278 if (Unit* caster = at->GetCaster())
279 {
280 if (caster->IsValidAttackTarget(unit) && !unit->HasAura(SPELL_HUNTER_BINDING_SHOT_IMMUNE, caster->GetGUID()))
281 {
284 }
285 }
286 }
287
288 void OnUnitExit(Unit* unit, AreaTriggerExitReason /*reason*/) override
289 {
291
292 if (at->IsRemoved())
293 return;
294
295 if (Unit* caster = at->GetCaster())
296 {
297 if (caster->IsValidAttackTarget(unit) && !unit->HasAura(SPELL_HUNTER_BINDING_SHOT_IMMUNE, caster->GetGUID()))
298 {
301 }
302 }
303 }
304
305 void OnUpdate(uint32 diff) override
306 {
307 _scheduler.Update(diff);
308 }
309
310private:
312};
313
314// 204089 - Bullseye
316{
317 static bool CheckEffectProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
318 {
319 return eventInfo.GetActionTarget()->HealthBelowPct(aurEff->GetAmount());
320 }
321
326};
327
328// 378750 - Cobra Sting
330{
331 bool Validate(SpellInfo const* spellInfo) override
332 {
333 return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } });
334 }
335
336 bool RollProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*procInfo*/)
337 {
338 return roll_chance(GetEffect(EFFECT_1)->GetAmount());
339 }
340
345};
346
347// 5116 - Concussive Shot (attached to 193455 - Cobra Shot and 56641 - Steady Shot)
349{
350 bool Validate(SpellInfo const* /*spellInfo*/) override
351 {
354 }
355
356 void HandleDuration(SpellEffIndex /*effIndex*/) const
357 {
358 Unit* caster = GetCaster();
359
360 if (Aura* concussiveShot = GetHitUnit()->GetAura(SPELL_HUNTER_CONCUSSIVE_SHOT, caster->GetGUID()))
361 {
362 SpellInfo const* steadyShot = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_STEADY_SHOT, GetCastDifficulty());
363 Milliseconds extraDuration = duration_cast<Milliseconds>(FloatSeconds(steadyShot->GetEffect(EFFECT_2).CalcValue(caster) / 10));
364 Milliseconds newDuration = Milliseconds(concussiveShot->GetDuration()) + extraDuration;
365 concussiveShot->SetDuration(newDuration.count());
366 concussiveShot->SetMaxDuration(newDuration.count());
367 }
368 }
369
374};
375
376// 459517 - Concussive Shot (attached to 186265 - Aspect of the Turtle and 5384 - Feign Death)
402
403// 109304 - Exhilaration
405{
406 bool Validate(SpellInfo const* /*spellInfo*/) override
407 {
409 }
410
416
417 void Register() override
418 {
420 }
421};
422
423// 212431 - Explosive Shot
425{
426 bool Validate(SpellInfo const* /*spellInfo*/) override
427 {
429 }
430
431 void HandlePeriodic(AuraEffect const* /*aurEff*/)
432 {
433 if (Unit* caster = GetCaster())
434 caster->CastSpell(GetTarget(), SPELL_HUNTER_EXPLOSIVE_SHOT_DAMAGE, true);
435 }
436
441};
442
443// 236775 - High Explosive Trap
444// 9810 - AreatriggerId
446{
448
449 void OnInitialize() override
450 {
451 if (Unit* caster = at->GetCaster())
452 for (AreaTrigger* other : caster->GetAreaTriggers(SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP))
453 other->SetDuration(0);
454 }
455
456 void OnUnitEnter(Unit* unit) override
457 {
458 if (Unit* caster = at->GetCaster())
459 {
460 if (caster->IsValidAttackTarget(unit))
461 {
463 at->Remove();
464 }
465 }
466 }
467};
468
469// 212658 - Hunting Party
471{
472 bool Validate(SpellInfo const* /*spellInfo*/) override
473 {
474 return ValidateSpellInfo(
475 {
478 });
479 }
480
481 void HandleProc(AuraEffect* aurEff, ProcEventInfo& /*eventInfo*/)
482 {
484 GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_HUNTER_EXHILARATION, duration_cast<Milliseconds>(FloatSeconds(-aurEff->GetAmount())));
485 GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_HUNTER_EXHILARATION_PET, duration_cast<Milliseconds>(FloatSeconds(-aurEff->GetAmount())));
486 }
487
492};
493
494// 462032 - Implosive Trap
495// 34378 - AreatriggerId
497{
499
500 void OnInitialize() override
501 {
502 if (Unit* caster = at->GetCaster())
503 for (AreaTrigger* other : caster->GetAreaTriggers(SPELL_HUNTER_IMPLOSIVE_TRAP))
504 other->SetDuration(0);
505 }
506
507 void OnUnitEnter(Unit* unit) override
508 {
509 if (Unit* caster = at->GetCaster())
510 {
511 if (caster->IsValidAttackTarget(unit))
512 {
514 at->Remove();
515 }
516 }
517 }
518};
519
520// 53478 - Last Stand Pet
522{
523 bool Validate(SpellInfo const* /*spellInfo*/) override
524 {
526 }
527
528 void HandleDummy(SpellEffIndex /*effIndex*/)
529 {
530 Unit* caster = GetCaster();
532 args.AddSpellBP0(caster->CountPctFromMaxHealth(30));
534 }
535
540};
541
542// 378016 - Latent Poison
544{
545 bool Validate(SpellInfo const* /*spellInfo*/) override
546 {
548 }
549
551 {
552 if (Aura* stack = GetHitUnit()->GetAura(SPELL_HUNTER_LATENT_POISON_STACK, GetCaster()->GetGUID()))
553 {
554 SetHitDamage(GetHitDamage() * stack->GetStackAmount());
555 stack->Remove();
556 }
557 }
558
563};
564
565// 19434 - Aimed Shot
566// 186270 - Raptor Strike
567// 217200 - Barbed Shot
568// 259387 - Mongoose Bite
587
588// 336904 - Latent Poison Injectors
590{
591 bool Validate(SpellInfo const* /*spellInfo*/) override
592 {
594 }
595
597 {
598 if (Aura* stack = GetHitUnit()->GetAura(SPELL_HUNTER_LATENT_POISON_INJECTORS_STACK, GetCaster()->GetGUID()))
599 {
600 SetHitDamage(GetHitDamage() * stack->GetStackAmount());
601 stack->Remove();
602 }
603 }
604
609};
610
611// 186270 - Raptor Strike
612// 259387 - Mongoose Bite
631
632// 194595 - Lock and Load
634{
635 bool Validate(SpellInfo const* /*spellInfo*/) override
636 {
638 }
639
640 static bool CheckProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/)
641 {
642 return roll_chance(aurEff->GetAmount());
643 }
644
645 static void HandleProc(AuraScript const&, AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo)
646 {
647 Unit* caster = eventInfo.GetActor();
650 });
651 }
652
658};
659
660// 1217788 - Manhunter
662{
663 bool Validate(SpellInfo const* /*spellInfo*/) override
664 {
666 }
667
668 static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
669 {
670 return eventInfo.GetProcTarget()->IsPlayer();
671 }
672
673 static void HandleEffectProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
674 {
676 .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
677 .TriggeringAura = aurEff
678 });
679 }
680
686};
687
688// 260309 - Master Marksman
690{
691 bool Validate(SpellInfo const* /*spellInfo*/) override
692 {
694 && sSpellMgr->AssertSpellInfo(SPELL_HUNTER_MASTER_MARKSMAN, DIFFICULTY_NONE)->GetEffect(EFFECT_0).GetPeriodicTickCount() > 0;
695 }
696
697 static void HandleProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
698 {
699 uint32 ticks = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_MASTER_MARKSMAN, DIFFICULTY_NONE)->GetEffect(EFFECT_0).GetPeriodicTickCount();
700 SpellEffectValue damage = CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()) / ticks;
701
703 .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
704 .SpellValueOverrides = { { SPELLVALUE_BASE_POINT0, damage } }
705 });
706 }
707
712};
713
714// 53271 - Masters Call
716{
717 bool Validate(SpellInfo const* spellInfo) override
718 {
719 return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } })
721 }
722
723 bool Load() override
724 {
725 return GetCaster()->GetTypeId() == TYPEID_PLAYER;
726 }
727
729 {
731 ASSERT(pet); // checked in Spell::CheckCast
732
733 if (!pet->IsPet() || !pet->IsAlive())
734 return SPELL_FAILED_NO_PET;
735
736 // Do a mini Spell::CheckCasterAuras on the pet, no other way of doing this
738 uint32 const unitflag = pet->m_unitData->Flags;
739 if (!pet->GetCharmerGUID().IsEmpty())
740 result = SPELL_FAILED_CHARMED;
741 else if (unitflag & UNIT_FLAG_STUNNED)
742 result = SPELL_FAILED_STUNNED;
743 else if (unitflag & UNIT_FLAG_FLEEING)
744 result = SPELL_FAILED_FLEEING;
745 else if (unitflag & UNIT_FLAG_CONFUSED)
746 result = SPELL_FAILED_CONFUSED;
747
748 if (result != SPELL_CAST_OK)
749 return result;
750
751 Unit* target = GetExplTargetUnit();
752 if (!target)
754
755 if (!pet->IsWithinLOSInMap(target))
757
758 return SPELL_CAST_OK;
759 }
760
761 void HandleDummy(SpellEffIndex /*effIndex*/)
762 {
764 }
765
767 {
769 }
770
778};
779
780// 34477 - Misdirection
809
810// 35079 - Misdirection (Proc)
823
824// 2643 - Multi-Shot
826{
827 bool Validate(SpellInfo const* /*spellInfo*/) override
828 {
830 }
831
832 bool Load() override
833 {
834 return GetCaster()->GetTypeId() == TYPEID_PLAYER;
835 }
836
838 {
839 // We need to check hunter's spec because it doesn't generate focus on other specs than MM
840 if (GetCaster()->ToPlayer()->GetPrimarySpecialization() == ChrSpecialization::HunterMarksmanship)
842 }
843
844 void Register() override
845 {
847 }
848};
849
850// 459783 - Penetrating Shots
852{
853 void CalcAmount(AuraEffect const* /*aurEff*/, SpellEffectValue& amount, bool const& /*canBeRecalculated*/) const
854 {
855 if (AuraEffect const* amountHolder = GetEffect(EFFECT_1))
856 {
857 float critChanceDone = GetUnitOwner()->GetUnitCriticalChanceDone(BASE_ATTACK);
858 amount = CalculatePct(critChanceDone, amountHolder->GetAmount());
859 }
860 }
861
862 void UpdatePeriodic(AuraEffect const* aurEff) const
863 {
864 if (AuraEffect* bonus = GetEffect(EFFECT_0))
865 bonus->RecalculateAmount(aurEff);
866 }
867
873};
874
875// 55709 - Pet Heart of the Phoenix
877{
878 bool Load() override
879 {
880 if (!GetCaster()->IsPet())
881 return false;
882 return true;
883 }
884
889
890 void HandleScript(SpellEffIndex /*effIndex*/)
891 {
892 Unit* caster = GetCaster();
893 if (Unit* owner = caster->GetOwner())
894 {
896 {
898 args.AddSpellBP0(100);
899 owner->CastSpell(caster, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED, args);
901 }
902 }
903 }
904
909};
910
911// 781 - Disengage
933
934// 260240 - Precise Shots
936{
937 bool Validate(SpellInfo const* /*spellInfo*/) override
938 {
940 }
941
942 void HandleProc(ProcEventInfo const& eventInfo) const
943 {
945 .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
946 .TriggeringSpell = eventInfo.GetProcSpell()
947 });
948 }
949
950 void Register() override
951 {
953 }
954};
955
956// 257044 - Rapid Fire
958{
959 bool Validate(SpellInfo const* /*spellInfo*/) override
960 {
962 }
963
964 void HandlePeriodic(AuraEffect const* /*aurEff*/)
965 {
966 if (Unit* caster = GetCaster())
967 caster->CastSpell(GetTarget(), SPELL_HUNTER_RAPID_FIRE_DAMAGE, true);
968 }
969
974};
975
976// 257045 - Rapid Fire Damage
978{
979 bool Validate(SpellInfo const* /*spellInfo*/) override
980 {
982 }
983
984 void HandleHit(SpellEffIndex /*effIndex*/)
985 {
987 }
988
993};
994
995// 385539 - Rejuvenating Wind
997{
998 bool Validate(SpellInfo const* /*spellInfo*/) override
999 {
1001 && sSpellMgr->AssertSpellInfo(SPELL_HUNTER_REJUVENATING_WIND_HEAL, DIFFICULTY_NONE)->GetEffect(EFFECT_0).GetPeriodicTickCount() > 0;
1002 }
1003
1004 void HandleProc(AuraEffect const* aurEff, ProcEventInfo const& /*procEvent*/)
1005 {
1007
1008 Unit* caster = GetTarget();
1009
1010 uint32 ticks = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_REJUVENATING_WIND_HEAL, DIFFICULTY_NONE)->GetEffect(EFFECT_0).GetPeriodicTickCount();
1011 SpellEffectValue heal = CalculatePct(caster->GetMaxHealth(), aurEff->GetAmount()) / ticks;
1012
1015 .SpellValueOverrides = { { SPELLVALUE_BASE_POINT0, heal } }
1016 });
1017 }
1018
1023};
1024
1025// 53480 - Roar of Sacrifice
1027{
1028 bool Validate(SpellInfo const* /*spellInfo*/) override
1029 {
1031 }
1032
1033 bool CheckProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
1034 {
1035 DamageInfo* damageInfo = eventInfo.GetDamageInfo();
1036 if (!damageInfo || !(damageInfo->GetSchoolMask() & aurEff->GetMiscValue()))
1037 return false;
1038
1039 if (!GetCaster())
1040 return false;
1041
1042 return true;
1043 }
1044
1045 void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
1046 {
1048
1049 CastSpellExtraArgs args(aurEff);
1050 args.AddSpellBP0(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()));
1052 }
1053
1059};
1060
1061// 37506 - Scatter Shot
1063{
1064 bool Load() override
1065 {
1066 return GetCaster()->GetTypeId() == TYPEID_PLAYER;
1067 }
1068
1069 void HandleDummy(SpellEffIndex /*effIndex*/)
1070 {
1071 Player* caster = GetCaster()->ToPlayer();
1072 // break Auto Shot and autohit
1074 caster->AttackStop();
1076 }
1077
1082};
1083
1084// 459455 - Scout's Instincts (attached to 186257 - Aspect of the Cheetah)
1086{
1087 bool Validate(SpellInfo const* spellInfo) override
1088 {
1090 && ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } })
1092 }
1093
1094 bool Load() override
1095 {
1097 }
1098
1099 static void HandleMinSpeed(SpellScript const&, WorldObject*& target)
1100 {
1101 target = nullptr;
1102 }
1103
1108};
1109
1110// 459533 - Scrappy
1112{
1114
1115 bool Validate(SpellInfo const* /*spellInfo*/) override
1116 {
1118 }
1119
1120 void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/) const
1121 {
1122 for (uint32 spellId : AffectedSpellIds)
1124 }
1125
1130};
1131
1132// 473520 - Shrapnel Shot
1134{
1135 bool Validate(SpellInfo const* /*spellInfo*/) override
1136 {
1138 }
1139
1149
1150 void Register() override
1151 {
1153 }
1154};
1155
1156// 56641 - Steady Shot
1185
1186// 260367 - Streamline (attached to 257044 - Rapid Fire)
1188{
1189 bool Validate(SpellInfo const* /*spellInfo*/) override
1190 {
1192 }
1193
1194 bool Load() override
1195 {
1197 }
1198
1206
1211};
1212
1213// 391559 - Surging Shots
1215{
1216 bool Validate(SpellInfo const* /*spellInfo*/) override
1217 {
1219 }
1220
1221 void HandleProc(ProcEventInfo const& /*eventInfo*/) const
1222 {
1224 }
1225
1226 void Register() override
1227 {
1229 }
1230};
1231
1232// 1515 - Tame Beast
1234{
1236 {
1237 883,
1238 83242,
1239 83243,
1240 83244,
1241 83245,
1242 };
1243
1245 {
1246 Player* caster = GetCaster()->ToPlayer();
1247 if (!caster)
1249
1250 if (!GetExplTargetUnit())
1252
1253 if (Creature* target = GetExplTargetUnit()->ToCreature())
1254 {
1255 if (target->GetLevelForTarget(caster) > caster->GetLevel())
1257
1258 // use SMSG_PET_TAME_FAILURE?
1259 if (!target->GetCreatureTemplate()->IsTameable(caster->CanTameExoticPets(), target->GetCreatureDifficulty()))
1261
1262 if (PetStable const* petStable = caster->GetPetStable())
1263 {
1264 if (petStable->CurrentPetIndex)
1266
1267 auto freeSlotItr = std::find_if(petStable->ActivePets.begin(), petStable->ActivePets.end(), [](Optional<PetStable::PetInfo> const& petInfo)
1268 {
1269 return !petInfo.has_value();
1270 });
1271
1272 if (freeSlotItr == petStable->ActivePets.end())
1273 {
1276 }
1277
1278 // Check for known Call Pet X spells
1279 std::size_t freeSlotIndex = std::distance(petStable->ActivePets.begin(), freeSlotItr);
1280 if (!caster->HasSpell(CallPetSpellIds[freeSlotIndex]))
1281 {
1284 }
1285 }
1286
1287 if (!caster->GetCharmedGUID().IsEmpty())
1289
1290 if (!target->GetOwnerGUID().IsEmpty())
1291 {
1294 }
1295 }
1296 else
1298
1299 return SPELL_CAST_OK;
1300 }
1301
1306};
1307
1308// 187700 - Tar Trap
1309// 4436 - AreatriggerId
1311{
1313
1314 void OnCreate(Spell const* /*creatingSpell*/) override
1315 {
1316 if (Unit* caster = at->GetCaster())
1317 {
1318 if (caster->HasAura(SPELL_HUNTER_ENTRAPMENT_TALENT))
1320 }
1321 }
1322
1323 void OnUnitEnter(Unit* unit) override
1324 {
1325 if (Unit* caster = at->GetCaster())
1326 {
1327 if (caster->IsValidAttackTarget(unit))
1329 }
1330 }
1331
1332 void OnUnitExit(Unit* unit, AreaTriggerExitReason /*reason*/) override
1333 {
1335 }
1336};
1337
1338// 187699 - Tar Trap
1339// 4435 - AreatriggerId
1341{
1343
1344 void OnInitialize() override
1345 {
1346 if (Unit* caster = at->GetCaster())
1347 for (AreaTrigger* other : caster->GetAreaTriggers(SPELL_HUNTER_TAR_TRAP))
1348 other->SetDuration(0);
1349 }
1350
1351 void OnUnitEnter(Unit* unit) override
1352 {
1353 if (Unit* caster = at->GetCaster())
1354 {
1355 if (caster->IsValidAttackTarget(unit))
1356 {
1358 at->Remove();
1359 }
1360 }
1361 }
1362};
1363
1364// 67151 - Item - Hunter T9 4P Bonus (Steady Shot)
1366{
1367 bool Validate(SpellInfo const* /*spellInfo*/) override
1368 {
1370 }
1371
1372 bool CheckProc(ProcEventInfo& eventInfo)
1373 {
1374 if (eventInfo.GetActor()->GetTypeId() == TYPEID_PLAYER && eventInfo.GetActor()->ToPlayer()->GetPet())
1375 return true;
1376 return false;
1377 }
1378
1379 void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
1380 {
1382 Unit* caster = eventInfo.GetActor();
1383
1384 caster->CastSpell(caster->ToPlayer()->GetPet(), SPELL_HUNTER_T9_4P_GREATNESS, aurEff);
1385 }
1386
1392};
1393
1394// 394366 - Find The Mark
1396{
1397 bool Validate(SpellInfo const* /*spellInfo*/) override
1398 {
1400 && sSpellMgr->AssertSpellInfo(SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE, DIFFICULTY_NONE)->GetEffect(EFFECT_0).GetPeriodicTickCount();
1401 }
1402
1403 void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
1404 {
1406
1407 Unit* caster = eventInfo.GetActor();
1408 uint32 ticks = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE, DIFFICULTY_NONE)->GetEffect(EFFECT_0).GetPeriodicTickCount();
1409 SpellEffectValue damage = CalculatePct(eventInfo.GetDamageInfo()->GetOriginalDamage(), aurEff->GetAmount()) / ticks;
1410
1412 .SetTriggeringSpell(eventInfo.GetProcSpell())
1414 }
1415
1420};
1421
1422// Called by 136 - Mend Pet
1424{
1429
1430 bool Load() override
1431 {
1432 Unit const* caster = GetCaster();
1433 if (!caster)
1434 return false;
1435
1437 if (!wildernessMedicine)
1438 return false;
1439
1440 _dispelChance = wildernessMedicine->GetAmount();
1441 return true;
1442 }
1443
1444 void OnPeriodic(AuraEffect const* aurEff) const
1445 {
1446 if (Unit* caster = GetCaster())
1450 .TriggeringAura = aurEff
1451 });
1452 }
1453
1458
1460};
1461
1463{
1512}
AreaTriggerExitReason
Definition AreaTrigger.h:69
@ DIFFICULTY_NONE
Definition DBCEnums.h:933
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::duration< double, Seconds::period > FloatSeconds
Definition Duration.h:29
#define ASSERT
Definition Errors.h:80
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
#define MAX_ACTIVE_PETS
Definition PetDefines.h:36
bool roll_chance(T chance)
Definition Random.h:55
#define RegisterAreaTriggerAI(ai_name)
Definition ScriptMgr.h:1428
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
#define EFFECT_FIRST_FOUND
@ TARGET_UNIT_CASTER
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SCHOOL_DAMAGE
@ BASE_ATTACK
SpellCastResult
@ SPELL_FAILED_STUNNED
@ SPELL_FAILED_BAD_IMPLICIT_TARGETS
@ SPELL_FAILED_ALREADY_HAVE_SUMMON
@ SPELL_FAILED_ALREADY_HAVE_CHARM
@ SPELL_FAILED_HIGHLEVEL
@ SPELL_FAILED_DONT_REPORT
@ SPELL_FAILED_BAD_TARGETS
@ SPELL_FAILED_CONFUSED
@ SPELL_CAST_OK
@ SPELL_FAILED_CHARMED
@ SPELL_FAILED_LINE_OF_SIGHT
@ SPELL_FAILED_FLEEING
@ SPELL_FAILED_NO_PET
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ AURA_REMOVE_BY_DEFAULT
@ AURA_REMOVE_BY_DEATH
@ AURA_REMOVE_BY_EXPIRE
@ AURA_REMOVE_BY_INTERRUPT
@ SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE
@ SPELL_AURA_OBS_MOD_HEALTH
@ SPELL_AURA_MOD_INCREASE_SPEED
@ SPELL_AURA_PROC_TRIGGER_SPELL
@ SPELL_AURA_CAST_WHILE_WALKING
@ SPELL_AURA_DUMMY
@ SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
@ SPELL_AURA_MOD_MINIMUM_SPEED
@ SPELL_AURA_PERIODIC_DUMMY
double SpellEffectValue
This is a double instead of float to be able to store full range of int32.
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
@ TRIGGERED_IGNORE_CAST_IN_PROGRESS
Will not check if a current cast is in progress.
@ TRIGGERED_DONT_REPORT_CAST_ERROR
Will return SPELL_FAILED_DONT_REPORT in CheckCast functions.
@ SPELLVALUE_BASE_POINT0
#define sSpellMgr
Definition SpellMgr.h:812
#define AuraProcFn(F)
#define SpellObjectTargetSelectFn(F, I, N)
#define SpellCheckCastFn(F)
#define AuraEffectProcFn(F, I, N)
#define SpellEffectFn(F, I, N)
#define AuraEffectCalcAmountFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define AuraCheckEffectProcFn(F, I, N)
#define SpellCastFn(F)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraCheckProcFn(F)
#define SpellHitFn(F)
#define AuraEffectRemoveFn(F, I, N, M)
@ UNIT_FLAG_STUNNED
@ UNIT_FLAG_CONFUSED
@ UNIT_FLAG_FLEEING
@ CURRENT_AUTOREPEAT_SPELL
Definition Unit.h:600
T CalculatePct(T base, U pct)
Definition Util.h:72
AreaTrigger *const at
AreaTriggerAI(AreaTrigger *a, uint32 scriptId={}) noexcept
GuidUnorderedSet const & GetInsideUnits() const
ObjectGuid const & GetCasterGuid() const
bool IsRemoved() const
Unit * GetCaster() const
int32 GetAmountAsInt() const
int32 GetMiscValue() const
SpellEffectValue GetAmount() const
void PreventDefaultAction()
AuraApplication const * GetTargetApplication() const
HookList< EffectApplyHandler > AfterEffectRemove
HookList< CheckEffectProcHandler > DoCheckEffectProc
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
HookList< EffectCalcAmountHandler > DoEffectCalcAmount
Unit * GetCaster() const
AuraEffect * GetEffect(uint8 effIndex) const
Unit * GetTarget() const
HookList< CheckProcHandler > DoCheckProc
HookList< EffectApplyHandler > OnEffectRemove
HookList< EffectProcHandler > OnEffectProc
Unit * GetUnitOwner() const
HookList< AuraProcHandler > OnProc
uint32 GetId() const
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
bool IsPlayer() const
Definition BaseEntity.h:173
TypeID GetTypeId() const
Definition BaseEntity.h:166
uint32 GetOriginalDamage() const
Definition Unit.h:453
SpellSchoolMask GetSchoolMask() const
Definition Unit.h:449
uint32 GetDamage() const
Definition Unit.h:452
bool IsEmpty() const
Definition ObjectGuid.h:362
Player * ToPlayer()
Definition Object.h:126
void SendAttackSwingCancelAttack() const
Definition Player.cpp:21841
bool CanTameExoticPets() const
Definition Player.h:2496
PetStable * GetPetStable()
Definition Player.h:1355
Pet * GetPet() const
Definition Player.cpp:22060
void SendTameFailure(PetTameResult result)
Definition Player.cpp:22221
bool HasSpell(uint32 spell) const override
Definition Player.cpp:3735
Unit * GetActionTarget() const
Definition Unit.h:500
Spell const * GetProcSpell() const
Definition Unit.h:514
DamageInfo * GetDamageInfo() const
Definition Unit.h:511
Unit * GetProcTarget() const
Definition Unit.h:501
Unit * GetActor() const
Definition Unit.h:499
SpellEffectValue CalcValue(WorldObject const *caster=nullptr, SpellEffectValue const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
bool IsAura() const
int32 CalcValueAsInt(WorldObject const *caster=nullptr, SpellEffectValue const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
void ResetCooldown(uint32 spellId, bool update=false)
void ModifyCooldown(uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown=false)
uint32 const Id
Definition SpellInfo.h:328
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:588
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
static bool ValidateSpellEffect(std::initializer_list< std::pair< uint32, SpellEffIndex > > effects)
HookList< CastHandler > AfterCast
HookList< CheckCastHandler > OnCheckCast
int32 GetHitDamage() const
Unit * GetCaster() const
HookList< HitHandler > AfterHit
int32 GetEffectValueAsInt() const
HookList< HitHandler > OnHit
Unit * GetHitUnit() const
SpellEffectInfo const & GetEffectInfo() const
HookList< EffectHandler > OnEffectHitTarget
HookList< ObjectTargetSelectHandler > OnObjectTargetSelect
HookList< CastHandler > OnCast
Spell * GetSpell() const
Difficulty GetCastDifficulty() const
void SetHitDamage(int32 damage)
WorldLocation const * GetExplTargetDest() const
Unit * GetExplTargetUnit() const
Definition Spell.h:277
TaskContext & Repeat(TaskScheduler::duration_t duration)
TaskScheduler & Schedule(duration_t time, task_handler_t task)
TaskScheduler & Update()
Update the scheduler to the current time.
void UnregisterRedirectThreat(uint32 spellId)
Definition Unit.h:635
uint64 CountPctFromMaxHealth(float pct) const
Definition Unit.h:797
ThreatManager & GetThreatManager()
Definition Unit.h:1078
bool IsPet() const
Definition Unit.h:751
ObjectGuid GetCharmedGUID() const
Definition Unit.h:1211
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID=ObjectGuid::Empty) const
Definition Unit.cpp:4604
bool IsAlive() const
Definition Unit.h:1185
uint64 GetMaxHealth() const
Definition Unit.h:789
float GetUnitCriticalChanceDone(WeaponAttackType attackType) const
Definition Unit.cpp:2876
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1881
bool HealthBelowPct(float pct) const
Definition Unit.h:792
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4804
SpellHistory * GetSpellHistory()
Definition Unit.h:1498
ObjectGuid GetCharmerGUID() const
Definition Unit.h:1208
void RemoveMovementImpairingAuras(bool withRoot)
Definition Unit.cpp:4294
Guardian * GetGuardianPet() const
Definition Unit.cpp:6231
bool AttackStop()
Definition Unit.cpp:5965
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3974
uint8 GetLevel() const
Definition Unit.h:757
void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed=true, bool withInstant=true)
Definition Unit.cpp:3159
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
Unit * GetOwner() const
Definition Object.cpp:1598
bool IsWithinLOSInMap(WorldObject const *obj, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:535
void HandleDummyTick(AuraEffect const *)
void RemoveEffect(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void HandleOnRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *spellInfo) override
static void HandleCastWhileWalking(SpellScript const &, WorldObject *&target)
void OnApply(AuraEffect const *, AuraEffectHandleModes)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void Register() override
static bool CheckEffectProc(AuraScript const &, AuraEffect const *aurEff, ProcEventInfo const &eventInfo)
void Register() override
bool RollProc(AuraEffect const *, ProcEventInfo &)
bool Validate(SpellInfo const *spellInfo) override
void Register() override
void HandleDuration(SpellEffIndex) const
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void Register() override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void HandlePeriodic(AuraEffect const *)
bool Validate(SpellInfo const *) override
void HandleProc(AuraEffect *aurEff, ProcEventInfo &)
bool Validate(SpellInfo const *) override
void HandleDummy(SpellEffIndex)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
static void HandleProc(AuraScript const &, AuraEffect const *, ProcEventInfo const &eventInfo)
static bool CheckProc(AuraScript const &, AuraEffect const *aurEff, ProcEventInfo const &)
static bool CheckProc(AuraScript const &, ProcEventInfo const &eventInfo)
static void HandleEffectProc(AuraScript const &, AuraEffect const *aurEff, ProcEventInfo const &eventInfo)
bool Validate(SpellInfo const *) override
void Register() override
bool Validate(SpellInfo const *) override
static void HandleProc(AuraScript const &, AuraEffect const *aurEff, ProcEventInfo const &eventInfo)
SpellCastResult DoCheckCast()
void HandleDummy(SpellEffIndex)
void HandleScriptEffect(SpellEffIndex)
bool Validate(SpellInfo const *spellInfo) override
void Register() override
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
void Register() override
void HandleProc(AuraEffect *aurEff, ProcEventInfo &)
void Register() override
bool Load() override
bool Validate(SpellInfo const *) override
void CalcAmount(AuraEffect const *, SpellEffectValue &amount, bool const &) const
void UpdatePeriodic(AuraEffect const *aurEff) const
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void Register() override
void HandleProc(ProcEventInfo const &eventInfo) const
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void HandleHit(SpellEffIndex)
void Register() override
bool Validate(SpellInfo const *) override
void HandlePeriodic(AuraEffect const *)
void HandleProc(AuraEffect const *aurEff, ProcEventInfo const &)
bool Validate(SpellInfo const *) override
bool CheckProc(AuraEffect const *aurEff, ProcEventInfo &eventInfo)
void HandleProc(AuraEffect *aurEff, ProcEventInfo &eventInfo)
bool Validate(SpellInfo const *) override
void HandleDummy(SpellEffIndex)
bool Validate(SpellInfo const *spellInfo) override
static void HandleMinSpeed(SpellScript const &, WorldObject *&target)
bool Validate(SpellInfo const *) override
void HandleEffectProc(AuraEffect const *aurEff, ProcEventInfo const &) const
static constexpr std::array< uint32, 3 > AffectedSpellIds
void Register() override
bool Validate(SpellInfo const *) override
void HandleProc(ProcEventInfo const &) const
bool Validate(SpellInfo const *) override
void Register() override
void Register() override
bool Validate(SpellInfo const *) override
void HandleAfterCast() const
void HandleProc(ProcEventInfo const &) const
bool Validate(SpellInfo const *) override
void HandleProc(AuraEffect *aurEff, ProcEventInfo &eventInfo)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void Register() override
void HandleProc(AuraEffect *aurEff, ProcEventInfo &eventInfo)
bool CheckProc(ProcEventInfo &eventInfo)
void Register() override
static constexpr uint32 CallPetSpellIds[MAX_ACTIVE_PETS]
SpellCastResult CheckCast()
void OnPeriodic(AuraEffect const *aurEff) const
bool Validate(SpellInfo const *) override
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
@ SPELL_DRAENEI_GIFT_OF_THE_NAARU
@ SPELL_HUNTER_MASTER_MARKSMAN
@ SPELL_HUNTER_ASPECT_OF_THE_TURTLE_PACIFY_AURA
@ SPELL_HUNTER_ENTRAPMENT_TALENT
@ SPELL_HUNTER_A_MURDER_OF_CROWS_DAMAGE
@ SPELL_HUNTER_BINDING_SHOT_VISUAL_ARROW
@ SPELL_HUNTER_MARKSMANSHIP_HUNTER_AURA
@ SPELL_HUNTER_GREVIOUS_INJURY
@ SPELL_HUNTER_EMERGENCY_SALVE_TALENT
@ SPELL_HUNTER_BINDING_SHOT_VISUAL
@ SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_1
@ SPELL_HUNTER_BINDING_SHOT_MARKER
@ SPELL_HUNTER_TAR_TRAP_SLOW
@ SPELL_HUNTER_SHRAPNEL_SHOT_TALENT
@ SPELL_HUNTER_STEADY_SHOT_FOCUS
@ SPELL_HUNTER_WILDERNESS_MEDICINE_DISPEL
@ SPELL_HUNTER_MISDIRECTION_PROC
@ SPELL_HUNTER_CONCUSSIVE_SHOT
@ SPELL_HUNTER_SHRAPNEL_SHOT_DEBUFF
@ SPELL_HUNTER_BINDING_SHOT
@ SPELL_HUNTER_LOCK_AND_LOAD
@ SPELL_HUNTER_POSTHASTE_TALENT
@ SPELL_HUNTER_MISDIRECTION
@ SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_2
@ SPELL_HUNTER_SCOUTS_INSTINCTS
@ SPELL_HUNTER_RAPID_FIRE_DAMAGE
@ SPELL_HUNTER_MASTERS_CALL_TRIGGERED
@ SPELL_HUNTER_RAPID_FIRE_ENERGIZE
@ SPELL_HUNTER_RAPID_FIRE
@ SPELL_HUNTER_BINDING_SHOT_STUN
@ SPELL_HUNTER_EXHILARATION_PET
@ SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_3
@ SPELL_HUNTER_INTIMIDATION
@ SPELL_HUNTER_EXHILARATION
@ SPELL_HUNTER_BINDING_SHOT_IMMUNE
@ SPELL_HUNTER_TAR_TRAP
@ SPELL_HUNTER_LATENT_POISON_STACK
@ SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_DEBUFF
@ SPELL_HUNTER_LATENT_POISON_INJECTORS_DAMAGE
@ SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED
@ SPELL_HUNTER_ASPECT_CHEETAH_SLOW
@ SPELL_HUNTER_STEADY_SHOT
@ SPELL_HUNTER_EXHILARATION_R2
@ SPELL_HUNTER_AIMED_SHOT
@ SPELL_HUNTER_MULTI_SHOT_FOCUS
@ SPELL_HUNTER_STREAMLINE_BUFF
@ SPELL_ROAR_OF_SACRIFICE_TRIGGERED
@ SPELL_HUNTER_STREAMLINE_TALENT
@ SPELL_HUNTER_IMPLOSIVE_TRAP
@ SPELL_HUNTER_ASPECT_OF_THE_FOX
@ SPELL_HUNTER_POSTHASTE_INCREASE_SPEED
@ SPELL_HUNTER_LATENT_POISON_DAMAGE
@ SPELL_HUNTER_REJUVENATING_WIND_HEAL
@ SPELL_HUNTER_ENTRAPMENT_ROOT
@ SPELL_HUNTER_PET_LAST_STAND_TRIGGERED
@ SPELL_HUNTER_EXPLOSIVE_SHOT_DAMAGE
@ SPELL_HUNTER_LONE_WOLF
@ SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP
@ SPELL_HUNTER_TAR_TRAP_AREATRIGGER
@ SPELL_HUNTER_PRECISE_SHOTS
@ SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE
@ SPELL_HUNTER_T9_4P_GREATNESS
@ SPELL_HUNTER_IMPLOSIVE_TRAP_DAMAGE
@ SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP_DAMAGE
@ SPELL_HUNTER_LATENT_POISON_INJECTORS_STACK
@ SPELL_HUNTER_WILDERNESS_MEDICINE_TALENT
@ SPELL_HUNTER_INTIMIDATION_MARKSMANSHIP
@ SPELL_HUNTER_EMERGENCY_SALVE_DISPEL
void AddSC_hunter_spell_scripts()
TriggerCastFlags TriggerFlags
CastSpellExtraArgs & AddSpellBP0(SpellEffectValue val)
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
void OnUnitEnter(Unit *unit) override
void OnUnitEnter(Unit *unit) override
void OnUnitEnter(Unit *unit) override
void OnUnitEnter(Unit *unit) override
void OnUnitExit(Unit *unit, AreaTriggerExitReason) override
void OnCreate(Spell const *) override
void OnUpdate(uint32 diff) override
TaskScheduler _scheduler
void OnUnitExit(Unit *unit, AreaTriggerExitReason) override
void OnCreate(Spell const *) override
void OnUnitEnter(Unit *unit) override
void OnInitialize() override
MiscSpells