mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-17 19:05:42 +00:00
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:
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user