diff options
author | Tartalo <none@none> | 2010-06-19 20:57:58 +0200 |
---|---|---|
committer | Tartalo <none@none> | 2010-06-19 20:57:58 +0200 |
commit | 6e871d6f4d93a9c1103fa619576e7e387e2b77d8 (patch) | |
tree | 3949a54b881eac8dea0b13ce5d6eb14b7cf16820 | |
parent | d183d94be81dd64501fe72d674b40dd2f0a94fed (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.sql | 12 | ||||
-rw-r--r-- | sql/updates/8638_world_scriptname.sql | 12 | ||||
-rw-r--r-- | src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp | 225 | ||||
-rw-r--r-- | src/server/scripts/Northrend/VioletHold/violet_hold.cpp | 935 | ||||
-rw-r--r-- | src/server/scripts/Northrend/VioletHold/violet_hold.h | 13 |
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 |