Skip to content

Commit 7d33481

Browse files
authored
Scripts/AQ40: Rewrite Huhuran (#31199)
1 parent 3a964bc commit 7d33481

File tree

2 files changed

+132
-104
lines changed

2 files changed

+132
-104
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
--
2+
UPDATE `creature_text` SET `Text` = '%s becomes enraged!', `BroadcastTextId` = 7798, `comment` = 'huhuran EMOTE_ENRAGE' WHERE `CreatureID` = 15509 AND `GroupID` = 0;
3+
UPDATE `creature_text` SET `BroadcastTextId` = 4428 WHERE `CreatureID` = 15509 AND `GroupID` = 1;
4+
5+
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_huhuran_wyvern_sting';
6+
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
7+
(26180, 'spell_huhuran_wyvern_sting');

src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp

Lines changed: 125 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -15,147 +15,168 @@
1515
* with this program. If not, see <http://www.gnu.org/licenses/>.
1616
*/
1717

18-
/* ScriptData
19-
SDName: Boss_Huhuran
20-
SD%Complete: 100
21-
SDComment:
22-
SDCategory: Temple of Ahn'Qiraj
23-
EndScriptData */
18+
/*
19+
* Timers requires to be revisited
20+
*/
2421

2522
#include "ScriptMgr.h"
2623
#include "ScriptedCreature.h"
24+
#include "SpellAuraEffects.h"
25+
#include "SpellScript.h"
2726
#include "temple_of_ahnqiraj.h"
2827

29-
enum Huhuran
28+
enum HuhuranTexts
3029
{
31-
EMOTE_FRENZY_KILL = 0,
32-
EMOTE_BERSERK = 1,
30+
EMOTE_ENRAGE = 0,
31+
EMOTE_BERSERK = 1
32+
};
3333

34-
SPELL_FRENZY = 26051,
34+
enum HuhuranSpells
35+
{
36+
SPELL_ACID_SPIT = 26050,
37+
SPELL_NOXIOUS_POISON = 26053,
38+
SPELL_WYVERN_STING = 26180,
39+
SPELL_ENRAGE = 26051,
3540
SPELL_BERSERK = 26068,
36-
SPELL_POISONBOLT = 26052,
37-
SPELL_NOXIOUSPOISON = 26053,
38-
SPELL_WYVERNSTING = 26180,
39-
SPELL_ACIDSPIT = 26050
41+
42+
SPELL_WYVERN_STING_DAMAGE = 26233
4043
};
4144

42-
class boss_huhuran : public CreatureScript
45+
enum HuhuranEvents
4346
{
44-
public:
45-
boss_huhuran() : CreatureScript("boss_huhuran") { }
47+
EVENT_ACID_SPIT = 1,
48+
EVENT_NOXIOUS_POISON,
49+
EVENT_WYVERN_STING,
50+
EVENT_ENRAGE,
51+
EVENT_BERSERK
52+
};
53+
54+
// 15509 - Princess Huhuran
55+
struct boss_huhuran : public BossAI
56+
{
57+
boss_huhuran(Creature* creature) : BossAI(creature, DATA_HUHURAN), _berserkTriggered(false) { }
58+
59+
void Reset() override
60+
{
61+
_Reset();
62+
_berserkTriggered = false;
63+
}
4664

47-
CreatureAI* GetAI(Creature* creature) const override
65+
void JustEngagedWith(Unit* who) override
4866
{
49-
return GetAQ40AI<boss_huhuranAI>(creature);
67+
BossAI::JustEngagedWith(who);
68+
69+
events.ScheduleEvent(EVENT_ACID_SPIT, 0s, 15s);
70+
events.ScheduleEvent(EVENT_NOXIOUS_POISON, 10s, 20s);
71+
events.ScheduleEvent(EVENT_WYVERN_STING, 35s, 45s);
72+
events.ScheduleEvent(EVENT_ENRAGE, 10s, 25s);
5073
}
5174

52-
struct boss_huhuranAI : public BossAI
75+
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
5376
{
54-
boss_huhuranAI(Creature* creature) : BossAI(creature, DATA_HUHURAN)
77+
if (!_berserkTriggered && me->HealthBelowPctDamaged(30, damage))
5578
{
56-
Initialize();
79+
_berserkTriggered = true;
80+
events.CancelEvent(EVENT_ENRAGE);
81+
events.ScheduleEvent(EVENT_BERSERK, 0s);
5782
}
83+
}
5884

59-
void Initialize()
85+
void OnSpellCast(SpellInfo const* spell) override
86+
{
87+
switch (spell->Id)
6088
{
61-
Frenzy_Timer = urand(25000, 35000);
62-
Wyvern_Timer = urand(18000, 28000);
63-
Spit_Timer = 8000;
64-
PoisonBolt_Timer = 4000;
65-
NoxiousPoison_Timer = urand(10000, 20000);
66-
FrenzyBack_Timer = 15000;
67-
68-
Frenzy = false;
69-
Berserk = false;
89+
case SPELL_ENRAGE:
90+
Talk(EMOTE_ENRAGE);
91+
break;
92+
case SPELL_BERSERK:
93+
Talk(EMOTE_BERSERK);
94+
break;
95+
default:
96+
break;
7097
}
98+
}
7199

72-
uint32 Frenzy_Timer;
73-
uint32 Wyvern_Timer;
74-
uint32 Spit_Timer;
75-
uint32 PoisonBolt_Timer;
76-
uint32 NoxiousPoison_Timer;
77-
uint32 FrenzyBack_Timer;
100+
void UpdateAI(uint32 diff) override
101+
{
102+
if (!UpdateVictim())
103+
return;
78104

79-
bool Frenzy;
80-
bool Berserk;
105+
events.Update(diff);
81106

82-
void Reset() override
83-
{
84-
Initialize();
85-
_Reset();
86-
}
107+
if (me->HasUnitState(UNIT_STATE_CASTING))
108+
return;
87109

88-
void UpdateAI(uint32 diff) override
110+
while (uint32 eventId = events.ExecuteEvent())
89111
{
90-
//Return since we have no target
91-
if (!UpdateVictim())
92-
return;
93-
94-
//Frenzy_Timer
95-
if (!Frenzy && Frenzy_Timer <= diff)
96-
{
97-
DoCast(me, SPELL_FRENZY);
98-
Talk(EMOTE_FRENZY_KILL);
99-
Frenzy = true;
100-
PoisonBolt_Timer = 3000;
101-
Frenzy_Timer = urand(25000, 35000);
102-
} else Frenzy_Timer -= diff;
103-
104-
// Wyvern Timer
105-
if (Wyvern_Timer <= diff)
112+
switch (eventId)
106113
{
107-
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
108-
DoCast(target, SPELL_WYVERNSTING);
109-
Wyvern_Timer = urand(15000, 32000);
110-
} else Wyvern_Timer -= diff;
114+
case EVENT_ACID_SPIT:
115+
DoCastVictim(SPELL_ACID_SPIT);
116+
events.Repeat(10s, 15s);
117+
break;
118+
case EVENT_NOXIOUS_POISON:
119+
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
120+
DoCast(target, SPELL_NOXIOUS_POISON);
121+
events.Repeat(10s, 25s);
122+
break;
123+
case EVENT_WYVERN_STING:
124+
DoCastSelf(SPELL_WYVERN_STING);
125+
events.Repeat(25s, 35s);
126+
break;
127+
case EVENT_ENRAGE:
128+
DoCastSelf(SPELL_ENRAGE);
129+
events.Repeat(10s, 20s);
130+
break;
131+
case EVENT_BERSERK:
132+
DoCastSelf(SPELL_BERSERK);
133+
break;
134+
default:
135+
break;
136+
}
111137

112-
//Spit Timer
113-
if (Spit_Timer <= diff)
114-
{
115-
DoCastVictim(SPELL_ACIDSPIT);
116-
Spit_Timer = urand(5000, 10000);
117-
} else Spit_Timer -= diff;
138+
if (me->HasUnitState(UNIT_STATE_CASTING))
139+
return;
140+
}
118141

119-
//NoxiousPoison_Timer
120-
if (NoxiousPoison_Timer <= diff)
121-
{
122-
DoCastVictim(SPELL_NOXIOUSPOISON);
123-
NoxiousPoison_Timer = urand(12000, 24000);
124-
} else NoxiousPoison_Timer -= diff;
142+
DoMeleeAttackIfReady();
143+
}
125144

126-
//PoisonBolt only if frenzy or berserk
127-
if (Frenzy || Berserk)
128-
{
129-
if (PoisonBolt_Timer <= diff)
130-
{
131-
DoCastVictim(SPELL_POISONBOLT);
132-
PoisonBolt_Timer = 3000;
133-
} else PoisonBolt_Timer -= diff;
134-
}
145+
private:
146+
bool _berserkTriggered;
147+
};
135148

136-
//FrenzyBack_Timer
137-
if (Frenzy && FrenzyBack_Timer <= diff)
138-
{
139-
me->InterruptNonMeleeSpells(false);
140-
Frenzy = false;
141-
FrenzyBack_Timer = 15000;
142-
} else FrenzyBack_Timer -= diff;
149+
// 26180 - Wyvern Sting
150+
class spell_huhuran_wyvern_sting : public AuraScript
151+
{
152+
PrepareAuraScript(spell_huhuran_wyvern_sting);
143153

144-
if (!Berserk && HealthBelowPct(31))
145-
{
146-
me->InterruptNonMeleeSpells(false);
147-
Talk(EMOTE_BERSERK);
148-
DoCast(me, SPELL_BERSERK);
149-
Berserk = true;
150-
}
154+
bool Validate(SpellInfo const* /*spellInfo*/) override
155+
{
156+
return ValidateSpellInfo({ SPELL_WYVERN_STING_DAMAGE });
157+
}
151158

152-
DoMeleeAttackIfReady();
159+
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
160+
{
161+
AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode();
162+
163+
if (Unit* caster = GetCaster())
164+
{
165+
int32 damage = removeMode == AURA_REMOVE_BY_ENEMY_SPELL ? 3000 : 500;
166+
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
167+
args.AddSpellBP0(damage);
168+
caster->CastSpell(GetTarget(), SPELL_WYVERN_STING_DAMAGE, args);
153169
}
154-
};
170+
}
155171

172+
void Register() override
173+
{
174+
AfterEffectRemove += AuraEffectRemoveFn(spell_huhuran_wyvern_sting::AfterRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
175+
}
156176
};
157177

158178
void AddSC_boss_huhuran()
159179
{
160-
new boss_huhuran();
180+
RegisterAQ40CreatureAI(boss_huhuran);
181+
RegisterSpellScript(spell_huhuran_wyvern_sting);
161182
}

0 commit comments

Comments
 (0)