Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2025-06-01 14:55:09 +08:00
66 changed files with 1638 additions and 550 deletions
+23 -1
View File
@@ -105,7 +105,8 @@ public:
{ "unitstate", HandleDebugUnitStateCommand, SEC_ADMINISTRATOR, Console::No },
{ "objectcount", HandleDebugObjectCountCommand, SEC_ADMINISTRATOR, Console::Yes},
{ "dummy", HandleDebugDummyCommand, SEC_ADMINISTRATOR, Console::No },
{ "mapdata", HandleDebugMapDataCommand, SEC_ADMINISTRATOR, Console::No }
{ "mapdata", HandleDebugMapDataCommand, SEC_ADMINISTRATOR, Console::No },
{ "boundary", HandleDebugBoundaryCommand, SEC_ADMINISTRATOR, Console::No }
};
static ChatCommandTable commandTable =
{
@@ -1388,6 +1389,27 @@ public:
handler->PSendSysMessage("Created Cells In Map: {} / {}", map->GetCreatedCellsInMapCount(), TOTAL_NUMBER_OF_CELLS_PER_MAP * TOTAL_NUMBER_OF_CELLS_PER_MAP);
return true;
}
static bool HandleDebugBoundaryCommand(ChatHandler* handler, Optional<uint32> durationArg, Optional<EXACT_SEQUENCE("fill")> fill, Optional<EXACT_SEQUENCE("z")> checkZ)
{
Player* player = handler->GetPlayer();
if (!player)
return false;
Creature* target = handler->getSelectedCreature();
if (!target || !target->IsAIEnabled)
return false;
uint32 duration = durationArg.value_or(5 * IN_MILLISECONDS);
if (duration > 180 * IN_MILLISECONDS) // arbitrary upper limit
duration = 180 * IN_MILLISECONDS;
int32 errMsg = target->AI()->VisualizeBoundary(duration, player, fill.has_value(), checkZ.has_value());
if (errMsg > 0)
handler->PSendSysMessage(errMsg);
return true;
}
};
void AddSC_debug_commandscript()
+34
View File
@@ -36,6 +36,7 @@ public:
{ "join", HandleGroupJoinCommand, SEC_GAMEMASTER, Console::No },
{ "remove", HandleGroupRemoveCommand, SEC_GAMEMASTER, Console::No },
{ "disband", HandleGroupDisbandCommand, SEC_GAMEMASTER, Console::No },
{ "revive", HandleGroupReviveCommand, SEC_GAMEMASTER, Console::No },
{ "leader", HandleGroupLeaderCommand, SEC_GAMEMASTER, Console::No }
};
@@ -257,6 +258,39 @@ public:
return true;
}
static bool HandleGroupReviveCommand(ChatHandler* handler, Optional<PlayerIdentifier> target)
{
if (!target)
target = PlayerIdentifier::FromTargetOrSelf(handler);
if (!target)
return false;
Player* targetPlayer = target->GetConnectedPlayer();
Group* group = targetPlayer->GetGroup();
std::string nameLink = handler->playerLink(target->GetName());
if (!group)
{
handler->SendErrorMessage(LANG_NOT_IN_GROUP, nameLink);
return false;
}
for (GroupReference* it = group->GetFirstMember(); it != nullptr; it = it->next())
{
Player* target = it->GetSource();
if (target)
{
target->RemoveAurasDueToSpell(27827); // Spirit of Redemption
target->ResurrectPlayer(!AccountMgr::IsPlayerAccount(target->GetSession()->GetSecurity()) ? 1.0f : 0.5f);
target->SpawnCorpseBones();
target->SaveToDB(false, false);
}
}
return true;
}
};
void AddSC_group_commandscript()
@@ -25,18 +25,6 @@
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
/* ScriptData
SDName: Karazhan
SD%Complete: 100
SDComment: Support for Barnes (Opera controller) and Berthold (Doorman), Support for Quest 9645.
SDCategory: Karazhan
EndScriptData */
/* ContentData
npc_barnes
npc_berthold
npc_image_of_medivh
EndContentData */
enum Spells
{
@@ -51,7 +39,17 @@ enum Spells
SPELL_FIRE_BALL = 30967,
SPELL_UBER_FIREBALL = 30971,
SPELL_CONFLAGRATION_BLAST = 30977,
SPELL_MANA_SHIELD = 31635
SPELL_MANA_SHIELD = 31635,
// Wrath of the Titans
SPELL_WRATH_OF_THE_TITANS = 30554,
SPELL_WRATH_PROC_BLAST = 30605,
SPELL_WRATH_PROC_BOLT = 30606,
SPELL_WRATH_PROC_FLAME = 30607,
SPELL_WRATH_PROC_SPITE = 30608,
SPELL_WRATH_PROC_CHILL = 30609,
};
enum Creatures
@@ -608,10 +606,106 @@ class spell_karazhan_temptation : public AuraScript
}
};
// 30610 - Wrath of the Titans Stacker
class spell_karazhan_wrath_titans_stacker : public SpellScript
{
PrepareSpellScript(spell_karazhan_wrath_titans_stacker);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_WRATH_OF_THE_TITANS });
}
void HandleDummy(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
Unit* caster = GetCaster();
if (!caster)
return;
caster->CastSpell(caster, SPELL_WRATH_OF_THE_TITANS, true);
if (Aura* aur = caster->GetAura(SPELL_WRATH_OF_THE_TITANS))
aur->SetStackAmount(5);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_karazhan_wrath_titans_stacker::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 30554 - Wrath of the Titans
class spell_karazhan_wrath_titans_aura : public AuraScript
{
PrepareAuraScript(spell_karazhan_wrath_titans_aura);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_WRATH_PROC_BLAST, SPELL_WRATH_PROC_BOLT, SPELL_WRATH_PROC_FLAME, SPELL_WRATH_PROC_SPITE, SPELL_WRATH_PROC_CHILL });
}
bool CheckProc(ProcEventInfo& eventInfo)
{
if (!eventInfo.GetSpellInfo())
return false;
if (GetFirstSchoolInMask(eventInfo.GetSpellInfo()->GetSchoolMask()) == SPELL_SCHOOL_NORMAL)
return false;
if (GetFirstSchoolInMask(eventInfo.GetSpellInfo()->GetSchoolMask()) == SPELL_SCHOOL_HOLY)
return false;
return true;
}
void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* target = eventInfo.GetActionTarget();
Player* caster = GetTarget()->ToPlayer();
if (!target || !caster)
return;
uint32 spellId = 0;
switch (GetFirstSchoolInMask(eventInfo.GetSpellInfo()->GetSchoolMask()))
{
case SPELL_SCHOOL_FIRE:
spellId = SPELL_WRATH_PROC_FLAME;
break;
case SPELL_SCHOOL_NATURE:
spellId = SPELL_WRATH_PROC_BOLT;
break;
case SPELL_SCHOOL_FROST:
spellId = SPELL_WRATH_PROC_CHILL;
break;
case SPELL_SCHOOL_SHADOW:
spellId = SPELL_WRATH_PROC_SPITE;
break;
case SPELL_SCHOOL_ARCANE:
spellId = SPELL_WRATH_PROC_BLAST;
break;
default:
return;
}
caster->CastSpell(target, spellId, true);
ModStackAmount(-1);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_karazhan_wrath_titans_aura::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_karazhan_wrath_titans_aura::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
void AddSC_karazhan()
{
new npc_barnes();
new npc_image_of_medivh();
new at_karazhan_side_entrance();
RegisterSpellScript(spell_karazhan_temptation);
RegisterSpellScript(spell_karazhan_wrath_titans_stacker);
RegisterSpellScript(spell_karazhan_wrath_titans_aura);
}
@@ -37,145 +37,28 @@
enum EyeOfAcherusMisc
{
SPELL_THE_EYE_OF_ACHERUS = 51852,
SPELL_EYE_OF_ACHERUS_VISUAL = 51892,
SPELL_EYE_OF_ACHERUS_FLIGHT_BOOST = 51923,
SPELL_EYE_OF_ACHERUS_FLIGHT = 51890,
SPELL_ROOT_SELF = 51860,
EVENT_ANNOUNCE_LAUNCH_TO_DESTINATION = 1,
EVENT_UNROOT = 2,
EVENT_LAUNCH_TOWARDS_DESTINATION = 3,
EVENT_GRANT_CONTROL = 4,
SAY_LAUNCH_TOWARDS_DESTINATION = 0,
SAY_EYE_UNDER_CONTROL = 1,
POINT_NEW_AVALON = 1,
EYE_POINT_DESTINATION_0 = 0,
EYE_POINT_DESTINATION_1 = 1,
EYE_POINT_DESTINATION_2 = 2,
EYE_POINT_DESTINATION_3 = 3
};
struct npc_eye_of_acherus : public ScriptedAI
{
npc_eye_of_acherus(Creature* creature) : ScriptedAI(creature)
{
creature->SetDisplayFromModel(0);
creature->SetReactState(REACT_PASSIVE);
}
void InitializeAI() override
{
DoCastSelf(SPELL_ROOT_SELF);
DoCastSelf(SPELL_EYE_OF_ACHERUS_VISUAL);
_events.ScheduleEvent(EVENT_ANNOUNCE_LAUNCH_TO_DESTINATION, 400ms);
}
void OnCharmed(bool apply) override
{
if (!apply)
{
me->GetCharmerOrOwner()->RemoveAurasDueToSpell(SPELL_THE_EYE_OF_ACHERUS);
me->GetCharmerOrOwner()->RemoveAurasDueToSpell(SPELL_EYE_OF_ACHERUS_FLIGHT_BOOST);
}
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ANNOUNCE_LAUNCH_TO_DESTINATION:
if (Unit* owner = me->GetCharmerOrOwner())
{
Talk(SAY_LAUNCH_TOWARDS_DESTINATION, owner);
}
_events.ScheduleEvent(EVENT_UNROOT, 400ms);
break;
case EVENT_UNROOT:
me->RemoveAurasDueToSpell(SPELL_ROOT_SELF);
DoCastSelf(SPELL_EYE_OF_ACHERUS_FLIGHT_BOOST);
_events.ScheduleEvent(EVENT_LAUNCH_TOWARDS_DESTINATION, 1s + 200ms);
break;
case EVENT_LAUNCH_TOWARDS_DESTINATION:
{
Position const EYE_DESTINATION_1 = { 2361.21f, -5660.45f, 496.744f, 0.0f };
Position const EYE_DESTINATION_2 = { 2341.571f, -5672.797f, 538.3942f, 0.0f };
Position const EYE_DESTINATION_3 = { 1957.4f, -5844.1f, 273.867f, 0.0f };
Position const EYE_DESTINATION_4 = { 1758.01f, -5876.79f, 166.867f, 0.0f };
Movement::MoveSplineInit init(me);
init.SetFly();
if (Unit* owner = me->GetCharmerOrOwner())
{
init.SetVelocity(owner->GetSpeed(MOVE_RUN));
}
me->GetMotionMaster()->MovePoint(EYE_POINT_DESTINATION_0, EYE_DESTINATION_1);
me->GetMotionMaster()->MovePoint(EYE_POINT_DESTINATION_1, EYE_DESTINATION_2);
me->GetMotionMaster()->MovePoint(EYE_POINT_DESTINATION_2, EYE_DESTINATION_3);
me->GetMotionMaster()->MovePoint(EYE_POINT_DESTINATION_3, EYE_DESTINATION_4);
_events.ScheduleEvent(EVENT_GRANT_CONTROL, 22s);
break;
}
case EVENT_GRANT_CONTROL:
if (Unit* owner = me->GetCharmerOrOwner())
{
Talk(SAY_EYE_UNDER_CONTROL, owner);
}
me->RemoveAurasDueToSpell(SPELL_ROOT_SELF);
DoCastSelf(SPELL_EYE_OF_ACHERUS_FLIGHT);
me->RemoveAurasDueToSpell(SPELL_EYE_OF_ACHERUS_FLIGHT_BOOST);
break;
default:
break;
}
}
}
void MovementInform(uint32 movementType, uint32 pointId) override
{
if (movementType != POINT_MOTION_TYPE)
return;
switch (pointId)
{
case POINT_NEW_AVALON:
DoCastSelf(SPELL_ROOT_SELF);
break;
default:
break;
}
}
private:
EventMap _events;
};
enum DeathComesFromOnHigh
{
SUMMON_GHOULS_ON_SCARLET_CRUSADE = 54522
SPELL_CALL_OF_THE_DEAD = 51900
};
// 51904 - Summon Ghouls On Scarlet Crusade
class spell_q12641_death_comes_from_on_high_summon_ghouls : public SpellScript
{
PrepareSpellScript(spell_q12641_death_comes_from_on_high_summon_ghouls);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SUMMON_GHOULS_ON_SCARLET_CRUSADE });
return ValidateSpellInfo({ SPELL_CALL_OF_THE_DEAD });
}
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
if (Unit* target = GetHitUnit())
GetCaster()->CastSpell(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), SUMMON_GHOULS_ON_SCARLET_CRUSADE, true);
target->CastSpell(target, SPELL_CALL_OF_THE_DEAD, true);
}
void Register() override
@@ -184,6 +67,35 @@ class spell_q12641_death_comes_from_on_high_summon_ghouls : public SpellScript
}
};
// 52694 - Recall Eye of Acherus
class spell_q12641_death_comes_from_on_high_recall_eye : public SpellScript
{
PrepareSpellScript(spell_q12641_death_comes_from_on_high_recall_eye);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_THE_EYE_OF_ACHERUS });
}
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
Unit* caster = GetCaster();
Unit* owner = caster->GetCharmerOrOwner();
if (!caster || !owner)
return;
if (owner->HasAura(SPELL_THE_EYE_OF_ACHERUS))
owner->RemoveAurasDueToSpell(SPELL_THE_EYE_OF_ACHERUS);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_q12641_death_comes_from_on_high_recall_eye::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
enum deathsChallenge
{
SPELL_DUEL = 52996,
@@ -1300,8 +1212,8 @@ class spell_lich_king_whisper : public SpellScript
void AddSC_the_scarlet_enclave_c1()
{
// Ours
RegisterCreatureAI(npc_eye_of_acherus);
RegisterSpellScript(spell_q12641_death_comes_from_on_high_summon_ghouls);
RegisterSpellScript(spell_q12641_death_comes_from_on_high_recall_eye);
new npc_death_knight_initiate();
RegisterSpellScript(spell_item_gift_of_the_harvester);
RegisterSpellScript(spell_q12698_the_gift_that_keeps_on_giving);
@@ -15,27 +15,77 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CreatureScript.h"
#include "ScriptedCreature.h"
#include "SpellAuras.h"
#include "SpellInfo.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
enum DevourHumanoid
{
NPC_HEARTHGLEN_CRUSADER = 29102,
NPC_TIRISFAL_CRUSADER = 29103
};
// 53110 - Devour Humanoid
class spell_q12779_an_end_to_all_things : public SpellScript
{
PrepareSpellScript(spell_q12779_an_end_to_all_things);
SpellCastResult CheckCast()
{
if (Unit* caster = GetCaster())
if (caster->FindNearestCreature(NPC_HEARTHGLEN_CRUSADER, 15.0f, true) || caster->FindNearestCreature(NPC_TIRISFAL_CRUSADER, 15.0f, true))
return SPELL_CAST_OK;
return SPELL_FAILED_BAD_TARGETS;
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
if (GetHitUnit())
GetHitUnit()->CastSpell(GetCaster(), GetEffectValue(), true);
if (Creature* c = GetHitUnit()->ToCreature())
if (Unit* caster = GetCaster())
{
c->AI()->AttackStart(caster);
c->CastSpell(caster, GetEffectValue(), true); // 53111
}
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_q12779_an_end_to_all_things::CheckCast);
OnEffectHitTarget += SpellEffectFn(spell_q12779_an_end_to_all_things::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 53111 - Devour Humanoid (casted by the devoured creature)
class spell_q12779_an_end_to_all_things_devour_aura : public AuraScript
{
PrepareAuraScript(spell_q12779_an_end_to_all_things_devour_aura);
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* caster = GetCaster();
Unit* target = GetTarget();
if (!caster || !target)
return;
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
{
caster->SetDisableGravity(true);
Unit::Kill(target, caster);
}
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_q12779_an_end_to_all_things_devour_aura::OnRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_the_scarlet_enclave_c3()
{
RegisterSpellScript(spell_q12779_an_end_to_all_things);
RegisterSpellScript(spell_q12779_an_end_to_all_things_devour_aura);
}
@@ -17,6 +17,8 @@
#include "AreaTriggerScript.h"
#include "CreatureScript.h"
#include "GameObjectAI.h"
#include "GameObjectScript.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"
@@ -488,6 +490,22 @@ public:
}
};
struct go_eredar_twins_blaze : GameObjectAI
{
explicit go_eredar_twins_blaze(GameObject *object) : GameObjectAI(object) { };
void InitializeAI() override
{
// required for the trap to apply its startDelay
if (InstanceScript* instance = me->GetInstanceScript())
if (ObjectGuid creatureGUID = instance->GetGuidData(DATA_ALYTHESS))
{
me->SetOwnerGUID(creatureGUID);
me->SetLootState(GO_NOT_READY);
}
}
};
void AddSC_boss_eredar_twins()
{
RegisterSunwellPlateauCreatureAI(boss_sacrolash);
@@ -501,4 +519,5 @@ void AddSC_boss_eredar_twins()
RegisterSpellScriptWithArgs(spell_eredar_twins_handle_touch_periodic, "spell_eredar_twins_handle_flame_touched_periodic", SPELL_FLAME_TOUCHED, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
RegisterSpellScriptWithArgs(spell_eredar_twins_handle_touch_periodic, "spell_eredar_twins_handle_flame_touched_flame_sear", SPELL_FLAME_TOUCHED, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE);
new at_sunwell_eredar_twins();
RegisterGameObjectAI(go_eredar_twins_blaze);
}
@@ -1003,6 +1003,9 @@ class spell_kiljaeden_sinister_reflection_clone : public SpellScript
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
targets.sort(Acore::ObjectDistanceOrderPred(GetCaster()));
WorldObject* target = targets.front();
@@ -1052,6 +1055,9 @@ class spell_kiljaeden_darkness_aura : public AuraScript
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
return;
if (GetUnitOwner()->IsCreature())
GetUnitOwner()->ToCreature()->AI()->DoAction(ACTION_NO_KILL_TALK);
@@ -1157,6 +1163,8 @@ class spell_kiljaeden_armageddon_missile : public SpellScript
}
};
// 45856 - Breath: Haste
// 45860 - Breath: Revitalize
class spell_kiljaeden_dragon_breath : public SpellScript
{
PrepareSpellScript(spell_kiljaeden_dragon_breath);
@@ -1166,9 +1174,16 @@ class spell_kiljaeden_dragon_breath : public SpellScript
targets.remove_if(Acore::UnitAuraCheck(true, SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT));
}
void HandleHit(SpellEffIndex /*effindex*/)
{
if (Unit* target = GetHitUnit())
target->RemoveMovementImpairingAuras(false);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kiljaeden_dragon_breath::FilterTargets, EFFECT_ALL, TARGET_UNIT_CONE_ALLY);
OnEffectHitTarget += SpellEffectFn(spell_kiljaeden_dragon_breath::HandleHit, EFFECT_ALL, SPELL_EFFECT_ANY);
}
};
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AreaDefines.h"
#include "CreatureScript.h"
#include "PassiveAI.h"
#include "Pet.h"
@@ -23,19 +24,6 @@
#include "SpellInfo.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
/* ScriptData
SDName: Isle_of_Queldanas
SD%Complete: 100
SDComment: Quest support: 11524, 11525, 11532, 11533, 11542, 11543, 11541
SDCategory: Isle Of Quel'Danas
EndScriptData */
/* ContentData
npc_converted_sentry
npc_greengill_slave
EndContentData */
/*###### OUR: ######*/
enum ThalorienNpcs
{
@@ -677,13 +665,31 @@ public:
};
};
// 45396, 45398 - Weapon Coating Enchant
class spell_gen_weapon_coating_enchant : public AuraScript
{
PrepareAuraScript(spell_gen_weapon_coating_enchant);
bool CheckProc(ProcEventInfo& eventInfo)
{
Unit* caster = eventInfo.GetActor();
if (!caster)
return false;
return (caster->GetZoneId() == AREA_ISLE_OF_QUEL_DANAS || caster->GetZoneId() == AREA_SUNWELL_PLATEAU || caster->GetZoneId() == AREA_MAGISTERS_TERRACE);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_gen_weapon_coating_enchant::CheckProc);
}
};
void AddSC_isle_of_queldanas()
{
// OUR:
new npc_bh_thalorien_dawnseeker();
RegisterSpellScript(spell_bh_cleanse_quel_delar);
new npc_grand_magister_rommath();
// THEIR:
new npc_greengill_slave();
RegisterSpellScript(spell_gen_weapon_coating_enchant);
}
+41 -1
View File
@@ -21,7 +21,8 @@
enum eNoblegarden
{
SPELL_NOBLEGARDEN_BUNNY = 61734
SPELL_NOBLEGARDEN_BUNNY = 61734,
SPELL_WELL_FED = 24870,
};
// 61712 Summon Noblegarden Bunny Controller
@@ -55,7 +56,46 @@ class spell_summon_noblegarden_bunny_controller : public SpellScript
}
};
// 61874 - Food (Noblegarden Chocolate, item 44791)
class spell_item_noblegarden_chocolate : public AuraScript
{
PrepareAuraScript(spell_item_noblegarden_chocolate);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_WELL_FED });
}
bool Load() override
{
_buffGiven = false;
return true;
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* caster = GetCaster())
{
uint32 duration = static_cast<uint32>(GetDuration());
if (duration <= 14000 && !_buffGiven)
{
_buffGiven = true;
caster->CastSpell(caster, SPELL_WELL_FED, true);
}
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_item_noblegarden_chocolate::HandlePeriodic, EFFECT_0, SPELL_AURA_OBS_MOD_HEALTH);
}
private:
bool _buffGiven;
};
void AddSC_event_noblegarden_scripts()
{
RegisterSpellScript(spell_summon_noblegarden_bunny_controller);
RegisterSpellScript(spell_item_noblegarden_chocolate);
}
@@ -48,7 +48,7 @@ enum AhnKahetCreatures
enum AhnkahetSpells
{
SPELL_SHADOW_SICKLE = 56701, // Shadow Sickle Normal
SPELL_SHADOW_SICKLE = 56701, // Shadow Sickle
};
enum AhnkahetObjects
@@ -102,11 +102,7 @@ Position const MushroomPositions[MAX_MUSHROOMS_COUNT] =
struct boss_amanitar : public BossAI
{
boss_amanitar(Creature* creature) : BossAI(creature, DATA_AMANITAR), mushroomsSummoned(false)
{
creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
creature->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
}
boss_amanitar(Creature* creature) : BossAI(creature, DATA_AMANITAR), mushroomsSummoned(false) { }
void Reset() override
{
@@ -101,9 +101,7 @@ struct boss_elder_nadox : public BossAI
events.ScheduleEvent(EVENT_PLAGUE, 5s, 8s);
if (IsHeroic())
{
events.ScheduleEvent(EVENT_BROOD_RAGE, 5s);
}
// Cache eggs
std::list<Creature*> eggs;
@@ -122,7 +120,7 @@ struct boss_elder_nadox : public BossAI
eggs.clear();
// Guardian eggs
// Guardian eggs
me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_GUARDIAN_EGG, 250.0f);
if (!eggs.empty())
{
@@ -139,17 +137,13 @@ struct boss_elder_nadox : public BossAI
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() == NPC_AHNKAHAR_GUARDIAN)
{
respectYourElders = false;
}
}
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer())
{
Talk(SAY_SLAY);
}
}
void JustDied(Unit* /*killer*/) override
@@ -160,7 +154,7 @@ struct boss_elder_nadox : public BossAI
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override
{
if (!guardianSummoned && me->HealthBelowPctDamaged(55, damage))
if (!guardianSummoned && me->HealthBelowPctDamaged(50, damage))
{
SummonHelpers(false);
guardianSummoned = true;
@@ -170,9 +164,7 @@ struct boss_elder_nadox : public BossAI
uint32 GetData(uint32 type) const override
{
if (type == DATA_RESPECT_YOUR_ELDERS)
{
return respectYourElders ? 1 : 0;
}
return 0;
}
@@ -180,16 +172,12 @@ struct boss_elder_nadox : public BossAI
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 const eventId = events.ExecuteEvent())
{
@@ -218,9 +206,8 @@ struct boss_elder_nadox : public BossAI
case EVENT_CHECK_HOME:
{
if (!me->HasAura(SPELL_ENRAGE) && (me->GetPositionZ() < 24.0f || !me->GetHomePosition().IsInDist(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 110.0f)))
{
DoCastSelf(SPELL_ENRAGE, true);
}
events.Repeat(1s);
break;
}
}
@@ -241,9 +228,7 @@ private:
if (swarm)
{
if (swarmEggs.empty())
{
return;
}
// Make a copy of guid list
GuidList swarmEggs2 = swarmEggs;
@@ -259,41 +244,29 @@ private:
}
if (swarmEggs2.empty())
{
return;
}
previousSwarmEgg_GUID = Acore::Containers::SelectRandomContainerElement(swarmEggs2);
if (Creature* egg = ObjectAccessor::GetCreature(*me, previousSwarmEgg_GUID))
{
egg->CastSpell(egg, SPELL_SUMMON_SWARMERS, true, nullptr, nullptr, me->GetGUID());
}
if (roll_chance_f(33))
{
Talk(SAY_EGG_SAC);
}
}
else
{
if (guardianEggs.empty())
{
return;
}
ObjectGuid const& guardianEggGUID = Acore::Containers::SelectRandomContainerElement(guardianEggs);
if (Creature* egg = ObjectAccessor::GetCreature(*me, guardianEggGUID))
{
egg->CastSpell(egg, SPELL_SUMMON_SWARM_GUARD, true, nullptr, nullptr, me->GetGUID());
}
Talk(EMOTE_HATCHES, me);
if (roll_chance_f(33))
{
Talk(SAY_EGG_SAC);
}
}
}
};
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AreaBoundary.h"
#include "InstanceMapScript.h"
#include "Player.h"
#include "ScriptedCreature.h"
@@ -38,6 +39,11 @@ DoorData const doorData[] =
{ 0, 0, DOOR_TYPE_ROOM }
};
BossBoundaryData const boundaries =
{
{ DATA_JEDOGA_SHADOWSEEKER, new ParallelogramBoundary(Position(460.365f, -661.997f, -20.985f), Position(364.958f,-790.211f, -14.207f), Position(347.436f,-657.978f,14.478f)) }
};
class instance_ahnkahet : public InstanceMapScript
{
public:
@@ -52,6 +58,7 @@ public:
SetPersistentDataCount(MAX_PERSISTENT_DATA);
LoadObjectData(creatureData, nullptr);
LoadDoorData(doorData);
LoadBossBoundaries(boundaries);
}
void OnGameObjectCreate(GameObject* go) override
@@ -126,15 +133,19 @@ public:
}
};
// 56702 Shadow Sickle
// 59103 Shadow Sickle
// 56702, 59103 - Shadow Sickle
class spell_shadow_sickle_periodic_damage : public AuraScript
{
PrepareAuraScript(spell_shadow_sickle_periodic_damage);
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
GetCaster()->CastSpell(nullptr, SPELL_SHADOW_SICKLE);
Unit* caster = GetCaster();
if (!caster->IsCreature())
return;
if (Unit* target = caster->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, 40.0f)) // Unknown if it targets only players
caster->CastSpell(target, SPELL_SHADOW_SICKLE, true);
}
void Register() override
@@ -94,6 +94,7 @@ public:
InstanceScript* pInstance;
EventMap events;
float ZapAngle;
uint8 step = 0;
void Reset() override
{
@@ -185,32 +186,37 @@ public:
{
Talk(SAY_AZURE);
Talk(SAY_AZURE_EMOTE);
switch (events.ExecuteEvent())
switch (step)
{
case EVENT_CALL_AZURE_RING_CAPTAIN_1:
me->CastSpell(me, SPELL_CALL_AZURE_RING_CAPTAIN_1, true);
case 0:
DoCast(SPELL_CALL_AZURE_RING_CAPTAIN_1);
events.ScheduleEvent(EVENT_CALL_AZURE_RING_CAPTAIN_2, 16s);
break;
case EVENT_CALL_AZURE_RING_CAPTAIN_2:
me->CastSpell(me, SPELL_CALL_AZURE_RING_CAPTAIN_2, true);
case 1:
DoCast(SPELL_CALL_AZURE_RING_CAPTAIN_2);
events.ScheduleEvent(EVENT_CALL_AZURE_RING_CAPTAIN_3, 16s);
break;
case EVENT_CALL_AZURE_RING_CAPTAIN_3:
me->CastSpell(me, SPELL_CALL_AZURE_RING_CAPTAIN_3, true);
case 2:
DoCast(SPELL_CALL_AZURE_RING_CAPTAIN_3);
events.ScheduleEvent(EVENT_CALL_AZURE_RING_CAPTAIN_4, 16s);
break;
case EVENT_CALL_AZURE_RING_CAPTAIN_4:
me->CastSpell(me, SPELL_CALL_AZURE_RING_CAPTAIN_4, true);
case 3:
DoCast(SPELL_CALL_AZURE_RING_CAPTAIN_4);
events.ScheduleEvent(EVENT_CALL_AZURE_RING_CAPTAIN_1, 16s);
break;
}
step++;
if (step > 3)
step = 0;
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
{
if (Creature* trigger = me->SummonCreature(NPC_ARCANE_BEAM, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 13000))
{
if (Creature* c = me->FindNearestCreature(NPC_AZURE_RING_CAPTAIN, 500.0f, true))
c->CastSpell(trigger, SPELL_ARCANE_BEAM_VISUAL, true);
trigger->GetMotionMaster()->MoveChase(target, 0.1f);
trigger->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f, MOTION_SLOT_ACTIVE, false, false); /// @todo: sniff speed for NPC_ARCANE_BEAM (ID: 28239)
trigger->CastSpell(me, SPELL_ARCANE_BEAM_PERIODIC_DAMAGE, true);
}
}
@@ -218,7 +218,11 @@ public:
{
EncounterStatus = IN_PROGRESS;
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
{
c->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
c->AI()->Talk(SAY_SINCLARI_LEAVING);
/// @todo: Missing orientation for Sinclari's movement and "interaction" animation with the nearby crystal.
}
events.RescheduleEvent(EVENT_GUARDS_FALL_BACK, 4s);
}
break;
@@ -451,6 +455,7 @@ public:
{
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
{
c->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
c->AI()->Talk(SAY_SINCLARI_DOOR_LOCK);
}
if (Creature* c = instance->GetCreature(NPC_DoorSealGUID))
@@ -568,7 +573,13 @@ public:
}
// reset positions of Sinclari and Guards
if (Creature* c = instance->GetCreature(NPC_SinclariGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); }
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
{
c->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
c->DespawnOrUnsummon();
c->SetRespawnTime(3);
}
for (uint8 i = 0; i < 4; ++i)
if (Creature* c = instance->GetCreature(NPC_GuardGUID[i]))
{
@@ -27,16 +27,15 @@
#include "SpellScriptLoader.h"
/// @todo: Missing Sinclari Trigger announcements (32204) Look at its creature_text for more info.
/// @todo: Activation Crystals (go_vh_activation_crystal) (193611) are spammable, should be a 1 time use per crystal.
enum Texts
{
GOSSIP_MENU_START_EVENT = 9998,
GOSSIP_MENU_ITEM = 9997,
GOSSIP_MENU_START_1 = 9997,
GOSSIP_MENU_START_2 = 9998,
GOSSIP_MENU_LATE_JOIN = 10275,
NPC_TEXT_SINCLARI_IN = 13853,
NPC_TEXT_SINCLARI_ITEM = 13854,
NPC_TEXT_SINCLARI_START = 13854,
NPC_TEXT_SINCLARI_DONE = 13910,
NPC_TEXT_SINCLARI_LATE_JOIN = 14271,
};
@@ -53,7 +52,11 @@ public:
bool OnGossipHello(Player* /*player*/, GameObject* go) override
{
if (InstanceScript* pInstance = go->GetInstanceScript())
{
pInstance->SetData(DATA_ACTIVATE_DEFENSE_SYSTEM, 1);
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
}
return true;
}
};
@@ -73,8 +76,7 @@ public:
switch (pInstance->GetData(DATA_ENCOUNTER_STATUS))
{
case NOT_STARTED:
AddGossipItemFor(player, GOSSIP_MENU_ITEM, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
AddGossipItemFor(player, GOSSIP_MENU_START_EVENT, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, GOSSIP_MENU_START_1, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, NPC_TEXT_SINCLARI_IN, creature->GetGUID());
break;
case IN_PROGRESS:
@@ -94,13 +96,14 @@ public:
switch (uiAction)
{
case GOSSIP_ACTION_INFO_DEF+1:
AddGossipItemFor(player, GOSSIP_MENU_START_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
SendGossipMenuFor(player, NPC_TEXT_SINCLARI_START, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+2:
CloseGossipMenuFor(player);
if (InstanceScript* pInstance = creature->GetInstanceScript())
pInstance->SetData(DATA_START_INSTANCE, 1);
break;
case GOSSIP_ACTION_INFO_DEF+2:
SendGossipMenuFor(player, NPC_TEXT_SINCLARI_ITEM, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+3:
player->NearTeleportTo(playerTeleportPosition.GetPositionX(), playerTeleportPosition.GetPositionY(), playerTeleportPosition.GetPositionZ(), playerTeleportPosition.GetOrientation(), true);
CloseGossipMenuFor(player);
+24 -3
View File
@@ -2131,9 +2131,31 @@ public:
}
};
enum WaterTerror
{
SPELL_WATER_TERROR_FROST_NOVA = 57668
};
// 57652 - Crashing Wave
class spell_crashing_wave : public SpellScript
{
PrepareSpellScript(spell_crashing_wave);
void RecalculateDamage()
{
if (Unit* target = GetHitUnit())
if (target->HasAura(SPELL_WATER_TERROR_FROST_NOVA))
SetHitDamage(GetHitDamage() * 2);
}
void Register() override
{
OnHit += SpellHitFn(spell_crashing_wave::RecalculateDamage);
}
};
void AddSC_icecrown()
{
// Ours
new npc_black_knight_graveyard();
new npc_battle_at_valhalas();
new npc_llod_generic();
@@ -2147,10 +2169,9 @@ void AddSC_icecrown()
new npc_infra_green_bomber_generic();
RegisterSpellScript(spell_onslaught_or_call_bone_gryphon);
RegisterSpellScript(spell_deliver_gryphon);
// Theirs
new npc_guardian_pavilion();
new npc_tournament_training_dummy();
new npc_blessed_banner();
new npc_frostbrood_skytalon();
RegisterSpellScript(spell_crashing_wave);
}
@@ -346,7 +346,7 @@ struct boss_alar : public BossAI
scheduler.Schedule(timer, GROUP_FLAME_BUFFET, [this](TaskContext context)
{
if (!me->SelectNearestTarget(me->GetCombatReach()) && !me->isMoving())
DoCastVictim(SPELL_FLAME_BUFFET);
DoCastAOE(SPELL_FLAME_BUFFET);
context.Repeat(2s);
});
@@ -372,11 +372,11 @@ struct boss_alar : public BossAI
{
_transitionScheduler.Update(diff);
scheduler.Update(diff);
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
+1 -1
View File
@@ -152,7 +152,7 @@ class spell_sha_totemic_mastery : public AuraScript
{
PreventDefaultAction();
for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
for (uint8 i = SUMMON_SLOT_TOTEM_FIRE; i < MAX_TOTEM_SLOT; ++i)
if (!GetTarget()->m_SummonSlot[i])
return;