*Emalon the Stormwatcher fully scripted, by Necroo (boss needs to be spawned and ScriptName needs to be updated)

*Added config options: DurabilityLoss.OnDeath and DurabilityLoss.InPvP, optimized Rate.RepairCost

--HG--
branch : trunk
This commit is contained in:
maximius
2009-08-07 12:12:42 -07:00
parent be74be36f6
commit fe3ba612d9
15 changed files with 489 additions and 36 deletions
+1
View File
@@ -484,6 +484,7 @@ SET(trinityscript_LIB_SRCS
scripts/zone/obsidian_sanctum/def_obsidian_sanctum.h
scripts/zone/vault_of_archavon/instance_vault_of_archavon.cpp
scripts/zone/vault_of_archavon/boss_archavon.cpp
scripts/zone/vault_of_archavon/boss_emalon.cpp
scripts/zone/vault_of_archavon/def_vault_of_archavon.h
scripts/zone/wintergrasp/wintergrasp.cpp
scripts/zone/ulduar/ulduar/boss_algalon.cpp
+4
View File
@@ -650,6 +650,8 @@ extern void AddSC_zuldrak();
//Dungeon
//Vault of Archavon
extern void AddSC_boss_archavon();
extern void AddSC_boss_emalon();
extern void AddSC_instance_archavon();
//Region
extern void AddSC_wintergrasp();
@@ -1558,6 +1560,8 @@ void ScriptsInit(char const* cfg_file = "trinitycore.conf")
//Dungeon
//Vault of Archavon
AddSC_boss_archavon();
AddSC_boss_emalon();
AddSC_instance_archavon();
//Region
AddSC_wintergrasp();
@@ -2833,6 +2833,10 @@
RelativePath="..\scripts\zone\vault_of_archavon\boss_archavon.cpp"
>
</File>
<File
RelativePath="..\scripts\zone\vault_of_archavon\boss_emalon.cpp"
>
</File>
<File
RelativePath="..\scripts\zone\vault_of_archavon\def_vault_of_archavon.h"
>
@@ -2834,6 +2834,10 @@
RelativePath="..\scripts\zone\vault_of_archavon\boss_archavon.cpp"
>
</File>
<File
RelativePath="..\scripts\zone\vault_of_archavon\boss_emalon.cpp"
>
</File>
<File
RelativePath="..\scripts\zone\vault_of_archavon\def_vault_of_archavon.h"
>
@@ -3,77 +3,77 @@ UPDATE `creature_template` SET `ScriptName`='boss_archavon' WHERE `entry`='31125
UPDATE `creature_template` SET `ScriptName`='mob_archavon_warder' WHERE `entry`='32353';
*** SQL END ***/
#include "precompiled.h"
#include "def_vault_of_archavon.h"
//These are patchwerk's yell
#define SAY_AGGRO1 -1533017
#define SAY_AGGRO2 -1533018
#define SAY_SLAY -1533019
#define SAY_DEATH -1533020
#define EMOTE_BERSERK -1533021
#define EMOTE_ENRAGE -1533022
#define EMOTE_BERSERK -1590002
//Spells Archavon
#define SPELL_ROCK_SHARDS 58678
#define SPELL_CRUSHING_LEAP HEROIC(58960,60894)//Instant (10-80yr range) -- Leaps at an enemy, inflicting 8000 Physical damage, knocking all nearby enemies away, and creating a cloud of choking debris.
#define SPELL_STOMP HEROIC(58663,60880)
#define SPELL_IMPALE HEROIC(58666,60882) //Lifts an enemy off the ground with a spiked fist, inflicting 47125 to 52875 Physical damage and 9425 to 10575 additional damage each second for 8 sec.
#define SPELL_BERSERK 47008
#define SPELL_ROCK_SHARDS 58678
#define SPELL_CRUSHING_LEAP HEROIC(58960,60894)//Instant (10-80yr range) -- Leaps at an enemy, inflicting 8000 Physical damage, knocking all nearby enemies away, and creating a cloud of choking debris.
#define SPELL_STOMP HEROIC(58663,60880)
#define SPELL_IMPALE HEROIC(58666,60882) //Lifts an enemy off the ground with a spiked fist, inflicting 47125 to 52875 Physical damage and 9425 to 10575 additional damage each second for 8 sec.
#define SPELL_BERSERK 47008
//Spells Archavon Warders
#define SPELL_ROCK_SHOWER HEROIC(60919,60923)
#define SPELL_SHIELD_CRUSH HEROIC(60897,60899)
#define SPELL_WHIRL HEROIC(60902,60916)
#define SPELL_ROCK_SHOWER HEROIC(60919,60923)
#define SPELL_SHIELD_CRUSH HEROIC(60897,60899)
#define SPELL_WHIRL HEROIC(60902,60916)
//4 Warders spawned
#define ARCHAVON_WARDER 32353 //npc 32353
#define ARCHAVON_WARDER 32353 //npc 32353
//Yell
#define SAY_LEAP "Archavon the Stone Watcher lunges for $N!" //$N should be the target
#define EVENT_ROCK_SHARDS 1 //15s cd
#define EVENT_CHOKING_CLOUD 2 //30s cd
#define EVENT_ROCK_SHARDS 1 //15s cd
#define EVENT_CHOKING_CLOUD 2 //30s cd
#define EVENT_STOMP 3 //45s cd
#define EVENT_IMPALE 4
#define EVENT_BERSERK 5 //300s cd
//mob
#define EVENT_ROCK_SHOWER 5 //set = 20s cd,unkown cd
#define EVENT_SHIELD_CRUSH 6 //set = 30s cd
#define EVENT_WHIRL 8 //set= 10s cd
#define EVENT_ROCK_SHOWER 5 //set = 20s cd,unkown cd
#define EVENT_SHIELD_CRUSH 6 //set = 30s cd
#define EVENT_WHIRL 8 //set= 10s cd
struct TRINITY_DLL_DECL boss_archavonAI : public ScriptedAI
{
boss_archavonAI(Creature *c) : ScriptedAI(c) {}
boss_archavonAI(Creature *c) : ScriptedAI(c)
{
pInstance = c->GetInstanceData();
}
ScriptedInstance* pInstance;
EventMap events;
void Reset()
{
events.Reset();
if(pInstance)
pInstance->SetData(DATA_ARCHAVON_EVENT, NOT_STARTED);
}
void KilledUnit(Unit* Victim)
{
if(!(rand()%5))
DoScriptText(SAY_SLAY, me);
}
void KilledUnit(Unit* Victim){}
void JustDied(Unit* Killer)
{
DoScriptText(SAY_DEATH, me);
if (pInstance)
pInstance->SetData(DATA_ARCHAVON_EVENT, DONE);
}
void EnterCombat(Unit *who)
{
DoScriptText((rand()%2) ? SAY_AGGRO1 : SAY_AGGRO2, me);
DoZoneInCombat();
events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000);
events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000);
events.ScheduleEvent(EVENT_STOMP, 45000);
events.ScheduleEvent(EVENT_BERSERK, 300000);
if(pInstance)
pInstance->SetData(DATA_ARCHAVON_EVENT, IN_PROGRESS);
}
// Below UpdateAI may need review/debug.
void UpdateAI(const uint32 diff)
{
//Return since we have no target
@@ -0,0 +1,284 @@
#include "precompiled.h"
#include "def_vault_of_archavon.h"
#define EMOTE_OVERCHARGE_TEMPEST_MINION -1590000
#define EMOTE_MINION_RESPAWN -1590001
//Spells Emalon
#define SPELL_CHAIN_LIGHTNING HEROIC(64213,64215)
#define SPELL_LIGHTNING_NOVA HEROIC(64216,65279)
#define SPELL_OVERCHARGE 64218
#define SPELL_BERSERK 47008
//Spells Tempest Minions
#define SPELL_OVERCHARGED 64217
#define SPELL_OVERCHARGED_BLAST 64219
#define SPELL_SHOCK 64363
//4 Warders spawned
#define TEMPEST_MINIONS 33998
#define EVENT_CHAIN_LIGHTNING 1 //5s cd
#define EVENT_OVERCHARGE 2 //45s cd
#define EVENT_LIGHTNING_NOVA 3 //40s cd
#define EVENT_BERSERK 4 //360s cd
#define EVENT_SHOCK 5 //20s cd
struct Location
{
float x, y, z, o;
};
static Location MinionLocation[]=
{
-231.713,-281.96,91.466,1.53213,
-205.585,-281.549,91.4661,1.75204,
-205.651,-296.394,91.4661,1.69549,
-232.235,-296.433,91.4998,1.44417
};
struct TRINITY_DLL_DECL boss_emalonAI : public ScriptedAI
{
boss_emalonAI(Creature *c) : ScriptedAI(c)
{
pInstance = c->GetInstanceData();
}
ScriptedInstance* pInstance;
EventMap events;
std::list<uint64> MinionList;
void Reset()
{
events.Reset();
DespawnAllMinions();
SummonAllMinions();
if(pInstance)
pInstance->SetData(DATA_EMALON_EVENT, NOT_STARTED);
}
void DespawnAllMinions()
{
if(!MinionList.empty())
{
for(std::list<uint64>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); itr++)
{
Unit *Minion = Unit::GetUnit(*m_creature, (*itr));
if(Minion)
Minion->RemoveFromWorld();
}
}
MinionList.clear();
}
void JustSummoned(Creature *Summoned)
{
MinionList.push_back(Summoned->GetGUID());
if(Unit* target = m_creature->getVictim())
Summoned->AI()->AttackStart(target);
}
void SummonAllMinions()
{
if(MinionList.empty())
for(uint8 i = 0; i < 4; i++)
SummonMinion(m_creature, MinionLocation[i].x, MinionLocation[i].y, MinionLocation[i].z, MinionLocation[i].o);
}
static void SummonMinion(Creature *Summoner, float x, float y, float z, float o)
{
Summoner->SummonCreature(TEMPEST_MINIONS, x, y, z, o, TEMPSUMMON_DEAD_DESPAWN, 0);
}
void KilledUnit(Unit* Victim){}
void JustDied(Unit* Killer)
{
DespawnAllMinions();
if (pInstance)
pInstance->SetData(DATA_EMALON_EVENT, DONE);
}
void EnterCombat(Unit *who)
{
if(!MinionList.empty())
{
for(std::list<uint64>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr)
{
Creature* Minion = (Unit::GetCreature(*m_creature, *itr));
Minion->AI()->AttackStart(who);
}
}
DoZoneInCombat();
events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 5000);
events.ScheduleEvent(EVENT_OVERCHARGE, 45000);
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 30000);
events.ScheduleEvent(EVENT_BERSERK, 360000);
events.ScheduleEvent(EVENT_SHOCK, 20000);
if(pInstance)
pInstance->SetData(DATA_EMALON_EVENT, IN_PROGRESS);
}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if(!UpdateVictim())
return;
events.Update(diff);
if(me->hasUnitState(UNIT_STAT_CASTING))
return;
while(uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_CHAIN_LIGHTNING:
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_CHAIN_LIGHTNING);
events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 20000);
return;
case EVENT_OVERCHARGE:
for(std::list<uint64>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr)
{
Creature* Minion = (Unit::GetCreature(*m_creature, *itr));
if(Minion && Minion->isAlive() && !Minion->HasAura(SPELL_OVERCHARGED))
{
Minion->CastSpell(me, SPELL_OVERCHARGED, true);
Minion->SetHealth(Minion->GetMaxHealth());
DoScriptText(EMOTE_OVERCHARGE_TEMPEST_MINION, m_creature);
events.ScheduleEvent(EVENT_OVERCHARGE, 45000);
return;
}
}
case EVENT_LIGHTNING_NOVA:
DoCast(me->getVictim(), SPELL_LIGHTNING_NOVA);
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 25000);
return;
case EVENT_SHOCK:
for(std::list<uint64>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr)
{
Creature* Minion = (Unit::GetCreature(*m_creature, *itr));
if(Minion && Minion->isAlive())
{
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
{
Minion->CastSpell(target, SPELL_SHOCK, true);
events.ScheduleEvent(EVENT_SHOCK, 20000);
return;
}
}
}
case EVENT_BERSERK:
DoCast(m_creature, SPELL_BERSERK);
return;
}
}
DoMeleeAttackIfReady();
}
};
/*######
## Mob Tempest Minions
######*/
struct TRINITY_DLL_DECL mob_tempest_minionsAI : public ScriptedAI
{
mob_tempest_minionsAI(Creature *c) : ScriptedAI(c)
{
pInstance = c->GetInstanceData();
EmalonGUID = pInstance ? pInstance->GetData64(DATA_EMALON) : 0;
Emalon = Unit::GetCreature(*m_creature, EmalonGUID);
}
ScriptedInstance* pInstance;
EventMap events;
uint64 EmalonGUID;
std::list<Creature*> MinionList;
Creature* Emalon;
uint32 SPELL_OVERCHARGED_Timer;
bool AlreadyOvercharged;
void Reset()
{
events.Reset();
AlreadyOvercharged = false;
SPELL_OVERCHARGED_Timer = 0;
}
void EnterCombat(Unit *who)
{
DoZoneInCombat();
if(Emalon)
Emalon->AI()->AttackStart(who);
}
void JustDied(Unit* Killer)
{
m_creature->RemoveCorpse();
m_creature->RemoveFromWorld();
if(Emalon)
{
boss_emalonAI::SummonMinion(Emalon, Emalon->GetPositionX(), Emalon->GetPositionY(), Emalon->GetPositionZ(), Emalon->GetOrientation());
DoScriptText(EMOTE_MINION_RESPAWN, m_creature);
}
}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if(!UpdateVictim())
return;
if(Aura *OverchargedAura = m_creature->GetAura(SPELL_OVERCHARGED))
{
if(OverchargedAura->GetStackAmount() < 10)
{
if (SPELL_OVERCHARGED_Timer < diff)
{
DoCast(me, SPELL_OVERCHARGED);
SPELL_OVERCHARGED_Timer = 2000;
}else SPELL_OVERCHARGED_Timer -=diff;
}
else
{
if(OverchargedAura->GetStackAmount() == 10 && (AlreadyOvercharged == false))
{
DoCast(me,SPELL_OVERCHARGED_BLAST);
AlreadyOvercharged = true;
}
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_mob_tempest_minions(Creature *_Creature)
{
return new mob_tempest_minionsAI (_Creature);
}
CreatureAI* GetAI_boss_emalon(Creature *_Creature)
{
return new boss_emalonAI (_Creature);
}
void AddSC_boss_emalon()
{
Script *newscript;
newscript = new Script;
newscript->Name="boss_emalon";
newscript->GetAI = &GetAI_boss_emalon;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name="mob_tempest_minions";
newscript->GetAI = &GetAI_mob_tempest_minions;
newscript->RegisterSelf();
}
@@ -1,4 +1,13 @@
#ifndef DEF_ARCHAVON_H
#define DEF_ARCHAVON_H
enum
{
DATA_ARCHAVON = 1,
DATA_EMALON = 2,
DATA_ARCHAVON_EVENT = 3,
DATA_EMALON_EVENT = 4
};
#endif
@@ -1,9 +1,112 @@
#include "precompiled.h"
#include "def_vault_of_archavon.h"
#define NUMBER_OF_ENCOUNTERS 2
struct TRINITY_DLL_DECL instance_archavon : public ScriptedInstance
{
instance_archavon(Map *Map) : ScriptedInstance(Map) {Initialize();};
std::string strInstData;
uint64 Archavon;
uint64 Emalon;
uint32 Encounters[NUMBER_OF_ENCOUNTERS];
void Initialize()
{
Archavon = 0;
Emalon = 0;
for(uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; i++)
Encounters[i] = NOT_STARTED;
}
bool IsEncounterInProgress() const
{
for(uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i)
if(Encounters[i] == IN_PROGRESS)
return true;
return false;
}
void OnCreatureCreate(Creature *creature, bool add)
{
switch(creature->GetEntry())
{
case 31125: Archavon = creature->GetGUID(); break;
case 33993: Emalon = creature->GetGUID(); break;
}
}
uint64 GetData64(uint32 identifier)
{
switch(identifier)
{
case DATA_ARCHAVON: return Archavon;
case DATA_EMALON: return Emalon;
}
return 0;
}
uint32 GetData(uint32 identifier)
{
switch(identifier)
{
case DATA_ARCHAVON_EVENT: return Encounters[0];
case DATA_EMALON_EVENT: return Encounters[1];
}
return 0;
}
void SetData(uint32 identifier, uint32 data)
{
switch(identifier)
{
case DATA_ARCHAVON_EVENT: Encounters[0] = data; break;
case DATA_EMALON_EVENT: Encounters[1] = data; break;
}
if (data == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << Encounters[0] << " " << Encounters[1];
strInstData = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
std::string GetSaveData()
{
return strInstData;
}
void Load(const char* chrIn)
{
if (!chrIn)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(chrIn);
std::istringstream loadStream(chrIn);
loadStream >> Encounters[0] >> Encounters[1];
for(uint8 i = 1; i < NUMBER_OF_ENCOUNTERS; ++i)
{
if (Encounters[i] == IN_PROGRESS)
Encounters[i] = NOT_STARTED;
}
OUT_LOAD_INST_DATA_COMPLETE;
}
};
InstanceData* GetInstanceData_instance_archavon(Map* map)