diff options
| author | Gacko <gacko28@gmx.de> | 2012-11-18 23:44:48 +0000 |
|---|---|---|
| committer | Nay <dnpd.dd@gmail.com> | 2012-11-18 23:46:03 +0000 |
| commit | 45b07f09311b2ab1a4cfad67db0c050d2270af66 (patch) | |
| tree | 761b796e516de9a88c8d935c50bf5348a3b95337 | |
| parent | 771aafc4990d915f52582aa4d0b5b68c32f722db (diff) | |
Scripts&DB: Nexus - Ormorok
Following improvements:
- Spellscript for crystal spikes
- Spawn crystal tanglers with spell
- Usage of event map
- Correct usage of frenzy
- Heroic spells
- Target selection for crystal tanglers
Details for the spell script:
There are 4 spells. Each of them spawns the same trigger but in another direction. The trigger gets an aura which triggers the spell which summoned him after 250ms. This time is too long, so it triggers on apply. Don't worry - test ingame first, it's working blizzlike (I watched some videos on YT to find out which is the best amount of time difference between spawn and next summon).
Some summon types don't store the spell id which summoned them. The trigger is one of them which are not doing so. So I had to move the line, which stores the spell id in the summon out of the if. This could be done more specific, but it works fine. This improvement is required to find out which spell the aura applied to the summoned trigger has to cast to keep the right direction.
Closes #8193
Signed-off-by: Nay <dnpd.dd@gmail.com>
| -rw-r--r-- | sql/updates/characters/2012_11_18_00_character_calendar.sql (renamed from sql/updates/characters/2012_11_11_00_character_calendar.sql) | 0 | ||||
| -rw-r--r-- | sql/updates/world/2012_11_18_00_world_ormorok.sql | 56 | ||||
| -rw-r--r-- | src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp | 376 |
3 files changed, 232 insertions, 200 deletions
diff --git a/sql/updates/characters/2012_11_11_00_character_calendar.sql b/sql/updates/characters/2012_11_18_00_character_calendar.sql index a3e7c352788..a3e7c352788 100644 --- a/sql/updates/characters/2012_11_11_00_character_calendar.sql +++ b/sql/updates/characters/2012_11_18_00_character_calendar.sql diff --git a/sql/updates/world/2012_11_18_00_world_ormorok.sql b/sql/updates/world/2012_11_18_00_world_ormorok.sql new file mode 100644 index 00000000000..0ec8d13fd64 --- /dev/null +++ b/sql/updates/world/2012_11_18_00_world_ormorok.sql @@ -0,0 +1,56 @@ +-- Crystal Spikes - Script Effect - Spell casted by Ormorok - Triggers one summon spell in every direction +DELETE FROM `spell_scripts` WHERE `id` IN (47958,57082); +INSERT INTO `spell_scripts`(`id`,`command`,`datalong`,`datalong2`) VALUES +-- Non heroic +(47958,15,47954,1), +(47958,15,47955,1), +(47958,15,47956,1), +(47958,15,47957,1), +-- Heroic +(57082,15,57077,1), +(57082,15,57078,1), +(57082,15,57080,1), +(57082,15,57081,1); + +DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (47958,48016,48017) OR `spellid0` IN (47958,48016,48017); +INSERT INTO `spelldifficulty_dbc`(`id`,`spellid0`,`spellid1`) VALUES +(47958,47958,57082), -- Crystal Spikes +(48016,48016,57066), -- Trample +(48017,48017,57086); -- Frenzy + +-- Assign aura script for spawning Crystal Spike rows +DELETE FROM `spell_script_names` WHERE `spell_id`=47941; +INSERT INTO `spell_script_names`(`spell_id`,`ScriptName`) VALUES +(47941,'spell_crystal_spike'); + +-- Apply aura to triggers +DELETE FROM `creature_template_addon` WHERE `entry` IN (27101,27079); +INSERT INTO `creature_template_addon`(`entry`,`auras`) VALUES +(27101,'47941'), -- Aura to summon the next trigger after 250ms +(27079,'47941'); -- Aura to summon the next trigger after 250ms and visual effect + +-- Assign core scripts and SmartAI to trigger +UPDATE `creature_template` SET `AIName`='',`ScriptName`='npc_crystal_spike_trigger' WHERE `entry` IN (27101,27079); +UPDATE `creature_template` SET `AIName`='SmartAI',`ScriptName`='' WHERE `entry`=27099; + +-- SAI for Crystal Spike (Damage dealer) +DELETE FROM `smart_scripts` WHERE `entryorguid`=27099 AND `source_type`=0; +INSERT INTO `smart_scripts`(`entryorguid`,`event_type`,`action_type`,`action_param1`,`action_param2`,`target_type`,`comment`) VALUES +(27099,54,80,2709900,2,1,'Crystal Spike - Is summoned - Call timed action list'); + +-- Timed action list +DELETE FROM `smart_scripts` WHERE `entryorguid`=2709900 AND `source_type`=9; +INSERT INTO `smart_scripts`(`entryorguid`,`source_type`,`id`,`event_param1`,`event_param2`,`action_type`,`action_param1`,`action_param2`,`target_type`,`comment`) VALUES +(2709900,9,1,2100,2100,11,47944,2,1,'Crystal Spike - Timed action list - Cast damage spell'), +(2709900,9,2,0,0,41,0,0,1,'Crystal Spike - Timed action list - Despawn'); + +-- Creature texts for the boss +DELETE FROM `script_texts` WHERE `entry` BETWEEN -1576024 AND -1576020; + +DELETE FROM `creature_text` WHERE `entry`=26794; +INSERT INTO `creature_text`(`entry`,`groupid`,`text`,`type`,`sound`,`comment`) VALUES +(26794,1,'Noo!',14,13328,'ormorok SAY_AGGRO'), +(26794,2,'Aaggh!',14,13330,'ormorok SAY_DEATH'), +(26794,3,'Back!',14,13331,'ormorok SAY_REFLECT'), +(26794,4,'Bleed!',14,13332,'ormorok SAY_CRYSTAL_SPIKES'), +(26794,5,'Aaggh! Kill!',14,13329,'ormorok SAY_KILL'); diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp index eb0b3692f01..b17494800f1 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp @@ -19,96 +19,86 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "nexus.h" +#include "SpellScript.h" enum Spells { - SPELL_CRYSTAL_SPIKES = 47958, //Don't work, using walkaround - H_SPELL_CRYSTAL_SPIKES = 57082, //Don't work, using walkaround - SPELL_CRYSTALL_SPIKE_DAMAGE = 47944, - H_SPELL_CRYSTALL_SPIKE_DAMAGE = 57067, - SPELL_CRYSTAL_SPIKE_PREVISUAL = 50442, - MOB_CRYSTAL_SPIKE = 27099, - SPELL_SPELL_REFLECTION = 47981, - SPELL_TRAMPLE = 48016, - H_SPELL_TRAMPLE = 57066, - SPELL_FRENZY = 48017, - SPELL_SUMMON_CRYSTALLINE_TANGLER = 61564, //summons npc 32665 - SPELL_ROOTS = 28858 //proper spell id is unknown + SPELL_SPELL_REFLECTION = 47981, + SPELL_TRAMPLE = 48016, + SPELL_FRENZY = 48017, + SPELL_SUMMON_CRYSTALLINE_TANGLER = 61564, + SPELL_CRYSTAL_SPIKES = 47958, }; enum Yells { - SAY_AGGRO = -1576020, - SAY_DEATH = -1576021, - SAY_REFLECT = -1576022, - SAY_CRYSTAL_SPIKES = -1576023, - SAY_KILL = -1576024 + SAY_AGGRO = 1, + SAY_DEATH = 2, + SAY_REFLECT = 3, + SAY_CRYSTAL_SPIKES = 4, + SAY_KILL = 5, }; -enum Creatures + +enum Events { - MOB_CRYSTALLINE_TANGLER = 32665 + EVENT_CRYSTAL_SPIKES = 1, + EVENT_TRAMPLE = 2, + EVENT_SPELL_REFLECTION = 3, + EVENT_CRYSTALLINE_TANGLER = 4, }; -#define SPIKE_DISTANCE 5.0f +class OrmorokTanglerPredicate +{ + public: + OrmorokTanglerPredicate(Unit* unit) : me(unit) {} + + bool operator() (WorldObject* object) const + { + return object->GetDistance2d(me) >= 5.0f; + } + + private: + Unit* me; +}; class boss_ormorok : public CreatureScript { public: boss_ormorok() : CreatureScript("boss_ormorok") { } - CreatureAI* GetAI(Creature* creature) const + struct boss_ormorokAI : public BossAI { - return new boss_ormorokAI (creature); - } + boss_ormorokAI(Creature* creature) : BossAI(creature, DATA_ORMOROK_EVENT) {} - struct boss_ormorokAI : public ScriptedAI - { - boss_ormorokAI(Creature* creature) : ScriptedAI(creature) + void EnterCombat(Unit* /*who*/) { - instance = creature->GetInstanceScript(); - } + _EnterCombat(); - InstanceScript* instance; - - bool bFrenzy; - bool bCrystalSpikes; - uint8 uiCrystalSpikesCount; - float fBaseX; - float fBaseY; - float fBaseZ; - float fBaseO; - float fSpikeXY[4][2]; - - uint32 uiCrystalSpikesTimer; - uint32 uiCrystalSpikesTimer2; - uint32 uiTrampleTimer; - uint32 uiFrenzyTimer; - uint32 uiSpellReflectionTimer; - uint32 uiSummonCrystallineTanglerTimer; - - void Reset() - { - uiCrystalSpikesTimer = 12*IN_MILLISECONDS; - uiTrampleTimer = 10*IN_MILLISECONDS; - uiSpellReflectionTimer = 30*IN_MILLISECONDS; - uiSummonCrystallineTanglerTimer = 17*IN_MILLISECONDS; - bFrenzy = false; - bCrystalSpikes = false; + events.ScheduleEvent(EVENT_CRYSTAL_SPIKES, 12000); + events.ScheduleEvent(EVENT_TRAMPLE, 10000); + events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000); + if (IsHeroic()) + events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000); + + Talk(SAY_AGGRO); if (instance) - instance->SetData(DATA_ORMOROK_EVENT, NOT_STARTED); + instance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); } - void EnterCombat(Unit* /*who*/) + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) { - DoScriptText(SAY_AGGRO, me); - - if (instance) - instance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); + if (!frenzy && HealthBelowPct(25)) + { + DoCast(me, SPELL_FRENZY); + frenzy = true; + } } void JustDied(Unit* /*killer*/) { - DoScriptText(SAY_DEATH, me); + _JustDied(); + + Talk(SAY_DEATH); if (instance) instance->SetData(DATA_ORMOROK_EVENT, DONE); @@ -116,195 +106,181 @@ public: void KilledUnit(Unit* /*victim*/) { - DoScriptText(SAY_KILL, me); + Talk(SAY_KILL); } void UpdateAI(const uint32 diff) { if (!UpdateVictim()) - { return; - } - if (bCrystalSpikes) - { - if (uiCrystalSpikesTimer2 <= diff) - { - fSpikeXY[0][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount* std::cos(fBaseO)); - fSpikeXY[0][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount* std::sin(fBaseO)); - fSpikeXY[1][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount* std::cos(fBaseO)); - fSpikeXY[1][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount* std::sin(fBaseO)); - fSpikeXY[2][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount* std::cos(fBaseO-(M_PI/2))); - fSpikeXY[2][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount* std::sin(fBaseO-(M_PI/2))); - fSpikeXY[3][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount* std::cos(fBaseO-(M_PI/2))); - fSpikeXY[3][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount* std::sin(fBaseO-(M_PI/2))); - for (uint8 i = 0; i < 4; ++i) - me->SummonCreature(MOB_CRYSTAL_SPIKE, fSpikeXY[i][0], fSpikeXY[i][1], fBaseZ, 0, TEMPSUMMON_TIMED_DESPAWN, 7*IN_MILLISECONDS); - if (++uiCrystalSpikesCount >= 13) - bCrystalSpikes = false; - uiCrystalSpikesTimer2 = 200; - } else uiCrystalSpikesTimer2 -= diff; - } - if (!bFrenzy && HealthBelowPct(25)) - { - DoCast(me, SPELL_FRENZY); - bFrenzy = true; - } + events.Update(diff); - if (uiTrampleTimer <= diff) - { - DoCast(me, SPELL_TRAMPLE); - uiTrampleTimer = 10*IN_MILLISECONDS; - } else uiTrampleTimer -= diff; - - if (uiSpellReflectionTimer <= diff) - { - DoScriptText(SAY_REFLECT, me); - DoCast(me, SPELL_SPELL_REFLECTION); - uiSpellReflectionTimer = 30*IN_MILLISECONDS; - } else uiSpellReflectionTimer -= diff; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (uiCrystalSpikesTimer <= diff) - { - DoScriptText(SAY_CRYSTAL_SPIKES, me); - bCrystalSpikes = true; - uiCrystalSpikesCount = 1; - uiCrystalSpikesTimer2 = 0; - fBaseX = me->GetPositionX(); - fBaseY = me->GetPositionY(); - fBaseZ = me->GetPositionZ(); - fBaseO = me->GetOrientation(); - uiCrystalSpikesTimer = 20*IN_MILLISECONDS; - } else uiCrystalSpikesTimer -= diff; - - if (IsHeroic() && (uiSummonCrystallineTanglerTimer <= diff)) + while (uint32 eventId = events.ExecuteEvent()) { - Creature* Crystalline_Tangler = me->SummonCreature(MOB_CRYSTALLINE_TANGLER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); - if (Crystalline_Tangler) + switch (eventId) { - Unit* target = NULL; - uint8 Healer = 0; - for (uint8 j = 1; j <= 4; j++) - { - switch (j) - { - case 1: Healer = CLASS_PRIEST; break; - case 2: Healer = CLASS_PALADIN; break; - case 3: Healer = CLASS_DRUID; break; - case 4: Healer = CLASS_SHAMAN; break; - } - std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* temp = Unit::GetUnit(*me, (*i)->getUnitGuid()); - if (temp && temp->GetTypeId() == TYPEID_PLAYER && temp->getClass() == Healer) - { - target = temp; - break; - } - } - if (target) - break; - } - if (!target) - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - { - Crystalline_Tangler->AI()->AttackStart(target); - Crystalline_Tangler->getThreatManager().addThreat(target, 1000000000.0f); - } + case EVENT_TRAMPLE: + DoCast(me, SPELL_TRAMPLE); + events.ScheduleEvent(EVENT_TRAMPLE, 10000); + break; + case EVENT_SPELL_REFLECTION: + Talk(SAY_REFLECT); + DoCast(me, SPELL_SPELL_REFLECTION); + events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000); + break; + case EVENT_CRYSTAL_SPIKES: + Talk(SAY_CRYSTAL_SPIKES); + DoCast(SPELL_CRYSTAL_SPIKES); + events.ScheduleEvent(EVENT_CRYSTAL_SPIKES, 12000); + break; + case EVENT_CRYSTALLINE_TANGLER: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, OrmorokTanglerPredicate(me))) + DoCast(target, SPELL_SUMMON_CRYSTALLINE_TANGLER); + events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000); + break; + default: + break; } - uiSummonCrystallineTanglerTimer = 17*IN_MILLISECONDS; - } else uiSummonCrystallineTanglerTimer -= diff; + } DoMeleeAttackIfReady(); } + + private: + bool frenzy; + }; + CreatureAI* GetAI(Creature* creature) const + { + return new boss_ormorokAI (creature); + } +}; + +enum CrystalSpikes +{ + NPC_CRYSTAL_SPIKE_INITIAL = 27101, + NPC_CRYSTAL_SPIKE_TRIGGER = 27079, + + DATA_COUNT = 1, + MAX_COUNT = 5, + + SPELL_CRYSTAL_SPIKE_DAMAGE = 47944, + + GO_CRYSTAL_SPIKE_TRAP = 188537, +}; + +uint32 const crystalSpikeSummon[3] = +{ + 47936, + 47942, + 47943 }; -class mob_crystal_spike : public CreatureScript +class npc_crystal_spike_trigger : public CreatureScript { public: - mob_crystal_spike() : CreatureScript("mob_crystal_spike") { } + npc_crystal_spike_trigger() : CreatureScript("npc_crystal_spike_trigger") { } - CreatureAI* GetAI(Creature* creature) const + struct npc_crystal_spike_triggerAI : public ScriptedAI { - return new mob_crystal_spikeAI (creature); - } + npc_crystal_spike_triggerAI(Creature* creature) : ScriptedAI(creature) {} - struct mob_crystal_spikeAI : public Scripted_NoMovementAI - { - mob_crystal_spikeAI(Creature* creature) : Scripted_NoMovementAI(creature) + void IsSummonedBy(Unit* owner) { - } + switch (me->GetEntry()) + { + case NPC_CRYSTAL_SPIKE_INITIAL: + _count = 0; + me->SetFacingToObject(owner); + break; + case NPC_CRYSTAL_SPIKE_TRIGGER: + if (Creature* trigger = owner->ToCreature()) + _count = trigger->AI()->GetData(DATA_COUNT) + 1; + break; + default: + _count = MAX_COUNT; + break; + } - uint32 SpellCrystalSpikeDamageTimer; - uint32 SpellCrystalSpikePrevisualTimer; + if (me->GetEntry() == NPC_CRYSTAL_SPIKE_TRIGGER) + if (GameObject* trap = me->FindNearestGameObject(GO_CRYSTAL_SPIKE_TRAP, 1.0f)) + trap->Use(me); - void Reset() + _despawntimer = 2000; + } + + uint32 GetData(uint32 type) { - SpellCrystalSpikeDamageTimer = 3700; - SpellCrystalSpikePrevisualTimer = 1*IN_MILLISECONDS; + return type == DATA_COUNT ? _count : 0; } void UpdateAI(const uint32 diff) { - if (SpellCrystalSpikePrevisualTimer <= diff) + if (_despawntimer <= diff) { - DoCast(me, SPELL_CRYSTAL_SPIKE_PREVISUAL); - SpellCrystalSpikePrevisualTimer = 10*IN_MILLISECONDS; - } else SpellCrystalSpikePrevisualTimer -= diff; + if (me->GetEntry() == NPC_CRYSTAL_SPIKE_TRIGGER) + if (GameObject* trap = me->FindNearestGameObject(GO_CRYSTAL_SPIKE_TRAP, 1.0f)) + trap->Delete(); - if (SpellCrystalSpikeDamageTimer <= diff) - { - DoCast(me, SPELL_CRYSTALL_SPIKE_DAMAGE); - SpellCrystalSpikeDamageTimer = 10*IN_MILLISECONDS; - } else SpellCrystalSpikeDamageTimer -= diff; + me->DespawnOrUnsummon(); + } + else + _despawntimer -= diff; } - }; -}; + private: + uint32 _count; + uint32 _despawntimer; -class mob_crystalline_tangler : public CreatureScript -{ -public: - mob_crystalline_tangler() : CreatureScript("mob_crystalline_tangler") { } + }; CreatureAI* GetAI(Creature* creature) const { - return new mob_crystalline_tanglerAI (creature); + return new npc_crystal_spike_triggerAI(creature); } +}; - struct mob_crystalline_tanglerAI : public ScriptedAI - { - mob_crystalline_tanglerAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 uiRootsTimer; +class spell_crystal_spike : public SpellScriptLoader +{ + public: + spell_crystal_spike() : SpellScriptLoader("spell_crystal_spike") { } - void Reset() + class spell_crystal_spike_AuraScript : public AuraScript { - uiRootsTimer = 1*IN_MILLISECONDS; - } + PrepareAuraScript(spell_crystal_spike_AuraScript); - void UpdateAI(const uint32 diff) - { - if (uiRootsTimer <= diff) + void HandlePeriodic(AuraEffect const* /*aurEff*/) { - if (me->IsWithinDist(me->getVictim(), 5.0f, false)) - { - DoCast(me->getVictim(), SPELL_ROOTS); - uiRootsTimer = 15*IN_MILLISECONDS; - } - } else uiRootsTimer -= diff; - } - }; + Unit* target = GetTarget(); + if (target->GetEntry() == NPC_CRYSTAL_SPIKE_INITIAL || target->GetEntry() == NPC_CRYSTAL_SPIKE_TRIGGER) + if (Creature* trigger = target->ToCreature()) + { + uint32 spell = target->GetEntry() == NPC_CRYSTAL_SPIKE_INITIAL ? crystalSpikeSummon[0] : crystalSpikeSummon[urand(0, 2)]; + if (trigger->AI()->GetData(DATA_COUNT) < MAX_COUNT) + trigger->CastSpell(trigger, spell, true); + } + } + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_crystal_spike_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_crystal_spike_AuraScript(); + } }; void AddSC_boss_ormorok() { new boss_ormorok(); - new mob_crystal_spike(); - new mob_crystalline_tangler(); + new npc_crystal_spike_trigger(); + new spell_crystal_spike(); } |
