diff options
| author | Spp <spp@jorge.gr> | 2012-01-31 11:49:53 +0100 |
|---|---|---|
| committer | Spp <spp@jorge.gr> | 2012-01-31 11:49:53 +0100 |
| commit | 37b66384f3d905fb8de506aae48237900a1b6065 (patch) | |
| tree | f6c36187e06f76704d7a661179857916b18b6469 /src/server/scripts/Northrend | |
| parent | fdbb3e52bcbaa236a26bd2bf8293a5deccb34a01 (diff) | |
| parent | d4670a558dd40fc03c9b143dcffa763c834ab966 (diff) | |
Merge branch 'master' into 4.x
Conflicts:
src/server/authserver/Server/AuthSocket.cpp
src/server/game/Entities/Object/Object.cpp
src/server/game/Entities/Player/Player.cpp
src/server/game/Entities/Unit/Unit.cpp
src/server/game/Handlers/AuctionHouseHandler.cpp
src/server/game/Handlers/CharacterHandler.cpp
src/server/game/Handlers/MovementHandler.cpp
src/server/game/Miscellaneous/SharedDefines.h
src/server/game/Spells/Spell.cpp
src/server/game/Spells/SpellEffects.cpp
Diffstat (limited to 'src/server/scripts/Northrend')
26 files changed, 1244 insertions, 891 deletions
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index e6678be3a2b..d3d92375d39 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -122,6 +122,11 @@ const Position SphereSpawn[6] = { 706.6383f, 161.5266f, 155.6701f, 0 }, }; +enum MovementPoints +{ + POINT_FALL_GROUND = 1 +}; + class boss_anubarak_trial : public CreatureScript { public: @@ -553,82 +558,68 @@ public: class mob_frost_sphere : public CreatureScript { -public: - mob_frost_sphere() : CreatureScript("mob_frost_sphere") { } - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_frost_sphereAI(creature); - }; + public: + mob_frost_sphere() : CreatureScript("mob_frost_sphere") { } - struct mob_frost_sphereAI : public ScriptedAI - { - mob_frost_sphereAI(Creature* creature) : ScriptedAI(creature) + struct mob_frost_sphereAI : public ScriptedAI { - } - - bool m_bFall; - uint32 m_uiPermafrostTimer; + mob_frost_sphereAI(Creature* creature) : ScriptedAI(creature) + { + } - void Reset() - { - m_bFall = false; - m_uiPermafrostTimer = 0; - me->SetReactState(REACT_PASSIVE); - me->SetFlying(true); - me->SetDisplayId(25144); - me->SetSpeed(MOVE_RUN, 0.5f, false); - me->GetMotionMaster()->MoveRandom(20.0f); - DoCast(SPELL_FROST_SPHERE); - } + void Reset() + { + _isFalling = false; + me->SetReactState(REACT_PASSIVE); + me->SetFlying(true); + me->SetDisplayId(me->GetCreatureInfo()->Modelid2); + me->SetSpeed(MOVE_RUN, 0.5f, false); + me->GetMotionMaster()->MoveRandom(20.0f); + DoCast(SPELL_FROST_SPHERE); + } - void DamageTaken(Unit* /*who*/, uint32& uiDamage) - { - if (me->GetHealth() < uiDamage) + void DamageTaken(Unit* /*who*/, uint32& damage) { - uiDamage = 0; - if (!m_bFall) + if (me->GetHealth() <= damage) { - m_bFall = true; - me->SetFlying(false); - me->GetMotionMaster()->MoveIdle(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //At hit the ground - me->GetMotionMaster()->MoveFall(142.2f, 0); - //me->FallGround(); //need correct vmap use (i believe it isn't working properly right now) + damage = 0; + if (!_isFalling) + { + _isFalling = true; + me->GetMotionMaster()->MoveIdle(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //At hit the ground + me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); + me->GetMotionMaster()->MoveFall(POINT_FALL_GROUND); + } } } - } - void MovementInform(uint32 uiType, uint32 uiId) - { - if (uiType != POINT_MOTION_TYPE) return; - - switch (uiId) + void MovementInform(uint32 type, uint32 pointId) { - case 0: - m_uiPermafrostTimer = IN_MILLISECONDS; - break; - } - } + if (type != EFFECT_MOTION_TYPE) + return; - void UpdateAI(const uint32 uiDiff) - { - if (m_uiPermafrostTimer) - { - if (m_uiPermafrostTimer <= uiDiff) + switch (pointId) { - m_uiPermafrostTimer = 0; - me->RemoveAurasDueToSpell(SPELL_FROST_SPHERE); - me->SetDisplayId(11686); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); - DoCast(SPELL_PERMAFROST_VISUAL); - DoCast(SPELL_PERMAFROST); - } else m_uiPermafrostTimer -= uiDiff; + case POINT_FALL_GROUND: + me->RemoveAurasDueToSpell(SPELL_FROST_SPHERE); + me->SetDisplayId(me->GetCreatureInfo()->Modelid1); + DoCast(SPELL_PERMAFROST_VISUAL); + DoCast(SPELL_PERMAFROST); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + break; + } } - } - }; + private: + bool _isFalling; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new mob_frost_sphereAI(creature); + }; }; class mob_anubarak_spike : public CreatureScript diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp index bc06a92ef07..a0d6f04f44c 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp @@ -67,6 +67,7 @@ class boss_bronjahm : public CreatureScript { boss_bronjahmAI(Creature* creature) : BossAI(creature, DATA_BRONJAHM) { + DoCast(me, SPELL_SOULSTORM_CHANNEL, true); } void InitializeAI() @@ -82,14 +83,17 @@ class boss_bronjahm : public CreatureScript events.Reset(); events.SetPhase(PHASE_1); events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); - events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000, 15000)); + events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000, 20000)); events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000, 35000), 0, PHASE_1); - me->CastSpell(me, SPELL_SOULSTORM_CHANNEL, true); - instance->SetBossState(DATA_BRONJAHM, NOT_STARTED); } + void JustReachedHome() + { + DoCast(me, SPELL_SOULSTORM_CHANNEL, true); + } + void EnterCombat(Unit* /*who*/) { DoScriptText(SAY_AGGRO, me); @@ -118,7 +122,7 @@ class boss_bronjahm : public CreatureScript events.SetPhase(PHASE_2); DoCast(me, SPELL_TELEPORT); events.ScheduleEvent(EVENT_FEAR, urand(12000, 16000), 0, PHASE_2); - events.ScheduleEvent(EVENT_SOULSTORM, 700, 0, PHASE_2); + events.ScheduleEvent(EVENT_SOULSTORM, 100, 0, PHASE_2); } } @@ -147,7 +151,7 @@ class boss_bronjahm : public CreatureScript { case EVENT_MAGIC_BANE: DoCastVictim(SPELL_MAGIC_S_BANE); - events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000, 15000)); + events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000, 20000)); break; case EVENT_SHADOW_BOLT: if (!me->IsWithinMeleeRange(me->getVictim())) @@ -201,7 +205,7 @@ class mob_corrupted_soul_fragment : public CreatureScript void MovementInform(uint32 type, uint32 id) { - if (type != TARGETED_MOTION_TYPE) + if (type != CHASE_MOTION_TYPE) return; if (instance) diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp index 8180a686e0e..fb39019fb84 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp @@ -306,6 +306,7 @@ class boss_devourer_of_souls : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { me->SetOrientation(me->GetAngle(target)); + me->SendMovementFlagUpdate(); DoCast(me, SPELL_WAILING_SOULS_BEAM); } @@ -332,6 +333,7 @@ class boss_devourer_of_souls : public CreatureScript case EVENT_WAILING_SOULS_TICK: beamAngle += beamAngleDiff; me->SetOrientation(beamAngle); + me->SendMovementFlagUpdate(); me->StopMoving(); DoCast(me, SPELL_WAILING_SOULS); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index 3b15bba5c5d..94a3da2672b 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -1159,7 +1159,7 @@ class npc_ball_of_flame : public CreatureScript void MovementInform(uint32 type, uint32 id) { - if (type == TARGETED_MOTION_TYPE && id == GUID_LOPART(_chaseGUID) && _chaseGUID) + if (type == CHASE_MOTION_TYPE && id == GUID_LOPART(_chaseGUID) && _chaseGUID) { me->RemoveAurasDueToSpell(SPELL_BALL_OF_FLAMES_PERIODIC); DoCast(me, SPELL_FLAMES); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 8396b6e6c85..31b3786a360 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -608,7 +608,7 @@ class npc_high_overlord_saurfang_icc : public CreatureScript me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); me->SendMovementFlagUpdate(); me->Relocate(me->GetPositionX(), me->GetPositionY(), 539.2917f); - me->SendMonsterMove(me->GetPositionX(), me->GetPositionY(), 539.2917f, SPLINEFLAG_FALLING, 0, 0.0f); + me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), 539.2917f, 0.0f); for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr) (*itr)->AI()->DoAction(ACTION_DESPAWN); break; @@ -815,7 +815,7 @@ class npc_muradin_bronzebeard_icc : public CreatureScript me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); me->SendMovementFlagUpdate(); me->Relocate(me->GetPositionX(), me->GetPositionY(), 539.2917f); - me->SendMonsterMove(me->GetPositionX(), me->GetPositionY(), 539.2917f, SPLINEFLAG_FALLING, 0, 0.0f); + me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), 539.2917f, 0.0f); for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr) (*itr)->AI()->DoAction(ACTION_DESPAWN); break; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 0d3640504c1..cf22338995b 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -75,6 +75,7 @@ enum Spells SPELL_PLAGUE_SICKNESS = 70953, SPELL_UNBOUND_PLAGUE_PROTECTION = 70955, SPELL_MUTATED_PLAGUE = 72451, + SPELL_MUTATED_PLAGUE_CLEAR = 72618, // Slime Puddle SPELL_GROW_STACKER = 70345, @@ -244,6 +245,7 @@ class boss_professor_putricide : public CreatureScript { _JustDied(); Talk(SAY_DEATH); + DoCast(SPELL_MUTATED_PLAGUE_CLEAR); } void JustSummoned(Creature* summon) @@ -1427,6 +1429,34 @@ class spell_putricide_regurgitated_ooze : public SpellScriptLoader } }; +class spell_putricide_clear_mutated_plague : public SpellScriptLoader +{ + public: + spell_putricide_clear_mutated_plague() : SpellScriptLoader("spell_putricide_clear_mutated_plague") { } + + class spell_putricide_clear_mutated_plague_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_clear_mutated_plague_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + uint32 auraId = sSpellMgr->GetSpellIdForDifficulty(uint32(GetEffectValue()), GetCaster()); + GetHitUnit()->RemoveAurasDueToSpell(auraId); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_putricide_clear_mutated_plague_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_clear_mutated_plague_SpellScript(); + } +}; + // Stinky and Precious spell, it's here because its used for both (Festergut and Rotface "pets") class spell_stinky_precious_decimate : public SpellScriptLoader { @@ -1478,5 +1508,6 @@ void AddSC_boss_professor_putricide() new spell_putricide_mutated_transformation(); new spell_putricide_mutated_transformation_dmg(); new spell_putricide_regurgitated_ooze(); + new spell_putricide_clear_mutated_plague(); new spell_stinky_precious_decimate(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 25610341a2f..3d3eaa1cc87 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -268,7 +268,7 @@ class boss_sindragosa : public CreatureScript void MovementInform(uint32 type, uint32 point) { - if (type != POINT_MOTION_TYPE) + if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) return; switch (point) @@ -638,7 +638,7 @@ class npc_spinestalker : public CreatureScript float moveTime = me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); me->SetDefaultMovementType(IDLE_MOTION_TYPE); - me->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE); + me->GetMotionMaster()->MoveIdle(); me->StopMoving(); me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SpinestalkerFlyPos); } @@ -646,7 +646,7 @@ class npc_spinestalker : public CreatureScript void MovementInform(uint32 type, uint32 point) { - if (type != POINT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND) + if (type != EFFECT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND) return; me->setActive(false); @@ -753,7 +753,7 @@ class npc_rimefang : public CreatureScript float moveTime = me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); me->SetDefaultMovementType(IDLE_MOTION_TYPE); - me->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE); + me->GetMotionMaster()->MoveIdle(); me->StopMoving(); me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos); } @@ -761,7 +761,7 @@ class npc_rimefang : public CreatureScript void MovementInform(uint32 type, uint32 point) { - if (type != POINT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND) + if (type != EFFECT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND) return; me->setActive(false); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 1fbdb7f4677..5029dbcceee 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -508,7 +508,7 @@ class boss_the_lich_king : public CreatureScript if (fabs(ground_Z - z) < 0.1f) return; - me->GetMotionMaster()->MoveFall(ground_Z); + me->GetMotionMaster()->MoveFall(); } void EnterCombat(Unit* target) @@ -801,7 +801,7 @@ class boss_the_lich_king : public CreatureScript events.ScheduleEvent(EVENT_INTRO_TALK_1, 9000, 0, PHASE_INTRO); break; case POINT_CENTER_1: - me->SetFacing(0.0f); + me->SetFacingTo(0.0f); Talk(SAY_LK_REMORSELESS_WINTER); SendMusicToPlayers(MUSIC_SPECIAL); me->SetReactState(REACT_PASSIVE); @@ -818,7 +818,7 @@ class boss_the_lich_king : public CreatureScript events.ScheduleEvent(EVENT_SOUL_REAPER, 94000, 0, PHASE_TWO); break; case POINT_CENTER_2: - me->SetFacing(0.0f); + me->SetFacingTo(0.0f); Talk(SAY_LK_REMORSELESS_WINTER); SendMusicToPlayers(MUSIC_SPECIAL); me->SetReactState(REACT_PASSIVE); @@ -1047,14 +1047,14 @@ class boss_the_lich_king : public CreatureScript break; case EVENT_OUTRO_TALK_3: if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING))) - me->SetFacing(0.0f, tirion); + me->SetFacingToObject(tirion); Talk(SAY_LK_OUTRO_3); break; case EVENT_OUTRO_MOVE_CENTER: me->GetMotionMaster()->MovePoint(POINT_LK_OUTRO_1, CenterPosition); break; case EVENT_OUTRO_TALK_4: - me->SetFacing(0.01745329f); + me->SetFacingTo(0.01745329f); Talk(SAY_LK_OUTRO_4); break; case EVENT_OUTRO_RAISE_DEAD: @@ -1070,7 +1070,7 @@ class boss_the_lich_king : public CreatureScript case EVENT_OUTRO_TALK_6: Talk(SAY_LK_OUTRO_6); if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->SetFacing(0.0f, me); + tirion->SetFacingToObject(me); me->ClearUnitState(UNIT_STAT_CASTING); DoCastAOE(SPELL_SUMMON_BROKEN_FROSTMOURNE_3); SetEquipmentSlots(false, EQUIP_UNEQUIP); @@ -1222,7 +1222,7 @@ class npc_tirion_fordring_tft : public CreatureScript void SpellHit(Unit* /*caster*/, SpellInfo const* spell) { if (spell->Id == SPELL_ICE_LOCK) - me->SetFacing(3.085098f); + me->SetFacingTo(3.085098f); else if (spell->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK) SetEquipmentSlots(true); // remove glow on ashbringer } @@ -1285,7 +1285,7 @@ class npc_tirion_fordring_tft : public CreatureScript SetEquipmentSlots(false, EQUIP_ASHBRINGER_GLOWING); if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING))) { - me->SetFacing(0.0f, lichKing); + me->SetFacingToObject(lichKing); lichKing->AI()->DoAction(ACTION_PLAY_MUSIC); } break; @@ -1621,7 +1621,7 @@ class npc_strangulate_vehicle : public CreatureScript void IsSummonedBy(Unit* summoner) { - me->SetFacing(0.0f, summoner); + me->SetFacingToObject(summoner); DoCast(summoner, SPELL_HARVEST_SOUL_VEHICLE); _events.Reset(); _events.ScheduleEvent(EVENT_MOVE_TO_LICH_KING, 2000); @@ -1656,7 +1656,8 @@ class npc_strangulate_vehicle : public CreatureScript switch (eventId) { case EVENT_TELEPORT: - me->GetMotionMaster()->MoveIdle(MOTION_SLOT_ACTIVE); + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); if (TempSummon* summ = me->ToTempSummon()) { if (Unit* summoner = summ->GetSummoner()) @@ -1788,7 +1789,7 @@ class npc_terenas_menethil : public CreatureScript _events.Reset(); _events.SetPhase(PHASE_OUTRO); if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING))) - me->SetFacing(0.0f, lichKing); + me->SetFacingToObject(lichKing); _events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_1, 2000, 0, PHASE_OUTRO); _events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_2, 14000, 0, PHASE_OUTRO); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index ab3046806db..6bd8f3cba7d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -1264,7 +1264,7 @@ struct npc_argent_captainAI : public ScriptedAI void EnterEvadeMode() { // not yet following - if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != TARGETED_MOTION_TYPE || IsUndead) + if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != CHASE_MOTION_TYPE || IsUndead) { ScriptedAI::EnterEvadeMode(); return; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp index 4c2348d30c9..58d3a4240b2 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp @@ -20,79 +20,185 @@ enum Spells { - SPELL_NECROTIC_AURA = 55593, - SPELL_SUMMON_SPORE = 29234, - SPELL_DEATHBLOOM = 29865, - H_SPELL_DEATHBLOOM = 55053, - SPELL_INEVITABLE_DOOM = 29204, - H_SPELL_INEVITABLE_DOOM = 55052 + SPELL_NECROTIC_AURA = 55593, + SPELL_WARN_NECROTIC_AURA = 59481, + SPELL_SUMMON_SPORE = 29234, + SPELL_DEATHBLOOM = 29865, + H_SPELL_DEATHBLOOM = 55053, + SPELL_INEVITABLE_DOOM = 29204, + H_SPELL_INEVITABLE_DOOM = 55052 +}; + +enum Texts +{ + SAY_NECROTIC_AURA_APPLIED = 0, + SAY_NECROTIC_AURA_REMOVED = 1, + SAY_NECROTIC_AURA_FADING = 2, }; enum Events { - EVENT_NONE, - EVENT_AURA, - EVENT_BLOOM, - EVENT_DOOM, + EVENT_NECROTIC_AURA = 1, + EVENT_DEATHBLOOM = 2, + EVENT_INEVITABLE_DOOM = 3, + EVENT_SPORE = 4, + EVENT_NECROTIC_AURA_FADING = 5, +}; + +enum Achievement +{ + DATA_ACHIEVEMENT_SPORE_LOSER = 21822183, }; class boss_loatheb : public CreatureScript { -public: - boss_loatheb() : CreatureScript("boss_loatheb") { } + public: + boss_loatheb() : CreatureScript("boss_loatheb") { } - CreatureAI* GetAI(Creature* creature) const - { - return new boss_loathebAI (creature); - } + struct boss_loathebAI : public BossAI + { + boss_loathebAI(Creature* creature) : BossAI(creature, BOSS_LOATHEB) + { + } - struct boss_loathebAI : public BossAI - { - boss_loathebAI(Creature* c) : BossAI(c, BOSS_LOATHEB) {} + void Reset() + { + _Reset(); + _doomCounter = 0; + _sporeLoserData = true; + } - void EnterCombat(Unit* /*who*/) - { - _EnterCombat(); - events.ScheduleEvent(EVENT_AURA, 10000); - events.ScheduleEvent(EVENT_BLOOM, 5000); - events.ScheduleEvent(EVENT_DOOM, 120000); - } + void EnterCombat(Unit* /*who*/) + { + _EnterCombat(); + events.ScheduleEvent(EVENT_NECROTIC_AURA, 17000); + events.ScheduleEvent(EVENT_DEATHBLOOM, 5000); + events.ScheduleEvent(EVENT_SPORE, IsHeroic() ? 18000 : 36000); + events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 120000); + } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; + void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) + { + _sporeLoserData = false; + } - events.Update(diff); + uint32 GetData(uint32 id) + { + if (id != DATA_ACHIEVEMENT_SPORE_LOSER) + return 0; - while (uint32 eventId = events.ExecuteEvent()) + return uint32(_sporeLoserData); + } + + void UpdateAI(uint32 const diff) { - switch (eventId) + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_AURA: - DoCastAOE(SPELL_NECROTIC_AURA); - events.ScheduleEvent(EVENT_AURA, 20000); - break; - case EVENT_BLOOM: - // TODO : Add missing text - DoCastAOE(SPELL_SUMMON_SPORE, true); - DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM, H_SPELL_DEATHBLOOM)); - events.ScheduleEvent(EVENT_BLOOM, 30000); - break; - case EVENT_DOOM: - DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM, H_SPELL_INEVITABLE_DOOM)); - events.ScheduleEvent(EVENT_DOOM, events.GetTimer() < 5*60000 ? 30000 : 15000); - break; + switch (eventId) + { + case EVENT_NECROTIC_AURA: + DoCastAOE(SPELL_NECROTIC_AURA); + DoCast(me, SPELL_WARN_NECROTIC_AURA); + events.ScheduleEvent(EVENT_NECROTIC_AURA, 20000); + events.ScheduleEvent(EVENT_NECROTIC_AURA_FADING, 14000); + break; + case EVENT_DEATHBLOOM: + DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM, H_SPELL_DEATHBLOOM)); + events.ScheduleEvent(EVENT_DEATHBLOOM, 30000); + break; + case EVENT_INEVITABLE_DOOM: + _doomCounter++; + DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM, H_SPELL_INEVITABLE_DOOM)); + events.ScheduleEvent(EVENT_INEVITABLE_DOOM, std::max(120000 - _doomCounter * 15000, 15000)); // needs to be confirmed + break; + case EVENT_SPORE: + DoCast(me, SPELL_SUMMON_SPORE, false); + events.ScheduleEvent(EVENT_SPORE, IsHeroic() ? 18000 : 36000); + break; + case EVENT_NECROTIC_AURA_FADING: + Talk(SAY_NECROTIC_AURA_FADING); + break; + default: + break; + } } + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); + private: + bool _sporeLoserData; + uint8 _doomCounter; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_loathebAI(creature); + } +}; + +class achievement_spore_loser : public AchievementCriteriaScript +{ + public: + achievement_spore_loser() : AchievementCriteriaScript("achievement_spore_loser") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->GetAI()->GetData(DATA_ACHIEVEMENT_SPORE_LOSER); } - }; +}; + +typedef boss_loatheb::boss_loathebAI LoathebAI; + +class spell_loatheb_necrotic_aura_warning : public SpellScriptLoader +{ + public: + spell_loatheb_necrotic_aura_warning() : SpellScriptLoader("spell_loatheb_necrotic_aura_warning") { } + + class spell_loatheb_necrotic_aura_warning_AuraScript : public AuraScript + { + PrepareAuraScript(spell_loatheb_necrotic_aura_warning_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellStore.LookupEntry(SPELL_WARN_NECROTIC_AURA)) + return false; + return true; + } + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTarget()->IsAIEnabled) + CAST_AI(LoathebAI, GetTarget()->GetAI())->Talk(SAY_NECROTIC_AURA_APPLIED); + } + + void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTarget()->IsAIEnabled) + CAST_AI(LoathebAI, GetTarget()->GetAI())->Talk(SAY_NECROTIC_AURA_REMOVED); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_loatheb_necrotic_aura_warning_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_loatheb_necrotic_aura_warning_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_loatheb_necrotic_aura_warning_AuraScript(); + } }; void AddSC_boss_loatheb() { new boss_loatheb(); + new achievement_spore_loser(); + new spell_loatheb_necrotic_aura_warning(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index b0138fb1a5e..be9168c6fd4 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -83,7 +83,11 @@ enum ThaddiusSpells SPELL_BALL_LIGHTNING = 28299, SPELL_CHAIN_LIGHTNING = 28167, H_SPELL_CHAIN_LIGHTNING = 54531, - SPELL_BERSERK = 27680 + SPELL_BERSERK = 27680, + SPELL_POSITIVE_CHARGE = 28062, + SPELL_POSITIVE_CHARGE_STACK = 29659, + SPELL_NEGATIVE_CHARGE = 28085, + SPELL_NEGATIVE_CHARGE_STACK = 29660 }; enum Events @@ -94,6 +98,11 @@ enum Events EVENT_BERSERK, }; +enum Achievement +{ + DATA_POLARITY_SWITCH = 76047605, +}; + class boss_thaddius : public CreatureScript { public: @@ -135,6 +144,7 @@ public: bool checkStalaggAlive; bool checkFeugenAlive; + bool polaritySwitch; uint32 uiAddsTimer; void KilledUnit(Unit* /*victim*/) @@ -194,6 +204,20 @@ public: me->SetReactState(REACT_AGGRESSIVE); } + void SetData(uint32 id, uint32 data) + { + if (id == DATA_POLARITY_SWITCH) + polaritySwitch = data ? true : false; + } + + uint32 GetData(uint32 id) + { + if (id != DATA_POLARITY_SWITCH) + return 0; + + return uint32(polaritySwitch); + } + void UpdateAI(const uint32 diff) { if (checkFeugenAlive && checkStalaggAlive) @@ -400,9 +424,101 @@ public: }; +class spell_thaddius_pos_neg_charge : public SpellScriptLoader +{ + public: + spell_thaddius_pos_neg_charge() : SpellScriptLoader("spell_thaddius_pos_neg_charge") { } + + class spell_thaddius_pos_neg_charge_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thaddius_pos_neg_charge_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_STACK)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_STACK)) + return false; + return true; + } + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void HandleTargets(std::list<Unit*>& targetList) + { + uint8 count = 0; + for (std::list<Unit*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit) + if ((*ihit)->GetGUID() != GetCaster()->GetGUID()) + if (Player* target = (*ihit)->ToPlayer()) + if (target->HasAura(GetTriggeringSpell()->Id)) + ++count; + + if (count) + { + uint32 spellId = 0; + + if (GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE) + spellId = SPELL_POSITIVE_CHARGE_STACK; + else // if (GetSpellInfo()->Id == SPELL_NEGATIVE_CHARGE) + spellId = SPELL_NEGATIVE_CHARGE_STACK; + + GetCaster()->SetAuraStack(spellId, GetCaster(), count); + } + } + + void HandleDamage(SpellEffIndex /*effIndex*/) + { + if (!GetTriggeringSpell()) + return; + + Unit* target = GetHitUnit(); + Unit* caster = GetCaster(); + + if (target->HasAura(GetTriggeringSpell()->Id)) + SetHitDamage(0); + else + { + if (target->GetTypeId() == TYPEID_PLAYER && caster->IsAIEnabled) + caster->ToCreature()->AI()->SetData(DATA_POLARITY_SWITCH, 1); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_thaddius_pos_neg_charge_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnUnitTargetSelect += SpellUnitTargetFn(spell_thaddius_pos_neg_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_thaddius_pos_neg_charge_SpellScript(); + } +}; + +class achievement_polarity_switch : public AchievementCriteriaScript +{ + public: + achievement_polarity_switch() : AchievementCriteriaScript("achievement_polarity_switch") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->GetAI()->GetData(DATA_POLARITY_SWITCH); + } +}; + void AddSC_boss_thaddius() { new boss_thaddius(); new mob_stalagg(); new mob_feugen(); + new spell_thaddius_pos_neg_charge(); + new achievement_polarity_switch(); } diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 32cb279ce5f..c05d9a21850 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -166,8 +166,8 @@ public: kelthuzadGUID = 0; kelthuzadTriggerGUID = 0; - playerDied = 0; - gothikDoorState = GO_STATE_ACTIVE; + playerDied = 0; + gothikDoorState = GO_STATE_ACTIVE; memset(portalsGUID, 0, sizeof(portalsGUID)); } diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 8e995a9b260..052fa3ba4a5 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -838,7 +838,7 @@ public: return; } - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f); } } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index e96801f3ecb..c6f72890d1f 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -61,7 +61,7 @@ enum eEnums //OTHER SPELLS //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other - //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above + SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above NPC_STORMFORGED_LIEUTENANT = 29240, SPELL_ARC_WELD = 59085, @@ -98,11 +98,13 @@ public: m_instance = creature->GetInstanceScript(); m_uiStance = STANCE_DEFENSIVE; memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID)); + canBuff = true; } InstanceScript* m_instance; bool m_bIsChangingStance; + bool canBuff; uint8 m_uiChargingStatus; uint8 m_uiStance; @@ -126,6 +128,10 @@ public: void Reset() { + if (canBuff) + if (!me->HasAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE)) + me->AddAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE, me); + m_bIsChangingStance = false; m_uiChargingStatus = 0; @@ -167,6 +173,16 @@ public: m_instance->SetData(TYPE_BJARNGRIM, NOT_STARTED); } + void EnterEvadeMode() + { + if (me->HasAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE)) + canBuff = true; + else + canBuff = false; + + ScriptedAI::EnterEvadeMode(); + } + void EnterCombat(Unit* /*who*/) { DoScriptText(SAY_AGGRO, me); @@ -211,7 +227,7 @@ public: void UpdateAI(const uint32 uiDiff) { //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim()) return; // Change stance diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 194c2a36862..1fc724c8b6c 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -243,7 +243,7 @@ public: { if (m_uiPause_Timer <= uiDiff) { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) if (me->getVictim()) me->GetMotionMaster()->MoveChase(me->getVictim()); @@ -421,7 +421,7 @@ public: // me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //Set in DB if (me->IsNonMeleeSpellCasted(false)) me->InterruptNonMeleeSpells(false); - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) me->GetMotionMaster()->MovementExpired(); m_bIsFrozen = true; } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp index 4ee71367b55..d1aba800094 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp @@ -174,7 +174,7 @@ public: bIsSlam = false; //and correct movement, if not already - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) { if (me->getVictim()) me->GetMotionMaster()->MoveChase(me->getVictim()); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp index 68435fffb1b..2c7532fcf70 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp @@ -634,7 +634,7 @@ class boss_stormcaller_brundir : public CreatureScript // Prevent to have Brundir somewhere in the air when he die in Air phase if (me->GetPositionZ() > FLOOR_Z) - me->GetMotionMaster()->MoveFall(FLOOR_Z); + me->GetMotionMaster()->MoveFall(); } void KilledUnit(Unit* /*who*/) diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index ea84502c16d..0c59097a9ec 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -18,7 +18,7 @@ /* ScriptData SDName: Boss_Ingvar_The_Plunderer SD%Complete: 95 -SDComment: Some Problems with Annhylde Movement, Blizzlike Timers +SDComment: Some Problems with Annhylde Movement, Blizzlike Timers (just shadow axe summon needs a new timer) SDCategory: Udgarde Keep EndScriptData */ @@ -45,16 +45,32 @@ enum Creatures MOB_INGVAR_UNDEAD = 23980, }; +enum Events +{ + EVENT_CLEAVE = 1, + EVENT_SMASH, + EVENT_STAGGERING_ROAR, + EVENT_ENRAGE, + + EVENT_DARK_SMASH, + EVENT_DREADFUL_ROAR, + EVENT_WOE_STRIKE, + EVENT_SHADOW_AXE +}; + +enum Phases +{ + PHASE_HUMAN = 1, + PHASE_UNDEAD, +}; + enum Spells { //Ingvar Spells human form SPELL_CLEAVE = 42724, SPELL_SMASH = 42669, - H_SPELL_SMASH = 59706, SPELL_STAGGERING_ROAR = 42708, - H_SPELL_STAGGERING_ROAR = 59708, SPELL_ENRAGE = 42705, - H_SPELL_ENRAGE = 59707, SPELL_INGVAR_FEIGN_DEATH = 42795, SPELL_SUMMON_BANSHEE = 42912, @@ -63,9 +79,7 @@ enum Spells //Ingvar Spells undead form SPELL_DARK_SMASH = 42723, SPELL_DREADFUL_ROAR = 42729, - H_SPELL_DREADFUL_ROAR = 59734, SPELL_WOE_STRIKE = 42730, - H_SPELL_WOE_STRIKE = 59735, ENTRY_THROW_TARGET = 23996, SPELL_SHADOW_AXE_SUMMON = 42749 @@ -83,9 +97,9 @@ public: struct boss_ingvar_the_plundererAI : public ScriptedAI { - boss_ingvar_the_plundererAI(Creature* c) : ScriptedAI(c) + boss_ingvar_the_plundererAI(Creature* creature) : ScriptedAI(creature) { - instance = c->GetInstanceScript(); + instance = creature->GetInstanceScript(); } InstanceScript* instance; @@ -93,10 +107,6 @@ public: bool bIsUndead; bool bEventInProgress; - uint32 uiCleaveTimer; - uint32 uiSmashTimer; - uint32 uiEnrageTimer; - uint32 uiRoarTimer; uint32 uiSpawnResTimer; void Reset() @@ -110,10 +120,18 @@ public: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); me->SetStandState(UNIT_STAND_STATE_STAND); - uiCleaveTimer = 2000; - uiSmashTimer = 5000; - uiEnrageTimer = 10000; - uiRoarTimer = 15000; + events.Reset(); + events.SetPhase(PHASE_HUMAN); + + events.ScheduleEvent(EVENT_CLEAVE, urand(6,12)*IN_MILLISECONDS, 0, PHASE_HUMAN); + events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_HUMAN); + events.ScheduleEvent(EVENT_ENRAGE, urand(7,14)*IN_MILLISECONDS, 0, PHASE_HUMAN); + events.ScheduleEvent(EVENT_SMASH, urand(12,17)*IN_MILLISECONDS, 0, PHASE_HUMAN); + + events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10,14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); uiSpawnResTimer = 3000; @@ -138,6 +156,7 @@ public: bEventInProgress = true; bIsUndead = true; + events.SetPhase(PHASE_UNDEAD); DoScriptText(YELL_DEAD_1, me); } @@ -208,70 +227,60 @@ public: return; } - if (uiCleaveTimer <= diff) - { - if (!me->HasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me->getVictim(), SPELL_WOE_STRIKE); - else - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = rand()%5000 + 2000; - } - } else uiCleaveTimer -= diff; + events.Update(diff); - if (uiSmashTimer <= diff) - { - if (!me->HasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me->getVictim(), SPELL_DARK_SMASH); - else - DoCast(me->getVictim(), SPELL_SMASH); - uiSmashTimer = 10000; - } - } else uiSmashTimer -= diff; + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; - if (!bIsUndead) - { - if (uiEnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - uiEnrageTimer = 10000; - } else uiEnrageTimer -= diff; - } else // In Undead form used to summon weapon + while (uint32 eventId = events.ExecuteEvent()) { - if (uiEnrageTimer <= diff) + switch (eventId) { - if (!me->HasUnitState(UNIT_STAT_CASTING)) - { - // Spawn target for Axe - Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1); - if (target) + // PHASE ONE + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, urand(6,12)*IN_MILLISECONDS, 0, PHASE_HUMAN); + break; + case EVENT_STAGGERING_ROAR: + DoCast(me, SPELL_STAGGERING_ROAR); + events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_HUMAN); + break; + case EVENT_ENRAGE: + DoCast(me, SPELL_ENRAGE); + events.ScheduleEvent(EVENT_ENRAGE, urand(7,14)*IN_MILLISECONDS, 0, PHASE_HUMAN); + break; + case EVENT_SMASH: + DoCastVictim(SPELL_SMASH); + events.ScheduleEvent(EVENT_SMASH, urand(12,17)*IN_MILLISECONDS, 0, PHASE_HUMAN); + break; + // PHASE TWO + case EVENT_DARK_SMASH: + DoCastVictim(SPELL_DARK_SMASH); + events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + break; + case EVENT_DREADFUL_ROAR: + DoCast(me, SPELL_DREADFUL_ROAR); + events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + break; + case EVENT_WOE_STRIKE: + DoCastVictim(SPELL_WOE_STRIKE); + events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10,14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + break; + case EVENT_SHADOW_AXE: + if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) { me->SummonCreature(ENTRY_THROW_TARGET, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 2000); - DoCast(me, SPELL_SHADOW_AXE_SUMMON); } - uiEnrageTimer = 30000; - } - } else uiEnrageTimer -= diff; - } - - if (uiRoarTimer <= diff) - { - if (!me->HasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me, SPELL_DREADFUL_ROAR); - else - DoCast(me, SPELL_STAGGERING_ROAR); - uiRoarTimer = 10000; + events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); + break; } - } else uiRoarTimer -= diff; + } DoMeleeAttackIfReady(); } + private: + EventMap events; }; }; @@ -381,8 +390,9 @@ public: { ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); - if (boss_ingvar_the_plunderer::boss_ingvar_the_plundererAI* pAI = CAST_AI(boss_ingvar_the_plunderer::boss_ingvar_the_plundererAI, ingvar->AI())) - pAI->StartZombiePhase(); + if (ingvar->getVictim()) + if (boss_ingvar_the_plunderer::boss_ingvar_the_plundererAI* ai = CAST_AI(boss_ingvar_the_plunderer::boss_ingvar_the_plundererAI, ingvar->AI())) + ai->StartZombiePhase(); me->GetMotionMaster()->MovePoint(2, x+1, y, z+30); ++uiResurectPhase; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp index dc93917f2e5..94a133c78a6 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp @@ -17,354 +17,323 @@ /* ScriptData SDName: Boss_Prince_Keleseth -SD%Complete: 90 -SDComment: Needs Prince Movements, Needs adjustments to blizzlike timers, Needs Shadowbolt castbar, Needs right Ressurect Visual, Needs Some Heroic Spells +SD%Complete: 100 +SDComment: SDCategory: Utgarde Keep EndScriptData */ #include "ScriptPCH.h" #include "utgarde_keep.h" -enum eEnums +enum KelsethEncounter { - ACHIEVEMENT_ON_THE_ROCKS = 1919, - SPELL_SHADOWBOLT = 43667, - SPELL_SHADOWBOLT_HEROIC = 59389, SPELL_FROST_TOMB = 48400, + SPELL_FROST_TOMB_STUN = 42672, SPELL_FROST_TOMB_SUMMON = 42714, + + SPELL_SHADOW_FISSURE = 50657, + SPELL_FULL_HEAL = 17683, SPELL_DECREPIFY = 42702, - SPELL_SCOURGE_RESSURRECTION = 42704, - CREATURE_FROSTTOMB = 23965, - CREATURE_SKELETON = 23970, - - SAY_AGGRO = -1574000, - SAY_FROST_TOMB = -1574001, - SAY_SKELETONS = -1574002, - SAY_KILL = -1574003, - SAY_DEATH = -1574004 + SPELL_BONE_ARMOR = 59386, + + NPC_FROSTTOMB = 23965, + NPC_SKELETON = 23970, + + SAY_START_COMBAT = 1, + SAY_SUMMON_SKELETONS, + SAY_FROST_TOMB, + SAY_FROST_TOMB_EMOTE, + SAY_DEATH, + + EVENT_SHADOWBOLT = 1, + EVENT_FROST_TOMB, + EVENT_SUMMON_SKELETONS, + + EVENT_DECREPIFY, + EVENT_FULL_HEAL, + EVENT_SHADOW_FISSURE, + EVENT_RESURRECT, + + DATA_ON_THE_ROCKS }; #define SKELETONSPAWN_Z 42.8668f -float SkeletonSpawnPoint[5][5]= +float const SkeletonSpawnPoint[1][2] = { {156.2559f, 259.2093f}, - {156.2559f, 259.2093f}, - {156.2559f, 259.2093f}, - {156.2559f, 259.2093f}, - {156.2559f, 259.2093f}, }; -float AttackLoc[3]={197.636f, 194.046f, 40.8164f}; +float AttackLoc[3]= {197.636f, 194.046f, 40.8164f}; -bool ShatterFrostTomb; // needed for achievement: On The Rocks(1919) - -class mob_frost_tomb : public CreatureScript +class npc_frost_tomb : public CreatureScript { public: - mob_frost_tomb() : CreatureScript("mob_frost_tomb") { } + npc_frost_tomb() : CreatureScript("npc_frost_tomb") {} CreatureAI* GetAI(Creature* creature) const { - return new mob_frost_tombAI(creature); + return new npc_frost_tombAI(creature); } - struct mob_frost_tombAI : public ScriptedAI + struct npc_frost_tombAI : public ScriptedAI { - mob_frost_tombAI(Creature* c) : ScriptedAI(c) + npc_frost_tombAI(Creature* creature) : ScriptedAI(creature) { - FrostTombGUID = 0; - } - - uint64 FrostTombGUID; + if (me->isSummon()) + if (Unit* summon = me->ToTempSummon()->GetSummoner()) + DoCast(summon, SPELL_FROST_TOMB, true); - void SetPrisoner(Unit* uPrisoner) - { - FrostTombGUID = uPrisoner->GetGUID(); + instance = creature->GetInstanceScript(); } - void Reset(){ FrostTombGUID = 0; } - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} - void JustDied(Unit* killer) + void JustDied(Unit* /*killer*/) { - if (killer->GetGUID() != me->GetGUID()) - ShatterFrostTomb = true; - - if (FrostTombGUID) - { - Unit* FrostTomb = Unit::GetUnit((*me), FrostTombGUID); - if (FrostTomb) - FrostTomb->RemoveAurasDueToSpell(SPELL_FROST_TOMB); - } + if (instance) + if (Unit* boss = me->GetUnit(*me, instance->GetData64(DATA_PRINCEKELESETH))) + if (boss->ToCreature() && boss->ToCreature()->AI()) + boss->ToCreature()->AI()->SetData(DATA_ON_THE_ROCKS, false); } - void UpdateAI(const uint32 /*diff*/) - { - Unit* temp = Unit::GetUnit((*me), FrostTombGUID); - if ((temp && temp->isAlive() && !temp->HasAura(SPELL_FROST_TOMB)) || !temp) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } + private: + InstanceScript* instance; }; - }; class boss_keleseth : public CreatureScript { public: - boss_keleseth() : CreatureScript("boss_keleseth") { } + boss_keleseth() : CreatureScript("boss_keleseth") {} CreatureAI* GetAI(Creature* creature) const { return new boss_kelesethAI (creature); } - struct boss_kelesethAI : public ScriptedAI + struct boss_kelesethAI : public BossAI { - boss_kelesethAI(Creature* c) : ScriptedAI(c) + boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCEKELESETH_EVENT) { - instance = c->GetInstanceScript(); + creature->SetReactState(REACT_DEFENSIVE); } - InstanceScript* instance; - - uint32 FrostTombTimer; - uint32 SummonSkeletonsTimer; - uint32 RespawnSkeletonsTimer; - uint32 ShadowboltTimer; - uint64 SkeletonGUID[5]; - bool Skeletons; - bool RespawnSkeletons; - void Reset() { - ShadowboltTimer = 0; - Skeletons = false; + instance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); - ShatterFrostTomb = false; + events.Reset(); + events.ScheduleEvent(EVENT_SHADOWBOLT, urand(2,3)*IN_MILLISECONDS); + events.ScheduleEvent(EVENT_FROST_TOMB, urand(14,19)*IN_MILLISECONDS); + events.ScheduleEvent(EVENT_SUMMON_SKELETONS, 6*IN_MILLISECONDS); - ResetTimer(); + summons.DespawnAll(); - if (instance) - instance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); + onTheRocks = true; } - void KilledUnit(Unit* victim) + void EnterCombat(Unit* /*who*/) { - if (victim == me) - return; - - DoScriptText(SAY_KILL, me); + me->SetInCombatWithZone(); + instance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); + Talk(SAY_START_COMBAT); } void JustDied(Unit* /*killer*/) { - DoScriptText(SAY_DEATH, me); - - if (IsHeroic() && !ShatterFrostTomb) - { - AchievementEntry const* AchievOnTheRocks = GetAchievementStore()->LookupEntry(ACHIEVEMENT_ON_THE_ROCKS); - if (AchievOnTheRocks) - { - Map* map = me->GetMap(); - if (map && map->IsDungeon()) - { - Map::PlayerList const &players = map->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievOnTheRocks); - } - } - } - - if (instance) - instance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); + instance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); + summons.DespawnAll(); + Talk(SAY_DEATH); } - void EnterCombat(Unit* /*who*/) + void SetData(uint32 data, uint32 value) { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (instance) - instance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); + if (data == DATA_ON_THE_ROCKS) + onTheRocks = value; } - void ResetTimer(uint32 inc = 0) + uint32 GetData(uint32 data) { - SummonSkeletonsTimer = 5000 + inc; - FrostTombTimer = 28000 + inc; + if (data == DATA_ON_THE_ROCKS) + return onTheRocks; + + return 0; } - void UpdateAI(const uint32 diff) + void ExecuteEvent(uint32 const eventId) { - if (!UpdateVictim()) - return; - - if (ShadowboltTimer <= diff) + switch (eventId) { - Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0); - if (target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER) - me->CastSpell(target, DUNGEON_MODE(SPELL_SHADOWBOLT, SPELL_SHADOWBOLT_HEROIC), true); - ShadowboltTimer = 10000; - } else ShadowboltTimer -= diff; - - if (!Skeletons) - { - if ((SummonSkeletonsTimer <= diff)) - { - Creature* Skeleton; - DoScriptText(SAY_SKELETONS, me); - for (uint8 i = 0; i < 5; ++i) + case EVENT_SUMMON_SKELETONS: + Talk(SAY_SUMMON_SKELETONS); + SummonSkeletons(); + break; + case EVENT_SHADOWBOLT: + DoCastVictim(SPELL_SHADOWBOLT); + events.ScheduleEvent(EVENT_SHADOWBOLT, urand(2,3)*IN_MILLISECONDS); + break; + case EVENT_FROST_TOMB: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true, -SPELL_FROST_TOMB)) { - Skeleton = me->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1], SKELETONSPAWN_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); - if (Skeleton) - { - Skeleton->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); - Skeleton->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); - Skeleton->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Skeleton); - } - } - Skeletons = true; - } else SummonSkeletonsTimer -= diff; - } + Talk(SAY_FROST_TOMB); + Talk(SAY_FROST_TOMB_EMOTE, target->GetGUID()); - if (FrostTombTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (target->isAlive()) - { - //DoCast(target, SPELL_FROST_TOMB_SUMMON, true); - if (Creature* pChains = me->SummonCreature(CREATURE_FROSTTOMB, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) - { - CAST_AI(mob_frost_tomb::mob_frost_tombAI, pChains->AI())->SetPrisoner(target); - pChains->CastSpell(target, SPELL_FROST_TOMB, true); - - DoScriptText(SAY_FROST_TOMB, me); - } + DoCast(target, SPELL_FROST_TOMB_STUN, true); + // checked from sniffs - the player casts the spell + target->CastSpell(target, SPELL_FROST_TOMB_SUMMON, true); } - FrostTombTimer = 15000; - } else FrostTombTimer -= diff; + events.ScheduleEvent(EVENT_FROST_TOMB, urand(14,19)*IN_MILLISECONDS); + break; + } + } - DoMeleeAttackIfReady(); + void SummonSkeletons() + { + // I could not found any spell casted for this + for (uint8 i = 0; i < 4; ++i) + me->SummonCreature(NPC_SKELETON, SkeletonSpawnPoint[0][0], SkeletonSpawnPoint[0][1], SKELETONSPAWN_Z, 0); } + private: + bool onTheRocks; }; - }; -class mob_vrykul_skeleton : public CreatureScript +class npc_vrykul_skeleton : public CreatureScript { public: - mob_vrykul_skeleton() : CreatureScript("mob_vrykul_skeleton") { } + npc_vrykul_skeleton() : CreatureScript("npc_vrykul_skeleton") {} CreatureAI* GetAI(Creature* creature) const { - return new mob_vrykul_skeletonAI (creature); + return new npc_vrykul_skeletonAI (creature); } - struct mob_vrykul_skeletonAI : public ScriptedAI + struct npc_vrykul_skeletonAI : public ScriptedAI { - mob_vrykul_skeletonAI(Creature* c) : ScriptedAI(c) - { - instance = c->GetInstanceScript(); - } - - InstanceScript* instance; - uint32 Respawn_Time; - uint64 Target_Guid; - uint32 Decrepify_Timer; - - bool isDead; + npc_vrykul_skeletonAI(Creature* creature) : ScriptedAI(creature) {} void Reset() { - Respawn_Time = 12000; - Decrepify_Timer = urand(10000, 20000); - isDead = false; + events.Reset(); + events.ScheduleEvent(EVENT_DECREPIFY, urand(4,6)*IN_MILLISECONDS); + + DoCast(SPELL_BONE_ARMOR); } - void EnterCombat(Unit* /*who*/){} - void DamageTaken(Unit* done_by, uint32 &damage) + void DamageTaken(Unit* /*done_by*/, uint32 &damage) { - if (done_by->GetGUID() == me->GetGUID()) - return; - if (damage >= me->GetHealth()) { - PretendToDie(); damage = 0; - } - } - void PretendToDie() - { - isDead = true; - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - }; + // There are some issues with pets + // they will still attack. I would say it is a PetAI bug + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + { + // from sniffs + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); - void Resurrect() - { - isDead = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_SCOURGE_RESSURRECTION, true); + events.Reset(); + events.ScheduleEvent(EVENT_RESURRECT, urand(18,22)*IN_MILLISECONDS); - if (me->getVictim()) - { - me->GetMotionMaster()->MoveChase(me->getVictim()); - me->AI()->AttackStart(me->getVictim()); + me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->MoveIdle(); + } } - else - me->GetMotionMaster()->Initialize(); - }; + } void UpdateAI(const uint32 diff) { - if (instance && instance->GetData(DATA_PRINCEKELESETH_EVENT) == IN_PROGRESS) + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - if (isDead) + switch (eventId) { - if (Respawn_Time <= diff) - { - Resurrect(); - Respawn_Time = 12000; - } else Respawn_Time -= diff; + case EVENT_DECREPIFY: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_DECREPIFY), SPELL_DECREPIFY); + events.ScheduleEvent(EVENT_DECREPIFY, urand(1,5)*IN_MILLISECONDS); + break; + case EVENT_RESURRECT: + events.ScheduleEvent(EVENT_FULL_HEAL, 1*IN_MILLISECONDS); + events.ScheduleEvent(EVENT_SHADOW_FISSURE, 1*IN_MILLISECONDS); + break; + case EVENT_FULL_HEAL: + DoCast(me, SPELL_FULL_HEAL, true); + break; + case EVENT_SHADOW_FISSURE: + DoCast(me, SPELL_SHADOW_FISSURE, true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + me->GetMotionMaster()->MoveChase(me->getVictim()); + events.ScheduleEvent(EVENT_DECREPIFY, urand(4,6)*IN_MILLISECONDS); + break; } - else - { - if (!UpdateVictim()) - return; + } - if (Decrepify_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DECREPIFY); - Decrepify_Timer = 30000; - } else Decrepify_Timer -= diff; + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + DoMeleeAttackIfReady(); + } - DoMeleeAttackIfReady(); - } - }else + private: + EventMap events; + }; +}; + +class spell_frost_tomb : public SpellScriptLoader +{ + public: + spell_frost_tomb() : SpellScriptLoader("spell_frost_tomb") {} + + class spell_frost_tomb_AuraScript : public AuraScript + { + PrepareAuraScript(spell_frost_tomb_AuraScript); + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (me->isAlive()) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH) + if (Unit* caster = GetCaster()) + if (caster->ToCreature() && caster->isAlive()) + caster->ToCreature()->DespawnOrUnsummon(1000); } + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_frost_tomb_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_frost_tomb_AuraScript(); } - }; +}; + + +class achievement_on_the_rocks : public AchievementCriteriaScript +{ + public: + achievement_on_the_rocks() : AchievementCriteriaScript("achievement_on_the_rocks") {} + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->IsAIEnabled && target->GetAI()->GetData(DATA_ON_THE_ROCKS); + } }; void AddSC_boss_keleseth() { new boss_keleseth(); - new mob_frost_tomb(); - new mob_vrykul_skeleton(); + new npc_frost_tomb(); + new npc_vrykul_skeleton(); + new spell_frost_tomb(); + new achievement_on_the_rocks(); } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index 1bedd7e19e9..d5cd79b25f1 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -288,7 +288,7 @@ public: me->Dismount(); if (Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILLISECONDS)) { - pGrauf->GetMotionMaster()->MoveFall(0); + pGrauf->GetMotionMaster()->MoveFall(); pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); } me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f); diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp index 01cd36266d0..5c1ec15030c 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp @@ -20,69 +20,94 @@ enum Spells { - SPELL_CALL_FLAMES = 48258, - SPELL_RITUAL_OF_THE_SWORD = 48276, //Effect #1 Teleport, Effect #2 Dummy + SPELL_SVALA_TRANSFORMING1 = 54140, + SPELL_SVALA_TRANSFORMING2 = 54205, + SPELL_TRANSFORMING_CHANNEL = 54142, + + SPELL_CALL_FLAMES = 48258, // caster effect only, triggers event 17841 SPELL_SINSTER_STRIKE = 15667, H_SPELL_SINSTER_STRIKE = 59409, - SPELL_SVALA_TRANSFORMING1 = 54140, - SPELL_SVALA_TRANSFORMING2 = 54205 + + SPELL_RITUAL_PREPARATION = 48267, + SPELL_RITUAL_OF_THE_SWORD = 48276, + SPELL_RITUAL_STRIKE_TRIGGER = 48331, // triggers 48277 & 59930, needs NPC_RITUAL_TARGET as spell_script_target + SPELL_RITUAL_DISARM = 54159, + SPELL_RITUAL_STRIKE_EFF_1 = 48277, + SPELL_RITUAL_STRIKE_EFF_2 = 59930, + + SPELL_SUMMONED_VIS = 64446, + SPELL_RITUAL_CHANNELER_1 = 48271, + SPELL_RITUAL_CHANNELER_2 = 48274, + SPELL_RITUAL_CHANNELER_3 = 48275, + + // Ritual Channeler spells + SPELL_PARALYZE = 48278, + SPELL_SHADOWS_IN_THE_DARK = 59407, + + // Scourge Hulk spells + SPELL_MIGHTY_BLOW = 48697, + SPELL_VOLATILE_INFECTION = 56785, + H_SPELL_VOLATILE_INFECTION = 59228 }; -//not in db + enum Yells { - SAY_DIALOG_WITH_ARTHAS_1 = -1575015, - SAY_DIALOG_WITH_ARTHAS_2 = -1575016, - SAY_DIALOG_WITH_ARTHAS_3 = -1575017, - SAY_AGGRO = -1575018, - SAY_SLAY_1 = -1575019, - SAY_SLAY_2 = -1575020, - SAY_SLAY_3 = -1575021, - SAY_DEATH = -1575022, - SAY_SACRIFICE_PLAYER_1 = -1575023, - SAY_SACRIFICE_PLAYER_2 = -1575024, - SAY_SACRIFICE_PLAYER_3 = -1575025, - SAY_SACRIFICE_PLAYER_4 = -1575026, - SAY_SACRIFICE_PLAYER_5 = -1575027, - SAY_DIALOG_OF_ARTHAS_1 = -1575028, - SAY_DIALOG_OF_ARTHAS_2 = -1575029 + // Svala + SAY_SVALA_INTRO_0 = 0, + + // Svala Sorrowgrave + SAY_SVALA_INTRO_1 = 0, + SAY_SVALA_INTRO_2 = 1, + SAY_AGGRO = 2, + SAY_SLAY = 3, + SAY_DEATH = 4, + SAY_SACRIFICE_PLAYER = 5, + + // Image of Arthas + SAY_DIALOG_OF_ARTHAS_1 = 0, + SAY_DIALOG_OF_ARTHAS_2 = 1 }; + enum Creatures { CREATURE_ARTHAS = 29280, // Image of Arthas CREATURE_SVALA_SORROWGRAVE = 26668, // Svala after transformation CREATURE_SVALA = 29281, // Svala before transformation - CREATURE_RITUAL_CHANNELER = 27281 + CREATURE_RITUAL_CHANNELER = 27281, + CREATURE_SPECTATOR = 26667, + CREATURE_RITUAL_TARGET = 27327, + CREATURE_FLAME_BRAZIER = 27273, + CREATURE_SCOURGE_HULK = 26555 }; -enum ChannelerSpells -{ - //ritual channeler's spells - SPELL_PARALYZE = 48278, - SPELL_SHADOWS_IN_THE_DARK = 59407 -}; -enum Misc + +enum Objects { - DATA_SVALA_DISPLAY_ID = 25944 + OBJECT_UTGARDE_MIRROR = 191745 }; -enum IntroPhase + +enum SvalaPhase { IDLE, INTRO, - FINISHED + NORMAL, + SACRIFICING, + SVALADEAD }; -enum CombatPhase + +enum SvalaPoint { - NORMAL, - SACRIFICING + POINT_FALL_GROUND = 1, }; -static Position RitualChannelerPos[]= +#define DATA_INCREDIBLE_HULK 2043 + +static const float spectatorWP[2][3] = { - {296.42f, -355.01f, 90.94f, 0.0f}, - {302.36f, -352.01f, 90.54f, 0.0f}, - {291.39f, -350.89f, 90.54f, 0.0f} + {296.95f,-312.76f,86.36f}, + {297.69f,-275.81f,86.36f} }; + static Position ArthasPos = { 295.81f, -366.16f, 92.57f, 1.58f }; -static Position SvalaPos = { 296.632f, -346.075f, 90.6307f, 1.58f }; class boss_svala : public CreatureScript { @@ -96,31 +121,96 @@ public: struct boss_svalaAI : public ScriptedAI { - boss_svalaAI(Creature* c) : ScriptedAI(c) + boss_svalaAI(Creature* creature) : ScriptedAI(creature), summons(creature) { - instance = c->GetInstanceScript(); + instance = creature->GetInstanceScript(); + Phase = IDLE; + + me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_RITUAL_STRIKE_EFF_1, true); + me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_RITUAL_STRIKE_EFF_2, true); } - uint32 uiIntroTimer; + InstanceScript* instance; + SummonList summons; + SvalaPhase Phase; + + Position pos; + float x, y, z; - uint8 uiIntroPhase; + uint32 introTimer; + uint8 introPhase; + uint8 sacrePhase; - IntroPhase Phase; + TempSummon* arthas; + uint64 arthasGUID; - TempSummon* pArthas; - uint64 uiArthasGUID; + uint32 sinsterStrikeTimer; + uint32 callFlamesTimer; + uint32 sacrificeTimer; - InstanceScript* instance; + bool sacrificed; void Reset() { - Phase = IDLE; - uiIntroTimer = 1 * IN_MILLISECONDS; - uiIntroPhase = 0; - uiArthasGUID = 0; + sacrificed = false; + SetCombatMovement(true); + + summons.DespawnAll(); + me->RemoveAllAuras(); + + if (Phase > INTRO) + { + me->SetFlying(true); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + if (Phase > NORMAL) + Phase = NORMAL; + + introTimer = 1 * IN_MILLISECONDS; + introPhase = 0; + arthasGUID = 0; if (instance) + { instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); + instance->SetData64(DATA_SACRIFICED_PLAYER, 0); + } + } + + void JustReachedHome() + { + if (Phase > INTRO) + { + me->SetFlying(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetOrientation(1.58f); + me->SendMovementFlagUpdate(); + } + } + + void EnterCombat(Unit* /*who*/) + { + Talk(SAY_AGGRO); + + sinsterStrikeTimer = 7 * IN_MILLISECONDS; + callFlamesTimer = urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS); + + if (instance) + instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature* summon) + { + if (summon->GetEntry() == CREATURE_RITUAL_CHANNELER) + summon->CastSpell(summon, SPELL_SUMMONED_VIS, true); + + summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature* summon) + { + summons.Despawn(summon); } void MoveInLineOfSight(Unit* who) @@ -132,287 +222,492 @@ public: { Phase = INTRO; me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (GameObject* mirror = GetClosestGameObjectWithEntry(me, OBJECT_UTGARDE_MIRROR, 100.0f)) + mirror->SetGoState(GO_STATE_READY); - if (Creature* pArthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) + if (Creature* arthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) { - pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - uiArthasGUID = pArthas->GetGUID(); + arthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + arthasGUID = arthas->GetGUID(); } } } + + void KilledUnit(Unit* victim) + { + if (victim != me) + Talk(SAY_SLAY); + } + + void DamageTaken(Unit* attacker, uint32 &damage) + { + if (Phase == SVALADEAD) + { + if (attacker != me) + damage = 0; + return; + } - void AttackStart(Unit* /*who*/) {} + if (damage >= me->GetHealth()) + { + if (Phase == SACRIFICING) + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + + damage = 0; + Phase = SVALADEAD; + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetHealth(1); + + SetCombatMovement(false); + me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); + me->GetMotionMaster()->MoveFall(POINT_FALL_GROUND); + } + } + + void MovementInform(uint32 motionType, uint32 pointId) + { + if (motionType != EFFECT_MOTION_TYPE) + return; + + if (pointId == POINT_FALL_GROUND) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + void JustDied(Unit* /*killer*/) + { + summons.DespawnAll(); + + if (instance) + instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); + + Talk(SAY_DEATH); + } + + void SpellHitTarget(Unit* /*target*/, const SpellInfo* spell) + { + if (spell->Id == SPELL_RITUAL_STRIKE_EFF_1 && Phase != NORMAL && Phase != SVALADEAD) + { + Phase = NORMAL; + SetCombatMovement(true); + + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f, true)) + me->GetMotionMaster()->MoveChase(target); + } + } void UpdateAI(const uint32 diff) { - if (Phase != INTRO) + if (Phase == IDLE) return; - if (uiIntroTimer <= diff) + if (Phase == INTRO) { - Creature* pArthas = Unit::GetCreature(*me, uiArthasGUID); - if (!pArthas) + if (introTimer <= diff) + { + Creature* arthas = Unit::GetCreature(*me, arthasGUID); + if (!arthas) + return; + + switch (introPhase) + { + case 0: + Talk(SAY_SVALA_INTRO_0); + ++introPhase; + introTimer = 8100; + break; + case 1: + arthas->AI()->Talk(SAY_DIALOG_OF_ARTHAS_1); + ++introPhase; + introTimer = 10000; + break; + case 2: + arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false); + me->SetFlying(true); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + pos.Relocate(me); + pos.m_positionZ += 8.0f; + me->GetMotionMaster()->MoveTakeoff(0, pos, 3.30078125f); + // spectators flee event + if (instance) + { + std::list<Creature*> lspectatorList; + GetCreatureListWithEntryInGrid(lspectatorList, me, CREATURE_SPECTATOR, 100.0f); + for (std::list<Creature*>::iterator itr = lspectatorList.begin(); itr != lspectatorList.end(); ++itr) + { + if ((*itr)->isAlive()) + { + (*itr)->SetStandState(UNIT_STAND_STATE_STAND); + (*itr)->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + (*itr)->GetMotionMaster()->MovePoint(1, spectatorWP[0][0], spectatorWP[0][1], spectatorWP[0][2]); + } + } + } + ++introPhase; + introTimer = 4200; + break; + case 3: + me->CastSpell(me, SPELL_SVALA_TRANSFORMING1, false); + ++introPhase; + introTimer = 6200; + break; + case 4: + me->CastSpell(me, SPELL_SVALA_TRANSFORMING2, false); + arthas->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->UpdateEntry(CREATURE_SVALA_SORROWGRAVE); + me->SetFacingToObject(arthas); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + ++introPhase; + introTimer = 3200; + break; + case 5: + Talk(SAY_SVALA_INTRO_1); + ++introPhase; + introTimer = 10000; + break; + case 6: + arthas->AI()->Talk(SAY_DIALOG_OF_ARTHAS_2); + ++introPhase; + introTimer = 7200; + break; + case 7: + Talk(SAY_SVALA_INTRO_2); + me->SetOrientation(1.58f); + me->SendMovementFlagUpdate(); + arthas->SetVisible(false); + ++introPhase; + introTimer = 13800; + break; + case 8: + me->SetFlying(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMovementFlagUpdate(); + pos.Relocate(me); + pos.m_positionX = me->GetHomePosition().GetPositionX(); + pos.m_positionY = me->GetHomePosition().GetPositionY(); + pos.m_positionZ = 90.6065f; + me->GetMotionMaster()->MoveLand(0, pos, 6.247422f); + ++introPhase; + introTimer = 3000; + break; + case 9: + if (GameObject* mirror = GetClosestGameObjectWithEntry(me, OBJECT_UTGARDE_MIRROR, 100.0f)) + mirror->SetGoState(GO_STATE_ACTIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + arthas->DespawnOrUnsummon(); + arthasGUID = 0; + Phase = NORMAL; + break; + } + } + else introTimer -= diff; + + return; + } + + if (Phase == NORMAL) + { + //Return since we have no target + if (!UpdateVictim()) return; - switch (uiIntroPhase) + if (me->IsWithinMeleeRange(me->getVictim()) && me->HasUnitMovementFlag(MOVEMENTFLAG_LEVITATING)) + { + me->SetFlying(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMovementFlagUpdate(); + } + + if (sinsterStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); + sinsterStrikeTimer = urand(5 * IN_MILLISECONDS, 9 * IN_MILLISECONDS); + } else sinsterStrikeTimer -= diff; + + if (callFlamesTimer <= diff) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(target, SPELL_CALL_FLAMES); + callFlamesTimer = urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS); + } + } else callFlamesTimer -= diff; + + if (!sacrificed) { - case 0: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_1, me); - ++uiIntroPhase; - uiIntroTimer = 3500; - break; - case 1: - DoScriptText(SAY_DIALOG_OF_ARTHAS_1, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3500; - break; - case 2: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_2, me); - ++uiIntroPhase; - uiIntroTimer = 3500; - break; - case 3: - DoScriptText(SAY_DIALOG_OF_ARTHAS_2, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3500; - break; - case 4: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_3, me); - DoCast(me, SPELL_SVALA_TRANSFORMING1); - ++uiIntroPhase; - uiIntroTimer = 2800; - break; - case 5: - DoCast(me, SPELL_SVALA_TRANSFORMING2); - ++uiIntroPhase; - uiIntroTimer = 200; - break; - case 6: - if (me->SummonCreature(CREATURE_SVALA_SORROWGRAVE, SvalaPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60*IN_MILLISECONDS)) + if (HealthBelowPct(50)) + { + if (Unit* sacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 80, true)) { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(DATA_SVALA_DISPLAY_ID); - pArthas->DespawnOrUnsummon(); - uiArthasGUID = 0; - Phase = FINISHED; + if (instance) + instance->SetData64(DATA_SACRIFICED_PLAYER, sacrificeTarget->GetGUID()); + + Talk(SAY_SACRIFICE_PLAYER); + + DoCast(sacrificeTarget, SPELL_RITUAL_PREPARATION); + + SetCombatMovement(false); + me->SetFlying(true); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + + Phase = SACRIFICING; + sacrePhase = 0; + sacrificeTimer = 1 * IN_MILLISECONDS; + + DoCast(me, SPELL_RITUAL_OF_THE_SWORD); + sacrificed = true; } - else - Reset(); - break; + } } - } else uiIntroTimer -= diff; + + DoMeleeAttackIfReady(); + } + else //SACRIFICING + { + if (sacrificeTimer <= diff) + { + switch (sacrePhase) + { + case 0: + // spawn ritual channelers + if (instance) + { + DoCast(me, SPELL_RITUAL_CHANNELER_1, true); + DoCast(me, SPELL_RITUAL_CHANNELER_2, true); + DoCast(me, SPELL_RITUAL_CHANNELER_3, true); + } + ++sacrePhase; + sacrificeTimer = 2 * IN_MILLISECONDS; + break; + case 1: + me->StopMoving(); + me->GetMotionMaster()->MoveIdle(); + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_RITUAL_STRIKE_TRIGGER, true); + ++sacrePhase; + sacrificeTimer = 200; + break; + case 2: + DoCast(me, SPELL_RITUAL_DISARM); + ++sacrePhase; + break; + case 3: + break; + } + } + else sacrificeTimer -= diff; + } } }; }; -class mob_ritual_channeler : public CreatureScript +class npc_ritual_channeler : public CreatureScript { public: - mob_ritual_channeler() : CreatureScript("mob_ritual_channeler") { } + npc_ritual_channeler() : CreatureScript("npc_ritual_channeler") { } CreatureAI* GetAI(Creature* creature) const { - return new mob_ritual_channelerAI(creature); + return new npc_ritual_channelerAI(creature); } - struct mob_ritual_channelerAI : public Scripted_NoMovementAI + struct npc_ritual_channelerAI : public Scripted_NoMovementAI { - mob_ritual_channelerAI(Creature* c) :Scripted_NoMovementAI(c) + npc_ritual_channelerAI(Creature* creature) :Scripted_NoMovementAI(creature) { - instance = c->GetInstanceScript(); + instance = creature->GetInstanceScript(); } InstanceScript* instance; + uint32 paralyzeTimer; void Reset() { - DoCast(me, SPELL_SHADOWS_IN_THE_DARK); - } - - // called by svala sorrowgrave to set guid of victim - void DoAction(const int32 /*action*/) - { + paralyzeTimer = 1600; if (instance) - if (Unit* victim = me->GetUnit(*me, instance->GetData64(DATA_SACRIFICED_PLAYER))) - DoCast(victim, SPELL_PARALYZE); + if (IsHeroic()) + DoCast(me, SPELL_SHADOWS_IN_THE_DARK); } - - void EnterCombat(Unit* /*who*/) + + void UpdateAI(const uint32 diff) { + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + if (paralyzeTimer <= diff) + { + if (instance) + if (Unit* victim = me->GetUnit(*me, instance->GetData64(DATA_SACRIFICED_PLAYER))) + DoCast(victim, SPELL_PARALYZE, false); + + paralyzeTimer = 200; + } + else + paralyzeTimer -= diff; } }; - }; -class boss_svala_sorrowgrave : public CreatureScript +class npc_spectator : public CreatureScript { public: - boss_svala_sorrowgrave() : CreatureScript("boss_svala_sorrowgrave") { } + npc_spectator() : CreatureScript("npc_spectator") { } CreatureAI* GetAI(Creature* creature) const { - return new boss_svala_sorrowgraveAI(creature); + return new npc_spectatorAI(creature); } - struct boss_svala_sorrowgraveAI : public ScriptedAI + struct npc_spectatorAI : public ScriptedAI { - boss_svala_sorrowgraveAI(Creature* c) : ScriptedAI(c), summons(c) + npc_spectatorAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() { } + + void MovementInform(uint32 motionType, uint32 pointId) { - instance = c->GetInstanceScript(); + if (motionType == POINT_MOTION_TYPE) + { + if (pointId == 1) + me->GetMotionMaster()->MovePoint(2,spectatorWP[1][0],spectatorWP[1][1],spectatorWP[1][2]); + else if (pointId == 2) + me->DespawnOrUnsummon(1000); + } } + }; +}; - uint32 uiSinsterStrikeTimer; - uint32 uiCallFlamesTimer; - uint32 uiRitualOfSwordTimer; - uint32 uiSacrificeTimer; +class checkRitualTarget +{ + public: + explicit checkRitualTarget(Unit* _caster) : caster(_caster) { } - CombatPhase Phase; + bool operator() (Unit* unit) + { + if (InstanceScript* instance = caster->GetInstanceScript()) + if (instance->GetData64(DATA_SACRIFICED_PLAYER) == unit->GetGUID()) + return false; - SummonList summons; + return true; + } - bool bSacrificed; + private: + Unit* caster; +}; - InstanceScript* instance; +class spell_paralyze_pinnacle : public SpellScriptLoader +{ + public: + spell_paralyze_pinnacle() : SpellScriptLoader("spell_paralyze_pinnacle") { } - void Reset() + class spell_paralyze_pinnacle_SpellScript : public SpellScript { - uiSinsterStrikeTimer = 7 * IN_MILLISECONDS; - uiCallFlamesTimer = 10 * IN_MILLISECONDS; - uiRitualOfSwordTimer = 20 * IN_MILLISECONDS; - uiSacrificeTimer = 8 * IN_MILLISECONDS; - - bSacrificed = false; - - Phase = NORMAL; - - DoTeleportTo(296.632f, -346.075f, 90.6307f); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALKING); + PrepareSpellScript(spell_paralyze_pinnacle_SpellScript); - summons.DespawnAll(); + void FilterTargets(std::list<Unit*>& unitList) + { + unitList.remove_if(checkRitualTarget(GetCaster())); + } - if (instance) + void Register() { - instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); - instance->SetData64(DATA_SACRIFICED_PLAYER, 0); + OnUnitTargetSelect += SpellUnitTargetFn(spell_paralyze_pinnacle_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } - } + }; - void EnterCombat(Unit* /*who*/) + SpellScript* GetSpellScript() const { - DoScriptText(SAY_AGGRO, me); - - if (instance) - instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); + return new spell_paralyze_pinnacle_SpellScript(); } +}; - void JustSummoned(Creature* summon) - { - summons.Summon(summon); - } +class npc_scourge_hulk : public CreatureScript +{ + public: + npc_scourge_hulk() : CreatureScript("npc_scourge_hulk") { } - void SummonedCreatureDespawn(Creature* summon) + struct npc_scourge_hulkAI : public ScriptedAI { - summons.Despawn(summon); - } + npc_scourge_hulkAI(Creature* creature) : ScriptedAI(creature) { } - void UpdateAI(const uint32 diff) - { - if (Phase == NORMAL) + uint32 mightyBlow; + uint32 volatileInfection; + + void Reset() + { + mightyBlow = urand(4000, 9000); + volatileInfection = urand(10000, 14000); + killedByRitualStrike = false; + } + + uint32 GetData(uint32 type) + { + return type == DATA_INCREDIBLE_HULK ? killedByRitualStrike : 0; + } + + void DamageTaken(Unit* attacker, uint32 &damage) + { + if (damage >= me->GetHealth() && attacker->GetEntry() == CREATURE_SVALA_SORROWGRAVE) + killedByRitualStrike = true; + } + + void UpdateAI(uint32 const diff) { - //Return since we have no target if (!UpdateVictim()) return; - if (uiSinsterStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); - uiSinsterStrikeTimer = urand(5 * IN_MILLISECONDS, 9 * IN_MILLISECONDS); - } else uiSinsterStrikeTimer -= diff; - - if (uiCallFlamesTimer <= diff) + if (mightyBlow <= diff) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(target, SPELL_CALL_FLAMES); - uiCallFlamesTimer = urand(8 * IN_MILLISECONDS, 12 * IN_MILLISECONDS); - } - } else uiCallFlamesTimer -= diff; + if (Unit* victim = me->getVictim()) + if (!victim->HasUnitState(UNIT_STAT_STUNNED)) // Prevent knocking back a ritual player + DoCast(victim, SPELL_MIGHTY_BLOW); + mightyBlow = urand(12000, 17000); + } + else + mightyBlow -= diff; - if (!bSacrificed) + if (volatileInfection <= diff) { - if (uiRitualOfSwordTimer <= diff) - { - if (Unit* pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(RAND(SAY_SACRIFICE_PLAYER_1, SAY_SACRIFICE_PLAYER_2, SAY_SACRIFICE_PLAYER_3, SAY_SACRIFICE_PLAYER_4, SAY_SACRIFICE_PLAYER_5), me); - DoCast(pSacrificeTarget, SPELL_RITUAL_OF_THE_SWORD); - //Spell doesn't teleport - DoTeleportPlayer(pSacrificeTarget, 296.632f, -346.075f, 90.63f, 4.6f); - me->SetUnitMovementFlags(MOVEMENTFLAG_CAN_FLY); - DoTeleportTo(296.632f, -346.075f, 120.85f); - Phase = SACRIFICING; - if (instance) - { - instance->SetData64(DATA_SACRIFICED_PLAYER, pSacrificeTarget->GetGUID()); - - for (uint8 i = 0; i < 3; ++i) - if (Creature* summon = me->SummonCreature(CREATURE_RITUAL_CHANNELER, RitualChannelerPos[i], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) - summon->AI()->DoAction(0); - } - - bSacrificed = true; - } - } else uiRitualOfSwordTimer -= diff; + DoCastVictim(SPELL_VOLATILE_INFECTION); + volatileInfection = urand(13000, 17000); } + else + volatileInfection -= diff; DoMeleeAttackIfReady(); } - else //SACRIFICING - { - if (uiSacrificeTimer <= diff) - { - Unit* pSacrificeTarget = instance ? Unit::GetUnit(*me, instance->GetData64(DATA_SACRIFICED_PLAYER)) : NULL; - if (instance && !summons.empty() && pSacrificeTarget && pSacrificeTarget->isAlive()) - me->Kill(pSacrificeTarget, false); // durability damage? - - //go down - Phase = NORMAL; - pSacrificeTarget = NULL; - me->SetUnitMovementFlags(MOVEMENTFLAG_WALKING); - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->GetMotionMaster()->MoveChase(target); - uiSacrificeTimer = 8 * IN_MILLISECONDS; - } - else uiSacrificeTimer -= diff; - } - } + private: + bool killedByRitualStrike; + }; - void KilledUnit(Unit* /*victim*/) + CreatureAI* GetAI(Creature* creature) const { - DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2, SAY_SLAY_3), me); + return new npc_scourge_hulkAI(creature); } +}; - void JustDied(Unit* killer) - { - if (instance) - { - Creature* pSvala = Unit::GetCreature((*me), instance->GetData64(DATA_SVALA)); - if (pSvala && pSvala->isAlive()) - killer->Kill(pSvala); +class achievement_incredible_hulk : public AchievementCriteriaScript +{ + public: + achievement_incredible_hulk() : AchievementCriteriaScript("achievement_incredible_hulk") { } - instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); - } - DoScriptText(SAY_DEATH, me); + bool OnCheck(Player* /*player*/, Unit* target) + { + return target && target->IsAIEnabled && target->GetAI()->GetData(DATA_INCREDIBLE_HULK); } - }; - }; void AddSC_boss_svala() { new boss_svala(); - new mob_ritual_channeler(); - new boss_svala_sorrowgrave(); + new npc_ritual_channeler(); + new npc_spectator(); + new spell_paralyze_pinnacle(); + new npc_scourge_hulk(); + new achievement_incredible_hulk(); } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp index c5bc235da1f..cb596f284c5 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp @@ -170,8 +170,12 @@ public: void SetData64(uint32 type, uint64 data) { - if (type == DATA_SACRIFICED_PLAYER) - uiSacrificedPlayer = data; + switch (type) + { + case DATA_SACRIFICED_PLAYER: + uiSacrificedPlayer = data; + break; + } } uint32 GetData(uint32 type) @@ -201,6 +205,7 @@ public: case DATA_MOB_ORB: return uiPalehoofOrb; case DATA_SVALA: return uiSvala; case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; + case DATA_SACRIFICED_PLAYER: return uiSacrificedPlayer; } return 0; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h index 7d10483ca1d..872314ee25e 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h @@ -53,7 +53,7 @@ enum eCreatures MOB_MASSIVE_JORMUNGAR = 26685, MOB_FEROCIOUS_RHINO = 26686, MOB_SVALA = 29281, - MOB_PALEHOOF_ORB = 26688, + MOB_PALEHOOF_ORB = 26688 }; #endif diff --git a/src/server/scripts/Northrend/dalaran.cpp b/src/server/scripts/Northrend/dalaran.cpp index 57007a93fa7..cd3cbf29d0d 100644 --- a/src/server/scripts/Northrend/dalaran.cpp +++ b/src/server/scripts/Northrend/dalaran.cpp @@ -32,7 +32,12 @@ Script Data End */ enum Spells { SPELL_TRESPASSER_A = 54028, - SPELL_TRESPASSER_H = 54029 + SPELL_TRESPASSER_H = 54029, + + SPELL_SUNREAVER_DISGUISE_FEMALE = 70973, + SPELL_SUNREAVER_DISGUISE_MALE = 70974, + SPELL_SILVER_COVENANT_DISGUISE_FEMALE = 70971, + SPELL_SILVER_COVENANT_DISGUISE_MALE = 70972, }; enum NPCs // All outdoor guards are within 35.0f of these NPCs @@ -71,8 +76,10 @@ public: Player* player = who->GetCharmerOrOwnerPlayerOrPlayerItself(); - // If player has Disguise aura for quest A Meeting With The Magister or An Audience With The Arcanist, do not teleport it away but let it pass - if (!player || player->isGameMaster() || player->IsBeingTeleported() || player->HasAura(70973) || player->HasAura(70971)) + if (!player || player->isGameMaster() || player->IsBeingTeleported() || + // If player has Disguise aura for quest A Meeting With The Magister or An Audience With The Arcanist, do not teleport it away but let it pass + player->HasAura(SPELL_SUNREAVER_DISGUISE_FEMALE) || player->HasAura(SPELL_SUNREAVER_DISGUISE_MALE) || + player->HasAura(SPELL_SILVER_COVENANT_DISGUISE_FEMALE) || player->HasAura(SPELL_SILVER_COVENANT_DISGUISE_MALE)) return; switch (me->GetEntry()) diff --git a/src/server/scripts/Northrend/grizzly_hills.cpp b/src/server/scripts/Northrend/grizzly_hills.cpp index de0c6a909ad..9eb73463795 100644 --- a/src/server/scripts/Northrend/grizzly_hills.cpp +++ b/src/server/scripts/Northrend/grizzly_hills.cpp @@ -16,115 +16,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Grizzly_Hills -SD%Complete: 80 -SDComment: Quest support: 12231, 12247 -SDCategory: Grizzly Hills -EndScriptData */ - -/* ContentData -npc_orsonn_and_kodian -EndContentData */ - #include "ScriptPCH.h" #include "ScriptedEscortAI.h" -#define GOSSIP_ITEM1 "You're free to go Orsonn, but first tell me what's wrong with the furbolg." -#define GOSSIP_ITEM2 "What happened then?" -#define GOSSIP_ITEM3 "Thank you, Son of Ursoc. I'll see what can be done." -#define GOSSIP_ITEM4 "Who was this stranger?" -#define GOSSIP_ITEM5 "Thank you, Kodian. I'll do what I can." - -enum eEnums -{ - GOSSIP_TEXTID_ORSONN1 = 12793, - GOSSIP_TEXTID_ORSONN2 = 12794, - GOSSIP_TEXTID_ORSONN3 = 12796, - - GOSSIP_TEXTID_KODIAN1 = 12797, - GOSSIP_TEXTID_KODIAN2 = 12798, - - NPC_ORSONN = 27274, - NPC_KODIAN = 27275, - - //trigger creatures - NPC_ORSONN_CREDIT = 27322, - NPC_KODIAN_CREDIT = 27321, - - QUEST_CHILDREN_OF_URSOC = 12247, - QUEST_THE_BEAR_GODS_OFFSPRING = 12231 -}; - -class npc_orsonn_and_kodian : public CreatureScript -{ -public: - npc_orsonn_and_kodian() : CreatureScript("npc_orsonn_and_kodian") { } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_CHILDREN_OF_URSOC) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_THE_BEAR_GODS_OFFSPRING) == QUEST_STATUS_INCOMPLETE) - { - switch (creature->GetEntry()) - { - case NPC_ORSONN: - if (!player->GetReqKillOrCastCurrentCount(QUEST_CHILDREN_OF_URSOC, NPC_ORSONN_CREDIT) || !player->GetReqKillOrCastCurrentCount(QUEST_THE_BEAR_GODS_OFFSPRING, NPC_ORSONN_CREDIT)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN1, creature->GetGUID()); - return true; - } - break; - case NPC_KODIAN: - if (!player->GetReqKillOrCastCurrentCount(QUEST_CHILDREN_OF_URSOC, NPC_KODIAN_CREDIT) || !player->GetReqKillOrCastCurrentCount(QUEST_THE_BEAR_GODS_OFFSPRING, NPC_KODIAN_CREDIT)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_KODIAN1, creature->GetGUID()); - return true; - } - break; - } - } - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction) - { - player->PlayerTalkClass->ClearMenus(); - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN2, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN3, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->CLOSE_GOSSIP_MENU(); - player->TalkedToCreature(NPC_ORSONN_CREDIT, creature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_KODIAN2, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->CLOSE_GOSSIP_MENU(); - player->TalkedToCreature(NPC_KODIAN_CREDIT, creature->GetGUID()); - break; - } - - return true; - } -}; - /*###### ## Quest 12027: Mr. Floppy's Perilous Adventure ######*/ @@ -801,7 +695,6 @@ public: void AddSC_grizzly_hills() { - new npc_orsonn_and_kodian; new npc_emily; new npc_mrfloppy; new npc_outhouse_bunny; diff --git a/src/server/scripts/Northrend/icecrown.cpp b/src/server/scripts/Northrend/icecrown.cpp index 28384455616..91522503d65 100644 --- a/src/server/scripts/Northrend/icecrown.cpp +++ b/src/server/scripts/Northrend/icecrown.cpp @@ -115,38 +115,6 @@ public: }; /*###### -## npc_dame_evniki_kapsalis -######*/ - -enum eDameEnvikiKapsalis -{ - TITLE_CRUSADER = 123 -}; - -class npc_dame_evniki_kapsalis : public CreatureScript -{ -public: - npc_dame_evniki_kapsalis() : CreatureScript("npc_dame_evniki_kapsalis") { } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (player->HasTitle(TITLE_CRUSADER)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction) - { - player->PlayerTalkClass->ClearMenus(); - if (uiAction == GOSSIP_ACTION_TRADE) - player->GetSession()->SendListInventory(creature->GetGUID()); - return true; - } -}; - -/*###### ## npc_squire_david ######*/ @@ -276,65 +244,6 @@ public: }; /*###### -## npc_alorah_and_grimmin -######*/ - -enum ealorah_and_grimmin -{ - SPELL_CHAIN = 68341, - NPC_FJOLA_LIGHTBANE = 36065, - NPC_EYDIS_DARKBANE = 36066, - NPC_PRIESTESS_ALORAH = 36101, - NPC_PRIEST_GRIMMIN = 36102 -}; - -class npc_alorah_and_grimmin : public CreatureScript -{ -public: - npc_alorah_and_grimmin() : CreatureScript("npc_alorah_and_grimmin") { } - - struct npc_alorah_and_grimminAI : public ScriptedAI - { - npc_alorah_and_grimminAI(Creature* creature) : ScriptedAI(creature) {} - - bool uiCast; - - void Reset() - { - uiCast = false; - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (uiCast) - return; - uiCast = true; - Creature* target = NULL; - - switch (me->GetEntry()) - { - case NPC_PRIESTESS_ALORAH: - target = me->FindNearestCreature(NPC_EYDIS_DARKBANE, 10.0f); - break; - case NPC_PRIEST_GRIMMIN: - target = me->FindNearestCreature(NPC_FJOLA_LIGHTBANE, 10.0f); - break; - } - if (target) - DoCast(target, SPELL_CHAIN); - - if (!UpdateVictim()) - return; - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_alorah_and_grimminAI(creature); - } -}; - -/*###### ## npc_guardian_pavilion ######*/ @@ -429,10 +338,8 @@ public: void AddSC_icecrown() { new npc_arete; - new npc_dame_evniki_kapsalis; new npc_squire_david; new npc_argent_valiant; - new npc_alorah_and_grimmin; new npc_guardian_pavilion; new npc_vereth_the_cunning; } |
