TrinityCore
Loading...
Searching...
No Matches
zone_nagrand.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/* ScriptData
19SDName: Nagrand
20SD%Complete: 90
21SDComment: Quest support: 9868, 9874, 10085. TextId's unknown for altruis_the_sufferer and greatmother_geyah (npc_text)
22SDCategory: Nagrand
23EndScriptData */
24
25/* ContentData
26npc_maghar_captive
27EndContentData */
28
29#include "ScriptMgr.h"
30#include "GameObject.h"
31#include "GameObjectAI.h"
32#include "MotionMaster.h"
33#include "Player.h"
34#include "ScriptedEscortAI.h"
35#include "ScriptedGossip.h"
36#include "SpellInfo.h"
37#include "SpellScript.h"
38#include "TemporarySummon.h"
39
40/*######
41## npc_maghar_captive
42#####*/
43
68
69static float m_afAmbushA[]= {-1568.805786f, 8533.873047f, 1.958f};
70static float m_afAmbushB[]= {-1491.554321f, 8506.483398f, 1.248f};
71
73{
74public:
75 npc_maghar_captive() : CreatureScript("npc_maghar_captive") { }
76
78 {
79 npc_maghar_captiveAI(Creature* creature) : EscortAI(creature)
80 {
81 Initialize();
82 }
83
85 {
87 HealTimer = 0;
88 FrostShockTimer = 6000;
89 }
90
94
95 void Reset() override
96 {
97 Initialize();
98 }
99
100 void JustEngagedWith(Unit* /*who*/) override
101 {
103 }
104
105 void JustDied(Unit* /*killer*/) override
106 {
108 return;
109
110 if (Player* player = GetPlayerForEscort())
111 {
112 if (player->GetQuestStatus(QUEST_TOTEM_KARDASH_H) != QUEST_STATUS_COMPLETE)
113 player->FailQuest(QUEST_TOTEM_KARDASH_H);
114 }
115 }
116
117 void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
118 {
119 switch (waypointId)
120 {
121 case 7:
123
125 temp->AI()->Talk(SAY_MAG_MORE_REPLY);
126
130 break;
131 case 16:
133
134 if (Player* player = GetPlayerForEscort())
135 player->GroupEventHappens(QUEST_TOTEM_KARDASH_H, me);
136 break;
137 }
138 }
139
140 void JustSummoned(Creature* summoned) override
141 {
142 if (summoned->GetEntry() == NPC_MURK_BRUTE)
143 summoned->AI()->Talk(SAY_MAG_NO_ESCAPE);
144
145 if (summoned->IsTotem())
146 return;
147
148 summoned->SetWalk(false);
150 summoned->AI()->AttackStart(me);
151
152 }
153
154 void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* spellInfo) override
155 {
156 if (spellInfo->Id == SPELL_CHAIN_LIGHTNING)
157 {
158 if (rand32() % 10)
159 return;
160
162 }
163 }
164
165 void UpdateAI(uint32 diff) override
166 {
167 EscortAI::UpdateAI(diff);
168
169 if (!UpdateVictim())
170 return;
171
173 return;
174
175 if (ChainLightningTimer <= diff)
176 {
178 ChainLightningTimer = urand(7000, 14000);
179 }
180 else
181 ChainLightningTimer -= diff;
182
183 if (HealthBelowPct(30))
184 {
185 if (HealTimer <= diff)
186 {
188 HealTimer = 5000;
189 }
190 else
191 HealTimer -= diff;
192 }
193
194 if (FrostShockTimer <= diff)
195 {
197 FrostShockTimer = urand(7500, 15000);
198 }
199 else
200 FrostShockTimer -= diff;
201
203 }
204
220 };
221
222 CreatureAI* GetAI(Creature* creature) const override
223 {
224 return new npc_maghar_captiveAI(creature);
225 }
226
227};
228
229/*#####
230## npc_kurenai_captive
231#####*/
232
257
258static float kurenaiAmbushA[]= {-1568.805786f, 8533.873047f, 1.958f};
259static float kurenaiAmbushB[]= {-1491.554321f, 8506.483398f, 1.248f};
260
262{
263public:
264 npc_kurenai_captive() : CreatureScript("npc_kurenai_captive") { }
265
267 {
269 {
270 Initialize();
271 }
272
274 {
275 ChainLightningTimer = 1000;
276 HealTimer = 0;
277 FrostShockTimer = 6000;
278 }
279
283
284 void Reset() override
285 {
286 Initialize();
287 }
288
289 void JustEngagedWith(Unit* /*who*/) override
290 {
292 }
293
294 void JustDied(Unit* /*killer*/) override
295 {
297 return;
298
299 if (Player* player = GetPlayerForEscort())
300 {
301 if (player->GetQuestStatus(QUEST_TOTEM_KARDASH_A) != QUEST_STATUS_COMPLETE)
302 player->FailQuest(QUEST_TOTEM_KARDASH_A);
303 }
304 }
305
306 void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
307 {
308 switch (waypointId)
309 {
310 case 3:
311 {
313
316
320 break;
321 }
322 case 7:
323 {
325
326 if (Player* player = GetPlayerForEscort())
327 player->GroupEventHappens(QUEST_TOTEM_KARDASH_A, me);
328 break;
329 }
330 }
331 }
332
333 void JustSummoned(Creature* summoned) override
334 {
335 if (summoned->GetEntry() == NPC_KUR_MURK_BRUTE)
337
338 // This function is for when we summoned enemies to fight - so that does NOT mean we should make our totem count in this!
339 if (summoned->IsTotem())
340 return;
341
342 summoned->SetWalk(false);
344 summoned->AI()->AttackStart(me);
345 }
346
347 void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* spellInfo) override
348 {
349 if (spellInfo->Id == SPELL_KUR_CHAIN_LIGHTNING)
350 {
351 if (rand32() % 30)
352 return;
353
355 }
356
357 if (spellInfo->Id == SPELL_KUR_FROST_SHOCK)
358 {
359 if (rand32() % 30)
360 return;
361
363 }
364 }
365
366 void UpdateAI(uint32 diff) override
367 {
368 EscortAI::UpdateAI(diff);
369
370 if (!UpdateVictim())
371 return;
372
374 return;
375
376 if (ChainLightningTimer <= diff)
377 {
379 ChainLightningTimer = urand(7000, 14000);
380 } else ChainLightningTimer -= diff;
381
382 if (HealthBelowPct(30))
383 {
384 if (HealTimer <= diff)
385 {
387 HealTimer = 5000;
388 } else HealTimer -= diff;
389 }
390
391 if (FrostShockTimer <= diff)
392 {
394 FrostShockTimer = urand(7500, 15000);
395 } else FrostShockTimer -= diff;
396
398 }
399
415 };
416
417 CreatureAI* GetAI(Creature* creature) const override
418 {
419 return new npc_kurenai_captiveAI(creature);
420 }
421};
422
435
437{
438public:
439 npc_nagrand_banner() : CreatureScript("npc_nagrand_banner") { }
440
442 {
443 npc_nagrand_bannerAI(Creature* creature) : ScriptedAI(creature), bannered(false)
444 {
446 {
448 });
449 }
450
451 void Reset() override
452 {
454 }
455
456 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
457 {
458 if (spellInfo->Id == SPELL_PLANT_WARMAUL_OGRE_BANNER || spellInfo->Id == SPELL_PLANT_KIL_SORROW_BANNER)
459 bannered = true;
460 }
461
462 void UpdateAI(uint32 diff) override
463 {
464 if (!UpdateVictim())
465 return;
466
467 scheduler.Update(diff, [this]
468 {
470 });
471 }
472
474 {
475 return bannered;
476 }
477
478 protected:
480
481 private:
483 };
484
486 {
493
497
498 void JustEngagedWith(Unit* /*who*/) override
499 {
500 has_fled = false;
501 interrupt_cooldown = 20000;
503 .Schedule(Seconds(0), [this](TaskContext ArcaneMissiles)
504 {
506 ArcaneMissiles.Repeat(Milliseconds(2400), Milliseconds(3800));
507 })
508 .Schedule(Seconds(3), Seconds(6), [this](TaskContext ChainsOfIce)
509 {
511 DoCast(target, SPELL_CHAINS_OF_ICE, true);
512 ChainsOfIce.Repeat(Seconds(20),Seconds(25));
513 });
514 }
515
516 void UpdateAI(uint32 diff) override
517 {
518 if (!UpdateVictim() || !me->GetVictim())
519 return;
520
521 interrupt_cooldown += diff;
523 return;
524
526 {
529 }
530
531 scheduler.Update(diff, [this]
532 {
534 });
535 }
536
537 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
538 {
539 if (!has_fled && me->GetHealth() > damage && me->HealthBelowPctDamaged(15, damage))
540 {
542 has_fled = true;
543 }
544 }
545
546 private:
549 };
550
552 {
554 {
555 SPELL_MIND_SEAR = 32000
556 };
557
559 {
560 }
561
562 void JustEngagedWith(Unit* /*who*/) override
563 {
565 .Schedule(Milliseconds(4500), [this](TaskContext MindSear)
566 {
568 MindSear.Repeat(Milliseconds(7000), Milliseconds(11000));
569 });
570 }
571 };
572
574 {
579
583
584 void JustEngagedWith(Unit* /*who*/) override
585 {
586 used_bloodthirst = false;
587 }
588
589 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
590 {
591 if (!used_bloodthirst && me->GetHealth() > damage && me->HealthBelowPctDamaged(50, damage))
592 {
594 used_bloodthirst = true;
595 }
596 }
597
598 private:
600 };
601
603 {
608
610 {
611 }
612
613 void JustEngagedWith(Unit* /*who*/) override
614 {
615 used_transform = false;
616 }
617
618 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
619 {
620 if (!used_transform && me->GetHealth() > damage && me->HealthBelowPctDamaged(65, damage))
621 {
623 used_transform = true;
624 }
625 }
626
627 private:
629 };
630
632 {
639
641 {
642 }
643
644 void JustEngagedWith(Unit* /*who*/) override
645 {
646 used_healing = false;
648 .Schedule(Seconds(2), [this](TaskContext /*SearingTotem*/)
649 {
651 })
652 .Schedule(Seconds(6), [this](TaskContext FrostShock)
653 {
655 FrostShock.Repeat(Seconds(12));
656 });
657 }
658
659 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
660 {
661 if (!used_healing && me->GetHealth() > damage && me->HealthBelowPctDamaged(50, damage))
662 {
664 used_healing = true;
665 }
666 }
667
668 private:
670 };
671
672 CreatureAI* GetAI(Creature* creature) const override
673 {
674 switch (creature->GetEntry())
675 {
677 return new npc_kil_sorrow_spellbinderAI(creature);
679 return new npc_kil_sorrow_cultistAI(creature);
681 return new npc_kil_sorrow_deathswornAI(creature);
683 return new npc_giselda_the_croneAI(creature);
685 return new npc_warmaul_shamanAI(creature);
686 default:
687 return new npc_nagrand_bannerAI(creature);
688 }
689 }
690};
691
693{
694public:
695 condition_nagrand_banner() : ConditionScript("conditition_nagrand_banner") {}
696
697 bool OnConditionCheck(Condition const* condition, ConditionSourceInfo& sourceInfo) override
698 {
699 WorldObject* target = sourceInfo.mConditionTargets[condition->ConditionTarget];
700 if (Creature* creature = target->ToCreature())
701 {
703 return !ai->IsBannered();
704 }
705 return false;
706 }
707};
708
716
717// 31959 - Fire Bomb Target Summon Trigger
719{
721
722 bool Validate(SpellInfo const* /*spellInfo*/) override
723 {
725 }
726
727 void HandleScript(SpellEffIndex /*effIndex*/)
728 {
729 if (TempSummon* casterSummon = GetCaster()->ToTempSummon())
730 if (Unit* summoner = casterSummon->GetSummonerUnit())
731 casterSummon->CastSpell(summoner, SPELL_FIRE_BOMB_TARGET_SUMMON_EFFECT);
732 }
733
738};
739
740// 31960 - Fire Bomb Target Summon Effect
760
761// 31961 - Fire Bomb
783
uint32_t uint32
Definition Define.h:133
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:27
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:105
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
uint32 rand32()
Definition Random.cpp:70
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
@ STATE_ESCORT_ESCORTING
SpellEffIndex
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_SCRIPT_EFFECT
@ FACTION_ESCORTEE_A_NEUTRAL_ACTIVE
@ FACTION_ESCORTEE_H_NEUTRAL_ACTIVE
#define SpellEffectFn(F, I, N)
#define CAST_AI(a, b)
Definition UnitAI.h:27
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
@ UNIT_STATE_CASTING
Definition Unit.h:235
DamageEffectType
Definition Unit.h:352
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void DoFleeToGetAssistance()
Definition Creature.cpp:973
CreatureAI * AI() const
Definition Creature.h:154
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
static Creature * ToCreature(Object *o)
Definition Object.h:186
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
uint32 GetQuestId() const
Definition QuestDef.h:229
uint32 Id
Definition SpellInfo.h:289
Unit * GetCaster() const
HookList< EffectHandler > OnEffectHit
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
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)
TaskScheduler & SetValidator(P &&predicate)
Sets a validator which is asked if tasks are allowed to be executed.
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:30
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
void SetFaction(uint32 faction) override
Definition Unit.h:974
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
Unit * EnsureVictim() const
Definition Unit.h:861
uint32 GetHealth() const
Definition Unit.h:913
bool SetWalk(bool enable)
Definition Unit.cpp:13268
Unit * GetVictim() const
Definition Unit.h:859
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition Unit.h:918
bool IsTotem() const
Definition Unit.h:886
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1992
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool OnConditionCheck(Condition const *condition, ConditionSourceInfo &sourceInfo) override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
PrepareSpellScript(spell_nagrand_fire_bomb_damage_missile)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_nagrand_fire_bomb_target_summon_effect)
PrepareSpellScript(spell_nagrand_fire_bomb_target_summon_trigger)
bool Validate(SpellInfo const *) override
WorldObject * mConditionTargets[MAX_CONDITION_TARGETS]
uint8 ConditionTarget
void Start(bool isActiveAttacker=true, ObjectGuid playerGUID=ObjectGuid::Empty, Quest const *quest=nullptr, bool instantRespawn=false, bool canLoopPath=false)
bool HasEscortState(uint32 escortState)
void LoadPath(uint32 pathId)
Player * GetPlayerForEscort()
void UpdateAI(uint32 diff) override
float GetPositionZ() const
Definition Position.h:81
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80
bool HealthBelowPct(uint32 pct) const
void JustSummoned(Creature *summoned) override
void OnQuestAccept(Player *player, Quest const *quest) override
void SpellHitTarget(WorldObject *, SpellInfo const *spellInfo) override
void WaypointReached(uint32 waypointId, uint32) override
void SpellHitTarget(WorldObject *, SpellInfo const *spellInfo) override
void OnQuestAccept(Player *player, Quest const *quest) override
void WaypointReached(uint32 waypointId, uint32) override
void JustSummoned(Creature *summoned) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
KurenaiCaptive
@ QUEST_TOTEM_KARDASH_A
@ NPC_KUR_MURK_BRUTE
@ SAY_KUR_NO_ESCAPE
@ PATH_ESCORT_KURENAI_CAPTIVE
@ SPELL_KUR_HEALING_WAVE
@ SAY_KUR_MORE_TWO
@ SAY_KUR_LIGHTNING
@ SPELL_KUR_FROST_SHOCK
@ SPELL_KUR_EARTHBIND_TOTEM
@ SPELL_KUR_CHAIN_LIGHTNING
@ SAY_KUR_MORE
@ NPC_KUR_MURK_PUTRIFIER
@ SAY_KUR_COMPLETE
@ SAY_KUR_START
@ SAY_KUR_SHOCK
@ NPC_KUR_MURK_SCAVENGER
@ NPC_KUR_MURK_RAIDER
void AddSC_nagrand()
PlantBannerQuests
@ NPC_GISELDA_THE_CRONE
@ SPELL_PLANT_WARMAUL_OGRE_BANNER
@ SPELL_PLANT_KIL_SORROW_BANNER
@ NPC_WARMAUL_SHAMAN
@ NPC_KIL_SORROW_DEATHSWORN
@ NPC_KIL_SORROW_SPELLBINDER
@ NPC_KIL_SORROW_CULTIST
@ NPC_WARMAUL_REAVER
static float kurenaiAmbushA[]
FireBomb
@ SPELL_FIRE_BOMB_DAMAGE_MISSILE
@ SPELL_FIRE_BOMB_TARGET_SUMMON_EFFECT
@ SPELL_FIRE_BOMB_FLAMES
@ SPELL_FIRE_BOMB_SUMMON_CATAPULT_BLAZE
MagharCaptive
@ QUEST_TOTEM_KARDASH_H
@ SPELL_EARTHBIND_TOTEM
@ NPC_MURK_SCAVENGER
@ NPC_MURK_RAIDER
@ SAY_MAG_START
@ PATH_ESCORT_MAGHAR_CAPTIVE
@ SAY_MAG_SHOCK
@ SAY_MAG_MORE_REPLY
@ SAY_MAG_LIGHTNING
@ SAY_MAG_MORE
@ SPELL_FROST_SHOCK
@ SAY_MAG_COMPLETE
@ SPELL_HEALING_WAVE
@ NPC_MURK_PUTRIFIER
@ SPELL_CHAIN_LIGHTNING
@ NPC_MURK_BRUTE
@ SAY_MAG_NO_ESCAPE
static float m_afAmbushB[]
static float m_afAmbushA[]
static float kurenaiAmbushB[]