diff options
author | Keader <keader.android@gmail.com> | 2016-10-14 19:01:58 -0300 |
---|---|---|
committer | joschiwald <joschiwald.trinity@gmail.com> | 2017-10-03 16:28:15 +0200 |
commit | c514227479938aec6fcda2ce520620484379a3c1 (patch) | |
tree | 4b68e735a5abad40f3ff8096de7171f5ffd111a6 | |
parent | 00dce76c5d59666b2827cefcadbc09844aa9143a (diff) |
Core/Scripts: Implemented right Snobold Vassal behavior on Gormok fight. (#17934)
(cherry picked from commit 8fb2dce01774bc0e1bcd96eddbfc1239200ae4ee)
-rw-r--r-- | sql/updates/world/master/2017_10_03_03_world_2016_10_14_06_world.sql | 20 | ||||
-rw-r--r-- | src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp | 422 |
2 files changed, 303 insertions, 139 deletions
diff --git a/sql/updates/world/master/2017_10_03_03_world_2016_10_14_06_world.sql b/sql/updates/world/master/2017_10_03_03_world_2016_10_14_06_world.sql new file mode 100644 index 00000000000..f42a57a5a5c --- /dev/null +++ b/sql/updates/world/master/2017_10_03_03_world_2016_10_14_06_world.sql @@ -0,0 +1,20 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_gormok_ride_player','spell_gormok_jump_to_hand','spell_gormok_snobolled'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(66245,'spell_gormok_ride_player'), +(66342,'spell_gormok_jump_to_hand'), +(66406,'spell_gormok_snobolled'); + +DELETE FROM `disables` WHERE `sourceType`=0 AND `entry`=66636; +INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, `comment`) VALUES +(0, 66636, 64, 0, 0, 'Disable LoS for Spell Rising Anger'); + +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=34796; +INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES +(34796, 46598, 0, 0); + +DELETE FROM `vehicle_template_accessory` WHERE `entry`=34796 AND `accessory_entry`=34800; +INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`, `summontimer`) VALUES +(34796,34800,0,0,'Snobold Vassal', 5,0), +(34796,34800,1,0,'Snobold Vassal', 5,0), +(34796,34800,2,0,'Snobold Vassal', 5,0), +(34796,34800,3,0,'Snobold Vassal', 5,0); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index 9024bd60468..e3ace1fec72 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -16,9 +16,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -// Known bugs: -// Gormok - Snobolled (creature at back) - #include "ScriptMgr.h" #include "InstanceScript.h" #include "Map.h" @@ -76,14 +73,16 @@ enum BossSpells //Gormok SPELL_IMPALE = 66331, SPELL_STAGGERING_STOMP = 67648, - SPELL_RISING_ANGER = 66636, //Snobold + SPELL_RISING_ANGER = 66636, SPELL_SNOBOLLED = 66406, SPELL_BATTER = 66408, SPELL_FIRE_BOMB = 66313, SPELL_FIRE_BOMB_1 = 66317, SPELL_FIRE_BOMB_DOT = 66318, SPELL_HEAD_CRACK = 66407, + SPELL_JUMP_TO_HAND = 66342, + SPELL_RIDE_PLAYER = 66245, //Acidmaw & Dreadscale Generic SPELL_SWEEP = 66794, @@ -122,38 +121,41 @@ enum BossSpells enum MyActions { ACTION_ENABLE_FIRE_BOMB = 1, - ACTION_DISABLE_FIRE_BOMB = 2 + ACTION_DISABLE_FIRE_BOMB = 2, + ACTION_ACTIVE_SNOBOLD = 3 }; enum Events { // Gormok EVENT_IMPALE = 1, - EVENT_STAGGERING_STOMP = 2, - EVENT_THROW = 3, + EVENT_STAGGERING_STOMP, + EVENT_THROW, // Snobold - EVENT_FIRE_BOMB = 4, - EVENT_BATTER = 5, - EVENT_HEAD_CRACK = 6, + EVENT_FIRE_BOMB, + EVENT_BATTER, + EVENT_HEAD_CRACK, + EVENT_SNOBOLLED, + EVENT_CHECK_MOUNT, // Acidmaw & Dreadscale - EVENT_BITE = 7, - EVENT_SPEW = 8, - EVENT_SLIME_POOL = 9, - EVENT_SPIT = 10, - EVENT_SPRAY = 11, - EVENT_SWEEP = 12, - EVENT_SUBMERGE = 13, - EVENT_EMERGE = 14, - EVENT_SUMMON_ACIDMAW = 15, + EVENT_BITE, + EVENT_SPEW, + EVENT_SLIME_POOL, + EVENT_SPIT, + EVENT_SPRAY, + EVENT_SWEEP, + EVENT_SUBMERGE, + EVENT_EMERGE, + EVENT_SUMMON_ACIDMAW, // Icehowl - EVENT_FEROCIOUS_BUTT = 16, - EVENT_MASSIVE_CRASH = 17, - EVENT_WHIRL = 18, - EVENT_ARCTIC_BREATH = 19, - EVENT_TRAMPLE = 20 + EVENT_FEROCIOUS_BUTT, + EVENT_MASSIVE_CRASH, + EVENT_WHIRL, + EVENT_ARCTIC_BREATH, + EVENT_TRAMPLE }; enum Phases @@ -163,6 +165,13 @@ enum Phases PHASE_SUBMERGED = 3 }; +enum GormokMisc +{ + DATA_NEW_TARGET = 1, + GORMOK_HAND_SEAT = 4, + PLAYER_VEHICLE_ID = 444, +}; + class boss_gormok : public CreatureScript { public: @@ -174,9 +183,9 @@ class boss_gormok : public CreatureScript void Reset() override { - events.ScheduleEvent(EVENT_IMPALE, urand(8*IN_MILLISECONDS, 10*IN_MILLISECONDS)); - events.ScheduleEvent(EVENT_STAGGERING_STOMP, 15*IN_MILLISECONDS); - events.ScheduleEvent(EVENT_THROW, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS)); + events.ScheduleEvent(EVENT_IMPALE, Seconds(8), Seconds(10)); + events.ScheduleEvent(EVENT_STAGGERING_STOMP, Seconds(15)); + events.ScheduleEvent(EVENT_THROW, Seconds(15), Seconds(30)); summons.DespawnAll(); } @@ -221,18 +230,7 @@ class boss_gormok : public CreatureScript void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - me->SetInCombatWithZone(); instance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_IN_PROGRESS); - - for (uint8 i = 0; i < MAX_SNOBOLDS; i++) - { - if (Creature* pSnobold = DoSpawnCreature(NPC_SNOBOLD_VASSAL, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0)) - { - pSnobold->EnterVehicle(me, i); - pSnobold->SetInCombatWithZone(); - pSnobold->AI()->DoAction(ACTION_ENABLE_FIRE_BOMB); - } - } } void DamageTaken(Unit* /*who*/, uint32& damage) override @@ -240,8 +238,14 @@ class boss_gormok : public CreatureScript // despawn the remaining passengers on death if (damage >= me->GetHealth()) for (uint8 i = 0; i < MAX_SNOBOLDS; ++i) - if (Unit* pSnobold = me->GetVehicleKit()->GetPassenger(i)) - pSnobold->ToCreature()->DespawnOrUnsummon(); + if (Unit* snobold = me->GetVehicleKit()->GetPassenger(i)) + snobold->ToCreature()->DespawnOrUnsummon(); + } + + void PassengerBoarded(Unit* who, int8 seatId, bool apply) override + { + if (apply && seatId == GORMOK_HAND_SEAT) + who->CastSpell(me, SPELL_RISING_ANGER, true); } void UpdateAI(uint32 diff) override @@ -260,30 +264,28 @@ class boss_gormok : public CreatureScript { case EVENT_IMPALE: DoCastVictim(SPELL_IMPALE); - events.ScheduleEvent(EVENT_IMPALE, urand(8*IN_MILLISECONDS, 10*IN_MILLISECONDS)); - return; + events.Repeat(Seconds(8), Seconds(10)); + break; case EVENT_STAGGERING_STOMP: DoCastVictim(SPELL_STAGGERING_STOMP); - events.ScheduleEvent(EVENT_STAGGERING_STOMP, 15*IN_MILLISECONDS); - return; + events.Repeat(Seconds(15)); + break; case EVENT_THROW: for (uint8 i = 0; i < MAX_SNOBOLDS; ++i) { - if (Unit* pSnobold = me->GetVehicleKit()->GetPassenger(i)) + if (Unit* snobold = me->GetVehicleKit()->GetPassenger(i)) { - pSnobold->ExitVehicle(); - pSnobold->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - pSnobold->ToCreature()->SetReactState(REACT_AGGRESSIVE); - pSnobold->ToCreature()->AI()->DoAction(ACTION_DISABLE_FIRE_BOMB); - pSnobold->CastSpell(me, SPELL_RISING_ANGER, true); - Talk(EMOTE_SNOBOLLED); + snobold->ExitVehicle(); + snobold->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + snobold->GetAI()->DoAction(ACTION_DISABLE_FIRE_BOMB); + snobold->CastSpell(me, SPELL_JUMP_TO_HAND, true); break; } } - events.ScheduleEvent(EVENT_THROW, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS)); - return; + events.Repeat(Seconds(15), Seconds(30)); + break; default: - return; + break; } } @@ -297,6 +299,23 @@ class boss_gormok : public CreatureScript } }; +class SnobolledTargetSelector : public std::unary_function<Unit*, bool> +{ +public: + SnobolledTargetSelector(Unit const* /*unit*/) { } + + bool operator()(Unit* unit) const + { + if (unit->GetTypeId() != TYPEID_PLAYER) + return false; + + if (unit->HasAura(SPELL_RIDE_PLAYER) || unit->HasAura(SPELL_SNOBOLLED)) + return false; + + return true; + } +}; + class npc_snobold_vassal : public CreatureScript { public: @@ -304,59 +323,24 @@ class npc_snobold_vassal : public CreatureScript struct npc_snobold_vassalAI : public ScriptedAI { - npc_snobold_vassalAI(Creature* creature) : ScriptedAI(creature) + npc_snobold_vassalAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _isActive(false) { - _targetDied = false; - _instance = creature->GetInstanceScript(); _instance->SetData(DATA_SNOBOLD_COUNT, INCREASE); + SetCombatMovement(false); } void Reset() override { - _events.ScheduleEvent(EVENT_BATTER, 5*IN_MILLISECONDS); - _events.ScheduleEvent(EVENT_HEAD_CRACK, 25*IN_MILLISECONDS); - - _targetGUID.Clear(); - _targetDied = false; - - //Workaround for Snobold me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit* who) override - { - _targetGUID = who->GetGUID(); - me->TauntApply(who); - DoCast(who, SPELL_SNOBOLLED); - } - - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) override - { - if (pDoneBy->GetGUID() == _targetGUID) - uiDamage = 0; - } - - void MovementInform(uint32 type, uint32 pointId) override - { - if (type != POINT_MOTION_TYPE) - return; - - switch (pointId) - { - case 0: - if (_targetDied) - me->DespawnOrUnsummon(); - break; - default: - break; - } + me->SetInCombatWithZone(); + _events.ScheduleEvent(EVENT_CHECK_MOUNT, Seconds(1)); + _events.ScheduleEvent(EVENT_FIRE_BOMB, Seconds(5), Seconds(30)); } void JustDied(Unit* /*killer*/) override { if (Unit* target = ObjectAccessor::GetPlayer(*me, _targetGUID)) - if (target->IsAlive()) - target->RemoveAurasDueToSpell(SPELL_SNOBOLLED); + target->RemoveAurasDueToSpell(SPELL_SNOBOLLED); _instance->SetData(DATA_SNOBOLD_COUNT, DECREASE); } @@ -365,50 +349,69 @@ class npc_snobold_vassal : public CreatureScript switch (action) { case ACTION_ENABLE_FIRE_BOMB: - _events.ScheduleEvent(EVENT_FIRE_BOMB, urand(5*IN_MILLISECONDS, 30*IN_MILLISECONDS)); + _events.ScheduleEvent(EVENT_FIRE_BOMB, Seconds(5), Seconds(30)); break; case ACTION_DISABLE_FIRE_BOMB: _events.CancelEvent(EVENT_FIRE_BOMB); break; + case ACTION_ACTIVE_SNOBOLD: + _isActive = true; + break; default: break; } } - void UpdateAI(uint32 diff) override + void SetGUID(ObjectGuid guid, int32 id) override + { + if (id == DATA_NEW_TARGET) + if (Unit* target = ObjectAccessor::GetPlayer(*me, guid)) + { + _targetGUID = guid; + AttackStart(target); + _events.ScheduleEvent(EVENT_BATTER, Seconds(5)); + _events.ScheduleEvent(EVENT_HEAD_CRACK, Seconds(25)); + _events.ScheduleEvent(EVENT_SNOBOLLED, Milliseconds(500)); + } + } + + void AttackStart(Unit* who) override { - if (!UpdateVictim() || _targetDied) + //Snobold only melee attack players that is your vehicle + if (!_isActive || who->GetGUID() != _targetGUID) return; - if (Unit* target = ObjectAccessor::GetPlayer(*me, _targetGUID)) + ScriptedAI::AttackStart(who); + } + + void MountOnBoss() + { + Unit* gormok = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_GORMOK)); + if (gormok && gormok->IsAlive()) { - if (!target->IsAlive()) - { - Unit* gormok = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_GORMOK)); - if (gormok && gormok->IsAlive()) - { - SetCombatMovement(false); - _targetDied = true; + me->AttackStop(); + _targetGUID.Clear(); + _isActive = false; + _events.CancelEvent(EVENT_BATTER); + _events.CancelEvent(EVENT_HEAD_CRACK); - // looping through Gormoks seats - for (uint8 i = 0; i < MAX_SNOBOLDS; i++) - { - if (!gormok->GetVehicleKit()->GetPassenger(i)) - { - me->EnterVehicle(gormok, i); - DoAction(ACTION_ENABLE_FIRE_BOMB); - break; - } - } - } - else if (Unit* target2 = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + for (uint8 i = 0; i < MAX_SNOBOLDS; i++) + { + if (!gormok->GetVehicleKit()->GetPassenger(i)) { - _targetGUID = target2->GetGUID(); - me->GetMotionMaster()->MoveJump(*target2, 15.0f, 15.0f); + me->EnterVehicle(gormok, i); + DoAction(ACTION_ENABLE_FIRE_BOMB); + break; } } } + //Without Boss, snobolds should jump in another players + else if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, SnobolledTargetSelector(me))) + me->CastSpell(target, SPELL_RIDE_PLAYER, true); + } + void UpdateAI(uint32 diff) override + { _events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) @@ -419,37 +422,47 @@ class npc_snobold_vassal : public CreatureScript switch (eventId) { case EVENT_FIRE_BOMB: - if (me->GetVehicleBase()) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, -me->GetVehicleBase()->GetCombatReach(), true)) - me->CastSpell(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), SPELL_FIRE_BOMB, true); - _events.ScheduleEvent(EVENT_FIRE_BOMB, 20*IN_MILLISECONDS); - return; + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, -me->GetVehicleBase()->GetCombatReach(), true)) + me->CastSpell(target, SPELL_FIRE_BOMB); + _events.Repeat(Seconds(20)); + break; case EVENT_HEAD_CRACK: - // commented out while SPELL_SNOBOLLED gets fixed - //if (Unit* target = ObjectAccessor::GetPlayer(*me, m_uiTargetGUID)) - DoCastVictim(SPELL_HEAD_CRACK); - _events.ScheduleEvent(EVENT_HEAD_CRACK, 30*IN_MILLISECONDS); - return; + DoCast(me->GetVehicleBase(), SPELL_HEAD_CRACK); + _events.Repeat(Seconds(30)); + break; case EVENT_BATTER: - // commented out while SPELL_SNOBOLLED gets fixed - //if (Unit* target = ObjectAccessor::GetPlayer(*me, m_uiTargetGUID)) - DoCastVictim(SPELL_BATTER); - _events.ScheduleEvent(EVENT_BATTER, 10*IN_MILLISECONDS); - return; + DoCast(me->GetVehicleBase(), SPELL_BATTER); + _events.Repeat(Seconds(10)); + break; + case EVENT_SNOBOLLED: + DoCastAOE(SPELL_SNOBOLLED); + break; + case EVENT_CHECK_MOUNT: + if (!me->GetVehicleBase()) + MountOnBoss(); + _events.Repeat(Seconds(1)); + break; default: - return; + break; } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } - // do melee attack only when not on Gormoks back - if (!me->GetVehicleBase()) + if (!UpdateVictim()) + return; + + // do melee attack only if is in player back. + if (_isActive) DoMeleeAttackIfReady(); } + private: EventMap _events; InstanceScript* _instance; ObjectGuid _targetGUID; - bool _targetDied; + bool _isActive; }; CreatureAI* GetAI(Creature* creature) const override @@ -1150,6 +1163,134 @@ class boss_icehowl : public CreatureScript } }; +class spell_gormok_jump_to_hand : public SpellScriptLoader +{ +public: + spell_gormok_jump_to_hand() : SpellScriptLoader("spell_gormok_jump_to_hand") { } + + class spell_gormok_jump_to_hand_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gormok_jump_to_hand_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_RIDE_PLAYER }); + } + + bool Load() override + { + if (GetCaster() && GetCaster()->GetEntry() == NPC_SNOBOLD_VASSAL) + return true; + return false; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + if (CreatureAI* gormokAI = GetTarget()->ToCreature()->AI()) + { + if (Unit* target = gormokAI->SelectTarget(SELECT_TARGET_RANDOM, 0, SnobolledTargetSelector(GetTarget()))) + { + gormokAI->Talk(EMOTE_SNOBOLLED); + caster->GetAI()->DoAction(ACTION_ACTIVE_SNOBOLD); + caster->CastSpell(target, SPELL_RIDE_PLAYER, true); + } + } + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_gormok_jump_to_hand_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gormok_jump_to_hand_AuraScript(); + } +}; + +class spell_gormok_ride_player : public SpellScriptLoader +{ +public: + spell_gormok_ride_player() : SpellScriptLoader("spell_gormok_ride_player") { } + + class spell_gormok_ride_player_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gormok_ride_player_AuraScript); + + bool Load() override + { + if (GetCaster() && GetCaster()->GetEntry() == NPC_SNOBOLD_VASSAL) + return true; + return false; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld()) + return; + + if (!target->CreateVehicleKit(PLAYER_VEHICLE_ID, 0)) + return; + + if (Unit *caster = GetCaster()) + caster->GetAI()->SetGUID(target->GetGUID(), DATA_NEW_TARGET); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveVehicleKit(); + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_gormok_ride_player_AuraScript::OnApply, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_gormok_ride_player_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gormok_ride_player_AuraScript(); + } +}; + +class spell_gormok_snobolled : public SpellScriptLoader +{ +public: + spell_gormok_snobolled() : SpellScriptLoader("spell_gormok_snobolled") { } + + class spell_gormok_snobolled_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gormok_snobolled_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_RIDE_PLAYER }); + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + if (!GetTarget()->HasAura(SPELL_RIDE_PLAYER)) + Remove(); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_gormok_snobolled_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gormok_snobolled_AuraScript(); + } +}; + class spell_jormungars_paralytic_toxin : public SpellScriptLoader { public: @@ -1294,6 +1435,9 @@ void AddSC_boss_northrend_beasts() new npc_snobold_vassal(); new npc_firebomb(); new spell_gormok_fire_bomb(); + new spell_gormok_jump_to_hand(); + new spell_gormok_ride_player(); + new spell_gormok_snobolled(); new boss_acidmaw(); new boss_dreadscale(); |