Merge [SD2]

r1205 Check pointer for NULL before use. - skip
r1206 Remove conflicting MovePoint and let creature fully use MoveChase for summoned in hyjal. - skip
r1207 Add instance bosses for map 602. Scripts can not be considered complete and must be tested further when databases has better values for misc (such as creature factions, health/mana etc)
r1208 Added handling of doors for second last boss in BRD. Apply sd2 code style and clean up last boss(es) scripts and spells. Patch by Turok - skip
r1209 Merge scripts for last bosses in BRD to one source file. Also not store pointers to creatures and create only when needed.
      Added creation of portal if Moria survive and Emperor is dead. - skip
r1210 Clean up and add script for second boss in SWP. Patch by paytheo (original by ckegg) - skip
note: in previous merge should be r120x insted of r200x. Sorry for that

--HG--
branch : trunk
This commit is contained in:
Kudlaty
2009-08-13 00:57:55 +02:00
parent ba91c78ceb
commit 57d2f5e7d2
5 changed files with 865 additions and 164 deletions

View File

@@ -1752,7 +1752,13 @@ INSERT INTO `script_texts` (`entry`, `content_default`, `content_loc1`, `content
(-1602008,'%s switches to Berserker Stance!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0,3,0,0,'bjarngrim EMOTE_BERSEKER_STANCE'),
(-1602009,'Give me your worst!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14150,1,0,0,'bjarngrim SAY_DEFENSIVE_STANCE'),
(-1602010,'%s switches to Defensive Stance!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0,3,0,0,'bjarngrim EMOTE_DEFENSIVE_STANCE'),
/* Loken */
(-1602011,'You wish to confront the master? You must weather the storm!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14453,1,0,0,'ionar SAY_AGGRO'),
(-1602012,'Shocking ... I know!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14456,1,0,0,'ionar SAY_SLAY_1'),
(-1602013,'You atempt the unpossible.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14457,1,0,0,'ionar SAY_SLAY_2'),
(-1602014,'Your spark of light is ... extinguish.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14458,1,0,0,'ionar SAY_SLAY_3'),
(-1602015,'Master... you have guests.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14459,1,0,0,'ionar SAY_DEATH'),
(-1602016,'The slightest spark shall be your undoing.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14454,1,0,0,'ionar SAY_SPLIT_1'),
(-1602017,'No one is safe!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14455,1,0,0,'ionar SAY_SPLIT_2'),
(-1602018,'What hope is there for you? None!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14162,1,0,0,'loken SAY_AGGRO0'),
(-1602019,'I have witnessed the rise and fall of empires. The birth and extinction of entire species. Over countless millennia the foolishness of mortals has remained beyond a constant. Your presence here confirms this.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14160,1,0,0,'loken SAY_INTRO_1'),
(-1602020,'My master has shown me the future, and you have no place in it. Azeroth will be reborn in darkness. Yogg-Saron shall be released! The Pantheon shall fall!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14162,1,0,0,'loken SAY_INTRO_2'),
@@ -1766,7 +1772,18 @@ INSERT INTO `script_texts` (`entry`, `content_default`, `content_loc1`, `content
(-1602028,'You stare blindly into the abyss!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14169,1,0,0,'loken SAY_75HEALTH'),
(-1602029,'Your ignorance is profound. Can you not see where this path leads?', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14170,1,0,0,'loken SAY_50HEALTH'),
(-1602030,'You cross the precipice of oblivion!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14171,1,0,0,'loken SAY_25HEALTH'),
(-1602031,'%s begins to cast Lightning Nova!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0,3,0,0,'loken EMOTE_NOVA');
(-1602031,'%s begins to cast Lightning Nova!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0,3,0,0,'loken EMOTE_NOVA'),
(-1602032,'It is you who have destroyed my children? You... shall... pay!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13960,1,0,0,'volkhan SAY_AGGRO'),
(-1602033,'The armies of iron will conquer all!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13965, 1,0,0,'volkhan SAY_SLAY_1'),
(-1602034,'Ha, pathetic!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13966,1,0,0,'volkhan SAY_SLAY_2'),
(-1602035,'You have cost me too much work!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13967,1,0,0,'volkhan SAY_SLAY_3'),
(-1602036,'The master was right... to be concerned.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13968,1,0,0,'volkhan SAY_DEATH'),
(-1602037,'I will crush you beneath my boots!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13963,1,0,0,'volkhan SAY_STOMP_1'),
(-1602038,'All my work... undone!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13964,1,0,0,'volkhan SAY_STOMP_2'),
(-1602039,'Life from the lifelessness... death for you.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13961,1,0,0,'volkhan SAY_FORGE_1'),
(-1602040,'Nothing is wasted in the process. You will see....', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13962,1,0,0,'volkhan SAY_FORGE_2'),
(-1602041,'runs to his anvil!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0,3,0,0,'volkhan EMOTE_TO_ANVIL'),
(-1602042,'prepares to shatter his Brittle Golems!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0,3,0,0,'volkhan EMOTE_SHATTER');
-- -1 615 000 OBSIDIAN SANCTUM
INSERT INTO `script_texts` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`, `sound`, `type`, `language`, `emote`, `comment`) VALUES

View File

@@ -492,6 +492,13 @@ UPDATE `creature_template` SET `ScriptName`='boss_bjarngrim' WHERE `entry`=28586
UPDATE `creature_template` SET `ScriptName`='mob_stormforged_lieutenant' WHERE `entry`=29240;
/* Loken */
UPDATE `creature_template` SET `ScriptName`='boss_loken' WHERE `entry`=28923;
/* Volkhan */
UPDATE `creature_template` SET `ScriptName`='boss_volkhan' WHERE `entry`=28587;
UPDATE `creature_template` SET `ScriptName`='mob_molten_golem' WHERE `entry`=28695;
UPDATE `creature_template` SET `ScriptName`='npc_volkhan_anvil' WHERE `entry`=28823;
/* Ionar */
UPDATE `creature_template` SET `ScriptName`='boss_ionar' WHERE `entry`=28546;
UPDATE `creature_template` SET `ScriptName`='mob_spark_of_ionar' WHERE `entry`=28926;
/* HELLFIRE CITADEL */

View File

@@ -0,0 +1,28 @@
DELETE FROM `script_texts` WHERE `entry` between -1602042 AND -1602032;
DELETE FROM `script_texts` WHERE `entry` between -1602017 AND -1602011;
INSERT INTO `script_texts` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`, `sound`, `type`, `language`, `emote`, `comment`) VALUES
(-1602011,'You wish to confront the master? You must weather the storm!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14453,1,0,0,'ionar SAY_AGGRO'),
(-1602012,'Shocking ... I know!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14456,1,0,0,'ionar SAY_SLAY_1'),
(-1602013,'You atempt the unpossible.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14457,1,0,0,'ionar SAY_SLAY_2'),
(-1602014,'Your spark of light is ... extinguish.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14458,1,0,0,'ionar SAY_SLAY_3'),
(-1602015,'Master... you have guests.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14459,1,0,0,'ionar SAY_DEATH'),
(-1602016,'The slightest spark shall be your undoing.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14454,1,0,0,'ionar SAY_SPLIT_1'),
(-1602017,'No one is safe!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,14455,1,0,0,'ionar SAY_SPLIT_2'),
(-1602032,'It is you who have destroyed my children? You... shall... pay!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13960,1,0,0,'volkhan SAY_AGGRO'),
(-1602033,'The armies of iron will conquer all!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13965, 1,0,0,'volkhan SAY_SLAY_1'),
(-1602034,'Ha, pathetic!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13966,1,0,0,'volkhan SAY_SLAY_2'),
(-1602035,'You have cost me too much work!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13967,1,0,0,'volkhan SAY_SLAY_3'),
(-1602036,'The master was right... to be concerned.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13968,1,0,0,'volkhan SAY_DEATH'),
(-1602037,'I will crush you beneath my boots!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13963,1,0,0,'volkhan SAY_STOMP_1'),
(-1602038,'All my work... undone!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13964,1,0,0,'volkhan SAY_STOMP_2'),
(-1602039,'Life from the lifelessness... death for you.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13961,1,0,0,'volkhan SAY_FORGE_1'),
(-1602040,'Nothing is wasted in the process. You will see....', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,13962,1,0,0,'volkhan SAY_FORGE_2'),
(-1602041,'runs to his anvil!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0,3,0,0,'volkhan EMOTE_TO_ANVIL'),
(-1602042,'prepares to shatter his Brittle Golems!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0,3,0,0,'volkhan EMOTE_SHATTER');
UPDATE creature_template SET ScriptName='boss_volkhan' WHERE entry=28587;
UPDATE creature_template SET ScriptName='mob_molten_golem' WHERE entry=28695;
UPDATE creature_template SET ScriptName='npc_volkhan_anvil' WHERE entry=28823;
UPDATE creature_template SET ScriptName='boss_ionar' WHERE entry=28546;
UPDATE creature_template SET ScriptName='mob_spark_of_ionar' WHERE entry=28926;

View File

@@ -1,101 +1,385 @@
/* Script Data Start
SDName: Boss ionar
SDAuthor: LordVanMartin
SD%Complete:
SDComment:
SDCategory:
Script Data End */
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ScriptData
SDName: Boss Ionar
SD%Complete: 80%
SDComment: Timer check
SDCategory: Halls of Lightning
EndScriptData */
/*** SQL START ***
update creature_template set scriptname = 'boss_ionar' where entry = '';
*** SQL END ***/
#include "precompiled.h"
#include "def_halls_of_lightning.h"
//Spells
#define SPELL_BALL_LIGHTNING 52780
#define SPELL_BALL_LIGHTNING_2 59800
#define SPELL_DISPERSE 52770 //Disperse into Sparks of Ionar.
#define SPELL_STATIC_OVERLOAD 52658 //Effect Apply Aura: Periodic Trigger Interval: 2 seconds Spell 52659
#define SPELL_STATIC_OVERLOAD_2 52658 //Effect Apply Aura: Periodic Trigger Interval: 2 seconds Spell 59796
enum
{
SAY_AGGRO = -1602011,
SAY_SLAY_1 = -1602012,
SAY_SLAY_2 = -1602013,
SAY_SLAY_3 = -1602014,
SAY_DEATH = -1602015,
SAY_SPLIT_1 = -1602016,
SAY_SPLIT_2 = -1602017,
//Spark of Ionar spells
#define NPC_SPARK_OF_IONAR 28962 //invulnerable
#define SPELL_ARCING_BURN 52617
#define SPELL_ARCING_BURN_2 59834
SPELL_BALL_LIGHTNING_N = 52780,
SPELL_BALL_LIGHTNING_H = 59800,
SPELL_STATIC_OVERLOAD_N = 52658,
SPELL_STATIC_OVERLOAD_H = 59795,
//Yell
#define SAY_AGGRO -1602008
#define SAY_SLAY_1 -1602009
#define SAY_SLAY_2 -1602010
#define SAY_SLAY_3 -1602011
#define SAY_DEATH -1602012
#define SAY_SPLIT_1 -1602013
#define SAY_SPLIT_2 -1602014
SPELL_DISPERSE = 52770,
SPELL_SUMMON_SPARK = 52746,
SPELL_SPARK_DESPAWN = 52776,
//he does "morph" every about 25% into 4 sparks of ionar that chase people around, they r slow and easily avoidable.
//Spark of Ionar
SPELL_SPARK_VISUAL_TRIGGER_N = 52667,
SPELL_SPARK_VISUAL_TRIGGER_H = 59833,
NPC_SPARK_OF_IONAR = 28926,
MAX_SPARKS = 5,
POINT_CALLBACK = 0
};
/*######
## Boss Ionar
######*/
struct TRINITY_DLL_DECL boss_ionarAI : public ScriptedAI
{
boss_ionarAI(Creature *c) : ScriptedAI(c) {}
void Reset() {}
void EnterCombat(Unit* who)
boss_ionarAI(Creature *pCreature) : ScriptedAI(pCreature)
{
DoScriptText(SAY_AGGRO, m_creature);
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
m_bIsHeroic = pCreature->GetMap()->IsHeroic();
Reset();
}
void AttackStart(Unit* who) {}
void MoveInLineOfSight(Unit* who) {}
void UpdateAI(const uint32 diff)
ScriptedInstance* m_pInstance;
std::list<uint64> m_lSparkGUIDList;
bool m_bIsHeroic;
bool m_bIsSplitPhase;
uint32 m_uiSplit_Timer;
uint32 m_uiSparkAtHomeCount;
uint32 m_uiStaticOverload_Timer;
uint32 m_uiBallLightning_Timer;
uint32 m_uiHealthAmountModifier;
void Reset()
{
//Return since we have no target
if(!UpdateVictim())
m_lSparkGUIDList.clear();
m_bIsSplitPhase = true;
m_uiSplit_Timer = 25000;
m_uiSparkAtHomeCount = 0;
m_uiStaticOverload_Timer = 5000 + rand()%1000;
m_uiBallLightning_Timer = 10000 + rand()%1000;
m_uiHealthAmountModifier = 1;
if (m_creature->GetVisibility() == VISIBILITY_OFF)
m_creature->SetVisibility(VISIBILITY_ON);
}
void AttackedBy(Unit* pAttacker)
{
if (m_creature->getVictim())
return;
DoMeleeAttackIfReady();
if (m_creature->GetVisibility() == VISIBILITY_OFF)
return;
AttackStart(pAttacker);
}
void Aggro(Unit* who)
{
DoScriptText(SAY_AGGRO, m_creature);
if (m_pInstance)
m_pInstance->SetData(TYPE_IONAR, IN_PROGRESS);
}
void JustReachedHome()
{
if (m_pInstance)
m_pInstance->SetData(TYPE_IONAR, NOT_STARTED);
}
void AttackStart(Unit* pWho)
{
if (m_creature->Attack(pWho, true))
{
m_creature->AddThreat(pWho, 0.0f);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
if (m_creature->GetVisibility() != VISIBILITY_OFF)
m_creature->GetMotionMaster()->MoveChase(pWho);
}
}
void JustDied(Unit* killer)
{
DoScriptText(SAY_DEATH, m_creature);
DespawnSpark();
if (m_pInstance)
m_pInstance->SetData(TYPE_IONAR, DONE);
}
void KilledUnit(Unit *victim)
{
if(victim == m_creature)
return;
switch(rand()%3)
{
case 0: DoScriptText(SAY_SLAY_1, m_creature);break;
case 1: DoScriptText(SAY_SLAY_2, m_creature);break;
case 2: DoScriptText(SAY_SLAY_3, m_creature);break;
case 0: DoScriptText(SAY_SLAY_1, m_creature); break;
case 1: DoScriptText(SAY_SLAY_2, m_creature); break;
case 2: DoScriptText(SAY_SLAY_3, m_creature); break;
}
}
void DespawnSpark()
{
if (m_lSparkGUIDList.empty())
return;
for(std::list<uint64>::iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr)
{
if (Creature* pTemp = (Creature*)Unit::GetUnit(*m_creature, *itr))
{
if (pTemp->isAlive())
pTemp->ForcedDespawn();
}
}
m_lSparkGUIDList.clear();
}
//make sparks come back
void CallBackSparks()
{
//should never be empty here, but check
if (m_lSparkGUIDList.empty())
return;
for(std::list<uint64>::iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr)
{
if (Creature* pSpark = (Creature*)Unit::GetUnit(*m_creature, *itr))
{
if (pSpark->isAlive())
{
if (pSpark->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
pSpark->GetMotionMaster()->MovementExpired();
pSpark->SetSpeed(MOVE_RUN, pSpark->GetCreatureInfo()->speed * 2);
pSpark->GetMotionMaster()->MovePoint(POINT_CALLBACK, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
}
}
}
}
void RegisterSparkAtHome()
{
++m_uiSparkAtHomeCount;
}
void JustSummoned(Creature* pSummoned)
{
if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR)
{
pSummoned->CastSpell(pSummoned, m_bIsHeroic ? SPELL_SPARK_VISUAL_TRIGGER_H : SPELL_SPARK_VISUAL_TRIGGER_N, true);
Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
if (m_creature->getVictim())
pSummoned->AI()->AttackStart(pTarget ? pTarget : m_creature->getVictim());
m_lSparkGUIDList.push_back(pSummoned->GetGUID());
}
}
void UpdateAI(const uint32 uiDiff)
{
// Splitted
if (m_creature->GetVisibility() == VISIBILITY_OFF)
{
if (!m_creature->getVictim())
{
Reset();
return;
}
if (m_uiSplit_Timer < uiDiff)
{
m_uiSplit_Timer = 2500;
// Return sparks to where Ionar splitted
if (m_bIsSplitPhase)
{
CallBackSparks();
m_bIsSplitPhase = false;
}
// Lightning effect and restore Ionar
else if (m_uiSparkAtHomeCount == MAX_SPARKS)
{
m_creature->SetVisibility(VISIBILITY_ON);
m_creature->CastSpell(m_creature, SPELL_SPARK_DESPAWN, false);
DespawnSpark();
m_uiSparkAtHomeCount = 0;
m_uiSplit_Timer = 25000;
m_bIsSplitPhase = true;
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
{
if (m_creature->getVictim())
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
}
}
}
else
m_uiSplit_Timer -= uiDiff;
return;
}
//Return since we have no target
if (!UpdateVictim())
return;
if (m_uiStaticOverload_Timer < uiDiff)
{
if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
DoCast(pTarget, m_bIsHeroic ? SPELL_STATIC_OVERLOAD_H : SPELL_STATIC_OVERLOAD_N);
m_uiStaticOverload_Timer = 5000 + rand()%1000;
}
else
m_uiStaticOverload_Timer -= uiDiff;
if (m_uiBallLightning_Timer < uiDiff)
{
DoCast(m_creature->getVictim(), m_bIsHeroic ? SPELL_BALL_LIGHTNING_H : SPELL_BALL_LIGHTNING_N);
m_uiBallLightning_Timer = 10000 + rand()%1000;
}
else
m_uiBallLightning_Timer -= uiDiff;
// Health check
if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier)))
{
++m_uiHealthAmountModifier;
switch(rand()%2)
{
case 0: DoScriptText(SAY_SPLIT_1, m_creature); break;
case 1: DoScriptText(SAY_SPLIT_2, m_creature); break;
}
if (m_creature->IsNonMeleeSpellCasted(false))
m_creature->InterruptNonMeleeSpells(false);
DoCast(m_creature, SPELL_DISPERSE);
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_boss_ionar(Creature* pCreature)
{
return new boss_ionarAI(pCreature);
}
bool EffectDummyCreature_boss_ionar(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget)
{
//always check spellid and effectindex
if (uiSpellId == SPELL_DISPERSE && uiEffIndex == 0)
{
if (pCreatureTarget->GetEntry() != NPC_IONAR)
return true;
for(uint8 i = 0; i < MAX_SPARKS; ++i)
{
pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true);
//TODO: remove this line of hack when summon implemented
pCreatureTarget->SummonCreature(NPC_SPARK_OF_IONAR, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
}
pCreatureTarget->AttackStop();
pCreatureTarget->SetVisibility(VISIBILITY_OFF);
if (pCreatureTarget->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
pCreatureTarget->GetMotionMaster()->MovementExpired();
//always return true when we are handling this spell and effect
return true;
}
return false;
}
/*######
## mob_spark_of_ionar
######*/
struct TRINITY_DLL_DECL mob_spark_of_ionarAI : public ScriptedAI
{
mob_spark_of_ionarAI(Creature *pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
Reset();
}
ScriptedInstance* m_pInstance;
void Reset() { }
void MovementInform(uint32 uiType, uint32 uiPointId)
{
if (uiType != POINT_MOTION_TYPE || !m_pInstance)
return;
if (uiPointId == POINT_CALLBACK)
{
if (Creature* pIonar = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_IONAR)))
{
if (!pIonar->isAlive())
{
m_creature->ForcedDespawn();
return;
}
if (boss_ionarAI* pIonarAI = dynamic_cast<boss_ionarAI*>(pIonar->AI()))
pIonarAI->RegisterSparkAtHome();
}
else
m_creature->ForcedDespawn();
}
}
};
struct TRINITY_DLL_DECL npc_spark_of_ionarAI : public ScriptedAI
CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature)
{
npc_spark_of_ionarAI(Creature *c) : ScriptedAI(c) {}
void Reset() {}
void EnterCombat(Unit* who) {}
void AttackStart(Unit* who) {}
void MoveInLineOfSight(Unit* who) {}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if(!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
void JustDied(Unit* killer) {}
};
CreatureAI* GetAI_npc_spark_of_ionar(Creature *_Creature)
{
return new npc_spark_of_ionarAI (_Creature);
}
CreatureAI* GetAI_boss_ionar(Creature *_Creature)
{
return new boss_ionarAI (_Creature);
return new mob_spark_of_ionarAI(pCreature);
}
void AddSC_boss_ionar()
@@ -103,12 +387,13 @@ void AddSC_boss_ionar()
Script *newscript;
newscript = new Script;
newscript->Name="boss_ionar";
newscript->Name = "boss_ionar";
newscript->GetAI = &GetAI_boss_ionar;
newscript->pEffectDummyCreature = &EffectDummyCreature_boss_ionar;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name="spark_of_ionar";
newscript->GetAI = &GetAI_npc_spark_of_ionar;
newscript->Name = "mob_spark_of_ionar";
newscript->GetAI = &GetAI_mob_spark_of_ionar;
newscript->RegisterSelf();
}

View File

@@ -1,115 +1,473 @@
/* Script Data Start
SDName: Boss volkhan
SDAuthor: LordVanMartin
SD%Complete:
SDComment:
SDCategory:
Script Data End */
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ScriptData
SDName: Boss Volkhan
SD%Complete: 60%
SDComment: Not considered complete. Some events may fail and need further development
SDCategory: Halls of Lightning
EndScriptData */
/*** SQL START ***
update creature_template set scriptname = 'boss_volkhan' where entry = '';
*** SQL END ***/
#include "precompiled.h"
#include "def_halls_of_lightning.h"
//Spells
#define SPELL_HEAT 52387
#define SPELL_HEAT_2 59528
#define SPELL_SHATTERING_STOMP 52237
#define SPELL_SHATTERING_STOMP_2 59529
#define SPELL_TEMPER 52238 //Dummy ---> Strikes Volkhan's Anvil, creating a number of Molten Golems.
#define NPC_VOLKHANS_ANVIL 28823
#define MOB_MOLTEN_GOLEM 28695
//Yells
#define SAY_AGGRO -1602028
#define SAY_SLAY_1 -1602029
#define SAY_SLAY_2 -1602030
#define SAY_SLAY_3 -1602031
#define SAY_DEATH -1602032
#define SAY_STOMP_1 -1602033
#define SAY_STOMP_2 -1602034
#define SAY_FORGE_1 -1602035
#define SAY_FORGE_2 -1602036
struct TRINITY_DLL_DECL boss_volkhanAI : public ScriptedAI
enum
{
boss_volkhanAI(Creature *c) : ScriptedAI(c) {}
SAY_AGGRO = -1602032,
SAY_SLAY_1 = -1602033,
SAY_SLAY_2 = -1602034,
SAY_SLAY_3 = -1602035,
SAY_DEATH = -1602036,
SAY_STOMP_1 = -1602037,
SAY_STOMP_2 = -1602038,
SAY_FORGE_1 = -1602039,
SAY_FORGE_2 = -1602040,
EMOTE_TO_ANVIL = -1602041,
EMOTE_SHATTER = -1602042,
void Reset() {}
void EnterCombat(Unit* who)
{
DoScriptText(SAY_AGGRO, m_creature);
}
void AttackStart(Unit* who) {}
void MoveInLineOfSight(Unit* who) {}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if(!UpdateVictim())
return;
SPELL_HEAT_N = 52387,
SPELL_HEAT_H = 59528,
SPELL_SHATTERING_STOMP_N = 52237,
SPELL_SHATTERING_STOMP_H = 59529,
DoMeleeAttackIfReady();
}
void JustDied(Unit* killer)
{
DoScriptText(SAY_DEATH, m_creature);
}
void KilledUnit(Unit *victim)
{
if(victim == m_creature)
return;
switch(rand()%3)
{
case 0: DoScriptText(SAY_SLAY_1, m_creature);break;
case 1: DoScriptText(SAY_SLAY_2, m_creature);break;
case 2: DoScriptText(SAY_SLAY_3, m_creature);break;
}
}
//unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on:
SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil
SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss
//SPELL_TEMPER_VISUAL = 52661, //summons GO
SPELL_SUMMON_MOLTEN_GOLEM = 52405,
//Molten Golem
SPELL_BLAST_WAVE = 23113,
SPELL_IMMOLATION_STRIKE_N = 52433,
SPELL_IMMOLATION_STRIKE_H = 59530,
SPELL_SHATTER_N = 52429,
SPELL_SHATTER_H = 59527,
NPC_VOLKHAN_ANVIL = 28823,
NPC_MOLTEN_GOLEM = 28695,
NPC_BRITTLE_GOLEM = 28681,
POINT_ID_ANVIL = 0,
MAX_GOLEM = 2
};
/*######
## Mob Molten Golem
## Boss Volkhan
######*/
//Molten Golem Spells
#define SPELL_BLAST_WAVE 23113
#define SPELL_IMMOLATION_STRIKE 52433
#define SPELL_IMMOLATION_STRIKE_2 59530
//Effect #1 Apply Aura: Periodic Damage, value: 900 every 3 seconds
//Effect #2 School Damage (Fire), value: 900
//Effect #3 Script Effect
#define SPELL_SHATTER 52429
//Effect #1 School Damage (Physical), value: 9250 to 10750, radius: 10 yards
//Effect #2 Dummy, Server-side script
#define SPELL_SHATTER_2
struct TRINITY_DLL_DECL mob_molten_golemAI : public ScriptedAI
struct TRINITY_DLL_DECL boss_volkhanAI : public ScriptedAI
{
mob_molten_golemAI(Creature *c) : ScriptedAI(c) {}
boss_volkhanAI(Creature *pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
m_bIsHeroic = pCreature->GetMap()->IsHeroic();
Reset();
}
void Reset() {}
void EnterCombat(Unit* who) {}
void AttackStart(Unit* who) {}
void MoveInLineOfSight(Unit* who) {}
void UpdateAI(const uint32 diff)
ScriptedInstance* m_pInstance;
std::list<uint64> m_lGolemGUIDList;
bool m_bIsHeroic;
bool m_bHasTemper;
bool m_bIsStriking;
bool m_bCanShatterGolem;
uint32 m_uiPause_Timer;
uint32 m_uiShatteringStomp_Timer;
uint32 m_uiShatter_Timer;
uint32 m_uiHealthAmountModifier;
void Reset()
{
m_bIsStriking = false;
m_bHasTemper = false;
m_bCanShatterGolem = false;
m_uiPause_Timer = 3500;
m_uiShatteringStomp_Timer = 0;
m_uiShatter_Timer = 5000;
m_uiHealthAmountModifier = 1;
DespawnGolem();
m_lGolemGUIDList.clear();
if (m_pInstance)
m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED);
}
void Aggro(Unit* pWho)
{
DoScriptText(SAY_AGGRO, m_creature);
if (m_pInstance)
m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS);
}
void AttackStart(Unit* pWho)
{
if (m_creature->Attack(pWho, true))
{
m_creature->AddThreat(pWho, 0.0f);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
if (!m_bHasTemper)
m_creature->GetMotionMaster()->MoveChase(pWho);
}
}
void JustDied(Unit* pKiller)
{
DoScriptText(SAY_DEATH, m_creature);
DespawnGolem();
if (m_pInstance)
m_pInstance->SetData(TYPE_VOLKHAN, DONE);
}
void KilledUnit(Unit* pVictim)
{
switch(rand()%3)
{
case 0: DoScriptText(SAY_SLAY_1, m_creature); break;
case 1: DoScriptText(SAY_SLAY_2, m_creature); break;
case 2: DoScriptText(SAY_SLAY_3, m_creature); break;
}
}
void DespawnGolem()
{
if (m_lGolemGUIDList.empty())
return;
for(std::list<uint64>::iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr)
{
if (Creature* pTemp = (Creature*)Unit::GetUnit(*m_creature, *itr))
{
if (pTemp->isAlive())
pTemp->ForcedDespawn();
}
}
m_lGolemGUIDList.clear();
}
void ShatterGolem()
{
if (m_lGolemGUIDList.empty())
return;
for(std::list<uint64>::iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr)
{
if (Creature* pTemp = (Creature*)Unit::GetUnit(*m_creature, *itr))
{
// only shatter brittle golems
if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM)
pTemp->CastSpell(pTemp, m_bIsHeroic ? SPELL_SHATTER_H : SPELL_SHATTER_N, false);
}
}
}
void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
{
if (pSpell->Id == SPELL_TEMPER_DUMMY)
m_bIsStriking = true;
}
void JustSummoned(Creature* pSummoned)
{
if (pSummoned->GetEntry() == NPC_MOLTEN_GOLEM)
{
m_lGolemGUIDList.push_back(pSummoned->GetGUID());
if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
pSummoned->AI()->AttackStart(pTarget);
//why healing when just summoned?
pSummoned->CastSpell(pSummoned, m_bIsHeroic ? SPELL_HEAT_H : SPELL_HEAT_N, false, NULL, NULL, m_creature->GetGUID());
}
}
void UpdateAI(const uint32 uiDiff)
{
//Return since we have no target
if(!UpdateVictim())
if (!UpdateVictim())
return;
if (m_bIsStriking)
{
if (m_uiPause_Timer < uiDiff)
{
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
{
if (m_creature->getVictim())
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
}
m_bHasTemper = false;
m_bIsStriking = false;
m_uiPause_Timer = 3500;
}
else
m_uiPause_Timer -= uiDiff;
return;
}
// When to start shatter? After 60, 40 or 20% hp?
if (!m_bHasTemper && m_uiHealthAmountModifier >= 3)
{
if (m_uiShatteringStomp_Timer < uiDiff)
{
//should he stomp even if he has no brittle golem to shatter?
switch(rand()%2)
{
case 0: DoScriptText(SAY_STOMP_1, m_creature); break;
case 1: DoScriptText(SAY_STOMP_2, m_creature); break;
}
DoCast(m_creature, m_bIsHeroic ? SPELL_SHATTERING_STOMP_H : SPELL_SHATTERING_STOMP_N);
DoScriptText(EMOTE_SHATTER, m_creature);
m_uiShatteringStomp_Timer = 30000;
m_bCanShatterGolem = true;
}
else
m_uiShatteringStomp_Timer -= uiDiff;
}
// Shatter Golems 3 seconds after Shattering Stomp
if (m_bCanShatterGolem)
{
if (m_uiShatter_Timer < uiDiff)
{
ShatterGolem();
m_uiShatter_Timer = 3000;
m_bCanShatterGolem = false;
}
else
m_uiShatter_Timer -= uiDiff;
}
// Health check
if (!m_bCanShatterGolem && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier)))
{
++m_uiHealthAmountModifier;
if (m_creature->IsNonMeleeSpellCasted(false))
m_creature->InterruptNonMeleeSpells(false);
switch(rand()%2)
{
case 0: DoScriptText(SAY_FORGE_1, m_creature); break;
case 1: DoScriptText(SAY_FORGE_2, m_creature); break;
}
m_bHasTemper = true;
m_creature->CastSpell(m_creature, SPELL_TEMPER, false);
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* killer) {}
};
CreatureAI* GetAI_mob_molten_golem(Creature *_Creature)
CreatureAI* GetAI_boss_volkhan(Creature* pCreature)
{
return new mob_molten_golemAI (_Creature);
return new boss_volkhanAI(pCreature);
}
CreatureAI* GetAI_boss_volkhan(Creature *_Creature)
bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget)
{
return new boss_volkhanAI (_Creature);
//always check spellid and effectindex
if (uiSpellId == SPELL_TEMPER_DUMMY && uiEffIndex == 0)
{
if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN)
return true;
for(uint8 i = 0; i < MAX_GOLEM; ++i)
{
pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true);
//TODO: remove this line of hack when summon effect implemented
pCreatureTarget->SummonCreature(NPC_MOLTEN_GOLEM,
pCaster->GetPositionX(), pCaster->GetPositionY(), pCaster->GetPositionZ(), 0.0f,
TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
}
//always return true when we are handling this spell and effect
return true;
}
return false;
}
/*######
## npc_volkhan_anvil
######*/
bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget)
{
//always check spellid and effectindex
if (uiSpellId == SPELL_TEMPER && uiEffIndex == 0)
{
if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL)
return true;
DoScriptText(EMOTE_TO_ANVIL, pCaster);
float fX, fY, fZ;
pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE);
pCaster->AttackStop();
if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
pCaster->GetMotionMaster()->MovementExpired();
((Creature*)pCaster)->GetMap()->CreatureRelocation((Creature*)pCaster, fX, fY, fZ, pCreatureTarget->GetOrientation());
((Creature*)pCaster)->SendMonsterMove(fX, fY, fZ, 0, ((Creature*)pCaster)->GetUnitMovementFlags(), 1);
pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false);
//always return true when we are handling this spell and effect
return true;
}
return false;
}
/*######
## mob_molten_golem
######*/
struct TRINITY_DLL_DECL mob_molten_golemAI : public ScriptedAI
{
mob_molten_golemAI(Creature *pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
m_bIsHeroic = pCreature->GetMap()->IsHeroic();
Reset();
}
ScriptedInstance* m_pInstance;
bool m_bIsHeroic;
bool m_bIsFrozen;
uint32 m_uiBlast_Timer;
uint32 m_uiDeathDelay_Timer;
uint32 m_uiImmolation_Timer;
void Reset()
{
m_bIsFrozen = false;
m_uiBlast_Timer = 20000;
m_uiDeathDelay_Timer = 0;
m_uiImmolation_Timer = 5000;
}
void AttackStart(Unit* pWho)
{
if (m_creature->Attack(pWho, true))
{
m_creature->AddThreat(pWho, 0.0f);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
if (!m_bIsFrozen)
m_creature->GetMotionMaster()->MoveChase(pWho);
}
}
void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
{
if (m_bIsFrozen)
{
//workaround for now, brittled should be immune to any kind of attacks
uiDamage = 0;
return;
}
if (uiDamage > m_creature->GetHealth())
{
m_bIsFrozen = true;
if (m_creature->IsNonMeleeSpellCasted(false))
m_creature->InterruptNonMeleeSpells(false);
m_creature->RemoveAllAuras();
m_creature->AttackStop();
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
m_creature->GetMotionMaster()->MovementExpired();
uiDamage = m_creature->GetHealth()-1;
m_creature->UpdateEntry(NPC_BRITTLE_GOLEM);
m_creature->SetHealth(1);
}
}
void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
{
//this is the dummy effect of the spells
if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H)
{
if (m_creature->GetEntry() == NPC_BRITTLE_GOLEM)
m_creature->ForcedDespawn();
}
}
void UpdateAI(const uint32 uiDiff)
{
//Return since we have no target or if we are frozen
if (!UpdateVictim() || m_bIsFrozen)
return;
if (m_uiBlast_Timer < uiDiff)
{
DoCast(m_creature, SPELL_BLAST_WAVE);
m_uiBlast_Timer = 20000;
}
else
m_uiBlast_Timer -= uiDiff;
if (m_uiImmolation_Timer < uiDiff)
{
DoCast(m_creature->getVictim(), m_bIsHeroic ? SPELL_IMMOLATION_STRIKE_H : SPELL_IMMOLATION_STRIKE_N);
m_uiImmolation_Timer = 5000;
}
else
m_uiImmolation_Timer -= uiDiff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_mob_molten_golem(Creature* pCreature)
{
return new mob_molten_golemAI(pCreature);
}
void AddSC_boss_volkhan()
@@ -117,12 +475,18 @@ void AddSC_boss_volkhan()
Script *newscript;
newscript = new Script;
newscript->Name="boss_volkhan";
newscript->Name = "boss_volkhan";
newscript->GetAI = &GetAI_boss_volkhan;
newscript->pEffectDummyCreature = &EffectDummyCreature_boss_volkhan;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name="mob_molten_golem";
newscript->Name = "npc_volkhan_anvil";
newscript->pEffectDummyCreature = &EffectDummyCreature_npc_volkhan_anvil;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_molten_golem";
newscript->GetAI = &GetAI_mob_molten_golem;
newscript->RegisterSelf();
}