TrinityCore
Loading...
Searching...
No Matches
zone_howling_fjord.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#include "ScriptMgr.h"
19#include "Containers.h"
20#include "MotionMaster.h"
21#include "ObjectAccessor.h"
22#include "ObjectMgr.h"
23#include "Player.h"
24#include "QuestDef.h"
25#include "ScriptedCreature.h"
26#include "ScriptedEscortAI.h"
27#include "ScriptedGossip.h"
28#include "Spell.h"
29#include "SpellInfo.h"
30#include "SpellScript.h"
31#include "TemporarySummon.h"
32#include "Vehicle.h"
33
34/*######
35## npc_daegarn
36######*/
37
39{
41 NPC_FIRJUS = 24213,
42 NPC_JLARBORN = 24215,
43 NPC_YOROS = 24214,
44 NPC_OLUF = 23931,
45 NPC_PRISONER_1 = 24253, // looks the same but has different abilities
48 SAY_TEXT = 0
49};
50
51static Position const daegarnSummonPosition = { 838.81f, -4678.06f, -94.182f, 0.0f };
52static Position const daegarnCenterPosition = { 801.88f, -4721.87f, -96.143f, 0.0f };
53
55struct npc_daegarn : public ScriptedAI
56{
57 npc_daegarn(Creature* creature) : ScriptedAI(creature), _eventInProgress(false), _summons(creature)
58 {
59 }
60
61 void Reset() override
62 {
63 _eventInProgress = false;
67
68 _scheduler.Schedule(40s, [this](TaskContext context)
69 {
71 context.Repeat(40s);
72 });
73 }
74
75 void EnterEvadeMode(EvadeReason why) override
76 {
77 if (!_EnterEvadeMode(why))
78 return;
79
80 if (!me->GetVehicle())
81 {
82 if (Unit* owner = me->GetCharmerOrOwner())
83 {
86 }
87 else
88 {
91 }
92 }
93
94 if (me->IsVehicle())
95 me->GetVehicleKit()->Reset(true);
96 }
97
98 void UpdateAI(uint32 diff) override
99 {
100 _scheduler.Update(diff);
101
102 if (!UpdateVictim())
103 return;
104
106 }
107
108 void JustSummoned(Creature* summon) override
109 {
110 _summons.Summon(summon);
111
113 {
114 if (player->IsAlive())
115 {
116 summon->SetWalk(false);
119 return;
120 }
121 }
122
123 Reset();
124 }
125
126 void SummonedCreatureDespawn(Creature* summon) override
127 {
128 _summons.Despawn(summon);
129 }
130
131 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
132 {
133 uint32 entry = 0;
134
135 _summons.Despawn(summon);
136
137 // will eventually reset the event if something goes wrong
138 switch (summon->GetEntry())
139 {
140 case NPC_FIRJUS:
141 entry = NPC_JLARBORN;
142 break;
143 case NPC_JLARBORN:
144 entry = NPC_YOROS;
145 break;
146 case NPC_YOROS:
147 entry = NPC_OLUF;
148 break;
149 case NPC_OLUF:
150 Reset();
151 return;
152 }
153
154 SummonGladiator(entry);
155 }
156
157 void OnQuestAccept(Player* player, Quest const* quest) override
158 {
159 if (quest->GetQuestId() == QUEST_DEFEAT_AT_RING)
160 {
162 return;
163
164 _eventInProgress = true;
165 _playerGUID = player->GetGUID();
168
169 _scheduler.Schedule(20s, [this](TaskContext context)
170 {
171 bool reset = true;
173 {
174 if (player->IsAlive() && player->IsEngaged())
175 {
176 for (auto itr = _summons.begin(); reset && itr != _summons.end(); ++itr)
177 {
178 Creature* summon = ObjectAccessor::GetCreature(*me, *_summons.begin());
179 if (summon && player->IsEngagedBy(summon))
180 {
181 context.Repeat(5s);
182 reset = false;
183 }
184 }
185 }
186 }
187
188 if (reset)
189 Reset();
190 });
191
193 }
194 }
195
196private:
198 {
199 me->SummonCreature(entry, daegarnSummonPosition, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30s);
200 }
201
206};
207
208/*######
209## Quest 11232: Guide Our Sights
210######*/
211
217
218// 43080 - Quest - Howling Fjord - Guide Our Sights - FX Master
245
246/*######
247## Quest 11310: Warning: Some Assembly Required
248######*/
249
257
258// 43393 - Ping Master
278
279// 42268 - Quest - Mindless Abomination Explosion FX Master
281{
283
293
295 {
296 Unit* caster = GetCaster();
318 }
319
324};
325
326/*######
327## Quest 11296: Rivenwood Captives
328######*/
329
345
360
361// 43288 - Rivenwood Captives: Player Not On Quest
381
382// 43287 - Rivenwood Captives: Player On Quest
408
409/*######
410## Quest 11317, 11322: The Cleansing
411######*/
412
423
424// 43365 - The Cleansing: Shrine Cast
426{
428
429 bool Validate(SpellInfo const* /*spellInfo*/) override
430 {
432 sObjectMgr->GetQuestTemplate(QUEST_THE_CLEANSING_H) &&
433 sObjectMgr->GetQuestTemplate(QUEST_THE_CLEANSING_A);
434 }
435
437 {
438 // Error is correct for quest check but may be not correct for aura and this may be a wrong place to send error
439 if (Player* target = GetExplTargetUnit()->ToPlayer())
440 {
441 if (target->HasAura(SPELL_RECENT_MEDITATION) || (!(target->GetQuestStatus(QUEST_THE_CLEANSING_H) == QUEST_STATUS_INCOMPLETE ||
442 target->GetQuestStatus(QUEST_THE_CLEANSING_A) == QUEST_STATUS_INCOMPLETE)))
443 {
445 return SPELL_FAILED_FIZZLE;
446 }
447 }
448 return SPELL_CAST_OK;
449 }
450
451 void HandleScript(SpellEffIndex /*effIndex*/)
452 {
454 }
455
461};
462
463// 43351 - Cleansing Soul
492
493// 50217 - The Cleansing: Script Effect Player Cast Mirror Image
513
514// 50238 - The Cleansing: Your Inner Turmoil's On Death Cast on Master
516{
518
519 bool Validate(SpellInfo const* spellInfo) override
520 {
521 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
522 }
523
524 void HandleScript(SpellEffIndex /*effIndex*/)
525 {
526 if (TempSummon* casterSummon = GetCaster()->ToTempSummon())
527 if (Unit* summoner = casterSummon->GetSummonerUnit())
528 summoner->CastSpell(summoner, uint32(GetEffectValue()));
529 }
530
535};
536
537/*######
538## Quest 11472: The Way to His Heart...
539######*/
540
546
547// 21014 - Anuniaq's Net
568
569// 44455 - The Way to His Heart...: Character Script Effect Reverse Cast
589
590// 44462 - The Way to His Heart...: Cast Quest Complete on Master
592{
594
595 bool Validate(SpellInfo const* spellInfo) override
596 {
597 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
598 }
599
600 void HandleScript(SpellEffIndex /*effIndex*/)
601 {
602 if (TempSummon* casterSummon = GetCaster()->ToTempSummon())
603 if (Unit* summoner = casterSummon->GetSummonerUnit())
604 summoner->CastSpell(summoner, uint32(GetEffectValue()), true);
605 }
606
611};
612
613/*######
614## Quest 11396, 11399: Bring Down Those Shields
615######*/
616
622
623// 50133 - Scourging Crystal Controller
625{
627
628 bool Validate(SpellInfo const* /*spellEntry*/) override
629 {
631 }
632
633 void HandleDummy(SpellEffIndex /*effIndex*/)
634 {
635 if (Unit* target = GetHitUnit())
636 if (target->HasAura(SPELL_FORCE_SHIELD_ARCANE_PURPLE_X3))
637 // Make sure nobody else is channeling the same target. Is it necessary?
638 if (!target->HasAura(SPELL_SCOURGING_CRYSTAL_CONTROLLER))
640 }
641
646};
647
648/*######
649## Quest 11306: Apply Heat and Stir
650######*/
651
665
666// 43972 - Mixing Blood
668{
670
671 void HandleEffect(SpellEffIndex /*effIndex*/)
672 {
673 if (Unit* caster = GetCaster())
674 if (Creature* trigger = caster->FindNearestCreature(NPC_GENERIC_TRIGGER_LAB, 100.0f))
675 trigger->AI()->DoCastSelf(SPELL_SPURTS_AND_SMOKE);
676 }
677
682};
683
684// 43375 - Mixing Vrykul Blood
686{
688
689 void HandleDummy(SpellEffIndex /*effIndex*/)
690 {
691 if (Unit* caster = GetCaster())
692 {
693 uint8 chance = urand(0, 99);
694 uint32 spellId = 0;
695
696 // 90% chance of getting one out of three failure effects
697 if (chance < 30)
698 spellId = SPELL_FAILED_MIX_1;
699 else if (chance < 60)
700 spellId = SPELL_FAILED_MIX_2;
701 else if (chance < 90)
702 spellId = SPELL_FAILED_MIX_3;
703 else // 10% chance of successful cast
704 spellId = SPELL_SUCCESSFUL_MIX;
705
706 caster->CastSpell(caster, spellId, true);
707 }
708 }
709
714};
715
716// 43376 - Failed Mix
733
734// 43378 - Failed Mix
751
752/*######
753## Quest 11448: The Explorers' League Outpost
754######*/
755
760
761// 51221 - Taxi to Explorers' League Outpost
781
782/*######
783## Quest 11323, 11325: In Worg's Clothing
784######*/
785
791
792// 43369 - Worg Disguise
818
819// 68347 - Worg Disguise
839
840/*######
841## Quest 11259: Towers of Certain Doom
842######*/
843
848
849// 49625 - Brave's Flare
851{
853
854 bool Validate(SpellInfo const* /*spellInfo*/) override
855 {
857 }
858
863
868};
869
870/*######
871## Quest 11245: Towers of Certain Doom
872######*/
873
878
879// 49634 - Sergeant's Flare
899
901{
925}
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
#define sObjectMgr
Definition ObjectMgr.h:1721
#define PET_FOLLOW_DIST
Definition PetDefines.h:85
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:107
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
bool roll_chance_i(int chance)
Definition Random.h:59
#define RegisterCreatureAI(ai_name)
Definition ScriptMgr.h:1139
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SEND_EVENT
SpellCastResult
@ SPELL_FAILED_FIZZLE
@ SPELL_CAST_OK
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_FORCE_REACTION
#define SpellCheckCastFn(F)
#define SpellEffectFn(F, I, N)
#define SpellCastFn(F)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraEffectRemoveFn(F, I, N, M)
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
@ UNIT_STAND_STATE_SIT
Definition UnitDefines.h:35
@ UNIT_STATE_EVADE
Definition Unit.h:242
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectApplyHandler > AfterEffectApply
Unit * GetTarget() const
bool _EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:293
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
void MoveFollow(Unit *target, float dist, ChaseAngle angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
void MoveTargetedHome()
void Clear()
Definition ObjectGuid.h:150
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
uint32 GetQuestId() const
Definition QuestDef.h:229
int32 CalcValue(WorldObject const *caster=nullptr, int32 const *basePoints=nullptr) const
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:483
HookList< CastHandler > AfterCast
HookList< CheckCastHandler > OnCheckCast
Unit * GetCaster() const
HookList< EffectHandler > OnEffectHit
Unit * GetHitUnit() const
int32 GetEffectValue() const
HookList< EffectHandler > OnEffectHitTarget
Item * GetCastItem() const
Unit * GetExplTargetUnit() const
SpellInfo const * GetSpellInfo() const
static void SendCastResult(Player *caster, SpellInfo const *spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError=SPELL_CUSTOM_ERROR_NONE, uint32 *param1=nullptr, uint32 *param2=nullptr)
Definition Spell.cpp:4177
void Despawn(Creature const *summon)
void Summon(Creature const *summon)
TaskContext & Repeat(std::chrono::duration< _Rep, _Period > const &duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(std::chrono::duration< _Rep, _Period > const &time, task_handler_t const &task)
TaskScheduler & Update(success_t const &callback=EmptyCallback)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
Definition Unit.h:769
bool IsVehicle() const
Definition Unit.h:887
Vehicle * GetVehicle() const
Definition Unit.h:1737
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool IsAlive() const
Definition Unit.h:1234
void AddUnitState(uint32 f)
Definition Unit.h:875
Unit * GetCharmerOrOwner() const
Definition Unit.h:1265
bool SetWalk(bool enable)
Definition Unit.cpp:13268
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
virtual float GetFollowAngle() const
Definition Unit.h:1782
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
Vehicle * GetVehicleKit() const
Definition Unit.h:1735
virtual bool IsEngaged() const
Definition Unit.h:1126
void Reset(bool evading=false)
Reapplies immunities and reinstalls accessories. Only has effect for creatures.
Definition Vehicle.cpp:137
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2099
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_fjord_braves_flare)
PrepareSpellScript(spell_fjord_failed_mix_concoction_1)
PrepareSpellScript(spell_fjord_failed_mix_concoction_2)
PrepareSpellScript(spell_fjord_guide_our_sights_fx_master)
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_fjord_mindless_abomination_explosion_fx_master)
PrepareSpellScript(spell_fjord_mindless_abomination_ping_master)
PrepareSpellScript(spell_fjord_mixing_blood)
void HandleEffect(SpellEffIndex)
PrepareSpellScript(spell_fjord_mixing_vrykul_blood)
PrepareSpellScript(spell_fjord_rivenwood_captives_not_on_quest)
PrepareSpellScript(spell_fjord_rivenwood_captives_on_quest)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_fjord_scourging_crystal_controller)
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_fjord_sergeants_flare)
PrepareAuraScript(spell_fjord_taxi_to_explorers_league_outpost)
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
PrepareAuraScript(spell_fjord_the_cleansing_cleansing_soul)
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
PrepareSpellScript(spell_fjord_the_cleansing_mirror_image_script_effect)
PrepareSpellScript(spell_fjord_the_cleansing_on_death_cast_on_master)
bool Validate(SpellInfo const *spellInfo) override
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_fjord_the_cleansing_shrine_cast)
PrepareSpellScript(spell_fjord_the_way_to_his_heart_anuniaq_net)
PrepareSpellScript(spell_fjord_the_way_to_his_heart_quest_complete)
bool Validate(SpellInfo const *spellInfo) override
bool Validate(SpellInfo const *spellInfo) override
PrepareSpellScript(spell_fjord_the_way_to_his_heart_reverse_cast)
PrepareAuraScript(spell_fjord_worg_disguise_dummy)
bool Validate(SpellInfo const *) override
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
PrepareAuraScript(spell_fjord_worg_disguise)
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:108
void UpdateAI(uint32 diff) override
void OnQuestAccept(Player *player, Quest const *quest) override
void SummonGladiator(uint32 entry)
void EnterEvadeMode(EvadeReason why) override
void Reset() override
void JustSummoned(Creature *summon) override
TaskScheduler _scheduler
void SummonedCreatureDies(Creature *summon, Unit *) override
void SummonedCreatureDespawn(Creature *summon) override
npc_daegarn(Creature *creature)
@ SPELL_SUMMON_WINTERSKORN_BERSERKER
@ SPELL_SUMMON_PUTRID_HORROR
@ SPELL_SUMMON_WINTERSKORN_TRIBESMAN
@ SPELL_SUMMON_BABY_RIVEN_WIDOWS
@ SPELL_SUMMON_FANGGORE_WORG
@ SPELL_SUMMON_WINTERSKORN_WOODSMAN
@ SPELL_SUMMON_GJALERBRON_WARRIOR
@ SPELL_SUMMON_GJALERBRON_SLEEPWATCHER
@ SPELL_SUMMON_WINTERSKORN_ORACLE
@ SPELL_SUMMON_FREED_MIST_WHISPER_SCOUT
@ SPELL_SUMMON_GJALERBRON_RUNECASTER
@ SPELL_SUMMON_DARKCLAW_BAT
SomeAssemblyRequired
@ SPELL_RANDOM_CIRCUMFERENCE_POINT_POISON
@ SPELL_RANDOM_CIRCUMFERENCE_POINT_BONE
@ SPELL_RANDOM_CIRCUMFERENCE_POINT_BONE_2
@ SPELL_MINDLESS_ABOMINATION_CONTROL
TowersOfCertainDoomAlliance
@ SPELL_SERGEANTS_FLARE_EFFECT
@ SPELL_FAILED_MIX_1
@ NPC_GENERIC_TRIGGER_LAB
@ SPELL_SUCCESSFUL_MIX
@ SPELL_FAILED_MIX_3
@ SAY_CONCOCTION_1
@ SAY_CONCOCTION_2
@ SPELL_SPURTS_AND_SMOKE
@ SPELL_FAILED_MIX_2
void AddSC_howling_fjord()
BringDownThoseShields
@ SPELL_FORCE_SHIELD_ARCANE_PURPLE_X3
@ SPELL_SCOURGING_CRYSTAL_CONTROLLER
TheExplorersLeagueOutpost
@ SPELL_TAXI_TO_EXPLORERS_LEAGUE
TowersOfCertainDoomHorde
@ SPELL_BRAVES_FLARE_EFFECT
@ SPELL_WORG_DISGUISE_DUMMY
@ SPELL_WORG_DISGUISE
@ QUEST_THE_CLEANSING_A
@ SPELL_CLEANSING_SOUL
@ QUEST_THE_CLEANSING_H
@ SPELL_MIRROR_IMAGE_AURA
@ SPELL_SUMMON_INNER_TURMOIL
@ SPELL_RECENT_MEDITATION
@ SPELL_FISHED_UP_REEF_SHARK
@ SPELL_CREATE_TASTY_REEF_FISH
static Position const daegarnSummonPosition
std::array< uint32, 11 > const CocoonSummonSpells
static Position const daegarnCenterPosition
@ SPELL_RANDOM_CIRCUMFERENCE_POINT_CANNON_PART_01
@ SPELL_RANDOM_CIRCUMFERENCE_POINT_CANNON_PART_02
@ QUEST_DEFEAT_AT_RING
@ NPC_PRISONER_3
@ NPC_JLARBORN
@ NPC_PRISONER_2
@ NPC_PRISONER_1