Fix Script Violet Hold/Ichoron.

Fixes issue #33.

- implement Dehydration achievement
- go frenzy at 25% health and no longer cast bubble
- loose health when water elements are killed (3%. may still need to be adjusted).
- use spawn loc for adds

--HG--
branch : trunk
This commit is contained in:
Trazom62
2010-01-31 16:23:28 +01:00
parent 4732618c22
commit d435366bce
@@ -17,25 +17,26 @@
/* Script Data Start /* Script Data Start
SDName: Boss ichoron SDName: Boss ichoron
SDAuthor: ckegg SDAuthor: ckegg
SD%Complete: SD%Complete: 80%
SDComment: SDComment: TODO: better spawn location for adds
SDCategory: SDCategory:
Script Data End */ Script Data End */
#include "ScriptedPch.h" #include "ScriptedPch.h"
#include "violet_hold.h" #include "violet_hold.h"
#include "SpellId.h"
enum Spells enum Spells
{ {
SPELL_DRAINED = 59820, SPELL_DRAINED = SPELL_DRAINED_59820,
SPELL_FRENZY = 54312, SPELL_FRENZY = SPELL_FRENZY_54312,
SPELL_FRENZY_H = 59522, SPELL_FRENZY_H = SPELL_FRENZY_59522,
SPELL_PROTECTIVE_BUBBLE = 54306, SPELL_PROTECTIVE_BUBBLE = SPELL_PROTECTIVE_BUBBLE_54306,
SPELL_WATER_BLAST = 54237, SPELL_WATER_BLAST = SPELL_WATER_BLAST_54237,
SPELL_WATER_BLAST_H = 59520, SPELL_WATER_BLAST_H = SPELL_WATER_BLAST_59520,
SPELL_WATER_BOLT_VOLLEY = 54241, SPELL_WATER_BOLT_VOLLEY = SPELL_WATER_BOLT_VOLLEY_54241,
SPELL_WATER_BOLT_VOLLEY_H = 59521, SPELL_WATER_BOLT_VOLLEY_H = SPELL_WATER_BOLT_VOLLEY_59521,
SPELL_SPLASH = 59516, SPELL_SPLASH = SPELL_SPLASH_59516,
}; };
enum IchoronCreatures enum IchoronCreatures
@@ -57,47 +58,53 @@ enum Yells
SAY_BUBBLE = -1608026 SAY_BUBBLE = -1608026
}; };
struct Locations enum Achievements
{ {
float x, y, z; ACHIEVEMENT_DEHYDRATION = 2041,
uint32 id;
}; };
static Locations PortalLoc[]= enum Actions
{ {
{1857.125, 763.295, 38.654}, ACTION_WATER_ELEMENT_HIT = 1,
{1925.480, 849.981, 47.174}, ACTION_WATER_ELEMENT_KILLED = 2,
{1892.737, 744.589, 47.666}, };
{1878.198, 850.005, 43.333},
{1909.381, 806.796, 38.645}, // TODO get those positions from spawn of creature 29326
{1936.101, 802.950, 52.417}, #define MAX_SPAWN_LOC 5
static Position SpawnLoc[MAX_SPAWN_LOC]=
{
{1840.64, 795.407, 44.079, 1.676},
{1886.24, 757.733, 47.750, 5.201},
{1877.91, 845.915, 43.417, 3.560},
{1918.97, 850.645, 47.225, 4.136},
{1935.50, 796.224, 52.492, 4.224},
}; };
struct TRINITY_DLL_DECL boss_ichoronAI : public ScriptedAI struct TRINITY_DLL_DECL boss_ichoronAI : public ScriptedAI
{ {
boss_ichoronAI(Creature* pCreature) : ScriptedAI(pCreature) boss_ichoronAI(Creature* pCreature) : ScriptedAI(pCreature), m_waterElements(pCreature)
{ {
pInstance = pCreature->GetInstanceData(); pInstance = pCreature->GetInstanceData();
} }
bool bIsExploded; bool bIsExploded;
bool bIsFrenzy; bool bIsFrenzy;
bool bAchievement;
uint32 uiBuubleChecker_Timer; uint32 uiBubbleCheckerTimer;
uint32 uiWaterBoltVolley_Timer; uint32 uiWaterBoltVolleyTimer;
uint32 uiShowup_Counter;
ScriptedInstance* pInstance; ScriptedInstance* pInstance;
std::list<uint64> m_lWaterElementsGUIDList; SummonList m_waterElements;
void Reset() void Reset()
{ {
bIsExploded = false; bIsExploded = false;
bIsFrenzy = false; bIsFrenzy = false;
uiBuubleChecker_Timer = 1000; bAchievement = true;
uiWaterBoltVolley_Timer = urand(10000, 15000); uiBubbleCheckerTimer = 1000;
uiShowup_Counter = 0; uiWaterBoltVolleyTimer = urand(10000, 15000);
m_creature->SetVisibility(VISIBILITY_ON); m_creature->SetVisibility(VISIBILITY_ON);
DespawnWaterElements(); DespawnWaterElements();
@@ -140,32 +147,45 @@ struct TRINITY_DLL_DECL boss_ichoronAI : public ScriptedAI
} }
} }
void WaterElementHit() void DoAction(const int32 param)
{ {
if (!m_creature->isAlive())
return;
switch(param)
{
case ACTION_WATER_ELEMENT_HIT:
m_creature->SetHealth(m_creature->GetHealth() + m_creature->GetMaxHealth() * 0.01); m_creature->SetHealth(m_creature->GetHealth() + m_creature->GetMaxHealth() * 0.01);
if (bIsExploded) if (bIsExploded)
{ DoExplodeCompleted();
DoCast(m_creature, SPELL_PROTECTIVE_BUBBLE);
bIsExploded = false; bAchievement = false;
m_creature->SetVisibility(VISIBILITY_ON); break;
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); case ACTION_WATER_ELEMENT_KILLED:
uint32 damage = (m_creature->GetMaxHealth()*3)/100;
m_creature->SetHealth(m_creature->GetHealth() - damage);
m_creature->LowerPlayerDamageReq(damage);
break;
} }
} }
void DespawnWaterElements() void DespawnWaterElements()
{ {
if (m_lWaterElementsGUIDList.empty()) m_waterElements.DespawnAll();
return; }
for(std::list<uint64>::iterator itr = m_lWaterElementsGUIDList.begin(); itr != m_lWaterElementsGUIDList.end(); ++itr) // call when explode shall stop.
// either when "hit" by a bubble, or when there is no bubble left.
void DoExplodeCompleted()
{ {
if (Creature* pTemp = (Creature*)Unit::GetUnit(*m_creature, *itr)) bIsExploded = false;
{
if (pTemp->isAlive()) if (!HealthBelowPct(25))
pTemp->Kill(pTemp, false); DoCast(m_creature, SPELL_PROTECTIVE_BUBBLE, true);
}
} m_creature->SetVisibility(VISIBILITY_ON);
m_lWaterElementsGUIDList.clear(); m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
} }
void MoveInLineOfSight(Unit* pWho) {} void MoveInLineOfSight(Unit* pWho) {}
@@ -176,68 +196,62 @@ struct TRINITY_DLL_DECL boss_ichoronAI : public ScriptedAI
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded)
{
DoCast(m_creature, DUNGEON_MODE(SPELL_FRENZY, SPELL_FRENZY_H), true);
bIsFrenzy = true;
}
if (!bIsFrenzy) if (!bIsFrenzy)
{ {
if (uiBuubleChecker_Timer < uiDiff) if (uiBubbleCheckerTimer <= uiDiff)
{ {
if (!bIsExploded) if (!bIsExploded)
{ {
if (!m_creature->HasAura(SPELL_PROTECTIVE_BUBBLE, 0)) if (!m_creature->HasAura(SPELL_PROTECTIVE_BUBBLE, 0))
{ {
DoCast(m_creature, DUNGEON_MODE(SPELL_WATER_BLAST, SPELL_WATER_BLAST_H)); DoCast(m_creature, DUNGEON_MODE(SPELL_WATER_BLAST, SPELL_WATER_BLAST_H));
//DoCast(m_creature, SPELL_DRAINED); DoCast(m_creature, SPELL_DRAINED);
bIsExploded = true; bIsExploded = true;
uiShowup_Counter = 0;
m_creature->AttackStop(); m_creature->AttackStop();
m_creature->SetVisibility(VISIBILITY_OFF); m_creature->SetVisibility(VISIBILITY_OFF);
for(uint8 i = 0; i < 10; i++) for(uint8 i = 0; i < 10; i++)
{ {
//int tmp = urand(0, 5); int tmp = urand(0, MAX_SPAWN_LOC-1);
//m_creature->SummonCreature(NPC_ICHOR_GLOBULE, PortalLoc[tmp].x, PortalLoc[tmp].y, PortalLoc[tmp].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); m_creature->SummonCreature(NPC_ICHOR_GLOBULE, SpawnLoc[tmp], TEMPSUMMON_CORPSE_DESPAWN);
m_creature->SummonCreature(NPC_ICHOR_GLOBULE, m_creature->GetPositionX()-10+rand()%20, m_creature->GetPositionY()-10+rand()%20, m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
} }
} }
uiBuubleChecker_Timer = 3000;
} }
else else
{ {
bool bIsWaterElementsAlive = false; bool bIsWaterElementsAlive = false;
++uiShowup_Counter; if (!m_waterElements.empty())
if (!m_lWaterElementsGUIDList.empty())
{ {
for(std::list<uint64>::iterator itr = m_lWaterElementsGUIDList.begin(); itr != m_lWaterElementsGUIDList.end(); ++itr) for (std::list<uint64>::iterator itr = m_waterElements.begin(); itr != m_waterElements.end(); ++itr)
if (Creature* pTemp = (Creature*)Unit::GetUnit(*m_creature, *itr)) if (Creature* pTemp = Unit::GetCreature(*m_creature, *itr))
if (pTemp->isAlive()) if (pTemp->isAlive())
bIsWaterElementsAlive = true;
}
if (!bIsWaterElementsAlive || uiShowup_Counter > 20)
{ {
DoCast(m_creature, SPELL_PROTECTIVE_BUBBLE); bIsWaterElementsAlive = true;
bIsExploded = false; break;
uiShowup_Counter = 0;
m_creature->SetVisibility(VISIBILITY_ON);
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
}
uiBuubleChecker_Timer = 1000;
} }
} }
else uiBuubleChecker_Timer -= uiDiff;
if (!bIsWaterElementsAlive)
DoExplodeCompleted();
}
uiBubbleCheckerTimer = 1000;
}
else uiBubbleCheckerTimer -= uiDiff;
} }
if (!bIsExploded) if (!bIsExploded)
{ {
if (uiWaterBoltVolley_Timer < uiDiff) if (uiWaterBoltVolleyTimer <= uiDiff)
{ {
DoCast(m_creature, DUNGEON_MODE(SPELL_WATER_BOLT_VOLLEY, SPELL_WATER_BOLT_VOLLEY_H)); DoCast(m_creature, DUNGEON_MODE(SPELL_WATER_BOLT_VOLLEY, SPELL_WATER_BOLT_VOLLEY_H));
uiWaterBoltVolley_Timer = urand(10000, 15000); uiWaterBoltVolleyTimer = urand(10000, 15000);
}
else uiWaterBoltVolley_Timer -= uiDiff;
if (!bIsFrenzy && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25)
{
DoCast(m_creature, DUNGEON_MODE(SPELL_FRENZY, SPELL_FRENZY_H));
bIsFrenzy = true;
} }
else uiWaterBoltVolleyTimer -= uiDiff;
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
@@ -247,10 +261,19 @@ struct TRINITY_DLL_DECL boss_ichoronAI : public ScriptedAI
{ {
DoScriptText(SAY_DEATH, m_creature); DoScriptText(SAY_DEATH, m_creature);
if (bIsExploded)
{
bIsExploded = false;
m_creature->SetVisibility(VISIBILITY_ON);
}
DespawnWaterElements(); DespawnWaterElements();
if (pInstance) if (pInstance)
{ {
if (IsHeroic() && bAchievement)
pInstance->DoCompleteAchievement(ACHIEVEMENT_DEHYDRATION);
if (pInstance->GetData(DATA_WAVE_COUNT) == 6) if (pInstance->GetData(DATA_WAVE_COUNT) == 6)
{ {
pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE);
@@ -266,9 +289,15 @@ struct TRINITY_DLL_DECL boss_ichoronAI : public ScriptedAI
void JustSummoned(Creature* pSummoned) void JustSummoned(Creature* pSummoned)
{ {
pSummoned->SetSpeed(MOVE_RUN, 0.2f); pSummoned->SetSpeed(MOVE_RUN, 0.3f);
pSummoned->GetMotionMaster()->MoveFollow(m_creature, 0, 0); pSummoned->GetMotionMaster()->MoveFollow(m_creature, 0, 0);
m_lWaterElementsGUIDList.push_back(pSummoned->GetGUID()); m_waterElements.push_back(pSummoned->GetGUID());
}
void SummonedCreatureDespawn(Creature *pSummoned)
{
m_waterElements.remove(pSummoned->GetGUID());
} }
void KilledUnit(Unit *victim) void KilledUnit(Unit *victim)
@@ -313,12 +342,11 @@ struct TRINITY_DLL_DECL mob_ichor_globuleAI : public ScriptedAI
{ {
if (Creature* pIchoron = ((Creature*)Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_ICHORON)))) if (Creature* pIchoron = ((Creature*)Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_ICHORON))))
{ {
//maybe 12.0f is not offlike, maybe 2.00f ? if (m_creature->IsWithinDist(pIchoron, 2.0f , false))
float fDistance = m_creature->GetDistance(pIchoron);
if (m_creature->IsWithinDist(pIchoron, fDistance <= 12.0f , false))
{ {
((boss_ichoronAI*)pIchoron->AI())->WaterElementHit(); if (pIchoron->AI())
m_creature->Kill(m_creature, false); pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT);
m_creature->ForcedDespawn();
} }
} }
} }
@@ -330,6 +358,9 @@ struct TRINITY_DLL_DECL mob_ichor_globuleAI : public ScriptedAI
void JustDied(Unit* pKiller) void JustDied(Unit* pKiller)
{ {
DoCast(m_creature, SPELL_SPLASH); DoCast(m_creature, SPELL_SPLASH);
if (Creature* pIchoron = ((Creature*)Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_ICHORON))))
if (pIchoron->AI())
pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED);
} }
}; };