fix(Core/Events): Apothecary Hummel (#10615)

* Fix(Core/Events): Apothecary Hummel

Co-authored-by: sirikfoll <sirikfoll@hotmail.com>
Co-authored-by: Killyana <Killyana@users.noreply.github.com>

* missed return

* Missing include

* Fixed delete

Co-authored-by: sirikfoll <sirikfoll@hotmail.com>
Co-authored-by: Killyana <Killyana@users.noreply.github.com>
This commit is contained in:
Nefertumm
2022-02-11 06:00:10 -03:00
committed by GitHub
parent 5d8b472ed7
commit c9ac48e824
7 changed files with 862 additions and 316 deletions

View File

@@ -0,0 +1,539 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "LFGMgr.h"
#include "Player.h"
#include "Group.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "shadowfang_keep.h"
#include "GridNotifiersImpl.h"
#include "TaskScheduler.h"
enum ApothecarySpells
{
SPELL_ALLURING_PERFUME = 68589,
SPELL_PERFUME_SPRAY = 68607,
SPELL_CHAIN_REACTION = 68821,
SPELL_SUMMON_TABLE = 69218,
SPELL_PERMANENT_FEIGN_DEATH = 29266,
SPELL_QUIET_SUICIDE = 3617,
SPELL_COLOGNE_SPRAY = 68948,
SPELL_VALIDATE_AREA = 68644,
SPELL_THROW_COLOGNE = 68841,
SPELL_BUNNY_LOCKDOWN = 69039,
SPELL_THROW_PERFUME = 68799,
SPELL_PERFUME_SPILL = 68798,
SPELL_COLOGNE_SPILL = 68614,
SPELL_PERFUME_SPILL_DAMAGE = 68927,
SPELL_COLOGNE_SPILL_DAMAGE = 68934
};
enum ApothecarySays
{
SAY_INTRO_0 = 0,
SAY_INTRO_1 = 1,
SAY_INTRO_2 = 2,
SAY_CALL_BAXTER = 3,
SAY_CALL_FRYE = 4,
SAY_HUMMEL_DEATH = 5,
SAY_SUMMON_ADDS = 6,
SAY_BAXTER_DEATH = 0,
SAY_FRYE_DEATH = 0
};
enum ApothecaryMisc
{
ACTION_START_EVENT = 1,
ACTION_START_FIGHT = 2,
GOSSIP_OPTION_START = 0,
GOSSIP_MENU_HUMMEL = 10847,
QUEST_YOUVE_BEEN_SERVED = 14488,
NPC_APOTHECARY_FRYE = 36272,
NPC_APOTHECARY_BAXTER = 36565,
NPC_VIAL_BUNNY = 36530,
NPC_CROWN_APOTHECARY = 36885,
PHASE_ALL = 0,
PHASE_INTRO = 1
};
Position const BaxterMovePos = { -221.4115f, 2206.825f, 79.93151f, 0.0f };
Position const FryeMovePos = { -196.2483f, 2197.224f, 79.9315f, 0.0f };
class boss_apothecary_hummel : public CreatureScript
{
public:
boss_apothecary_hummel() : CreatureScript("boss_apothecary_hummel") { }
struct boss_apothecary_hummelAI : public BossAI
{
boss_apothecary_hummelAI(Creature* creature) : BossAI(creature, DATA_APOTHECARY_HUMMEL), _deadCount(0), _isDead(false)
{
_scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
{
if (menuId == GOSSIP_MENU_HUMMEL && gossipListId == GOSSIP_OPTION_START)
{
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
CloseGossipMenuFor(player);
DoAction(ACTION_START_EVENT);
}
}
void Reset() override
{
_Reset();
_deadCount = 0;
_isDead = false;
_phase = PHASE_ALL;
me->SetFaction(FACTION_FRIENDLY);
me->SummonCreatureGroup(1);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
void EnterEvadeMode() override
{
summons.DespawnAll();
_EnterEvadeMode();
}
void DoAction(int32 action) override
{
if (action == ACTION_START_EVENT && events.IsInPhase(PHASE_ALL))
{
events.SetPhase(PHASE_INTRO);
_phase = PHASE_INTRO;
_scheduler.Schedule(1ms, [this](TaskContext /*context*/)
{
Talk(SAY_INTRO_0);
})
.Schedule(4s, [this](TaskContext /*context*/)
{
Talk(SAY_INTRO_1);
})
.Schedule(8s, [this](TaskContext /*context*/)
{
Talk(SAY_INTRO_2);
})
.Schedule(12s, [this](TaskContext context)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
DoZoneInCombat();
context.Schedule(6s, [this](TaskContext /*context*/) // Call Baxter
{
Talk(SAY_CALL_BAXTER);
EntryCheckPredicate pred(NPC_APOTHECARY_BAXTER);
summons.DoAction(ACTION_START_FIGHT, pred);
summons.DoZoneInCombat(NPC_APOTHECARY_BAXTER);
})
.Schedule(14s, [this](TaskContext /*context*/) // Call Frye
{
Talk(SAY_CALL_FRYE);
EntryCheckPredicate pred(NPC_APOTHECARY_FRYE);
summons.DoAction(ACTION_START_FIGHT, pred);
})
.Schedule(3640ms, [this](TaskContext context) // Perfume spray
{
DoCastVictim(SPELL_PERFUME_SPRAY);
context.Repeat(3640ms);
})
.Schedule(15s, [this](TaskContext context) // Chain Reaction
{
DoCastVictim(SPELL_SUMMON_TABLE, true);
DoCastAOE(SPELL_CHAIN_REACTION);
context.Repeat(25s);
})
.Schedule(15s, [this](TaskContext /*context*/) // Call Crazed Apothecary (text)
{
Talk(SAY_SUMMON_ADDS);
})
.Schedule(15s, [this](TaskContext context) // Call Crazed Apothecary
{
instance->SetData(DATA_SPAWN_VALENTINE_ADDS, 0);
context.Repeat(4s, 6s);
});
std::list<Creature*> trashs;
me->GetCreatureListWithEntryInGrid(trashs, NPC_CROWN_APOTHECARY, 100.f);
for (Creature* crea : trashs)
{
crea->DespawnOrUnsummon();
}
});
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->SetFaction(FACTION_MONSTER);
summons.DoAction(ACTION_START_EVENT);
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (damage >= me->GetHealth())
{
if (_deadCount < 2)
{
damage = me->GetHealth() - 1;
if (!_isDead)
{
_isDead = true;
me->RemoveAurasDueToSpell(SPELL_ALLURING_PERFUME);
DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH, true);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
Talk(SAY_HUMMEL_DEATH);
}
}
}
}
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() == NPC_APOTHECARY_FRYE || summon->GetEntry() == NPC_APOTHECARY_BAXTER)
{
_deadCount++;
}
if (me->HasAura(SPELL_PERMANENT_FEIGN_DEATH) && _deadCount == 2)
{
DoCastSelf(SPELL_QUIET_SUICIDE, true);
}
}
void JustDied(Unit* /*killer*/) override
{
if (!_isDead)
{
Talk(SAY_HUMMEL_DEATH);
}
_scheduler.CancelAll();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
instance->SetBossState(DATA_APOTHECARY_HUMMEL, DONE);
Map::PlayerList const& players = me->GetMap()->GetPlayers();
if (!players.IsEmpty())
{
if (Group* group = players.begin()->GetSource()->GetGroup())
{
if (group->isLFGGroup())
{
sLFGMgr->FinishDungeon(group->GetGUID(), 288, me->GetMap());
}
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() && _phase != PHASE_INTRO)
{
return;
}
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
private:
uint8 _deadCount;
bool _isDead;
TaskScheduler _scheduler;
uint8 _phase;
};
bool OnQuestReward(Player* /*player*/, Creature* creature, const Quest* quest, uint32 /*slot*/) override
{
if (quest->GetQuestId() == QUEST_YOUVE_BEEN_SERVED)
{
if (creature && creature->AI())
{
creature->AI()->DoAction(ACTION_START_EVENT);
}
}
return true;
}
CreatureAI* GetAI(Creature* creature) const override
{
return new boss_apothecary_hummelAI(creature);
}
};
struct npc_apothecary_genericAI : public ScriptedAI
{
npc_apothecary_genericAI(Creature* creature, Position pos) : ScriptedAI(creature), _movePos(pos) { }
void DoAction(int32 action) override
{
if (action == ACTION_START_EVENT)
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->SetFaction(FACTION_MONSTER);
me->GetMotionMaster()->MovePoint(1, _movePos);
}
else if (action == ACTION_START_FIGHT)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
DoZoneInCombat();
}
}
void MovementInform(uint32 type, uint32 pointId) override
{
if (type == POINT_MOTION_TYPE && pointId == 1)
{
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
}
}
protected:
Position _movePos;
};
struct npc_apothecary_frye : public npc_apothecary_genericAI
{
npc_apothecary_frye(Creature* creature) : npc_apothecary_genericAI(creature, FryeMovePos) { }
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_FRYE_DEATH);
}
};
struct npc_apothecary_baxter : public npc_apothecary_genericAI
{
npc_apothecary_baxter(Creature* creature) : npc_apothecary_genericAI(creature, BaxterMovePos)
{
_scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
_scheduler.CancelAll();
_scheduler.Schedule(7s, [this](TaskContext context)
{
DoCastVictim(SPELL_COLOGNE_SPRAY);
context.Repeat(4s);
})
.Schedule(12s, [this](TaskContext context)
{
DoCastVictim(SPELL_SUMMON_TABLE);
DoCastVictim(SPELL_CHAIN_REACTION);
context.Repeat(25s);
});
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_BAXTER_DEATH);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
private:
TaskScheduler _scheduler;
};
// 68965 - [DND] Lingering Fumes Targetting (starter)
class spell_apothecary_lingering_fumes : public SpellScript
{
PrepareSpellScript(spell_apothecary_lingering_fumes);
void HandleAfterCast()
{
Unit* caster = GetCaster();
if (!caster->IsInCombat() || roll_chance_i(50))
return;
std::list<Creature*> triggers;
caster->GetCreatureListWithEntryInGrid(triggers, NPC_VIAL_BUNNY, 100.0f);
if (triggers.empty())
return;
Creature* trigger = Acore::Containers::SelectRandomContainerElement(triggers);
caster->GetMotionMaster()->MovePoint(0, trigger->GetPosition());
}
void HandleScript(SpellEffIndex /*effindex*/)
{
Unit* caster = GetCaster();
caster->CastSpell(GetHitUnit(), SPELL_VALIDATE_AREA, true);
}
void Register() override
{
AfterCast += SpellCastFn(spell_apothecary_lingering_fumes::HandleAfterCast);
OnEffectHitTarget += SpellEffectFn(spell_apothecary_lingering_fumes::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 68644 - [DND] Valentine Boss Validate Area
class spell_apothecary_validate_area : public SpellScript
{
PrepareSpellScript(spell_apothecary_validate_area);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_BUNNY_LOCKDOWN, SPELL_THROW_COLOGNE, SPELL_THROW_PERFUME });
}
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(Acore::UnitAuraCheck(true, SPELL_BUNNY_LOCKDOWN));
if (targets.empty())
return;
WorldObject* target = Acore::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
}
void HandleScript(SpellEffIndex /*effindex*/)
{
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_BUNNY_LOCKDOWN, true);
GetCaster()->CastSpell(GetHitUnit(), RAND(SPELL_THROW_COLOGNE, SPELL_THROW_PERFUME), true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_apothecary_validate_area::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_apothecary_validate_area::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 69038 - Throw Cologne
class spell_apothecary_throw_cologne : public SpellScript
{
PrepareSpellScript(spell_apothecary_throw_cologne);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_COLOGNE_SPILL });
}
void HandleScript(SpellEffIndex /*effindex*/)
{
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_COLOGNE_SPILL, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_apothecary_throw_cologne::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 68966 - Throw Perfume
class spell_apothecary_throw_perfume : public SpellScript
{
PrepareSpellScript(spell_apothecary_throw_perfume);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PERFUME_SPILL });
}
void HandleScript(SpellEffIndex /*effindex*/)
{
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_PERFUME_SPILL, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_apothecary_throw_perfume::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 68798 - Concentrated Alluring Perfume Spill
class spell_apothecary_perfume_spill : public AuraScript
{
PrepareAuraScript(spell_apothecary_perfume_spill);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PERFUME_SPILL_DAMAGE });
}
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
GetTarget()->CastSpell(GetTarget(), SPELL_PERFUME_SPILL_DAMAGE, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_apothecary_perfume_spill::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 68614 - Concentrated Irresistible Cologne Spill
class spell_apothecary_cologne_spill : public AuraScript
{
PrepareAuraScript(spell_apothecary_cologne_spill);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_COLOGNE_SPILL_DAMAGE });
}
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
GetTarget()->CastSpell(GetTarget(), SPELL_COLOGNE_SPILL_DAMAGE, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_apothecary_cologne_spill::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
void AddSC_boss_apothecary_hummel()
{
new boss_apothecary_hummel();
RegisterShadowfangKeepCreatureAI(npc_apothecary_baxter);
RegisterShadowfangKeepCreatureAI(npc_apothecary_frye);
RegisterSpellScript(spell_apothecary_lingering_fumes);
RegisterSpellScript(spell_apothecary_validate_area);
RegisterSpellScript(spell_apothecary_throw_cologne);
RegisterSpellScript(spell_apothecary_throw_perfume);
RegisterSpellScript(spell_apothecary_perfume_spill);
RegisterSpellScript(spell_apothecary_cologne_spill);
}

View File

@@ -20,13 +20,10 @@
#include "TemporarySummon.h"
#include "shadowfang_keep.h"
//enum Creatures
//{
// NPC_ASH = 3850,
// NPC_ADA = 3849,
// NPC_ARCHMAGE_ARUGAL = 4275,
// NPC_ARUGAL_VOIDWALKER = 4627
//};
enum Spells
{
SPELL_SUMMON_VALENTINE_ADD = 68610
};
class instance_shadowfang_keep : public InstanceMapScript
{
@@ -47,6 +44,18 @@ public:
memset(&_encounters, 0, sizeof(_encounters));
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
case NPC_DND_CRAZED_APOTHECARY_GENERATOR:
_crazedApothecaryGeneratorGUIDs.push_back(creature->GetGUID());
break;
default:
break;
}
}
void OnGameObjectCreate(GameObject* gameobject) override
{
switch (gameobject->GetEntry())
@@ -63,6 +72,8 @@ public:
if (_encounters[TYPE_WOLF_MASTER_NANDOS] == DONE)
HandleGameObject(ObjectGuid::Empty, true, gameobject);
break;
default:
break;
}
}
@@ -75,6 +86,17 @@ public:
case TYPE_WOLF_MASTER_NANDOS:
_encounters[type] = data;
break;
case DATA_SPAWN_VALENTINE_ADDS:
for (ObjectGuid guid : _crazedApothecaryGeneratorGUIDs)
{
if (Creature* generator = instance->GetCreature(guid))
{
generator->CastSpell(nullptr, SPELL_SUMMON_VALENTINE_ADD);
}
}
break;
default:
break;
}
if (data == DONE)
@@ -109,6 +131,7 @@ public:
private:
uint32 _encounters[MAX_ENCOUNTERS];
GuidVector _crazedApothecaryGeneratorGUIDs;
};
};

View File

@@ -20,13 +20,23 @@
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "CreatureAIImpl.h"
#define ShadowfangKeepScriptName "instance_shadowfang_keep"
enum DataTypes
{
TYPE_COURTYARD = 0,
TYPE_FENRUS_THE_DEVOURER = 1,
TYPE_WOLF_MASTER_NANDOS = 2,
MAX_ENCOUNTERS = 3
MAX_ENCOUNTERS = 3,
DATA_APOTHECARY_HUMMEL = 4,
DATA_SPAWN_VALENTINE_ADDS = 5
};
enum SKCreatures
{
NPC_DND_CRAZED_APOTHECARY_GENERATOR = 36212
};
enum GameObjects
@@ -36,4 +46,12 @@ enum GameObjects
GO_ARUGAL_DOOR = 18971
};
template <class AI, class T>
inline AI* GetShadowfangKeepAI(T* obj)
{
return GetInstanceAI<AI>(obj, ShadowfangKeepScriptName);
}
#define RegisterShadowfangKeepCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetShadowfangKeepAI)
#endif

View File

@@ -103,6 +103,7 @@ void AddSC_boss_kirtonos_the_herald();
void AddSC_boss_darkmaster_gandling();
void AddSC_boss_kormok();
void AddSC_instance_scholomance(); //Scholomance
void AddSC_boss_apothecary_hummel();
void AddSC_instance_shadowfang_keep(); //Shadowfang keep
void AddSC_boss_baroness_anastari();
void AddSC_boss_jarien_and_sothos();
@@ -252,6 +253,7 @@ void AddEasternKingdomsScripts()
AddSC_boss_darkmaster_gandling();
AddSC_boss_kormok();
AddSC_instance_scholomance(); //Scholomance
AddSC_boss_apothecary_hummel();
AddSC_instance_shadowfang_keep(); //Shadowfang keep
AddSC_boss_baroness_anastari();
AddSC_boss_jarien_and_sothos();

View File

@@ -255,289 +255,25 @@ struct npc_love_in_air_snivel_real : public ScriptedAI
}
};
///////////////////////////////////////
////// BOSS
///////////////////////////////////////
enum hummel
{
QUEST_YOUVE_BEEN_SERVED = 14488,
NPC_APOTHECARY_HUMMEL = 36296,
NPC_APOTHECARY_FRYE = 36272,
NPC_APOTHECARY_BAXTER = 36565,
SPELL_COLOGNE_IMMUNE = 68530,
SPELL_COLOGNE_PASSIVE_DAMAGE = 68947,
SPELL_PERFUME_PASSIVE_DAMAGE = 68641,
SPELL_THROW_COLOGNE = 68614,
SPELL_THROW_PERFUME = 68798,
// Real fight
SPELL_COLOGNE_SPRAY = 68948,
SPELL_ALLURING_PERFUME_SPRAY = 68607,
SPELL_CHAIN_REACTION = 68821,
ACTION_START_EVENT = 1,
ACTION_RELEASE_HELPER = 2,
EVENT_CALL_BAXTER = 1,
EVENT_CALL_FRYE = 2,
EVENT_SPELL_PERFUME_SPRAY = 3,
EVENT_SPELL_CHAIN_REACTION = 4,
EVENT_SPELL_THROW = 5,
};
enum HummelSay
{
SAY_HUMMEL_0 = 0,
SAY_HUMMEL_1 = 1,
SAY_HUMMEL_2 = 2,
SAY_HUMMEL_5 = 5
};
class npc_love_in_air_hummel : public CreatureScript
{
public:
npc_love_in_air_hummel() : CreatureScript("npc_love_in_air_hummel") { }
struct npc_love_in_air_hummelAI : public ScriptedAI
{
npc_love_in_air_hummelAI(Creature* creature) : ScriptedAI(creature), summons(me) { speachTimer = 0; }
SummonList summons;
EventMap events;
uint32 speachTimer;
bool CanBeSeen(Player const* player) override
{
if (player->IsGameMaster())
{
return true;
}
Group const* group = player->GetGroup();
return group && sLFGMgr->GetDungeon(group->GetGUID()) == lfg::LFG_DUNGEON_CROWN_CHEMICAL_CO;
}
void Reset() override
{
speachTimer = 0;
me->SetFaction(FACTION_FRIENDLY);
summons.DespawnAll();
events.Reset();
me->SummonCreature(NPC_APOTHECARY_FRYE, -205.449f, 2219.56f, 79.7633f, 0.7f);
me->SummonCreature(NPC_APOTHECARY_BAXTER, -209.602f, 2215.42f, 79.7633f, 0.723503f);
}
void DoAction(int32 param) override
{
if (param == ACTION_START_EVENT)
speachTimer = 1;
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_HUMMEL_5);
Map::PlayerList const& players = me->GetMap()->GetPlayers();
if (!players.IsEmpty() && players.begin()->GetSource() && players.begin()->GetSource()->GetGroup())
sLFGMgr->FinishDungeon(players.begin()->GetSource()->GetGroup()->GetGUID(), lfg::LFG_DUNGEON_CROWN_CHEMICAL_CO, me->FindMap());
}
void JustSummoned(Creature* cr) override
{
summons.Summon(cr);
cr->SetFaction(FACTION_FRIENDLY);
cr->SetControlled(true, UNIT_STATE_STUNNED);
cr->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
void UpdateAI(uint32 diff) override
{
if (speachTimer)
{
speachTimer += diff;
if (speachTimer < 10000)
{
Talk(SAY_HUMMEL_0);
speachTimer = 10000;
}
else if (speachTimer >= 16000 && speachTimer < 20000)
{
Talk(SAY_HUMMEL_1);
speachTimer = 20000;
}
else if (speachTimer >= 26000 && speachTimer < 30000)
{
Talk(SAY_HUMMEL_2);
speachTimer = 0;
me->SetFaction(FACTION_MONSTER_2);
me->SetInCombatWithZone();
if (Unit* target = SelectTargetFromPlayerList(40.0f))
{
AttackStart(target);
events.ScheduleEvent(EVENT_CALL_BAXTER, 10000);
events.ScheduleEvent(EVENT_CALL_FRYE, 20000);
events.ScheduleEvent(EVENT_SPELL_PERFUME_SPRAY, 7000);
events.ScheduleEvent(EVENT_SPELL_CHAIN_REACTION, 12000);
}
else
EnterEvadeMode();
}
return;
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_CALL_BAXTER:
{
EntryCheckPredicate pred(NPC_APOTHECARY_BAXTER);
summons.DoAction(ACTION_RELEASE_HELPER, pred);
break;
}
case EVENT_CALL_FRYE:
{
EntryCheckPredicate pred(NPC_APOTHECARY_FRYE);
summons.DoAction(ACTION_RELEASE_HELPER, pred);
break;
}
case EVENT_SPELL_PERFUME_SPRAY:
DoCastVictim(SPELL_ALLURING_PERFUME_SPRAY);
events.RepeatEvent(6000);
break;
case EVENT_SPELL_CHAIN_REACTION:
DoCastVictim(SPELL_CHAIN_REACTION);
events.RepeatEvent(12000);
break;
}
DoMeleeAttackIfReady();
}
};
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 /*action*/) override
{
creature->AI()->DoAction(ACTION_START_EVENT);
CloseGossipMenuFor(player);
return true;
}
bool OnQuestReward(Player* /*player*/, Creature* creature, const Quest* _Quest, uint32 /*slot*/) override
{
if (_Quest->GetQuestId() == QUEST_YOUVE_BEEN_SERVED)
{
creature->AI()->DoAction(ACTION_START_EVENT);
}
return true;
}
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_love_in_air_hummelAI(creature);
};
};
enum HummelHelperSay
{
SAY_HUMMEL_HELPER_SAY_5 = 5,
};
struct npc_love_in_air_hummel_helper : public ScriptedAI
{
npc_love_in_air_hummel_helper(Creature* creature) : ScriptedAI(creature) { }
EventMap events;
bool CanBeSeen(Player const* player) override
{
if (player->IsGameMaster())
{
return true;
}
Group const* group = player->GetGroup();
return group && sLFGMgr->GetDungeon(group->GetGUID()) == lfg::LFG_DUNGEON_CROWN_CHEMICAL_CO;
}
void Reset() override
{
}
void DoAction(int32 param) override
{
if (param == ACTION_RELEASE_HELPER)
{
me->SetControlled(false, UNIT_STATE_STUNNED);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetFaction(FACTION_MONSTER_2);
me->SetInCombatWithZone();
if (Unit* target = SelectTargetFromPlayerList(40.0f))
AttackStart(target);
if (me->GetEntry() == NPC_APOTHECARY_BAXTER)
{
events.ScheduleEvent(EVENT_SPELL_PERFUME_SPRAY, 7000);
events.ScheduleEvent(EVENT_SPELL_CHAIN_REACTION, 12000);
}
else
events.ScheduleEvent(EVENT_SPELL_THROW, 5000);
}
}
void JustDied(Unit* /*killer*/) override
{
me->AI()->Talk(SAY_HUMMEL_HELPER_SAY_5);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_PERFUME_SPRAY:
DoCastVictim(SPELL_COLOGNE_SPRAY);
events.RepeatEvent(6000);
break;
case EVENT_SPELL_CHAIN_REACTION:
DoCastVictim(SPELL_CHAIN_REACTION);
events.RepeatEvent(12000);
break;
case EVENT_SPELL_THROW:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
{
Position pos(*me);
me->Relocate(target);
me->CastSpell(me, RAND(SPELL_THROW_COLOGNE, SPELL_THROW_PERFUME), true, nullptr, nullptr, me->GetGUID());
me->Relocate(pos);
}
events.RepeatEvent(10000);
break;
}
DoMeleeAttackIfReady();
}
};
///////////////////////////////////////
////// SPELLS
///////////////////////////////////////
enum SpellsCologneImmune
{
SPELL_COLOGNE_IMMUNE = 68530,
SPELL_COLOGNE_PASSIVE_DAMAGE = 68947,
SPELL_PERFUME_PASSIVE_DAMAGE = 68641,
SPELL_THROW_COLOGNE = 68614,
SPELL_THROW_PERFUME = 68798,
// Real fight
SPELL_COLOGNE_SPRAY = 68948,
SPELL_ALLURING_PERFUME_SPRAY = 68607,
SPELL_CHAIN_REACTION = 68821
};
class spell_love_in_air_perfume_immune : public AuraScript
{
PrepareAuraScript(spell_love_in_air_perfume_immune);
@@ -583,29 +319,6 @@ class spell_love_in_air_perfume_immune : public AuraScript
}
};
class spell_love_in_air_periodic_perfumes : public AuraScript
{
PrepareAuraScript(spell_love_in_air_periodic_perfumes);
void PeriodicTick(AuraEffect const* /*aurEff*/)
{
ObjectGuid guid = GetCaster() ? GetCaster()->GetGUID() : ObjectGuid::Empty;
if (Unit* target = GetTarget())
{
uint32 spellId = (GetId() == SPELL_THROW_COLOGNE ? 68934 : 68927);
if (target->IsImmunedToSpell(sSpellMgr->GetSpellInfo(spellId)))
return;
target->CastSpell(target, spellId, true, nullptr, nullptr, guid);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_love_in_air_periodic_perfumes::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
enum CreateHeartCandy
{
SPELL_CREATE_HEART_CANDY_1 = 26668,
@@ -773,13 +486,8 @@ void AddSC_event_love_in_the_air()
RegisterCreatureAI(npc_love_in_air_snivel);
RegisterCreatureAI(npc_love_in_air_snivel_real);
// Boss
new npc_love_in_air_hummel();
RegisterCreatureAI(npc_love_in_air_hummel_helper);
// Spells
RegisterSpellScript(spell_love_in_air_perfume_immune);
RegisterSpellScript(spell_love_in_air_periodic_perfumes);
RegisterSpellScript(spell_item_create_heart_candy);
RegisterSpellScript(spell_love_is_in_the_air_romantic_picnic);
RegisterSpellScript(spell_gen_aura_service_uniform);