aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTartalo <none@none>2010-06-19 20:57:58 +0200
committerTartalo <none@none>2010-06-19 20:57:58 +0200
commit6e871d6f4d93a9c1103fa619576e7e387e2b77d8 (patch)
tree3949a54b881eac8dea0b13ce5d6eb14b7cf16820
parentd183d94be81dd64501fe72d674b40dd2f0a94fed (diff)
Violet Hold: Instance mechanics fixes, by PivoNRoll
Closes issue #2733 Implements door hiting by trash, trash waypoints and more --HG-- branch : trunk
-rw-r--r--sql/scripts/world_scripts_full.sql12
-rw-r--r--sql/updates/8638_world_scriptname.sql12
-rw-r--r--src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp225
-rw-r--r--src/server/scripts/Northrend/VioletHold/violet_hold.cpp935
-rw-r--r--src/server/scripts/Northrend/VioletHold/violet_hold.h13
5 files changed, 1066 insertions, 131 deletions
diff --git a/sql/scripts/world_scripts_full.sql b/sql/scripts/world_scripts_full.sql
index 1aaae94d91b..6b36f9f0928 100644
--- a/sql/scripts/world_scripts_full.sql
+++ b/sql/scripts/world_scripts_full.sql
@@ -1491,6 +1491,18 @@ UPDATE `creature_template` SET `ScriptName`='boss_moragg' WHERE `entry`=29316;
UPDATE `creature_template` SET `ScriptName`='boss_xevozz' WHERE `entry`=29266;
UPDATE `creature_template` SET `ScriptName`='mob_ethereal_sphere' WHERE `entry`=29271;
UPDATE `creature_template` SET `ScriptName`='boss_cyanigosa' WHERE `entry`=31134;
+update `creature_template` SET `scriptname`='mob_azure_invader' WHERE `entry`=30661;
+update `creature_template` SET `scriptname`='mob_azure_spellbreaker' WHERE `entry`=30662;
+update `creature_template` SET `scriptname`='mob_azure_binder' WHERE `entry`=30663;
+update `creature_template` SET `scriptname`='mob_azure_mage_slayer' WHERE `entry`=30664;
+update `creature_template` SET `scriptname`='mob_azure_captain' WHERE `entry`=30666;
+update `creature_template` SET `scriptname`='mob_azure_sorceror' WHERE `entry`=30667;
+update `creature_template` SET `scriptname`='mob_azure_raider' WHERE `entry`=30668;
+update `creature_template` SET `scriptname`='mob_azure_stalker' WHERE `entry`=32191;
+update `creature_template` SET `scriptname`='mob_azure_invader' WHERE `entry`=30961;
+update `creature_template` SET `scriptname`='mob_azure_spellbreaker' WHERE `entry`=30962;
+update `creature_template` SET `scriptname`='mob_azure_binder' WHERE `entry`=30918;
+update `creature_template` SET `scriptname`='mob_azure_mage_slayer' WHERE `entry`=30963;
UPDATE `instance_template` SET `script`='instance_violet_hold' WHERE `map`=608;
/* WAILING CAVERNS */
diff --git a/sql/updates/8638_world_scriptname.sql b/sql/updates/8638_world_scriptname.sql
new file mode 100644
index 00000000000..d3f357f43bf
--- /dev/null
+++ b/sql/updates/8638_world_scriptname.sql
@@ -0,0 +1,12 @@
+update `creature_template` SET `scriptname`='mob_azure_invader' WHERE `entry`=30661; -- Azure Invader 1
+update `creature_template` SET `scriptname`='mob_azure_spellbreaker' WHERE `entry`=30662; -- Azure Spellbreaker
+update `creature_template` SET `scriptname`='mob_azure_binder' WHERE `entry`=30663; -- Azure Binder 1
+update `creature_template` SET `scriptname`='mob_azure_mage_slayer' WHERE `entry`=30664; -- Azure Mage Slayer 1
+update `creature_template` SET `scriptname`='mob_azure_captain' WHERE `entry`=30666; -- Azure Captain
+update `creature_template` SET `scriptname`='mob_azure_sorceror' WHERE `entry`=30667; -- Azure Sorceror
+update `creature_template` SET `scriptname`='mob_azure_raider' WHERE `entry`=30668; -- Azure Raider
+update `creature_template` SET `scriptname`='mob_azure_stalker' WHERE `entry`=32191; -- Azure Stalker
+update `creature_template` SET `scriptname`='mob_azure_invader' WHERE `entry`=30961; -- Azure Invader 2
+update `creature_template` SET `scriptname`='mob_azure_spellbreaker' WHERE `entry`=30962; -- Azure Spellbreaker
+update `creature_template` SET `scriptname`='mob_azure_binder' WHERE `entry`=30918; -- Azure Binder 2
+update `creature_template` SET `scriptname`='mob_azure_mage_slayer' WHERE `entry`=30963; -- Azure Mage Sl
diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
index 9b220ae36cc..d5702980ff8 100644
--- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
@@ -34,12 +34,12 @@ enum GameObjects
const Position PortalLocation[] =
{
- {1936.07, 803.198, 53.3749, 3.12414},
- {1877.51, 850.104, 44.6599, 4.7822 },
- {1890.64, 753.471, 48.7224, 1.71042},
- {1908.31, 809.657, 38.7037, 3.08701},
- {1918.37, 853.437, 47.1624, 4.12294},
- {1927.61, 758.436, 51.4533, 2.20891}
+ {1877.51, 850.104, 44.6599, 4.7822 }, // WP 1
+ {1918.37, 853.437, 47.1624, 4.12294}, // WP 2
+ {1936.07, 803.198, 53.3749, 3.12414}, // WP 3
+ {1927.61, 758.436, 51.4533, 2.20891}, // WP 4
+ {1890.64, 753.471, 48.7224, 1.71042}, // WP 5
+ {1908.31, 809.657, 38.7037, 3.08701} // WP 6
};
struct instance_violet_hold : public ScriptedInstance
@@ -65,6 +65,7 @@ struct instance_violet_hold : public ScriptedInstance
uint64 uiXevozzCell;
uint64 uiZuramatCell;
uint64 uiMainDoor;
+ uint64 uiTeleportationPortal;
uint64 uiActivationCrystal[3];
@@ -75,6 +76,10 @@ struct instance_violet_hold : public ScriptedInstance
uint8 uiFirstBoss;
uint8 uiSecondBoss;
uint8 uiRemoveNpc;
+ uint32 uiDoorSpellTimer;
+
+ uint8 uiMainDoorState;
+ uint8 uiDoorIntegrity;
uint8 m_auiEncounter[MAX_ENCOUNTER];
uint8 uiCountErekemGuards;
@@ -82,6 +87,9 @@ struct instance_violet_hold : public ScriptedInstance
bool bActive;
bool bWiped;
+ bool bIsDoorSpellCasted;
+
+ std::list<uint8> NpcAtDoorCastingList;
std::string str_data;
@@ -105,8 +113,13 @@ struct instance_violet_hold : public ScriptedInstance
uiXevozzCell = 0;
uiZuramatCell = 0;
uiMainDoor = 0;
+ uiTeleportationPortal = 0;
+
uiRemoveNpc = 0;
+ uiMainDoorState = GO_STATE_ACTIVE;
+ uiDoorIntegrity = 100;
+
uiWaveCount = 0;
uiLocation = urand(0,5);
uiFirstBoss = 0;
@@ -115,9 +128,10 @@ struct instance_violet_hold : public ScriptedInstance
uiCountActivationCrystals = 0;
uiActivationTimer = 5000;
+ uiDoorSpellTimer = 2000;
bActive = false;
- bWiped = false;
+ bIsDoorSpellCasted = false;
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
}
@@ -242,6 +256,38 @@ struct instance_violet_hold : public ScriptedInstance
case DATA_REMOVE_NPC:
uiRemoveNpc = data;
break;
+ case DATA_PORTAL_LOCATION:
+ uiLocation = (uint8)data;
+ break;
+ case DATA_DOOR_INTEGRITY:
+ uiDoorIntegrity = data;
+ DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, uiDoorIntegrity);
+ break;
+ case DATA_NPC_PRESENCE_AT_DOOR_ADD:
+ NpcAtDoorCastingList.push_back(data);
+ break;
+ case DATA_NPC_PRESENCE_AT_DOOR_REMOVE:
+ if(!NpcAtDoorCastingList.empty())
+ NpcAtDoorCastingList.pop_back();
+ break;
+ case DATA_MAIN_DOOR:
+ if(GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
+ {
+ switch(data)
+ {
+ case GO_STATE_ACTIVE:
+ pMainDoor->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_STATE_READY:
+ pMainDoor->SetGoState(GO_STATE_READY);
+ break;
+ case GO_STATE_ACTIVE_ALTERNATIVE:
+ pMainDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
+ break;
+ }
+ }
+ uiMainDoorState = data;
+ break;
}
}
@@ -254,6 +300,39 @@ struct instance_violet_hold : public ScriptedInstance
case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2];
case DATA_WAVE_COUNT: return uiWaveCount;
case DATA_REMOVE_NPC: return uiRemoveNpc;
+ case DATA_PORTAL_LOCATION: return uiLocation;
+ case DATA_DOOR_INTEGRITY: return uiDoorIntegrity;
+ case DATA_NPC_PRESENCE_AT_DOOR: return NpcAtDoorCastingList.size();
+ case DATA_MAIN_DOOR: return uiMainDoorState;
+ }
+
+ return 0;
+ }
+
+ uint64 GetData64(uint32 identifier)
+ {
+ switch(identifier)
+ {
+ case DATA_MORAGG: return uiMoragg;
+ case DATA_EREKEM: return uiErekem;
+ case DATA_EREKEM_GUARD_1: return uiErekemGuard[0];
+ case DATA_EREKEM_GUARD_2: return uiErekemGuard[1];
+ case DATA_ICHORON: return uiIchoron;
+ case DATA_LAVANTHOR: return uiLavanthor;
+ case DATA_XEVOZZ: return uiXevozz;
+ case DATA_ZURAMAT: return uiZuramat;
+ case DATA_CYANIGOSA: return uiCyanigosa;
+ case DATA_MORAGG_CELL: return uiMoraggCell;
+ case DATA_EREKEM_CELL: return uiErekemCell;
+ case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell;
+ case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell;
+ case DATA_ICHORON_CELL: return uiIchoronCell;
+ case DATA_LAVANTHOR_CELL: return uiLavanthorCell;
+ case DATA_XEVOZZ_CELL: return uiXevozzCell;
+ case DATA_ZURAMAT_CELL: return uiZuramatCell;
+ case DATA_MAIN_DOOR: return uiMainDoor;
+ case DATA_SINCLARI: return uiSinclari;
+ case DATA_TELEPORTATION_PORTAL: return uiTeleportationPortal;
}
return 0;
@@ -261,9 +340,10 @@ struct instance_violet_hold : public ScriptedInstance
void SpawnPortal()
{
+ SetData(DATA_PORTAL_LOCATION, (GetData(DATA_PORTAL_LOCATION) + urand(1,5))%6);
if (Creature *pSinclari = instance->GetCreature(uiSinclari))
- if (Creature *pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL,PortalLocation[uiLocation],TEMPSUMMON_CORPSE_DESPAWN))
- uiLocation = (uiLocation+urand(1,5))%6;
+ if(Creature *portal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL,PortalLocation[GetData(DATA_PORTAL_LOCATION)],TEMPSUMMON_CORPSE_DESPAWN))
+ uiTeleportationPortal = portal->GetGUID();
}
void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true)
@@ -275,8 +355,6 @@ struct instance_violet_hold : public ScriptedInstance
case BOSS_MORAGG:
HandleGameObject(uiMoraggCell,bForceRespawn);
pBoss = instance->GetCreature(uiMoragg);
- if (pBoss)
- pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
break;
case BOSS_EREKEM:
HandleGameObject(uiErekemCell, bForceRespawn);
@@ -284,8 +362,6 @@ struct instance_violet_hold : public ScriptedInstance
HandleGameObject(uiErekemLeftGuardCell, bForceRespawn);
pBoss = instance->GetCreature(uiErekem);
- if (pBoss)
- pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0]))
{
@@ -306,40 +382,38 @@ struct instance_violet_hold : public ScriptedInstance
case BOSS_ICHORON:
HandleGameObject(uiIchoronCell,bForceRespawn);
pBoss = instance->GetCreature(uiIchoron);
- if (pBoss)
- pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
break;
case BOSS_LAVANTHOR:
HandleGameObject(uiLavanthorCell,bForceRespawn);
pBoss = instance->GetCreature(uiLavanthor);
- if (pBoss)
- pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
break;
case BOSS_XEVOZZ:
HandleGameObject(uiXevozzCell,bForceRespawn);
pBoss = instance->GetCreature(uiXevozz);
- if (pBoss)
- pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
break;
case BOSS_ZURAMAT:
HandleGameObject(uiZuramatCell,bForceRespawn);
pBoss = instance->GetCreature(uiZuramat);
- if (pBoss)
- pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
break;
}
- if (!bForceRespawn && pBoss)
+ // generic boss state changes
+ if (pBoss)
{
- if (pBoss->isDead())
+ pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
+ pBoss->SetReactState(REACT_AGGRESSIVE);
+
+ if (!bForceRespawn)
{
- // respawn but avoid to be looted again
- pBoss->Respawn();
- pBoss->RemoveLootMode(1);
+ if (pBoss->isDead())
+ {
+ // respawn but avoid to be looted again
+ pBoss->Respawn();
+ pBoss->RemoveLootMode(1);
+ }
+ pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
+ uiWaveCount = 0;
}
- pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE);
- SetData(DATA_WAVE_COUNT,0);
- uiWaveCount = 0;
}
}
@@ -347,7 +421,6 @@ struct instance_violet_hold : public ScriptedInstance
{
DoUpdateWorldState(WORLD_STATE_VH, 1);
DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, uiWaveCount);
- DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); // TODO
switch(uiWaveCount)
{
@@ -375,43 +448,14 @@ struct instance_violet_hold : public ScriptedInstance
{
if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
pMainDoor->SetGoState(GO_STATE_READY);
+ DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100);
}
default:
- if (!bWiped)
- SpawnPortal();
- bWiped = false;
+ SpawnPortal();
break;
}
}
- uint64 GetData64(uint32 identifier)
- {
- switch(identifier)
- {
- case DATA_MORAGG: return uiMoragg;
- case DATA_EREKEM: return uiErekem;
- case DATA_EREKEM_GUARD_1: return uiErekemGuard[0];
- case DATA_EREKEM_GUARD_2: return uiErekemGuard[1];
- case DATA_ICHORON: return uiIchoron;
- case DATA_LAVANTHOR: return uiLavanthor;
- case DATA_XEVOZZ: return uiXevozz;
- case DATA_ZURAMAT: return uiZuramat;
- case DATA_CYANIGOSA: return uiCyanigosa;
- case DATA_MORAGG_CELL: return uiMoraggCell;
- case DATA_EREKEM_CELL: return uiErekemCell;
- case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell;
- case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell;
- case DATA_ICHORON_CELL: return uiIchoronCell;
- case DATA_LAVANTHOR_CELL: return uiLavanthorCell;
- case DATA_XEVOZZ_CELL: return uiXevozzCell;
- case DATA_ZURAMAT_CELL: return uiZuramatCell;
- case DATA_MAIN_DOOR: return uiMainDoor;
- case DATA_SINCLARI: return uiSinclari;
- }
-
- return 0;
- }
-
std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
@@ -483,7 +527,8 @@ struct instance_violet_hold : public ScriptedInstance
if (!instance->HavePlayers())
return;
- if (bActive)
+ // portals should spawn if other portal is dead and doors are closed
+ if (bActive && GetData(DATA_MAIN_DOOR) == GO_STATE_READY)
{
if (uiActivationTimer < diff)
{
@@ -493,23 +538,55 @@ struct instance_violet_hold : public ScriptedInstance
} else uiActivationTimer -= diff;
}
- if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
- if (pMainDoor->GetGoState() != GO_STATE_ACTIVE && CheckWipe())
+ // if doors are closed (means event is in progres) and players have wiped then reset instance
+ if (GetData(DATA_MAIN_DOOR) != GO_STATE_ACTIVE && CheckWipe())
+ {
+ SetData(DATA_REMOVE_NPC, 1);
+ StartBossEncounter(uiFirstBoss, false);
+ StartBossEncounter(uiSecondBoss, false);
+
+ SetData(DATA_MAIN_DOOR,GO_STATE_ACTIVE);
+ SetData(DATA_WAVE_COUNT, 0);
+
+ if (Creature* pSinclari = instance->GetCreature(uiSinclari))
{
- SetData(DATA_REMOVE_NPC, 1);
- StartBossEncounter(uiFirstBoss, false);
- StartBossEncounter(uiSecondBoss, false);
- bWiped = true;
- if (Creature* pSinclari = instance->GetCreature(uiSinclari))
+ pSinclari->SetVisibility(VISIBILITY_ON);
+
+ std::list<Creature*> GuardList;
+ pSinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f);
+ if (!GuardList.empty())
{
- pSinclari->DisappearAndDie();
- pSinclari->Respawn(true);
+ for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr)
+ {
+ if (Creature* pGuard = *itr)
+ {
+ pGuard->SetVisibility(VISIBILITY_ON);
+ pGuard->SetReactState(REACT_AGGRESSIVE);
+ pGuard->GetMotionMaster()->MovePoint(1,pGuard->GetHomePosition());
+ }
+ }
}
+ pSinclari->GetMotionMaster()->MovePoint(1,pSinclari->GetHomePosition());
+ pSinclari->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NOT_SELECTABLE);
+ }
+ }
- if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
- pMainDoor->SetGoState(GO_STATE_ACTIVE);
- SetData(DATA_WAVE_COUNT, 0);
+ // if there are NPCs in front of the prison door, which are casting the door seal spell and doors are active
+ if(GetData(DATA_NPC_PRESENCE_AT_DOOR) && (GetData(DATA_MAIN_DOOR) == GO_STATE_READY))
+ {
+ // if door integrity is > 0 then decrase it's integrity state
+ if(GetData(DATA_DOOR_INTEGRITY))
+ {
+ if(uiDoorSpellTimer < diff)
+ {
+ SetData(DATA_DOOR_INTEGRITY,GetData(DATA_DOOR_INTEGRITY)-1);
+ uiDoorSpellTimer =2000;
+ } else uiDoorSpellTimer -= diff;
}
+ // else set door state to active (means door will open and group have failed to sustain mob invasion on the door)
+ else
+ SetData(DATA_MAIN_DOOR,GO_STATE_ACTIVE);
+ }
}
};
diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
index 169f933ef45..b46f4d68c11 100644
--- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
@@ -1,4 +1,5 @@
#include "ScriptPCH.h"
+#include "ScriptedEscortAI.h"
#include "violet_hold.h"
#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay."
@@ -7,29 +8,184 @@
enum PortalCreatures
{
- CREATURE_AZURE_INVADER = 30661,
- CREATURE_AZURE_SPELLBREAKER = 30662,
- CREATURE_AZURE_BINDER = 30663,
- CREATURE_AZURE_MAGE_SLAYER = 30664,
+ CREATURE_AZURE_INVADER_1 = 30661,
+ CREATURE_AZURE_INVADER_2 = 30961,
+ CREATURE_AZURE_SPELLBREAKER_1 = 30662,
+ CREATURE_AZURE_SPELLBREAKER_2 = 30962,
+ CREATURE_AZURE_BINDER_1 = 30663,
+ CREATURE_AZURE_BINDER_2 = 30918,
+ CREATURE_AZURE_MAGE_SLAYER_1 = 30664,
+ CREATURE_AZURE_MAGE_SLAYER_2 = 30963,
CREATURE_AZURE_CAPTAIN = 30666,
CREATURE_AZURE_SORCEROR = 30667,
CREATURE_AZURE_RAIDER = 30668,
CREATURE_AZURE_STALKER = 32191
};
+enum AzureInvaderSpells
+{
+ SPELL_CLEAVE = 15496,
+ SPELL_IMPALE = 58459,
+ H_SPELL_IMPALE = 59256,
+ SPELL_BRUTAL_STRIKE = 58460,
+ SPELL_SUNDER_ARMOR = 58461
+};
+
+enum AzureSellbreakerSpells
+{
+ SPELL_ARCANE_BLAST = 58462,
+ H_SPELL_ARCANE_BLAST = 59257,
+ SPELL_SLOW = 25603,
+ SPELL_CHAINS_OF_ICE = 58464,
+ SPELL_CONE_OF_COLD = 58463,
+ H_SPELL_CONE_OF_COLD = 59258
+};
+
+enum AzureBinderSpells
+{
+ SPELL_ARCANE_BARRAGE = 58456,
+ H_SPELL_ARCANE_BARRAGE = 59248,
+ SPELL_ARCANE_EXPLOSION = 58455,
+ H_SPELL_ARCANE_EXPLOSION = 59245,
+ SPELL_FROST_NOVA = 58458,
+ H_SPELL_FROST_NOVA = 59253,
+ SPELL_FROSTBOLT = 58457,
+ H_SPELL_FROSTBOLT = 59251,
+};
+
+enum AzureMageSlayerSpells
+{
+ SPELL_ARCANE_EMPOWERMENT = 58469,
+ SPELL_SPELL_LOCK = 30849
+};
+
+enum AzureCaptainSpells
+{
+ SPELL_MORTAL_STRIKE = 32736,
+ SPELL_WHIRLWIND_OF_STEEL = 41057
+};
+
+enum AzureSorcerorSpells
+{
+ SPELL_ARCANE_STREAM = 60181,
+ H_SPELL_ARCANE_STREAM = 60204,
+ SPELL_MANA_DETONATION = 60182,
+ H_SPELL_MANA_DETONATION = 60205
+};
+
+enum AzureRaiderSpells
+{
+ SPELL_CONCUSSION_BLOW = 52719,
+ SPELL_MAGIC_REFLECTION = 60158
+};
+
+enum AzureStalkerSpells
+{
+ SPELL_BACKSTAB = 58471,
+ SPELL_TACTICAL_BLINK = 58470
+};
+
+enum TrashDoorSpell
+{
+ SPELL_DESTROY_DOOR_SEAL = 58040
+};
+
enum Spells
{
- SPELL_PORTAL_CHANNEL = 58012
+ SPELL_PORTAL_CHANNEL = 58012,
+ SPELL_CRYSTALL_ACTIVATION = 57804
};
enum eSinclari
{
- NPC_VIOLET_HOLD_GUARD = 30659,
+ SAY_SINCLARI_1 = -1608045
+};
+
+float FirstPortalWPs [6][3] =
+{
+ {1877.670288, 842.280273, 43.333591},
+ {1877.338867, 834.615356, 38.762287},
+ {1872.161011, 823.854309, 38.645401},
+ {1864.860474, 815.787170, 38.784843},
+ {1858.953735, 810.048950, 44.008759},
+ {1843.707153, 805.807739, 44.135197}
+ //{1825.736084, 807.305847, 44.363785}
+};
+
+float SecondPortalFirstWPs [9][3] =
+{
+ {1902.561401, 853.334656, 47.106117},
+ {1895.486084, 855.376404, 44.334591},
+ {1882.805176, 854.993286, 43.333591},
+ {1877.670288, 842.280273, 43.333591},
+ {1877.338867, 834.615356, 38.762287},
+ {1872.161011, 823.854309, 38.645401},
+ {1864.860474, 815.787170, 38.784843},
+ {1858.953735, 810.048950, 44.008759},
+ {1843.707153, 805.807739, 44.135197}
+ //{1825.736084, 807.305847, 44.363785}
+};
- SAY_SINCLARI_1 = -1608045,
+float SecondPortalSecondWPs [8][3] =
+{
+ {1929.392212, 837.614990, 47.136166},
+ {1928.290649, 824.750427, 45.474411},
+ {1915.544922, 826.919373, 38.642811},
+ {1900.933960, 818.855652, 38.801647},
+ {1886.810547, 813.536621, 38.490490},
+ {1869.079712, 808.701538, 38.689003},
+ {1860.843384, 806.645020, 44.008789},
+ {1843.707153, 805.807739, 44.135197}
+ //{1825.736084, 807.305847, 44.363785}
+};
+
+float ThirdPortalWPs [8][3] =
+{
+ {1934.049438, 815.778503, 52.408699},
+ {1928.290649, 824.750427, 45.474411},
+ {1915.544922, 826.919373, 38.642811},
+ {1900.933960, 818.855652, 38.801647},
+ {1886.810547, 813.536621, 38.490490},
+ {1869.079712, 808.701538, 38.689003},
+ {1860.843384, 806.645020, 44.008789},
+ {1843.707153, 805.807739, 44.135197}
+ //{1825.736084, 807.305847, 44.363785}
+};
+
+float FourthPortalWPs [9][3] =
+{
+ {1921.658447, 761.657043, 50.866741},
+ {1910.559814, 755.780457, 47.701447},
+ {1896.664673, 752.920898, 47.667004},
+ {1887.398804, 763.633240, 47.666851},
+ {1879.020386, 775.396973, 38.705990},
+ {1872.439087, 782.568604, 38.808292},
+ {1863.573364, 791.173584, 38.743660},
+ {1857.811890, 796.765564, 43.950329},
+ {1845.577759, 800.681152, 44.104248}
+ //{1827.100342, 801.605957, 44.363358}
+};
+
+float FifthPortalWPs [6][3] =
+{
+ {1887.398804, 763.633240, 47.666851},
+ {1879.020386, 775.396973, 38.705990},
+ {1872.439087, 782.568604, 38.808292},
+ {1863.573364, 791.173584, 38.743660},
+ {1857.811890, 796.765564, 43.950329},
+ {1845.577759, 800.681152, 44.104248}
+ //{1827.100342, 801.605957, 44.363358}
+};
+
+float SixthPoralWPs [4][3] =
+{
+ {1888.861084, 805.074768, 38.375790},
+ {1869.793823, 804.135804, 38.647018},
+ {1861.541504, 804.149780, 43.968292},
+ {1843.567017, 804.288208, 44.139091}
+ //{1826.889648, 803.929993, 44.363239}
};
-const Position DoorPosition = { 1828.300049, 797.309021, 46.135502, 1.48353};
const Position MovePosition = { 1806.955566, 803.851807, 44.363323};
struct npc_sinclariAI : public ScriptedAI
@@ -69,22 +225,6 @@ struct npc_sinclariAI : public ScriptedAI
}
}
- void MovementInform(uint32 uiType, uint32 /*uiId*/)
- {
- if (uiType != POINT_MOTION_TYPE)
- return;
-
- if (pInstance)
- {
- pInstance->SetData(DATA_WAVE_COUNT,1);
- pInstance->SetData(DATA_REMOVE_NPC,0); // might not have been reset after a wipe on a boss.
- }
-
- //She should not be despawned, she will be used by the instance to summon some npcs
- me->SetVisibility(VISIBILITY_OFF);
- me->SetReactState(REACT_PASSIVE);
- }
-
void UpdateAI(const uint32 uiDiff)
{
ScriptedAI::UpdateAI(uiDiff);
@@ -96,10 +236,11 @@ struct npc_sinclariAI : public ScriptedAI
switch(uiPhase)
{
case 1:
- DoScriptText(SAY_SINCLARI_1, me);
- uiTimer = 4000;
- uiPhase = 2;
- break;
+ me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NOT_SELECTABLE);
+ DoScriptText(SAY_SINCLARI_1, me);
+ uiTimer = 4000;
+ uiPhase = 2;
+ break;
case 2:
{
std::list<Creature*> GuardList;
@@ -136,6 +277,18 @@ struct npc_sinclariAI : public ScriptedAI
}
case 4:
me->GetMotionMaster()->MovePoint(0, MovePosition);
+ uiTimer = 4000;
+ uiPhase = 5;
+ break;
+ case 5:
+ if (pInstance)
+ {
+ pInstance->SetData(DATA_MAIN_DOOR,GO_STATE_READY);
+ pInstance->SetData(DATA_WAVE_COUNT,1);
+ pInstance->SetData(DATA_REMOVE_NPC,0); // might not have been reset after a wipe on a boss.
+ }
+ me->SetVisibility(VISIBILITY_OFF);
+ me->SetReactState(REACT_PASSIVE);
uiTimer = 0;
uiPhase = 0;
break;
@@ -187,23 +340,29 @@ bool GossipSelect_npc_sinclari(Player* pPlayer, Creature* pCreature, uint32 /*ui
struct npc_teleportation_portalAI : public ScriptedAI
{
- npc_teleportation_portalAI(Creature *c) : ScriptedAI(c)
+ npc_teleportation_portalAI(Creature *c) : ScriptedAI(c), listOfMobs(me)
{
pInstance = c->GetInstanceData();
+ uiTypeOfMobsPortal = urand(0,1); // 0 - elite mobs 1 - portal guardian or portal keeper with regular mobs
+ bPortalGuardianOrKeeperOrEliteSpawn = false;
}
uint32 uiSpawnTimer;
- bool bPortalGuardianOrKeeperSpawn;
+ bool bPortalGuardianOrKeeperOrEliteSpawn;
+ uint8 uiTypeOfMobsPortal;
+
+ SummonList listOfMobs;
ScriptedInstance *pInstance;
void Reset()
{
uiSpawnTimer = 10000;
- bPortalGuardianOrKeeperSpawn = false;
+ bPortalGuardianOrKeeperOrEliteSpawn = false;
}
void EnterCombat(Unit * /*who*/) {}
+
void MoveInLineOfSight(Unit * /*who*/) {}
void UpdateAI(const uint32 diff)
@@ -214,33 +373,63 @@ struct npc_teleportation_portalAI : public ScriptedAI
pInstance->SetData(DATA_REMOVE_NPC, 0);
}
- if (uiSpawnTimer <= diff)
+ switch(uiTypeOfMobsPortal)
{
- if (bPortalGuardianOrKeeperSpawn)
- {
- uint8 k = pInstance->GetData(DATA_WAVE_COUNT) < 12 ? 2 : 3;
- for (uint8 i = 0; i < k; ++i)
+ // spawn elite mobs and then set portals visibility to make it look like it dissapeard
+ case 0:
+ if(!bPortalGuardianOrKeeperOrEliteSpawn)
{
- uint32 entry = RAND(CREATURE_AZURE_CAPTAIN,CREATURE_AZURE_RAIDER,CREATURE_AZURE_STALKER,CREATURE_AZURE_SORCEROR);
- if (Creature* pSummon = DoSummon(entry, me, 2.0f, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT))
- pSummon->GetMotionMaster()->MovePoint(0, DoorPosition);
+ if (uiSpawnTimer <= diff)
+ {
+ bPortalGuardianOrKeeperOrEliteSpawn = true;
+ uint8 k = pInstance->GetData(DATA_WAVE_COUNT) < 12 ? 2 : 3;
+ for (uint8 i = 0; i < k; i)
+ {
+ uint32 entry = RAND(CREATURE_AZURE_CAPTAIN,CREATURE_AZURE_RAIDER,CREATURE_AZURE_STALKER,CREATURE_AZURE_SORCEROR);
+ DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN);
+ }
+ me->SetVisibility(VISIBILITY_OFF);
+ } else uiSpawnTimer -= diff;
}
- }
- else
- {
- bPortalGuardianOrKeeperSpawn = true;
- uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER);
- if (Creature *pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN))
- me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false);
- }
- uiSpawnTimer = SPAWN_TIME;
- } else uiSpawnTimer -= diff;
+ else
+ {
+ // if all spawned elites have died kill portal
+ if(!listOfMobs.size())
+ {
+ me->Kill(me, false);
+ me->RemoveCorpse();
+ }
+ }
+ break;
+ // spawn portal guardian or portal keeper with regular mobs
+ case 1:
+ if (uiSpawnTimer <= diff)
+ {
+ if(bPortalGuardianOrKeeperOrEliteSpawn)
+ {
+ uint8 k = pInstance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4;
+ for (uint8 i = 0; i < k; i)
+ {
+ uint32 entry = RAND(CREATURE_AZURE_INVADER_1,CREATURE_AZURE_INVADER_2,CREATURE_AZURE_SPELLBREAKER_1,CREATURE_AZURE_SPELLBREAKER_2,CREATURE_AZURE_MAGE_SLAYER_1,CREATURE_AZURE_MAGE_SLAYER_2,CREATURE_AZURE_BINDER_1,CREATURE_AZURE_BINDER_2);
+ DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN);
+ }
+ }
+ else
+ {
+ bPortalGuardianOrKeeperOrEliteSpawn = true;
+ uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER);
+ if (Creature *pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN))
+ me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false);
+ }
+ uiSpawnTimer = SPAWN_TIME;
+ } else uiSpawnTimer -= diff;
- if (bPortalGuardianOrKeeperSpawn && !me->IsNonMeleeSpellCasted(false))
- {
- me->Kill(me, false);
- me->RemoveCorpse();
- return;
+ if (bPortalGuardianOrKeeperOrEliteSpawn && !me->IsNonMeleeSpellCasted(false))
+ {
+ me->Kill(me, false);
+ me->RemoveCorpse();
+ }
+ break;
}
}
@@ -249,6 +438,16 @@ struct npc_teleportation_portalAI : public ScriptedAI
if (pInstance)
pInstance->SetData(DATA_WAVE_COUNT,pInstance->GetData(DATA_WAVE_COUNT)+1);
}
+
+ void JustSummoned(Creature *summoned)
+ {
+ listOfMobs.Summon(summoned);
+ }
+
+ void SummonedMobDied(Creature *summoned)
+ {
+ listOfMobs.Despawn(summoned);
+ }
};
CreatureAI* GetAI_npc_teleportation_portal(Creature *pCreature)
@@ -256,6 +455,594 @@ CreatureAI* GetAI_npc_teleportation_portal(Creature *pCreature)
return new npc_teleportation_portalAI(pCreature);
}
+struct violet_hold_trashAI : public npc_escortAI
+{
+ violet_hold_trashAI(Creature *c):npc_escortAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ bHasGotMovingPoints = false;
+ portalLocationID = pInstance->GetData(DATA_PORTAL_LOCATION);
+ Reset();
+ }
+
+ public:
+ ScriptedInstance* pInstance;
+ bool bHasGotMovingPoints;
+ uint32 portalLocationID;
+ uint32 secondPortalRouteID;
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(portalLocationID)
+ {
+ case 0:
+ if (uiPointId == 5)
+ CreatureStartAttackDoor(me->GetGUID());
+ break;
+ case 1:
+ if((uiPointId == 8 && secondPortalRouteID == 0) || (uiPointId == 7 && secondPortalRouteID == 1))
+ CreatureStartAttackDoor(me->GetGUID());
+ break;
+ case 2:
+ if(uiPointId == 7)
+ CreatureStartAttackDoor(me->GetGUID());
+ break;
+ case 3:
+ if(uiPointId == 8)
+ CreatureStartAttackDoor(me->GetGUID());
+ break;
+ case 4:
+ if(uiPointId == 5)
+ CreatureStartAttackDoor(me->GetGUID());
+ break;
+ case 5:
+ if(uiPointId == 3)
+ CreatureStartAttackDoor(me->GetGUID());
+ break;
+ }
+ }
+
+ void UpdateAI(const uint32)
+ {
+ if(pInstance->GetData(DATA_MAIN_DOOR) != GO_STATE_READY)
+ me->CastStop();
+
+ if(!bHasGotMovingPoints)
+ {
+ bHasGotMovingPoints = true;
+ switch(portalLocationID)
+ {
+ case 0:
+ for(int i=0;i<6;i++)
+ AddWaypoint(i,FirstPortalWPs[i][0]+irand(-1,1),FirstPortalWPs[i][1]+irand(-1,1),FirstPortalWPs[i][2]+irand(-1,1),0);
+ me->SetHomePosition(FirstPortalWPs[5][0],FirstPortalWPs[5][1],FirstPortalWPs[5][2],3.149439);
+ break;
+ case 1:
+ secondPortalRouteID = urand(0,1);
+ switch(secondPortalRouteID)
+ {
+ case 0:
+ for(int i=0;i<9;i++)
+ AddWaypoint(i,SecondPortalFirstWPs[i][0]+irand(-1,1),SecondPortalFirstWPs[i][1]+irand(-1,1),SecondPortalFirstWPs[i][2],0);
+ me->SetHomePosition(SecondPortalFirstWPs[8][0]+irand(-1,1),SecondPortalFirstWPs[8][1]+irand(-1,1),SecondPortalFirstWPs[8][2]+irand(-1,1),3.149439);
+ break;
+ case 1:
+ for(int i=0;i<8;i++)
+ AddWaypoint(i,SecondPortalSecondWPs[i][0]+irand(-1,1),SecondPortalSecondWPs[i][1]+irand(-1,1),SecondPortalSecondWPs[i][2],0);
+ me->SetHomePosition(SecondPortalSecondWPs[7][0],SecondPortalSecondWPs[7][1],SecondPortalSecondWPs[7][2],3.149439);
+ break;
+ }
+ break;
+ case 2:
+ for(int i=0;i<8;i++)
+ AddWaypoint(i,ThirdPortalWPs[i][0]+irand(-1,1),ThirdPortalWPs[i][1]+irand(-1,1),ThirdPortalWPs[i][2],0);
+ me->SetHomePosition(ThirdPortalWPs[7][0],ThirdPortalWPs[7][1],ThirdPortalWPs[7][2],3.149439);
+ break;
+ case 3:
+ for(int i=0;i<9;i++)
+ AddWaypoint(i,FourthPortalWPs[i][0]+irand(-1,1),FourthPortalWPs[i][1]+irand(-1,1),FourthPortalWPs[i][2],0);
+ me->SetHomePosition(FourthPortalWPs[8][0],FourthPortalWPs[8][1],FourthPortalWPs[8][2],3.149439);
+ break;
+ case 4:
+ for(int i=0;i<6;i++)
+ AddWaypoint(i,FifthPortalWPs[i][0]+irand(-1,1),FifthPortalWPs[i][1]+irand(-1,1),FifthPortalWPs[i][2],0);
+ me->SetHomePosition(FifthPortalWPs[5][0],FifthPortalWPs[5][1],FifthPortalWPs[5][2],3.149439);
+ break;
+ case 5:
+ for(int i=0;i<4;i++)
+ AddWaypoint(i,SixthPoralWPs[i][0]+irand(-1,1),SixthPoralWPs[i][1]+irand(-1,1),SixthPoralWPs[i][2],0);
+ me->SetHomePosition(SixthPoralWPs[3][0],SixthPoralWPs[3][1],SixthPoralWPs[3][2],3.149439);
+ break;
+ }
+ SetDespawnAtEnd(false);
+ Start(true,true);
+ }
+ }
+
+ void JustDied(Unit *unit)
+ {
+ Creature* portal = Unit::GetCreature((*me),pInstance->GetData64(DATA_TELEPORTATION_PORTAL));
+ if (portal)
+ CAST_AI(npc_teleportation_portalAI,portal->AI())->SummonedMobDied(me);
+ pInstance->SetData(DATA_NPC_PRESENCE_AT_DOOR_REMOVE,1);
+ }
+
+ void CreatureStartAttackDoor(uint32 creature_guid)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ DoCast(SPELL_DESTROY_DOOR_SEAL);
+ pInstance->SetData(DATA_NPC_PRESENCE_AT_DOOR_ADD,1);
+ }
+
+};
+
+struct mob_azure_invaderAI : public violet_hold_trashAI
+{
+ mob_azure_invaderAI(Creature *c) : violet_hold_trashAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiCleaveTimer;
+ uint32 uiImpaleTimer;
+ uint32 uiBrutalStrikeTimer;
+ uint32 uiSunderArmorTimer;
+
+ void Reset()
+ {
+ uiCleaveTimer = 5000;
+ uiImpaleTimer = 4000;
+ uiBrutalStrikeTimer = 5000;
+ uiSunderArmorTimer = 4000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ violet_hold_trashAI::UpdateAI(diff);
+ npc_escortAI::UpdateAI(diff);
+
+ if(!UpdateVictim())
+ return;
+
+ if(me->GetEntry() == CREATURE_AZURE_INVADER_1)
+ {
+ if(uiCleaveTimer <= diff)
+ {
+ DoCast(me->getVictim(),SPELL_CLEAVE);
+ uiCleaveTimer = 5000;
+ }else uiCleaveTimer -= diff;
+
+ if(uiImpaleTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
+ if(pTarget)
+ DoCast(pTarget,SPELL_IMPALE);
+ uiImpaleTimer = 4000;
+ }else uiImpaleTimer -= diff;
+ }
+
+ if(me->GetEntry() == CREATURE_AZURE_INVADER_2)
+ {
+ if(uiBrutalStrikeTimer <= diff)
+ {
+ DoCast(me->getVictim(),SPELL_BRUTAL_STRIKE);
+ uiBrutalStrikeTimer = 5000;
+ }else uiBrutalStrikeTimer -= diff;
+
+ if(uiSunderArmorTimer <= diff)
+ {
+ DoCast(me->getVictim(),SPELL_SUNDER_ARMOR);
+ uiSunderArmorTimer = urand(8000,10000);
+ }else uiSunderArmorTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+};
+
+struct mob_azure_spellbreakerAI : public violet_hold_trashAI
+{
+ mob_azure_spellbreakerAI(Creature* c) : violet_hold_trashAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiArcaneBlastTimer;
+ uint32 uiSlowTimer;
+ uint32 uiChainsOfIceTimer;
+ uint32 uiConeOfColdTimer;
+
+ void Reset()
+ {
+ uiArcaneBlastTimer = 5000;
+ uiSlowTimer = 4000;
+ uiChainsOfIceTimer = 5000;
+ uiConeOfColdTimer = 4000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ violet_hold_trashAI::UpdateAI(diff);
+ npc_escortAI::UpdateAI(diff);
+
+ if(!UpdateVictim())
+ return;
+
+ if(me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_1)
+ {
+ if(uiArcaneBlastTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
+ if(pTarget)
+ DoCast(pTarget,DUNGEON_MODE(SPELL_ARCANE_BLAST,H_SPELL_ARCANE_BLAST));
+ uiArcaneBlastTimer = 6000;
+ }else uiArcaneBlastTimer -= diff;
+
+ if(uiSlowTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
+ if(pTarget)
+ DoCast(pTarget,SPELL_SLOW);
+ uiSlowTimer = 5000;
+ }else uiSlowTimer -= diff;
+ }
+
+ if(me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_2)
+ {
+ if(uiChainsOfIceTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
+ if(pTarget)
+ DoCast(pTarget,SPELL_CHAINS_OF_ICE);
+ uiChainsOfIceTimer = 7000;
+ }else uiChainsOfIceTimer -= diff;
+
+ if(uiConeOfColdTimer <= diff)
+ {
+ DoCast(DUNGEON_MODE(SPELL_CONE_OF_COLD,H_SPELL_CONE_OF_COLD));
+ uiConeOfColdTimer = 5000;
+ }else uiConeOfColdTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_azure_binderAI : public violet_hold_trashAI
+{
+ mob_azure_binderAI(Creature *c) : violet_hold_trashAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiArcaneExplosionTimer;
+ uint32 uiArcainBarrageTimer;
+ uint32 uiFrostNovaTimer;
+ uint32 uiFrostboltTimer;
+
+ void Reset()
+ {
+ uiArcaneExplosionTimer = 5000;
+ uiArcainBarrageTimer = 4000;
+ uiFrostNovaTimer = 5000;
+ uiFrostboltTimer = 4000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ violet_hold_trashAI::UpdateAI(diff);
+ npc_escortAI::UpdateAI(diff);
+
+ if(!UpdateVictim())
+ return;
+
+ if(me->GetEntry() == CREATURE_AZURE_BINDER_1)
+ {
+ if(uiArcaneExplosionTimer <= diff)
+ {
+ DoCast(DUNGEON_MODE(SPELL_ARCANE_EXPLOSION,H_SPELL_ARCANE_EXPLOSION));
+ uiArcaneExplosionTimer = 5000;
+ }else uiArcaneExplosionTimer -= diff;
+
+ if(uiArcainBarrageTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
+ if(pTarget)
+ DoCast(pTarget,DUNGEON_MODE(SPELL_ARCANE_BARRAGE,H_SPELL_ARCANE_BARRAGE));
+ uiArcainBarrageTimer = 6000;
+ }else uiArcainBarrageTimer -= diff;
+ }
+
+ if(me->GetEntry() == CREATURE_AZURE_BINDER_2)
+ {
+ if(uiFrostNovaTimer <= diff)
+ {
+ DoCast(DUNGEON_MODE(SPELL_FROST_NOVA,H_SPELL_FROST_NOVA));
+ uiFrostNovaTimer = 5000;
+ }else uiFrostNovaTimer -= diff;
+
+ if(uiFrostboltTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
+ if(pTarget)
+ DoCast(pTarget,DUNGEON_MODE(SPELL_FROSTBOLT,H_SPELL_FROSTBOLT));
+ uiFrostboltTimer = 6000;
+ }else uiFrostboltTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_azure_mage_slayerAI : public violet_hold_trashAI
+{
+ mob_azure_mage_slayerAI(Creature *c) : violet_hold_trashAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiArcaneEmpowermentTimer;
+ uint32 uiSpellLockTimer;
+
+ void Reset()
+ {
+ uiArcaneEmpowermentTimer = 5000;
+ uiSpellLockTimer = 5000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ violet_hold_trashAI::UpdateAI(diff);
+ npc_escortAI::UpdateAI(diff);
+
+ if(!UpdateVictim())
+ return;
+
+ if(me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_1)
+ {
+ if(uiArcaneEmpowermentTimer <= diff)
+ {
+ DoCast(me,SPELL_ARCANE_EMPOWERMENT);
+ uiArcaneEmpowermentTimer = 14000;
+ }else uiArcaneEmpowermentTimer -= diff;
+ }
+
+ if(me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_2)
+ {
+ if(uiSpellLockTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
+ if(pTarget)
+ DoCast(pTarget,SPELL_SPELL_LOCK);
+ uiSpellLockTimer = 9000;
+ }else uiSpellLockTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_azure_captainAI : public violet_hold_trashAI
+{
+ mob_azure_captainAI(Creature *c) : violet_hold_trashAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiMortalStrikeTimer;
+ uint32 uiWhirlwindTimer;
+
+ void Reset()
+ {
+ uiMortalStrikeTimer = 5000;
+ uiWhirlwindTimer = 8000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ violet_hold_trashAI::UpdateAI(diff);
+ npc_escortAI::UpdateAI(diff);
+
+ if(!UpdateVictim())
+ return;
+
+ if(uiMortalStrikeTimer <= diff)
+ {
+ DoCast(me->getVictim(),SPELL_MORTAL_STRIKE);
+ uiMortalStrikeTimer = 5000;
+ }else uiMortalStrikeTimer -= diff;
+
+ if(uiWhirlwindTimer <= diff)
+ {
+ DoCast(me,SPELL_WHIRLWIND_OF_STEEL);
+ uiWhirlwindTimer = 8000;
+ }else uiWhirlwindTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_azure_sorcerorAI : public violet_hold_trashAI
+{
+ mob_azure_sorcerorAI(Creature *c) : violet_hold_trashAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiArcaneStreamTimer;
+ uint32 uiArcaneStreamTimerStartingValueHolder;
+ uint32 uiManaDetonationTimer;
+
+ void Reset()
+ {
+ uiArcaneStreamTimer = 4000;
+ uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer;
+ uiManaDetonationTimer = 5000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ violet_hold_trashAI::UpdateAI(diff);
+ npc_escortAI::UpdateAI(diff);
+
+ if(!UpdateVictim())
+ return;
+
+ if(uiArcaneStreamTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
+ if(pTarget)
+ DoCast(pTarget,DUNGEON_MODE(SPELL_ARCANE_STREAM,H_SPELL_ARCANE_STREAM));
+ uiArcaneStreamTimer = urand(0,5000)+5000;
+ uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer;
+ }else uiArcaneStreamTimer -= diff;
+
+ if(uiManaDetonationTimer <= diff && uiArcaneStreamTimer >=1500 && uiArcaneStreamTimer <= uiArcaneStreamTimerStartingValueHolder/2)
+ {
+ DoCast(DUNGEON_MODE(SPELL_MANA_DETONATION,H_SPELL_MANA_DETONATION));
+ uiManaDetonationTimer = urand(2000,6000);
+ }else uiManaDetonationTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_azure_raiderAI : public violet_hold_trashAI
+{
+ mob_azure_raiderAI(Creature *c) : violet_hold_trashAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiConcussionBlowTimer;
+ uint32 uiMagicReflectionTimer;
+
+ void Reset()
+ {
+ uiConcussionBlowTimer = 5000;
+ uiMagicReflectionTimer = 8000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ violet_hold_trashAI::UpdateAI(diff);
+ npc_escortAI::UpdateAI(diff);
+
+ if(!UpdateVictim())
+ return;
+
+ if(uiConcussionBlowTimer <= diff)
+ {
+ DoCast(me->getVictim(),SPELL_CONCUSSION_BLOW);
+ uiConcussionBlowTimer = 5000;
+ }else uiConcussionBlowTimer -= diff;
+
+ if(uiMagicReflectionTimer <= diff)
+ {
+ DoCast(SPELL_MAGIC_REFLECTION);
+ uiMagicReflectionTimer = urand(10000,15000);
+ }else uiMagicReflectionTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_azure_stalkerAI : public violet_hold_trashAI
+{
+ mob_azure_stalkerAI(Creature *c) : violet_hold_trashAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+ uint32 uiBackstabTimer;
+ uint32 uiTacticalBlinkTimer;
+ bool TacticalBlinkCasted;
+
+ void Reset()
+ {
+ uiBackstabTimer = 1300;
+ uiTacticalBlinkTimer = 8000;
+ TacticalBlinkCasted =false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ violet_hold_trashAI::UpdateAI(diff);
+ npc_escortAI::UpdateAI(diff);
+
+ if(!UpdateVictim())
+ return;
+
+ if(!TacticalBlinkCasted)
+ {
+ if(uiTacticalBlinkTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true);
+ if(pTarget)
+ DoCast(pTarget,SPELL_TACTICAL_BLINK);
+ uiTacticalBlinkTimer = 6000;
+ TacticalBlinkCasted = true;
+ }else uiTacticalBlinkTimer -= diff;
+ }
+
+ else
+ {
+ if(uiBackstabTimer <= diff)
+ {
+ Unit* pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true);
+ DoCast(pTarget,SPELL_BACKSTAB);
+ TacticalBlinkCasted = false;
+ uiBackstabTimer =1300;
+ }else uiBackstabTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+
+CreatureAI* GetAI_mob_azure_invader(Creature* pCreature)
+{
+ return new mob_azure_invaderAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_azure_spellbreaker(Creature* pCreature)
+{
+ return new mob_azure_spellbreakerAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_azure_binder(Creature* pCreature)
+{
+ return new mob_azure_binderAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_azure_mage_slayer(Creature* pCreature)
+{
+ return new mob_azure_mage_slayerAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_azure_captain(Creature* pCreature)
+{
+ return new mob_azure_captainAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_azure_sorceror(Creature* pCreature)
+{
+ return new mob_azure_sorcerorAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_azure_raider(Creature* pCreature)
+{
+ return new mob_azure_raiderAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_azure_stalker(Creature* pCreature)
+{
+ return new mob_azure_stalkerAI (pCreature);
+}
+
void AddSC_violet_hold()
{
Script *newscript;
@@ -271,4 +1058,44 @@ void AddSC_violet_hold()
newscript->Name = "npc_teleportation_portal_vh";
newscript->GetAI = &GetAI_npc_teleportation_portal;
newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_azure_invader";
+ newscript->GetAI = &GetAI_mob_azure_invader;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_azure_spellbreaker";
+ newscript->GetAI = &GetAI_mob_azure_invader;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_azure_binder";
+ newscript->GetAI = &GetAI_mob_azure_binder;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_azure_mage_slayer";
+ newscript->GetAI = &GetAI_mob_azure_mage_slayer;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_azure_captain";
+ newscript->GetAI = &GetAI_mob_azure_captain;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_azure_sorceror";
+ newscript->GetAI = &GetAI_mob_azure_sorceror;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_azure_raider";
+ newscript->GetAI = &GetAI_mob_azure_raider;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_azure_stalker";
+ newscript->GetAI = &GetAI_mob_azure_stalker;
+ newscript->RegisterSelf();
}
diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.h b/src/server/scripts/Northrend/VioletHold/violet_hold.h
index 4476d5e823a..459cfc884ee 100644
--- a/src/server/scripts/Northrend/VioletHold/violet_hold.h
+++ b/src/server/scripts/Northrend/VioletHold/violet_hold.h
@@ -14,7 +14,8 @@ enum Creatures
CREATURE_EREKEM_GUARD = 29395,
CREATURE_MORAGG = 29316,
CREATURE_CYANIGOSA = 31134,
- CREATURE_SINCLARI = 30658
+ CREATURE_SINCLARI = 30658,
+ NPC_VIOLET_HOLD_GUARD = 30659
};
enum Data
@@ -23,7 +24,12 @@ enum Data
DATA_2ND_BOSS_EVENT,
DATA_CYANIGOSA_EVENT,
DATA_WAVE_COUNT,
- DATA_REMOVE_NPC
+ DATA_REMOVE_NPC,
+ DATA_PORTAL_LOCATION,
+ DATA_DOOR_INTEGRITY,
+ DATA_NPC_PRESENCE_AT_DOOR,
+ DATA_NPC_PRESENCE_AT_DOOR_ADD,
+ DATA_NPC_PRESENCE_AT_DOOR_REMOVE
};
enum Data64
@@ -46,7 +52,8 @@ enum Data64
DATA_XEVOZZ_CELL,
DATA_ZURAMAT_CELL,
DATA_MAIN_DOOR,
- DATA_SINCLARI
+ DATA_SINCLARI,
+ DATA_TELEPORTATION_PORTAL
};
enum Bosses